2013-03-12 3 views
1

Можно ли включать в себя заявления о случаях в лямбда?заявления о делах в lambdas

Я пытаюсь сделать функцию, которая рекурсивно добавляет два числа рекурсивно в Erlang без везения.

Mult = fun(X) -> (fun(Y) -> case Y of 
    0 -> 0; 
    Y -> X + fun(Y-1) 
    end) 
end. 

получает ошибку

syntax error before: 'end' 
+0

Какую функцию вы хотите вызвать в разделе 'Y -> X + fun (Y-1)'? –

+1

Как отмечалось, 'fun (Y-1)' является проблемой. См. [Этот ответ] (http://stackoverflow.com/a/1179904/113848) для примера того, как анонимная функция может вызывать себя. – legoscia

ответ

2

Посмотри на этой странице http://rosettacode.org/wiki/Y_combinator ,

Применительно к вашему делу это дает:

1> Y = fun(M) -> (fun(X) -> X(X) end)(fun (F) -> M(fun(A) -> (F(F))(A) end) end) end. 
#Fun<erl_eval.6.82930912> 
2> Mul = fun (F) -> fun ({X,0}) -> 0; ({X,N}) -> X + F({X,N-1}) end end. 
#Fun<erl_eval.6.82930912> 
3> (Y(Mul))({5,4}).              
20 
4> 

Я должен признать, что это немного сложно для меня ...

+0

Я не указывал ничего другого, кроме как иметь возможность определять рекурсивные вызовы без необходимости в модуле, и это был первый ответ. +1 для открытия шлюза для комбинаторов. – aug2uag

0

Я не думаю, что case выражение в коде вызывает проблему. Скорее, само определение функции неверно.

Если я правильно интерпретирую ваш код, вы хотите определить рекурсивную функцию для умножения. И fun(Y-1) предназначен как вызов рекурсивной функции?

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

Как насчет следующей вариации:

-module (mult). 
-export ([mult/1]). 

mult(X) -> 
    fun (Y) -> 
    case Y of 
     0 -> 0; 
     Y -> X + (mult(X))(Y-1) 
    end 
end. 

(положить в отдельный файл).

+0

Точно, экспериментировал способ реализации рекурсивных вызовов без использования модуля, где, как вы показали выше, могут быть реализованы рекурсивные вызовы (с или без лямбда, классный код!) – aug2uag

+0

Причиной синтаксической ошибки является то, что 'fun' является зарезервированным слово в Erlang, определяющее анонимную функцию, поэтому вам не разрешается использовать ее в вызове типа «fun (Y-1)». – aronisstav

2

Вы не можете использовать само заявление внутри лямбды (по крайней мере, до R16), но вы можете отправить его в качестве параметра:

Mult = fun(X) -> 
    YFun = fun(0, _) -> 0; 
       (Y, M) -> 
        X + M(Y - 1, M) 
      end, 
    fun(Y) -> 
     YFun(Y, YFun) 
    end 
end. 

И вы получите

> (Mult(2))(3). 
6 
1

Помните, что Erlang делает поиск по шаблону, даже в анонимных функций. Здесь вам вообще не нужна заявка.

-module (math). 
-export ([mult/1]). 

mult(X) -> 
    fun(0) -> 0; 
     (Y) -> X + (mult(X))(Y-1) 
    end.