Search code examples
erlangerlang-shell

Is it possible to define a recursive function within Erlang shell?


I am reading Programming Erlang, when I type these into erlang REPL:

perms([]) -> [[]];
perms(L) -> [[H|T] || H <- L, T <- perms(L--[H])].
* 1: syntax error before: '->'

I know I cannot define functions this way in shell, so I change it to:

2> Perms = fun([]) -> [[]];(L) -> [[H|T] || H <- L, T <- Perms(L--[H])] end.
* 1: variable 'Perms' is unbound

Does this mean I cannot define a recursive function within shell?


Solution

  • Since OTP 17.0 there are named funs:

    • Funs can now be given names

    More details in README:

    OTP-11537  Funs can now be a given a name. Thanks to to Richard O'Keefe
               for the idea (EEP37) and to Anthony Ramine for the
               implementation.
    
    1> Perms = fun F([]) -> [[]];
                   F(L) -> [[H|T] || H <- L, T <- F(L--[H])]
               end.    
    #Fun<erl_eval.30.54118792>
    2> Perms([a,b,c]).
    [[a,b,c],[a,c,b],[b,a,c],[b,c,a],[c,a,b],[c,b,a]]
    

    In older releases, you have to be a little bit more clever but once you get it:

    1> Perms = fun(List) ->
                   G = fun(_, []) -> [[]];
                          (F, L) -> [[H|T] || H <- L, T <- F(F, L--[H])]
                       end,
                   G(G, List)
               end.    
    #Fun<erl_eval.30.54118792>
    2> Perms([a,b,c]).
    [[a,b,c],[a,c,b],[b,a,c],[b,c,a],[c,a,b],[c,b,a]]