1

Is it possible to incorporate case statements in a lambda?

I'm trying to make a function that recursively adds two numbers recursively in Erlang with no luck.

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

Receives error

syntax error before: 'end'
aug2uag
  • 3,379
  • 3
  • 32
  • 53
  • What function do you want to call in clause `Y -> X + fun(Y-1)`? – Dmitry Belyaev Mar 13 '13 at 09:48
  • 1
    As noted, `fun(Y-1)` is the problem. See [this answer](http://stackoverflow.com/a/1179904/113848) for an example of how an anonymous function can call itself. – legoscia Mar 13 '13 at 10:50

4 Answers4

2

You cannot use self declaration inside lambda (at least before R16) but you can send it as a parameter:

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

And you get

> (Mult(2))(3).
6
Dmitry Belyaev
  • 2,573
  • 12
  • 17
2

Have a look at this page http://rosettacode.org/wiki/Y_combinator.

Applied to your case it gives:

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> 

I must confess it is a bit complex for me...

Pascal
  • 13,977
  • 2
  • 24
  • 32
  • I didn't specify anything else other than to be able to define recursive calls without the need for a module, and this was first answer. +1 for opening the gateway to combinators. – aug2uag Mar 14 '13 at 01:19
1

Remember that Erlang does pattern matching, even in anonymous functions. You don't really need a case statement here at all.

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

mult(X) -> 
    fun(0) -> 0;
       (Y) -> X + (mult(X))(Y-1)
    end.
Inaimathi
  • 13,853
  • 9
  • 49
  • 93
0

I don't think that the case expression in your code causes the problem. Rather the function definition itself is malformed.

If I interpret your code correctly, you want to define a recursive function for multiplication. And fun(Y-1) is intended as recursive function call?

But in your case Mult is a variable which is assigned an anonymous function (or rather two nested anonymous functions) and I don't think that anonymous functions allow for recursion.

How about the following variation:

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

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

(to be put in a separate file).

chris
  • 4,988
  • 20
  • 36
  • Precise, was experimenting a way to implement recursive calls without using module, where as you demonstrated above recursive calls can be implemented (with or without lambda; cool code!) – aug2uag Mar 13 '13 at 04:35
  • The cause of the syntax error is that `fun` is a reserved word in Erlang, defining an anonymous function, so you are not allowed to use it in a call like `fun(Y-1)`. – aronisstav Mar 13 '13 at 08:38