什么是函数式编程

函数式编程是众多编程范式中的一种,常见的编程范式主要包括命令式编程和函数式编程,面向对象编程就属于命令式编程,好比:C++,Java等。而咱们学习的Scala语言同时兼容了命令式编程和函数式编程两种编程风格。

对于命令式编程,因为涉及多线程之间的状态共享,就须要进入锁机制实现并发控制。而函数式编程则不会在多个线程之间共享状态,不会形成资源争用,也就不须要用锁机制来保护可变状态,天然也就不会出现死锁,这样能够更好地实现并行处理。所以,函数式编程可以更好地利用多个处理器(核)提供的并行处理能力,因此,函数式编程开始受到普遍关注。

函数式编程中的函数这个术语不是指计算机中的函数,而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖外部的状态也不修改外部的状态,函数调用的结果不依赖调用的时间和位置。好比 sqrt(x) 函数计算 x 的平方根,只要 x 不变,不论何时调用,调用几回,值都是不变的,这样写的代码容易进行推理,不容易出错。这使得单元测试和调试都更容易。

Scala语言虽然具备函数式语言的特色,是面向数学的抽象,按道理来说更容易被人们所理解,可是对于以C语言或Java语言入门的程序员来讲,里面的不少概念与以前所理解的编程语言有很大不一样,因此也不容易理解,这也正是笔者写这篇文章的初衷。java

在数学语言里,函数表示的是一种映射关系,其做用是对输入的值进行计算,并返回一个结果,函数内部对外部的全局状态没有任何影响,即在数学语言里,函数是没有反作用的。在编程语言里,咱们把这种无反作用的函数称为纯函数,纯函数编程正是借用了这种纯函数的概念。纯函数的行为表现出与上下文无关的透明性和无反作用性,即函数的调用结果只与输入值有关,而不会受到调用时间和位置的影响,另外函数的调用也不会改变任何全局对象,这些特性使得多线程的并发应用中最复杂的状态同步问题不复存在。这即是函数式编程的巨大优点。程序员

在纯函数式语言里,变量就像数学语言里的代数符号,一经肯定就不能改变。若是须要修改一个变量的值,就只能定义一个新的变量,并将要修改的值赋值给新的变量。尽管这些规定乍一看不符合编程的常理,但正是这种不可变性,造就了函数和普通的值之间的自然对等关系。咱们形象的说函数≈变量。在纯函数式编程中,函数成为了和普通的值同样的“头等公民”,能够像其余任何数据类型的值同样被传递和操做,也就是说,函数的使用方式和其余任何数据类型的使用方式彻底一致。web

函数的定义与使用

定义函数最通用的方法是做为某个类或对象的成员,这种函数被称为方法,实际上,这种方式也是C++和Java(指Java8之前)这种面向对象的语言中定义对象的惟一方法,如下咱们称为“第一种定义方法”。

而若是咱们将函数做为“头等公民”看待,函数应该有“类型”和“值”的区分,“类型”须要明确函数到底接收多少个参数、每一个参数的类型以及函数返回结果的类型;“值”则是函数的一个具体实现,如下咱们称为“第二种定义方式”。

第一种定义方式

方法前用关键字def来修饰。

方法参数前不能加上val或var关键字来限定,由于全部方法参数都是不可变类型。

对于无参数的方法,定义时能够省略括号。不过,若是定义时省略了括号,那么在调用时也不能带有括号。

若是方法只有一个参数,能够省略点号(.)而采用中缀表示法(即中缀操做符调用方法),形式为:“调用者 方法名 参数”。

若是方法体中只有一条语句,则能够省略方法体大括号。

对于Scala而言,方法体中最后一个表达式的值就是方法的返回值。若是咱们可以推断出方法的返回值类型,那么系统确定也能推断出来,这时候就能够省略方法的返回值类型。

下面给你们举几个例子:shell

def method1(arg1:Int):Unit = {println(arg1)}//该方法未省略任何部分

def getValue():Int = value //该方法省略了方法体的大括号,其实()这里也能省略

def getValue(temp:int) = {temp} //该方法省略了返回值类型,由于能够推断出来

第二种定义方式

这种定义方式虽然用来定义函数,可是遵循的是Scala中定义变量的标准语法。

也就是说,把函数看作一个变量去定义。

如下是例子:编程

val counter : (Int) => Int = { (value:Int) => value + 1 } //没有省略任何定义部分

上例中的counter表明函数名,(Int) => Int 表明函数类型,{ (value:Int) => value + 1 } 能够认为是函数的值。

是否是很像Scala中字段的定义方式呢:多线程

var num :Int = 5 //num表示字段名,Int表示该字段的数据类型,5表示该字段的值

回到前一个例子,在counter函数里,counter函数的类型为“(Int) => Int”,表示该函数具备一个整数类型参数并返回一个整数。因为只有一个参数,所以圆括号也能够省略。counter的初始化值为“{ (value:Int) => value + 1 } ”,其中“>=”前面的value是参数名,因为前面申明了参数value的数据类型为Int,因此这里的(value:Int)可省略为:value,“>=”后面是具体的运算语句或表达式,最后一个表达式的值做为函数的返回值,若是只有一条语句,能够省略{ }.

上面的函数定义语法太过繁琐,那么,得益于Scala的类型推断系统,咱们可将上例的函数定义代码简写为:并发

val counter = (value : Int) >= value+1

匿名函数

根据以上的函数定义信息,系统彻底能够推断出counter函数的类型为:Int=>Int,因此省略了函数类型。而“(value : Int) >= value+1”称为函数字面量,也称匿名函数,在有的函数式语言中称为Lambda表达式。

经过以上表述不难看出,所谓匿名函数,实际上不过是把咱们上面提到的函数的类型省略了,变成了:val 函数名 = 函数字面量

下面举几个匿名函数的例子:jvm

val add = (a:Int,b:Int) => a+b

add(3,5) //执行,结果为:8

val show = (s:String) => println(s)

show("hello world") //执行,结果为:hello world

val javaHome= () => System.getProperty("java.home")

println(javaHome()) //执行,结果为:/usr/lib/jvm/java-8-openjdk-amd64/jre

咱们应该注意到:匿名函数的返回值的数据类型依赖于函数体的最后一行表达式的值,这个由程序本身判断,匿名函数的返回值类型不能手工指定!

基于此,在定义函数时,参数的数据类型就必须由咱们手动指定了不然系统判定不出返回值类型。编程语言

占位符简化函数字面量表示

当函数的每一个参数在函数字面量内只出现过一次(也就是传过来的一个参数在我函数方法体里只用了一次),这种状况下能够省略“=>”并用下划线做为参数的占位符来简化函数字面量的表示,第一个下划线表明第一个参数,第二个下划线表明第二个参数,以此类推。(占位符无非就是省略了函数字面量中“=>”之前的内容,只留下实际的方法执行体,并把参数类型体如今方法执行体中)

下面是例子:svg

scala> val counter = (_:Int) + 1 //有类型时括号不能省略,等效于"x:Int=>x+1"

counter: Int => Int =

scala> val add = (_:Int)+(_:Int) //等效于"(a:Int,b:Int)=>a+b"

add: (Int,Int) =>Int =

scala> val m1 = List(1,2,3)

m1: List[Int] = List(1,2,3)

scala> val m2 = m1.map(_*2) //map接受一个函数做为参数,至关于"m1.map(x=>x*2",

//参数的类型能够根据m1的元素类型推断出,因此能够省略

m2: List[Int] = List(2,4,6)

另外,scala中函数能够有多个参数列表,以下:

scala> def multiplier(factor:Int)(x:Int)=x*factor

multiplier: (x: Int)(factor: Int) Int //带有两个参数列表的函数

scala> multiplier(2)(5)

rest2: Int = 10

高阶函数

定义:当一个函数包含其余函数做为其参数或者返回结果为一个函数时,该函数被称为高阶函数。

能够说,支持高阶函数是函数式编程最基本的要求,高阶函数能够将灵活、细粒度的代码块集合成更大,更复杂的程序。

为了实现和高阶函数相同的功能,C++语言须要采用复杂的函数指针;Java8之前则须要经过繁琐的接口来实现。相比之下,Scala中实现高阶函数则显得很是直观。

按照个人理解,所谓高阶函数无非就是把一个匿名函数(该匿名函数具体的执行过程能够在高阶函数执行的时候再自定义)做为参数放入另外一个函数的参数列表。

下面举一个例子来讲明:

def sum(f: Int => Int, a:Int ,b:Int) :Int = {

if(a>b) 0 else f(a)+sum(f,a+1,b)

}

而后调用sum函数:

sum(x=>x,1,5)

Int = 15 //至关因而从1到5的累加和

再次调用:

sum(x=>x*x,1,5)

Int = 55 //至关因而从1到5的累加平方和

还能够传入一个已经定义好的方法:

def powerOfTwo(x: Int) :Int = {

if(x==0) 1 else 2 * powerOfTwo(x - 1)

} //该方法实际上就是运算2的x次幂

sum(powerOfTwo,1,5)

Int = 62

c++语言里平方根值函数,函数式编程之函数定义与使用(以scala语言为例)相关推荐

  1. python语言支持函数式编程_Python语言之Pyhton入门笔记函数式编程

    本文主要向大家介绍了Python语言之Pyhton入门笔记函数式编程,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. 一,匿名函数 def add(x,y) return x+y ...

  2. c语言和高数的函数,数学函数与编程函数 数学的函数与编程的函数一样吗?

    1, 数学的函数与编程的函数一样吗? 是相通但不同领域的概念.数学中的函数是根据给定的输入计算或转换得到结果.而编程中的函数则是一个处理过程,它可以执行数学中的函数一类的纯粹计算过程也可以做更多更复杂 ...

  3. JavaScript 中的函数式编程:函数,组合和柯里化

    作者:Fernando Doglio 译者:前端小智 来源:medium 移动端阅读:点这里 点赞再看,微信搜索 [大迁世界] 关注这个没有大厂背景,但有着一股向上积极心态人.本文 GitHub ht ...

  4. javascript里的偏函数——本质函数式编程+闭包,返回函数

    最终效果: var greet = function(greeting, name) {return greeting + ' ' + name; };var sayHelloTo = _.parti ...

  5. 函数式编程 -- 纯函数、柯里化函数

    文章内容输出来源:拉勾教育 大前端高薪训练营 前言 学习函数式编程,要知道什么是纯函数,使用纯函数的好处,了解有关副作用的相关信息,以及纯函数相关的功能库Lodash,还有什么是函数的柯里化. 一.纯 ...

  6. 什么是函数式编程,函数合并与柯里化又是什么意思?

    函数式编程在耳边回响了多年,今天就来详细了解一下它吧. 函数式编程的主要特征是:函数是一等公民.它建议大家写纯函数.没有副作用的函数. 讨论完纯函数的内容,我们会看一下最重要的应用:函数的柯里化. 纯 ...

  7. elm具体实现过程_函数式编程中的战斗机(二)---elm语言MUV设计模式应用实例...

    1 elm语言设计模式的特点 1.1 面向对象设计模式的特点 每种编程语言都有其独特的语法和优缺点,从而导致与众不同的设计模式和固定架构.面向对象编程因其竭力接近和模拟现实世界的多态和继承,导致面向对 ...

  8. 【scala函数式编程】函数设计的通用结构——Monad

    1. monad单子(monads) 定义:monad是一个满足associativity和identity法则的monadic组合的最小集合的实现,是对象类型的包装,用一个对象包装另一个对象,mon ...

  9. 【基于JS 函数式编程 -1】什么是函数式编程 | 纯函数 | 命令式与声明式 | 优点

    ⭐️ 本文首发自 前端修罗场(点击即可加入),一个专注 Web 技术.答疑解惑.面试辅导.职业发展的社区. 相关文章 [函数式编程]基于JS 进行函数式编程(一)引入 | 什么是函数式编程 | 函数式 ...

  10. Python函数-函数式编程

    文章目录 1 函数式编程 2 Python函数式编程 2.1 map() 2.2 filter() 2.3 filter() 1 函数式编程 所谓函数式编程,是指代码中每一块都是不可变的(immuta ...

最新文章

  1. python潜力开源项目_比较了1000多个Python开源项目,精选出这34个
  2. 在win7下安装SQL sever2005
  3. 真人语音朗读软件_才知道,手机还自带文字转语音功能,一键按下便可实现,网友:赞...
  4. c#输出一个平行四边形_如果Java 和 C# 同时出现,生态也差不多,你选择谁?
  5. c语言基础回顾 —— 其他知识点
  6. oracle的删除的row如何,Oracle 删除大表中部分数据
  7. C#坏习惯:通过不好的例子学习如何制作好的代码——第5部分
  8. 大数据之-Hadoop3.x_MapReduce_二次排序案例---大数据之hadoop3.x工作笔记0116
  9. cat >> ipconf << EOF > EOF是什么意思
  10. SQlite数据库的C编程接口(三) 预处理语句(Prepared Statements) ——《Using SQlite》读书笔记 .
  11. 翻译任务中的BPE词表实践总结
  12. 如何在 Windows 操作系统中使用 Office 模板?
  13. c语言读取文件指定行和列
  14. JavaScript入门案例
  15. simics虚拟机+solaris 9 sparc系统运行memory compiler(非常详细)
  16. 微信扫码 android sdk,H5中js-sdk扫码功能,Android手机微信中无法调用扫码?
  17. gazebo中给机器人添加16线激光雷达跑LIO-SAM
  18. 软件工程作业--网上书店
  19. NGINX中如何根据客户端IP地址控制访问
  20. (十四)懈寄生(4)

热门文章

  1. 75 颜色分类(排序)
  2. 华为手机鸿蒙系统官方下载入口,华为鸿蒙系统官方下载入口
  3. 【转】Linux编译程序报错 undefined reference to error 的解决方法
  4. 数字证书相关的知识点
  5. 如何启动软件YouTube频道
  6. 讨论小程序游戏开发用什么好?
  7. python计算目标文件夹中各文件的GC含量
  8. Vue中图片裁剪的实现
  9. excel设置下拉菜单多选_如何设置多选Excel下拉菜单
  10. 一天破万:二十一个微信公众号推广技巧