Scala函数式编程专题--函数思想介绍

为什么我们需要学习函数式编程?或者说函数式编程有什么优势?这个系列中我会用 scala 给你讲述函数式编程中的优势,以及一些函数式的哲学。不懂 scala 也没关系,scala 和 java 是类似的,在每篇的开头我也会先说明这节中用到的 scala 语法。

为什么函数式编程这几年火起来

如 Python 一样,函数式编程(FP,即Functional Programming)也是近几年才逐渐为人们所知,但它并不是一个多么新的概念。它拥有和面向对象编程(OOP)几乎等长的历史。但纵观每件事的脉络,总是有原因的,函数式编程这几年变火的原因是什么呢?

最主要的原因是摩尔定律的逐渐失效,计算机的发展道路趋向于多核 CPU 与分布式的方向。我们经常使用的面向对象编程的优势在于能够很好得对要解决的问题领域进行建模,但它在多线程编程环境下的同步阻塞调用,以及由此带来的线程安全问题,与函数式编程天然适合分布式并发编程的编程方式相比,当真相形见绌。而未来明显是大数据的时代,故而函数式编程只会越加重要,甚至未来可能是函数式编程的时代。

摩尔定律:1965年,英特尔公司创始人戈登·摩尔提出,在至多10年内,集成电路的集成度会每两年翻一番,即摩尔定律。后来这个周期被缩短到了18个月。也就是说,每隔18个月,计算机等IT产品的性能就会翻一番;或者说相同性能的计算机等IT产品,每18个月价钱会降一半。几十年来IT行业的发展始终遵循着摩尔定律预测的速度。

函数式编程思想介绍

有一篇有趣的文章,或许可以让你对函数式编程有所了解,可以先看看它,稍后再看看对函数式的正式定义,函数式编程圣经。

所谓函数式编程,其实就是以纯函数的方式编写代码,纯函数的定义如下:

纯函数:一个函数在程序的执行过程中除了根据输入参数给出运算结果之外没用其他影响,就可以说是没有副作用的,我们就可以将这一类函数称之为纯函数。

纯函数最核心的目的是为了编写无副作用的代码,它的很多特性,包括不变量,惰性求值等等都是为了这个目标。那什么叫做无副作用呢?我们用一个例子来看看。

咖啡店购物的例子 --scala

先来看一段有副作用(非函数式)的代码

class Cafe {
  //用户购买一杯咖啡执行的函数
  def buyCoffee(Cc: CreditCard) : Coffee = {
    val cup = new Coffee()
    //副作用所在,除了返回一杯咖啡,它还去通知信用卡公司扣费
    cc.charge(cup.price)
    cup
  }
}

这个函数的副作用是什么呢?就是在购买了一杯咖啡的时候使用信用卡去计费,它会通知信用卡公司去进行一系列处理。

这样会导致什么问题呢?首先,副作用会让这段代码变成线程不安全。其次,会让这段代码难以测试,如果想测试这段代码的逻辑,就不得不每次都让信用卡扣费。但我们只是想测试一下逻辑而已,并不想真正扣费。再者,当你想要一次购买多杯咖啡的时候怎么办,你只能跳脚。

这时候我们再看看函数式的方式去实现:

函数式的咖啡店

case class Charge(cc: CreditCard,amount: Double)
class Cafe{
  def buyCoffee(cc:CreditCard) : (Coffee,Charge) = {
    val cup = new Coffee()
    (cup,Charge(cc,cup.price))
  }
}

看到了吗,经过我们这样改变之后,函数变得没有副作用了。也就是说,无论执行这个 buyCoffee 函数多少次,它只会返回给我一杯咖啡以及它的价钱,这样我们就可以很方便得对它的逻辑进行测试而不必担心影响到信用卡。并且它可以安全得运行在多线程环境下。

其实从面向对象的角度来看,这是不是有点像面向对象里面的一些设计模式呢?这样做解耦了咖啡和信用卡之间的关系,在后面添加其他功能的时候我们可以方便得进行组合,比如说想要有一个多杯咖啡计费的功能,如果是用上面那段代码来实现需求,那么无疑会很痛苦。但通过函数式的方式改编后,一些变得清晰起来~

从这个角度来说,函数式编程其实也可以是一种编程思维,它无法帮你立即获得更好的职位,但却可以从某种程度上改变你编程的思维,让你写出更优秀的代码。

结语

最近几年,很多新火起来的概念,但它们其实早在上世纪就已经被发明出来,无论时机器学习,深度学习,Python语言,还是函数式编程。这是为什么呢?这是因为这些技术的边界发生变化,或者说这个时代的技术边界变了。

每个时代都有每个时代的技术边界,真正的工程师会知道边界在哪里,只有外行才会无法无边。巴菲特说他不投资自己不懂的东西,正是因为他给自己的划定了一个边界。

苹果公司能够成功的一个重要原因正是因为它清楚得知道时代的边界,并且能在边界内做到最好。你看苹果很多产品都具有划时代的意义是吧,但其实那些产品都不是苹果首创,比如智能手机,最早是日本公司 DOCOMO 发明,个人平板电脑是英国首先发明。IPod,MP3 也是韩国先出品的。苹果公司用的很多技术甚至在 30 年前就有了,但为什么直到被发明出来才为人们所知?

正是因为苹果了解时代的技术边界,并在边界内做到最好。

往小了说,当我们在学习新的技术,或是使用新技术完成某项工作的时候,我们一定要直到它的边界在哪里。往大了说,我们应该像苹果一样,多多思考这个时代的技术边界在哪里,这样才不至于陷入无休止的技术追赶之中。

(0)

相关推荐

  • 深入理解Scala函数式编程过程

    深入理解Scala函数式编程过程 我们马上开始一段变态的过程 如果要求立方和,可以这么做 35 * 35 * 35 68 * 68 * 68 没毛病,抽象一点儿,写个函数: def cube(n: Int) = n * n * n cube(35) cube(68) 省事儿了,如果求1到10的立方和,OK,写个递归 def cube(n: Int) = n * n * n def sumCube(a: Int, b: Int): Int = if (a > b) 0 else cube(a) +

  • Scala函数式编程专题--函数思想介绍

    为什么我们需要学习函数式编程?或者说函数式编程有什么优势?这个系列中我会用 scala 给你讲述函数式编程中的优势,以及一些函数式的哲学.不懂 scala 也没关系,scala 和 java 是类似的,在每篇的开头我也会先说明这节中用到的 scala 语法. 为什么函数式编程这几年火起来 如 Python 一样,函数式编程(FP,即Functional Programming)也是近几年才逐渐为人们所知,但它并不是一个多么新的概念.它拥有和面向对象编程(OOP)几乎等长的历史.但纵观每件事的脉络

  • Scala函数式编程专题--scala集合和函数

    前情提要: Scala函数式编程专题-- 函数式思想介绍 scala函数式编程专题--scala基础语法介绍 前面已经稍微介绍了scala的常用语法以及面向对象的一些简要知识,这次是补充上一章的,主要会介绍集合和函数. 注意噢,函数和方法是不一样的,方法是在类里面定义的,函数是可以单独存在的(严格来说,在scala内部,每个函数都是一个类) 一.scala集合介绍 还记得上一章介绍的object的apply方法吗,很多数据结构其实都用到了它,从而让我们可以直接用List(...)这样来新建一个L

  • Scala函数式编程专题--scala基础语法介绍

    上次我们介绍了函数式编程的好处,并使用scala写了一个小小的例子帮助大家理解,从这里开始我将真正开始介绍scala编程的一些内容. 这里会先重点介绍scala的一些语法.当然,这里是假设你有一些java或者python的基础,毕竟大部分人不会将scala当作第一门学习编程的语言. 不过这些语法知识记不住也没关系,本身语法这种东西就应该在使用中被记住.这里写这篇的目的也只是梳理一遍,方便大家对语法有个初步的印象,后面可以随时查询. PS:所使用的版本是scala 2.11.8,那我们开始吧 一.

  • Kotlin函数式编程超详细介绍

    目录 1.函数式编程 2.函数类别 3.变换函数(transform) 4.过滤函数(filter) 5.合并函数(combine) 1.函数式编程 我们都知道java是面向对象编程范式.在java的世界,一切皆对象. 函数式编程范式是有抽象数学的lambda演算发展而来,主要依赖高阶函数返回的数据,这些高级函数专用于处理各种集合,可以方便的联合多个函数构建链式操作,以创建复杂的计算行为. 所谓高级函数就是以函数为参数或返回值是函数的函数.这点,前面的文章,有过简单介绍. 2.函数类别 一个函数

  • SpringBoot2使用WebFlux函数式编程的方法

    本文只是简单使用SpringBoot2使用WebFlux的函数式编程简单使用,后续会继续写关于Webflux相关的文章. 最近一直在研究WebFlux,后续会陆续出一些相关的文章. 首先看一下Srping官网上的一张图,对比一下SpringMvc和Spring WebFlux,如图: 在查看一下WebFlux的官方文档:https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html,W

  • .NET并发编程之函数闭包

    函数式编程 一个函数输出当做另一个函数输入.有时候一个复杂问题,我们拆分成很多个步骤函数,这些函数组合起来调用解决一个复杂问题. 在C#中不支持函数组合,但可以直接像这样调用B(A(n)),这也是函数组合,但这不利于阅读,人们习惯从左往右阅读,而不是相反的方向.通过创建扩展方法可以任何组合两个函数,像下面这样 Func<A,C> Compose<A,B,C>(this Func<A.B> f ,Func<B,C> g)=>(n)=>g(f(n))

  • Java中的函数式编程

    目录 1.Lambda 2.函数接口 2.1 函数描述符 3.Java函数接口 3.1 Predicate 3.2 Consumer 3.3 Function 3.4 Supplier 3.5 Primitive Specializations 4.类型检查 4.1 Capturing Lambda 5.方法引用 5.1 构造函数引用 5.2 组合Lambda 5.3 Comparators 5.4 Predicates 5.5 Functions 6.总结 函数式编程是一种编程范式,其中程序是

  • 深入浅出讲解Java8函数式编程

    目录 什么是函数式编程 Java8内置了一些常用的方法接口FunctionalInterface 用的比较多的函数接口 总结 什么是函数式编程 函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用.而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的. 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还

  • ​​​​​​​Python 入门学习之函数式编程

    目录 前言 把函数作为对象 把对象作为函数 数据结构内的函数 把函数作为参数和返回值 嵌套函数 单表达式函数(Lambda 表达式) Map.Filter 和 Reduce Map Filter Reduce 前言 本文对 Python 中的函数式编程技术进行了简单的入门介绍. 在 Python 中,函数是「头等公民」(first-class).也就是说,函数与其他数据类型(如 int)处于平等地位. 因而,我们可以将函数赋值给变量,也可以将其作为参数传入其他函数,将它们存储在其他数据结构(如

随机推荐