2014-11-04 3 views
2

Эрланг уделяет особое внимание читабельности.Передача анонимной функции в качестве параметра функции в Erlang?

Удовлетворение по шаблону, понимание списка - это хорошие инструменты для минимизации вашего кода, фактически не разрушая читаемость. Однако часто анонимные функции передаются как параметр функции в erlang.

для меня это досадно читать. Есть ли какая-то особая причина, почему это делается?

для exmple в целом:

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

Пожалуйста, приведите пример. – bereal

+0

@bereal: ok..2 minutes –

ответ

3

Вы можете справиться с этим так, как вам нравится. Синтаксис может сначала раздражать, но вы, скорее всего, привыкнете к нему. В любом случае вы пытаетесь передать значение функции, как и любой другой параметр. Если вы помните это, вы поймете, что у вас есть три способа сделать это.

Рассмотрим следующий пример модуля:

-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). 

Я не могу думать о какой-либо лучшего способа, чтобы объяснить это, чем с указанным кодом.

Я предпочитаю внешний путь, если я знаю, что я буду использовать ту же самую кучу мест (в этом случае мне действительно нужно определить процедуру, а не переписывать ее анонимно везде). Я предпочитаю внутренний путь, когда мне нужно передать нетривиальное или многострочное условие функции (просто мне легче читать, и я ненавижу отступы в аргументах), или если я буду нуждаться в ней более одного раза в одной и той же функции , и я предпочитаю встроенный способ для тривиальных проверок в чем-то вроде фильтра или сгиба.

+0

не может быть внешним внешний (X) -> add_one (x). –

+2

@ DarkHorse Это, безусловно, может! Но это побеждает цель демонстрации трех способов передачи функции в качестве аргумента, поэтому я этого не делал. :-) Когда вы попадаете в более интересные случаи, например, когда 'external/1' выполняет другую работу, чем просто применять другую функцию к своему аргументу (например, вести журнал, например, что произошло), тогда вам нужно делать это путь. – zxq9

+0

Genius.Thx.so мы можем напрямую передать аргументы и использовать его во внутренних вызовах функций. Я буду придерживаться его и внешнего. –

1

Выбор синтаксиса - это вопрос вкуса или правил кодирования компании, но интересна сила этой функции. вот пример, когда я отправляю функцию в сообщении на другой узел, который, в свою очередь, пересылает список процессов, которые в конечном итоге выполняют его (обратите внимание, что я выбрал анонимную функцию, делая это, я уверен, что принимающий узел сможет для выполнения функции):

старта 2 узлов:

erl -sname node1 
erl -sname node2 

на node1, в оболочке (нуждается в 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)). 

на node2:

([email protected])1>net_adm:ping([email protected]).                
pong    
([email protected])2> {server,[email protected]} ! {forward,{do,fun(X) ->Self = self(), io:format("~p state is ~p~n",[Self,X]),X end}}. 
{forward,{do,#Fun<erl_eval.6.90072148>}} 
([email protected])3> {server,[email protected]} ! {forward,{do,fun(X) -> X + 1 end}}.        
{forward,{do,#Fun<erl_eval.6.90072148>}} 
([email protected])4> {server,[email protected]} ! {forward,{do,fun(X) ->Self = self(), io:format("~p state is ~p~n",[Self,X]),X end}}. 
{forward,{do,#Fun<erl_eval.6.90072148>}} 
([email protected])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 
([email protected])5> 
Смежные вопросы