将匿名函数作为参数传递给Erlang中的函数?

时间:2014-11-04 05:50:27

标签: erlang

Erlang非常重视可读性。

模式匹配,列表推导是最小化代码而不会实际破坏可读性的好工具。 但是,匿名函数通常作为函数参数传入erlang。

对我来说,阅读它是很烦人的。有什么特别的原因可以解决这个问题吗?

通常为exmple

hhfuns:fold(fun(A,B) -> A + B end, 0, lists:seq(1,6)).

2 个答案:

答案 0 :(得分:7)

您可以按照自己喜欢的方式处理此问题。一开始语法可能很烦人,但你可能会习惯它。在任何情况下,您都试图将传递给函数,就像执行任何其他参数一样。如果你牢记这一点,你会发现你有三种方法可以做到这一点。

考虑以下示例模块:

-module(funplay).
-export([external/1, internal/1, inline/1]).

apply_foo(Foo, Thingy) -> Foo(Thingy).

add_one(N) -> N + 1.

external(X) ->
    apply_foo(fun add_one/1, X).

internal(X) ->
    AddOne = fun(N) -> N + 1 end,
    apply_foo(AddOne, X).

inline(X) ->
    apply_foo(fun(N) -> N + 1 end, X).

我无法想到解释它的方法比上面的代码更好。

如果我知道我会在一堆地方使用相同的东西(在这种情况下,我真的需要定义程序,而不是在任何地方匿名重写它),我更喜欢外部方式。每当我需要将非平凡或多行条件传递给函数时(我更容易阅读,I hate indentation in arguments)或者如果我在同一函数中需要不止一次,我更喜欢内部方式,我更喜欢使用内联方式进行琐碎的检查,例如过滤器或折叠。

答案 1 :(得分:1)

选择语法是品味或公司编码规则的问题,但有趣的是此功能的强大功能。这里是一个例子,我将一个消息中的函数发送到另一个节点,该节点又转发到最终执行它的进程列表(注意我选择了匿名函数,这样做我确信接收节点能够执行功能):

启动2个节点:

erl -sname node1
erl -sname node2

在node1上,在shell中(需要R17才能使用这种语法):

Loop = fun Loop(X) -> receive                                             
{forward, Mess} -> lists:foreach(fun(Pid) -> Pid ! Mess end, X), Loop(X); 
stop -> ok                                                                
end                                                                       
end.

Proc = fun Proc(X) -> receive
{do,Fun} -> Y = Fun(X), Proc(Y);
stop -> ok                     
end                            
end.                           

L = [spawn(fun() -> Proc(0) end) || _ <- lists:seq(1,10)].

register(server,spawn(fun() -> Loop(L) end)).
节点2上的

(node2@XXX)1>net_adm:ping(node1@XXX).                                                              
pong               
(node2@XXX)2> {server,node1@XXX} ! {forward,{do,fun(X) ->Self = self(), io:format("~p state is ~p~n",[Self,X]),X end}}.
{forward,{do,#Fun<erl_eval.6.90072148>}}
(node2@XXX)3> {server,node1@XXX} ! {forward,{do,fun(X) -> X + 1  end}}.                            
{forward,{do,#Fun<erl_eval.6.90072148>}}
(node2@XXX)4> {server,node1@XXX} ! {forward,{do,fun(X) ->Self = self(), io:format("~p state is ~p~n",[Self,X]),X end}}.
{forward,{do,#Fun<erl_eval.6.90072148>}}
(node2@XXX)4> 

node1上的结果:

<0.42.0> state is 0   
<0.43.0> state is 0   
<0.44.0> state is 0   
<0.45.0> state is 0   
<0.46.0> state is 0   
<0.47.0> state is 0   
<0.48.0> state is 0   
<0.49.0> state is 0   
<0.50.0> state is 0   
<0.51.0> state is 0   
<0.43.0> state is 1   
<0.42.0> state is 1   
<0.44.0> state is 1   
<0.45.0> state is 1   
<0.46.0> state is 1   
<0.47.0> state is 1   
<0.48.0> state is 1   
<0.49.0> state is 1   
<0.50.0> state is 1   
<0.51.0> state is 1   
(node1@XXX)5>