Quantcast

recursive fun()

classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

recursive fun()

deepblue_other
hello
I have this going on

FunVar =
   fun() ->
      ...
      FunVar()
   end.

so the compiler is complaining that FunVar is unbound at the place where its being used inside fun(); this makes sense, however Im wondering how to make this into a recursive function since there's no name to reference the function with.

thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Edwin Fine
I'm assuming that you want to do this in the shell, otherwise it would be easier just to write the function in the usual way, e.g.

myfun() ->
    blah, blah,
    myfun().

To create a fun that calls itself, you must realize that you are creating an unnamed function. When you write

fun(X) -> X * 2 end.

this is compiled to a Fun data type, e.g. #Fun<erl_eval.6.13229925>.

Since the function does not have a name, it cannot refer to itself.

When you write FunVar = fun(X) -> X * 2 end, the function is bound to the variable FunVar. Because the binding takes place *after* the fun is created, the fun cannot refer to the variable FunVar within its definition.

So how is it done? You have to pass the variable to the function so that it "knows" what to call:

FunVar =
   fun(MySelf) ->
      ...
      MySelf().

Then when you call it, you call FunVar(FunVar). Looks strange but it works.

Example: Writing a simple generate and fold function using only a fun() variable.

9> GenFold =
   fun(0, Acc, _) ->
      Acc;

   (X, Acc, Fun) ->
      Fun(X - 1, [X|Acc], Fun)

   end.
#Fun<erl_eval.18.105910772>
10> GenFold(10, [], GenFold).                                                     
[1,2,3,4,5,6,7,8,9,10]
11>

Or a for loop:

22> For =
    fun(Max, Max, ExecFun, _) ->
       ok;
   (N, Max, ExecFun, Next) ->
      ExecFun(N),
      Next(N + 1, Max, ExecFun, Next)
   end.       

#Fun<erl_eval.4.105156089>
23> For(0,10,fun(I) -> io:format("~B ", [I]) end, For).                                                                            
0 1 2 3 4 5 6 7 8 9 ok
24>

Stuff like this is described in Joe Armstrong's Erlang book.

Hope this helps.

On Sat, Oct 4, 2008 at 11:19 PM, deepblue_other <[hidden email]> wrote:

hello
I have this going on

FunVar =
  fun() ->
     ...
     FunVar()
  end.

so the compiler is complaining that FunVar is unbound at the place where its
being used inside fun(); this makes sense, however Im wondering how to make
this into a recursive function since there's no name to reference the
function with.

thanks
--
View this message in context: http://www.nabble.com/recursive-fun%28%29-tp19820386p19820386.html
Sent from the Erlang Questions mailing list archive at Nabble.com.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Richard Carlsson-2
In reply to this post by deepblue_other
deepblue_other wrote:

> hello
> I have this going on
>
> FunVar =
>    fun() ->
>       ...
>       FunVar()
>    end.
>
> so the compiler is complaining that FunVar is unbound at the place where its
> being used inside fun(); this makes sense, however Im wondering how to make
> this into a recursive function since there's no name to reference the
> function with.

You have to make it keep "itself" around as an additional parameter,
so that you can first create it and then hand it the self-reference:

FunVar =
   fun(Myself) ->
       ...
       Myself(Myself)
    end

then call it like this:

FunVar(FunVar).

If you want the result to be a function of arity 0,
as in your example, then replace the last line with

FinalFunVar = fun () -> FunVar(FunVar) end

    /Richard

--
 "Having users is like optimization: the wise course is to delay it."
   -- Paul Graham
_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Richard Andrews-4
In reply to this post by deepblue_other


> FunVar =
>    fun() ->
>       ...
>       FunVar()
>    end.
>
> so the compiler is complaining that FunVar is unbound at the place where its
> being used inside fun(); this makes sense, however Im wondering how to make
> this into a recursive function since there's no name to reference the
> function with.


Maybe have the fun call a real (recursive) function.

eg.

F(A) ->
    ...
    F(B).

Caller(Data) ->
    ...
    FunVar = fun(A) -> F(A) end,
    ...
    foo:use_fun(FunVar, Data).

--
  Rich


      Make the switch to the world&#39;s best email. Get Yahoo!7 Mail! http://au.yahoo.com/y7mail
_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Ciprian Dorin Craciun
In reply to this post by Richard Carlsson-2
On Sun, Oct 5, 2008 at 12:30 PM, Richard Carlsson <[hidden email]> wrote:

> deepblue_other wrote:
>> hello
>> I have this going on
>>
>> FunVar =
>>    fun() ->
>>       ...
>>       FunVar()
>>    end.
>>
>> so the compiler is complaining that FunVar is unbound at the place where its
>> being used inside fun(); this makes sense, however Im wondering how to make
>> this into a recursive function since there's no name to reference the
>> function with.
>
> You have to make it keep "itself" around as an additional parameter,
> so that you can first create it and then hand it the self-reference:
>
> FunVar =
>   fun(Myself) ->
>       ...
>       Myself(Myself)
>    end
>
> then call it like this:
>
> FunVar(FunVar).
>
> If you want the result to be a function of arity 0,
> as in your example, then replace the last line with
>
> FinalFunVar = fun () -> FunVar(FunVar) end
>
>    /Richard
>
> --
>  "Having users is like optimization: the wise course is to delay it."
>   -- Paul Graham


    About this subject, I would ask if isn't it better / easier /
clearer to add a special function name / keyword that would refer to
the function itself. This would also have a few advantages:
    * first it will solve the recursivity problem described above;
    * (maybe) it could also improve efficiency (because you know
exactly what function you're calling, without any lookup); (this is
just an assumption, maybe inside the beam file the lookup does not
exist); (certainly it is more efficient than the proposed solution ---
sending the function as an argument;)
    * it will assist in refactoring --- changing a recursive function
name will have no impact on it's code;
    * it could clearly mark the fact that the function calls itself.

    As for disadvantages I really do not see any. (Except of having a
new keyword / special function.)

    So any comments?

    Ciprian.

    P.S.: I think this solution could be equally applied to all
languages (mainly Lisp like).
_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Edwin Fine
In reply to this post by Edwin Fine
Just noticed a mistake.

FunVar =
   fun(MySelf) ->
      ...
      MySelf().

should have been

FunVar =
   fun(MySelf) ->
      ...
      MySelf(MySelf).

On Sun, Oct 5, 2008 at 5:13 AM, Edwin Fine <[hidden email]> wrote:
I'm assuming that you want to do this in the shell, otherwise it would be easier just to write the function in the usual way, e.g.

myfun() ->
    blah, blah,
    myfun().

To create a fun that calls itself, you must realize that you are creating an unnamed function. When you write

fun(X) -> X * 2 end.

this is compiled to a Fun data type, e.g. #Fun<erl_eval.6.13229925>.

Since the function does not have a name, it cannot refer to itself.

When you write FunVar = fun(X) -> X * 2 end, the function is bound to the variable FunVar. Because the binding takes place *after* the fun is created, the fun cannot refer to the variable FunVar within its definition.

So how is it done? You have to pass the variable to the function so that it "knows" what to call:

FunVar =
   fun(MySelf) ->
      ...
      MySelf().

Then when you call it, you call FunVar(FunVar). Looks strange but it works.

Example: Writing a simple generate and fold function using only a fun() variable.

9> GenFold =
   fun(0, Acc, _) ->
      Acc;

   (X, Acc, Fun) ->
      Fun(X - 1, [X|Acc], Fun)

   end.
#Fun<erl_eval.18.105910772>
10> GenFold(10, [], GenFold).                                                     
[1,2,3,4,5,6,7,8,9,10]
11>

Or a for loop:

22> For =
    fun(Max, Max, ExecFun, _) ->
       ok;
   (N, Max, ExecFun, Next) ->
      ExecFun(N),
      Next(N + 1, Max, ExecFun, Next)
   end.       

#Fun<erl_eval.4.105156089>
23> For(0,10,fun(I) -> io:format("~B ", [I]) end, For).                                                                            
0 1 2 3 4 5 6 7 8 9 ok
24>

Stuff like this is described in Joe Armstrong's Erlang book.

Hope this helps.


On Sat, Oct 4, 2008 at 11:19 PM, deepblue_other <[hidden email]> wrote:

hello
I have this going on

FunVar =
  fun() ->
     ...
     FunVar()
  end.

so the compiler is complaining that FunVar is unbound at the place where its
being used inside fun(); this makes sense, however Im wondering how to make
this into a recursive function since there's no name to reference the
function with.

thanks
--
View this message in context: http://www.nabble.com/recursive-fun%28%29-tp19820386p19820386.html
Sent from the Erlang Questions mailing list archive at Nabble.com.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions




_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

deepblue_other
In reply to this post by Edwin Fine

Edwin Fine-2 wrote
I'm assuming that you want to do this in the shell, otherwise it would be
easier just to write the function in the usual way, e.g.

myfun() ->
    blah, blah,
    myfun().
no shell is not the reason, I need a function that will only be called from within another function and I dont want to "pollute" the "module wide" space with another function, so Im putting in a nested one...
I would prefer to declare a regular function, but as far as I know there are no nested functions in Erlang (regular named functions).
Edwin Fine-2 wrote
To create a fun that calls itself, you must realize that you are creating an
unnamed function. When you write

fun(X) -> X * 2 end.

this is compiled to a Fun data type, e.g. #Fun<erl_eval.6.13229925>.

Since the function does not have a name, it cannot refer to itself.

When you write FunVar = fun(X) -> X * 2 end, the function is bound to the
variable FunVar. Because the binding takes place *after* the fun is created,
the fun cannot refer to the variable FunVar within its definition.

So how is it done? You have to pass the variable to the function so that it
"knows" what to call:

FunVar =
   fun(MySelf) ->
      ...
      MySelf().

Then when you call it, you call FunVar(FunVar). Looks strange but it works.

Example: Writing a simple generate and fold function using only a fun()
variable.

9> GenFold =
   fun(0, Acc, _) ->
      Acc;
   (X, Acc, Fun) ->
      Fun(X - 1, [X|Acc], Fun)
   end.
#Fun<erl_eval.18.105910772>
10> GenFold(10, [],
GenFold).
[1,2,3,4,5,6,7,8,9,10]
11>

Or a for loop:

22> For =
    fun(Max, Max, ExecFun, _) ->
       ok;
   (N, Max, ExecFun, Next) ->
      ExecFun(N),
      Next(N + 1, Max, ExecFun, Next)
   end.
#Fun<erl_eval.4.105156089>
23> For(0,10,fun(I) -> io:format("~B ", [I]) end,
For).

0 1 2 3 4 5 6 7 8 9 ok
24>

Stuff like this is described in Joe Armstrong's Erlang book.

Hope this helps.

On Sat, Oct 4, 2008 at 11:19 PM, deepblue_other <cktgatb@gmail.com> wrote:

>
> hello
> I have this going on
>
> FunVar =
>   fun() ->
>      ...
>      FunVar()
>   end.
>
> so the compiler is complaining that FunVar is unbound at the place where
> its
> being used inside fun(); this makes sense, however Im wondering how to make
> this into a recursive function since there's no name to reference the
> function with.
>
> thanks
> --
> View this message in context:
> http://www.nabble.com/recursive-fun%28%29-tp19820386p19820386.html
> Sent from the Erlang Questions mailing list archive at Nabble.com.
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@erlang.org
> http://www.erlang.org/mailman/listinfo/erlang-questions
>
>

_______________________________________________
erlang-questions mailing list
erlang-questions@erlang.org
http://www.erlang.org/mailman/listinfo/erlang-questions
what you have described makes perfect sense
thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: recursive fun()

Zvi-2
In reply to this post by deepblue_other
Otherwise, than passing the Fun as argument to itself, one can implement recursive functions, using code, like this:

fact(0) -> 1;
fact(N) when N>0 ->
            {M,F,_A} = element(2,process_info(self(),current_function)),
            N * {M,F}(N-1).

But this doesn't work for funs, if there are was something like:

Fact = fun(0) -> 1;
               (N) when N>0 ->
                    Fun = element(2,process_info(self(),current_fun)),
                    N * Fun(N-1).

Zvi

deepblue_other wrote
hello
I have this going on

FunVar =
   fun() ->
      ...
      FunVar()
   end.

so the compiler is complaining that FunVar is unbound at the place where its being used inside fun(); this makes sense, however Im wondering how to make this into a recursive function since there's no name to reference the function with.

thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: recursive fun()

deepblue_other
so definitely no named nested functions?
Zvi wrote
Otherwise, than passing the Fun as argument to itself, one can implement recursive functions, using code, like this:

fact(0) -> 1;
fact(N) when N>0 ->
            {M,F,_A} = element(2,process_info(self(),current_function)),
            N * {M,F}(N-1).

But this doesn't work for funs, if there are was something like:

Fact = fun(0) -> 1;
               (N) when N>0 ->
                    Fun = element(2,process_info(self(),current_fun)),
                    N * Fun(N-1).

Zvi

deepblue_other wrote
hello
I have this going on

FunVar =
   fun() ->
      ...
      FunVar()
   end.

so the compiler is complaining that FunVar is unbound at the place where its being used inside fun(); this makes sense, however Im wondering how to make this into a recursive function since there's no name to reference the function with.

thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Alpár Jüttner-2
You may do a trick like this:

1> Fact = fun(0) -> 1; (N) -> Fun=get(fact), N*Fun(N-1) end.
#Fun<erl_eval.6.13229925>
2> put(fact,Fact).
undefined
3> Fact(5).
120

Regards,
Alpar


On Sun, 2008-10-05 at 09:07 -0700, deepblue_other wrote:

> so definitely no named nested functions?
>
> Zvi wrote:
> >
> > Otherwise, than passing the Fun as argument to itself, one can implement
> > recursive functions, using code, like this:
> >
> > fact(0) -> 1;
> > fact(N) when N>0 ->
> >             {M,F,_A} = element(2,process_info(self(),current_function)),
> >             N * {M,F}(N-1).
> >
> > But this doesn't work for funs, if there are was something like:
> >
> > Fact = fun(0) -> 1;
> >                (N) when N>0 ->
> >                     Fun = element(2,process_info(self(),current_fun)),
> >                     N * Fun(N-1).
> >
> > Zvi
> >
> >
> > deepblue_other wrote:
> >>
> >> hello
> >> I have this going on
> >>
> >> FunVar =
> >>    fun() ->
> >>       ...
> >>       FunVar()
> >>    end.
> >>
> >> so the compiler is complaining that FunVar is unbound at the place where
> >> its being used inside fun(); this makes sense, however Im wondering how
> >> to make this into a recursive function since there's no name to reference
> >> the function with.
> >>
> >> thanks
> >>
> >
> >
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Richard O'Keefe
In reply to this post by deepblue_other
On 5 Oct 2008, at 4:19 pm, deepblue_other wrote:
> I have this going on
>
> FunVar =
>   fun() ->
>      ...
>      FunVar()
>   end.
>
Shouldn't this go in a FAQ somewhere?
Maybe it belongs in the reference manual.

The quick answer is that if you need a recursive
function, why not write a recursive function in the
usual way?

There's something particularly nasty about this
example.  One normally proves (or at any rate
argues with vigourously waving hands for) the
termination of a recursive function by showing
that some non-negative measure of its arguments
strictly decreases on each recursive call, but
this function has no arguments.  I think we need
to see more of it.

The long answer is that you can always do

        Rec = fun (Self, Args) ->
                ....
                Self(Self, Args')
              end,
        Foo = fun (Args) -> Rec(Rec, Args) end,

It's possible, but you are working against the
grain of the language, and there is most likely
a better way to achieve your goals.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

deepblue_other
the example I gave was not suppose to be a practical one, I just wanted to ask how to recursively call a anonymous function...
Richard O'Keefe wrote
On 5 Oct 2008, at 4:19 pm, deepblue_other wrote:
> I have this going on
>
> FunVar =
>   fun() ->
>      ...
>      FunVar()
>   end.
>
Shouldn't this go in a FAQ somewhere?
Maybe it belongs in the reference manual.

The quick answer is that if you need a recursive
function, why not write a recursive function in the
usual way?

There's something particularly nasty about this
example.  One normally proves (or at any rate
argues with vigourously waving hands for) the
termination of a recursive function by showing
that some non-negative measure of its arguments
strictly decreases on each recursive call, but
this function has no arguments.  I think we need
to see more of it.

The long answer is that you can always do

        Rec = fun (Self, Args) ->
                ....
                Self(Self, Args')
              end,
        Foo = fun (Args) -> Rec(Rec, Args) end,

It's possible, but you are working against the
grain of the language, and there is most likely
a better way to achieve your goals.

_______________________________________________
erlang-questions mailing list
erlang-questions@erlang.org
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Steven Grady
In reply to this post by Edwin Fine
BTW, this question has apparently come up before (multiple times).  The key google phrase is "Y combinator":

Steven

On Oct 5, 2008, at 2:13 AM, Edwin Fine wrote:

I'm assuming that you want to do this in the shell, otherwise it would be easier just to write the function in the usual way, e.g.

myfun() ->
    blah, blah,
    myfun().

To create a fun that calls itself, you must realize that you are creating an unnamed function. When you write

fun(X) -> X * 2 end.

this is compiled to a Fun data type, e.g. #Fun<erl_eval.6.13229925>.

Since the function does not have a name, it cannot refer to itself.

When you write FunVar = fun(X) -> X * 2 end, the function is bound to the variable FunVar. Because the binding takes place *after* the fun is created, the fun cannot refer to the variable FunVar within its definition.

So how is it done? You have to pass the variable to the function so that it "knows" what to call:

FunVar =
   fun(MySelf) ->
      ...
      MySelf().

Then when you call it, you call FunVar(FunVar). Looks strange but it works.

Example: Writing a simple generate and fold function using only a fun() variable.

9> GenFold =
   fun(0, Acc, _) ->
      Acc;

   (X, Acc, Fun) ->
      Fun(X - 1, [X|Acc], Fun)

   end.
#Fun<erl_eval.18.105910772>
10> GenFold(10, [], GenFold).                                                     
[1,2,3,4,5,6,7,8,9,10]
11>

Or a for loop:

22> For =
    fun(Max, Max, ExecFun, _) ->
       ok;
   (N, Max, ExecFun, Next) ->
      ExecFun(N),
      Next(N + 1, Max, ExecFun, Next)
   end.       

#Fun<erl_eval.4.105156089>
23> For(0,10,fun(I) -> io:format("~B ", [I]) end, For).                                                                            
0 1 2 3 4 5 6 7 8 9 ok
24>

Stuff like this is described in Joe Armstrong's Erlang book.

Hope this helps.

On Sat, Oct 4, 2008 at 11:19 PM, deepblue_other <[hidden email]> wrote:

hello
I have this going on

FunVar =
  fun() ->
     ...
     FunVar()
  end.

so the compiler is complaining that FunVar is unbound at the place where its
being used inside fun(); this makes sense, however Im wondering how to make
this into a recursive function since there's no name to reference the
function with.

thanks
--
View this message in context: http://www.nabble.com/recursive-fun%28%29-tp19820386p19820386.html
Sent from the Erlang Questions mailing list archive at Nabble.com.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Richard O'Keefe
In reply to this post by deepblue_other

On 6 Oct 2008, at 4:12 am, deepblue_other wrote:
> no shell is not the reason, I need a function that will only be  
> called from
> within another function and I dont want to "pollute" the "module  
> wide" space
> with another function, so Im putting in a nested one...

This seems an extraordinarily weak reason.
Putting local functions into a namespace that is
designed for local functions is hardly polluting it!

Note that if the 'inner' function is needed in two
clauses of the same function, it cannot be inside
both, so it would have to be at top level anyway.

Somehow, I find myself writing nested functions all
the time in Haskell, but never wanting to in Erlang.
Of course, many functional language compilers implement
nested functions by moving them out to top level anyway...

It's a fundamental property of Erlang scope rules that
there is no letrec.


_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Richard O'Keefe
In reply to this post by Ciprian Dorin Craciun

On 6 Oct 2008, at 3:11 am, Ciprian Dorin Craciun wrote:
>    About this subject, I would ask if isn't it better / easier /
> clearer to add a special function name / keyword that would refer to
> the function itself. This would also have a few advantages:

Please write an EEP about this.

>
>    * first it will solve the recursivity problem described above;

The particular example here seems to be one that would have been
better addressed using existing debugging tools.

Recursiveness is not a problem; it's *anonymous* recursive
functions.
>
>    * (maybe) it could also improve efficiency (because you know
> exactly what function you're calling, without any lookup); (this is
> just an assumption, maybe inside the beam file the lookup does not
> exist); (certainly it is more efficient than the proposed solution ---
> sending the function as an argument;)

The best recommendation that has been given is to use a plain
ordinary top level function.  This is _already_ more efficient
than anything based on funs could be (because it is _certain_
not to need to unpack or repack outer variables), and it is
certainly easier to get your head around (*some* variables
in a function refer to outer variables, *some* do not,
despite having the same name as outer variables).

>
>    * it will assist in refactoring --- changing a recursive function
> name will have no impact on it's code;

Yes it will.  Suppose we add something like

        Factorial = fun:Self (N) when N >  1 -> N*Self(N-1)
                            ; (N) when N >= 0 -> 1
                     end,
         [Factorial(X) || X <- [3,1,4,1,5,9,2,6,5,3,5]]

Changing "Self" in one place means it had better be changed
in other places.  For that matter, changing "Factorial" in
one place means it has to be changed in other places.

>
>    * it could clearly mark the fact that the function calls itself.

It's hard to see how.  The mere existence of a mark (such as :Self)
is no guarantee that the body of the function *uses* it.  And if
you are thinking in terms of something like this_fun(), please,
we've suffered enough from C already, and don't need any more like
that.  Consider

        F = fun:Outer (...) ->
            ... G = fun:Inner (...) ->
                    ... Inner(X) ...
                    ... Outer(Y) ...
                    end
            ... Outer ... G ...
            end

With a hook like this, the inner function can not only refer to
itself, but also to the function that contains it.  With a
'this_fun()' approach, it can't.

>    As for disadvantages I really do not see any.

Try looking just a _little_ harder.
>

>    P.S.: I think this solution could be equally applied to all
> languages (mainly Lisp like).

Most functional languages don't *need* it because they
have 'letrec'.  (In Lisp it's called 'labels'.)
Even BCPL had letrec,
        let F(...) = E1
        and G(...) = E2
        and H(...) = E3
was a letrec in which F G and H could refer to each other.


>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://www.erlang.org/mailman/listinfo/erlang-questions
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Hynek Vychodil


On Tue, Oct 7, 2008 at 4:43 AM, Richard O'Keefe <[hidden email]> wrote:

On 6 Oct 2008, at 3:11 am, Ciprian Dorin Craciun wrote:
>    About this subject, I would ask if isn't it better / easier /
> clearer to add a special function name / keyword that would refer to
> the function itself. This would also have a few advantages:

Please write an EEP about this.

>
>    * first it will solve the recursivity problem described above;

The particular example here seems to be one that would have been
better addressed using existing debugging tools.

Recursiveness is not a problem; it's *anonymous* recursive
functions.
>
>    * (maybe) it could also improve efficiency (because you know
> exactly what function you're calling, without any lookup); (this is
> just an assumption, maybe inside the beam file the lookup does not
> exist); (certainly it is more efficient than the proposed solution ---
> sending the function as an argument;)

The best recommendation that has been given is to use a plain
ordinary top level function.  This is _already_ more efficient
than anything based on funs could be (because it is _certain_
not to need to unpack or repack outer variables), and it is
certainly easier to get your head around (*some* variables
in a function refer to outer variables, *some* do not,
despite having the same name as outer variables).

>
>    * it will assist in refactoring --- changing a recursive function
> name will have no impact on it's code;

Yes it will.  Suppose we add something like

       Factorial = fun:Self (N) when N >  1 -> N*Self(N-1)
                           ; (N) when N >= 0 -> 1
                    end,
        [Factorial(X) || X <- [3,1,4,1,5,9,2,6,5,3,5]]

Changing "Self" in one place means it had better be changed
in other places.  For that matter, changing "Factorial" in
one place means it has to be changed in other places.

>
>    * it could clearly mark the fact that the function calls itself.

It's hard to see how.  The mere existence of a mark (such as :Self)
is no guarantee that the body of the function *uses* it.  And if
you are thinking in terms of something like this_fun(), please,
we've suffered enough from C already, and don't need any more like
that.  Consider

       F = fun:Outer (...) ->
           ... G = fun:Inner (...) ->
                   ... Inner(X) ...
                   ... Outer(Y) ...
                   end
           ... Outer ... G ...
           end

Is there any problem write this think this way?

F = begin
      Outher  = fun(OSelf, ...) ->
          ...
          Inner = fun(ISelf, ....) ->
             ... ISelf(ISelf, X) ...
             ... OSelf(OSelf, Y) ...
          end,
      ... OSelf(OSelf, ...) ... Inner(Inner, ...) ...
      fun(Args) -> Outher(Outher, Args) end
  end.

For Example factorial:

Fact = begin F = fun(_, 0) -> 1; (Self, N) -> Self(Self, N-1)*N end, fun(N) -> F(F, N) end end.

Some nontrivial example:

4> UpToGen = begin
              Outher = fun(_OSelf, M, M) -> [];
                                (OSelf, Step, M) ->
                                     Inner = fun(_ISelf, N) when N>M -> [];
                                                    (ISelf, N) -> [N | ISelf(ISelf, N+Step) ]
                                     end,
                               [Inner(Inner, 0) | OSelf(OSelf, Step+1, M)]
              end,
              fun(Max) -> Outher(Outher, 1, Max) end
    end.
#Fun<erl_eval.6.13229925>
5> UpToGen(10).
[[0,1,2,3,4,5,6,7,8,9,10],
 [0,2,4,6,8,10],
 [0,3,6,9],
 [0,4,8],
 [0,5,10],
 [0,6],
 [0,7],
 [0,8],
 [0,9]]

 

With a hook like this, the inner function can not only refer to
itself, but also to the function that contains it.  With a
'this_fun()' approach, it can't.

>    As for disadvantages I really do not see any.

Try looking just a _little_ harder.
>

>    P.S.: I think this solution could be equally applied to all
> languages (mainly Lisp like).

Most functional languages don't *need* it because they
have 'letrec'.  (In Lisp it's called 'labels'.)
Even BCPL had letrec,
       let F(...) = E1
       and G(...) = E2
       and H(...) = E3
was a letrec in which F G and H could refer to each other.


>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://www.erlang.org/mailman/listinfo/erlang-questions
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions



--
--Hynek (Pichi) Vychodil

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

dmercer

On Tuesday, October 07, 2008, Hynek Vychodil wrote:

 

> Is there any problem write this think this way?

. . .

> For Example factorial:

>

> Fact = begin F = fun(_, 0) -> 1; (Self, N) -> Self(Self, N-1)*N end, fun(N) -> F(F, N) end end.

 

My only objection is that it pollutes the shell variable space with the extra function F.  How about:

 

Fact = fun(N) -> F = fun(_, 0) -> 1; (Self, N) -> Self(Self, N-1)*N end, F(F, N) end.

 

Cheers,

 

David


_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Hynek Vychodil
Yes of course, it can be done. There is little difference when closure is made.

this second example can be rewritten (and simplified) in same manner:

UpToGen = fun(Max) ->
              Outer = fun(_OSelf, Max) -> [];
                                (OSelf, Step) ->
                                     Inner = fun(_ISelf, N) when N>Max -> [];
                                                    (ISelf, N) -> [N | ISelf(ISelf, N+Step) ]
                                     end,
                               [Inner(Inner, 0) | OSelf(OSelf, Step+1)]
              end,
              Outer(Outer, 1)
  end.
  
On Tue, Oct 7, 2008 at 4:29 PM, David Mercer <[hidden email]> wrote:

On Tuesday, October 07, 2008, Hynek Vychodil wrote:

 

> Is there any problem write this think this way?

. . .

> For Example factorial:

>

> Fact = begin F = fun(_, 0) -> 1; (Self, N) -> Self(Self, N-1)*N end, fun(N) -> F(F, N) end end.

 

My only objection is that it pollutes the shell variable space with the extra function F.  How about:

 

Fact = fun(N) -> F = fun(_, 0) -> 1; (Self, N) -> Self(Self, N-1)*N end, F(F, N) end.

 

Cheers,

 

David




--
--Hynek (Pichi) Vychodil

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Robert Virding
It seems like there are two separate threads here: one is about defining recursive functions in the shell; and the other is about defining local (recursive) functions in a module.

The first case has been reasonably covered in how you create a fun with a reference to itself so it can call itself recursively.

In the second case I must agree with Richard, there is no *need* to have local (to a function) functions, you can just use normal top-level functions. They *are * more efficient than funs. I have found, however, that I sometimes use funs as local functions when I want to stress that these are local functions. Especially after a bout of LFE hacking which has them.

However, if it was really desired it would be possible to add them, of course you would need both the recursive and non-recursive options. It would be a bit of a contrived expression as it would not, *could not*, return anything sensible. I would not like to add a scoping let type construction as we don't have having scoping anywhere else. Well except in funs and comprehensions where the scoping is a bit off actually. The visibility rules for the defined functions would be a bit hairy, very hairy really, but the best would be to make them the same as for variables, which are very hairy.

I have no intention of adding an EEP!

I don't like the idea of Self.

A rather humourous note is local functions in Core erlang. In Core yo have local functions, but only the mutually recursive type. These were originally added to implement comprehensions so only the recursive kind were needed.

A solution would be do what I used to threaten Bjarne with: do an E2 and get it right. What ever right is.

Robert


_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: re cursive fun()

Hynek Vychodil


On Tue, Oct 7, 2008 at 10:09 PM, Robert Virding <[hidden email]> wrote:
It seems like there are two separate threads here: one is about defining recursive functions in the shell; and the other is about defining local (recursive) functions in a module.

You can use same tricks in module as in shell (if you are pervert a little ;-).


The first case has been reasonably covered in how you create a fun with a reference to itself so it can call itself recursively.

In the second case I must agree with Richard, there is no *need* to have local (to a function) functions, you can just use normal top-level functions. They *are * more efficient than funs. I have found, however, that I sometimes use funs as local functions when I want to stress that these are local functions. Especially after a bout of LFE hacking which has them.

I agree, there is always way how to do refactoring to local recursive functions and make up funs from those. (There should not be difference in performance, it is Erlang fault if is. But there is long way to this goal, for example hot spot compiler and such thinks.)

I strongly agree with following, especially with EPP and Self thinks.


However, if it was really desired it would be possible to add them, of course you would need both the recursive and non-recursive options. It would be a bit of a contrived expression as it would not, *could not*, return anything sensible. I would not like to add a scoping let type construction as we don't have having scoping anywhere else. Well except in funs and comprehensions where the scoping is a bit off actually. The visibility rules for the defined functions would be a bit hairy, very hairy really, but the best would be to make them the same as for variables, which are very hairy.

I have no intention of adding an EEP!

I don't like the idea of Self.

A rather humourous note is local functions in Core erlang. In Core yo have local functions, but only the mutually recursive type. These were originally added to implement comprehensions so only the recursive kind were needed.

A solution would be do what I used to threaten Bjarne with: do an E2 and get it right. What ever right is.

Robert




--
--Hynek (Pichi) Vychodil

_______________________________________________
erlang-questions mailing list
[hidden email]
http://www.erlang.org/mailman/listinfo/erlang-questions
12
Loading...