scala中,带有函数式编程思想的代码很多,如何去理解才更加容易?

  • 传统

    1
    2
    3
    def plusOne(num:Int):Int = {
    num+1
    }
  • 改革过程

    1
    2
    3
    4
    5
    6
    7
    (Int)=>Int // 函数的"类型"提取

    (num)=>{
    num+1 // 函数的"值"提取
    }

    (num)=>num+1
  • 结合改革成果

    1
    2
    3
    val plusOne:Int=>Int={
    (num)=>num+1
    }
  • 还可以变

    1
    val plusOne=(num:Int) => num+1
  • 函数的字面量

    1
    (num:Int) => num+1

何处使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
val nums=List[Int](1,2,3)
@#
map(f:Int => B)
// 这是scala中map方法的定义
// 这里指出map方法需要接受一个Int类型的值f,任意的表达式运算B
// 回过头再把函数的的变革过程想一遍那它应该是怎样"一类的函数"

//下面是我的理解
(x:Int) => B // 此时B看作最后的运算结果得到的类型

(x)=>{
B // 此时B看作是一个过程
}

val plusOne=(x:Int) => x+1
val mString=(x:Int) => x.toString

@A
nums.map((x:Int) => x+1)

@B
nums.map(plusOne)

@C
nums.map(mString)
  • @A和@B达到了同样的效果
  • plusOne和mString是一类函数,可插拔(引用透明)
  • plusOne和mString都是从值=>值的过程,是一条线(纯函数),这就涉及到函数的副作用

函数副作用(摘自维基)

函数副作用指当调用函数时,除了返回函数值之外,还对主调用函数产生附加的影响。例如修改全局变量(函数外的变量)或修改参数。

  • 纯函数
    • 输入输出数据流全是显式(Explicit)的
    • 函数与外界交换数据只有一个唯一渠道——参数和返回值
    • 没有副作用的函数
  • 非纯函数
    • 函数通过隐式(Implicit)方式,从外界获取数据,或者向外部输出数据
    • 比如,读取全局变量,修改全局变量
  • 引用透明
    • 引用透明(Referential Transparent)的概念与函数的副作用相关,且受其影响
    • 如果程序中任意两处具有相同输入值的函数调用能够互相置换,而不影响程序的动作,那么该程序就具有引用透明性

范例

  • 纯函数

    1
    2
    3
    f(x) { 
    return x + 1
    }
  • 非纯函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    a = 0 
    q(x) {
    b = a
    }

    p(x){
    print“hello”
    }
    // p(x)通过I/O API输出了一个字符串。p(x)是非纯函数。

纯函数优点

  • 无状态。线程安全。不需要线程同步。
  • 纯函数相互调用组装起来的函数,还是纯函数。
  • 应用程序或者运行环境(Runtime)可以对纯函数的运算结果进行缓存,运算加快速度。

参考

http://blog.csdn.net/bluishglc/article/details/45291533

https://zh.wikipedia.org/wiki/%E5%87%BD%E6%95%B0%E5%89%AF%E4%BD%9C%E7%94%A8