我们先来看fun函数的一个简单使用,来理解它的概念。
1> D=fun(X)->2*X end.
#Fun<erl_eval.6.80484245>
2> D(3).
6
上面的代码以及log是在erlang shell中运行的程序及其相应结果。打印的这段#Fun<erl_eval.6.80484245>,我们暂时不去理会。
这段代码看完,我们应该对fun函数有一个简单的理解了,接下来我们看一个更加有意思的事情。
3> Double=D.
#Fun<erl_eval.6.80484245>
4> Double(5).
10
没错!函数被当成变量一样赋值了,而且函数的功能也被传递了,这也是为什么我们使用大写开头的D和Double的原因,它们既是函数又是变量。
现在这些内容看上去好像也比较平凡,是因为我们现在还没有领略到fun的强大。
我们再来看看下面的内容:
5> L=[1,2,3,4,5,6].
[1,2,3,4,5,6]
6> lists:map(Double,L).
[2,4,6,8,10,12]
lists是标准库中的一个模块,其中包含了很多对于列表操作的函数,例子中的map就是一个。看了这个例子,或许我们对fun又有了一个新的认识。
函数Double作为参数传递给了高阶函数map。
对于这个概念我们再做一点补充:
7> Even=fun(X)-> X>3 end.
#Fun<erl_eval.6.80484245>
8> lists:filter(Even,L).
[4,5,6]
接下来,我们看一些有点绕的内容。
Erlang之父在其所编写的书中说到,fun不仅可以用作函数的参数(比如map和filter),而且其他函数也可以将fun当作返回值。
这句话未免说得有点绕,我们还是直接看例子:
9> Season=[spring,summer,autumn].
[spring,summer,autumn]
10> Test=fun(L)->(fun(X)->lists:member(X,L) end) end.
#Fun<erl_eval.6.80484245>
11> IsSeason=Test(Season).
#Fun<erl_eval.6.80484245>
12> IsSeason(spring).
true
13> IsSeason(winter).
false
返回fun的fun似乎很让人疑惑,返回正常值的fun一般是这样的D=fun(X)->(2*X) end.括号中的代码2*X就是函数的返回值,D(3)就是将3传给fun函数的参数X
而现在Test=fun(L)->(fun(X)->lists:member(X,L) end) end.外层fun的括号中的返回值是fun(X)->lists:member(X,L) end,而其中的L就是外层fun的参数L。
因此Test是IsSeason的一个泛化版本,在传递给它一个参数L的值之后(函数中L一个列表,因此我们传递给它Season这个列表),Test细化成了IsSeason这个函数,被剥去了外层的fun。