Erlang fun

Erlang (fun函数 | 闭包 | Lambda表达式)

fun

fun函数能将变量的当前值封存起来。

Make fun

1
2
3
4
5
6
7
8
9
10
11
12
13
14
%% 匿名fun函数
F = fun(A1, A2) when A1 > A2 ->
A1;
(_A1, A2) ->
A2
end,

%% 本Module函数别名的fun函数
%% 这种定义方法实际上是语法糖
%% 等同于 fun(Arg1, Arg2) -> which_is_bigger(Arg1, Arg2) end
F = fun which_is_bigger/2

%% 跨Module函数别名的fun函数
F = fun other_module:which_is_bigger/2

Apply fun

1
2
3
4
case F(1, 2) of
1 -> io:format("One is bigger.");
2 -> io:format("Two is bigger.")
end

Difference

匿名fun函数与本Module函数别名fun函数,都依赖于代码的特定版本,在fun函数所属Module重新加载后就会失效,再次调用会抛出异常,fun函数不适合长期保存,若将fun函数以消息的形式发送给别的Erlang系统,接收方必须持有相同版本的代码才能调用。

跨Module函数别名fun函数则不依赖代码的特定版本,被调用时,总是指向被引用函数的最新版本,fun函数类型的值仅仅是函数的符号引用,因此可以被长期保存或者以消息的形式在Erlang系统间传递。

一般来说,只要能保证各Erlang节点的beam文件相同,fun函数作为参数传递就不会有问题。

Higher-Order Functions

高阶函数
将fun函数作为参数或者返回值

1
2
3
4
5
6
7
which_is_bigger(List) ->
F = fun({X, Y}) when X > Y ->
X;
({_X, Y}) ->
Y
end,
lists:map(F, List).
1
2
3
4
5
6
which_is_bigger({X, Y}) when X > Y ->
X;
which_is_bigger({_X, Y}) ->
Y;
which_is_bigger(List) when is_list(List) ->
lists:map(fun which_is_bigger/1, List).

Tail Recursion

1
2
3
4
5
6
SumF = fun(_Self, [], Result) ->
Result;
(Self, [One | List], Result) ->
Self(Self, List, Result + One)
end,
Ans = SumF(SumF, [1,2,3], 0).
1
2
3
4
5
6
7
8
9
SumF = fun(AllList) ->
F = fun(_Self, [], Result) ->
Result;
(Self, [One | List], Result) ->
Self(Self, List, Result + One)
end,
F(F, AllList, 0)
end,
SumF([1,2,3]).
1
2
3
4
5
6
7
8
9
10
11
12
Y = fun(M) ->
F = fun(Self) ->
M(fun(A) -> (Self(Self))(A) end)
end,
F(F)
end,
C = fun(F) ->
fun (0) -> 1;
(N) -> N * F(N-1)
end
end,
(Y(C))(5).