Implementing recursive lambda with MethodHandle

Joshua Bloch jjb at google.com
Mon Feb 22 09:49:07 PST 2010


Rémi,

Sorry to sound so negative today, but I don't like any of these.  They all
force you to define a variable or method in the scope enclosing the lambda,
cluttering up this scope.  One of the things that I love about for-lops (as
opposed, for example, to while loops) is that they allow you to declare
index variables and bounds within the scope of the loop.  I don't consider
the recursive lambda case to be all that important (definitely a corner
case), but I much prefer to use a local variable declared within the scope
of the lambda:

    #i(int i) {
        #int(int) thisFn = this;
        return i == 0 ? 1 : i * thisFn.(i - 1);
     };

This does not require any fancy (i.e., recursive) type inference and does
hot pollute the surrounding scope with an unused local variable or method
declaration.

          Josh

On Mon, Feb 22, 2010 at 3:52 AM, Rémi Forax <forax at univ-mlv.fr> wrote:

> To summarize, there is three ways to have recursive lambda:
> 1) No recursive lambda:
>     If you need a recursive function, create it has a private method
> and call it in the lambda
>     (this is my favorite choice :)
>
>     static int sum(int x) {
>       return (x==0)?0:x + sum(x-1);
>     }
>     #int(int) a= #int(int x) {
>         return sum(x);
>      };
>
> 2) this refers to the current lambda
>     In that case you can use this.() to do the recursive call.
>     #int(int) a= #int(int x) {
>         return (x==0)?0:x + this.(x-1);
>      };
>
> 3) allow a reference to a lambda to be used inside a lambda
>      #int(int) a= #int(int x) {
>         return (x==0)?0:x + a.(x-1);
>      };
>
> How to implement solution 2 or 3 with method handles ?
> First, it's not simple because a method handle is an
> object that contains a function pointer to a method,
> so there is no dedicated class.
>
> You have to first create the method handle and then inject itself to be
> available
> in the body of the function referenced.
> Because injecting the method handle creates a new method handle
> so you have a eggs and chicken problem that you can solve with an array.
>
> static int $lambda$1(MethodHandle[] mh, int x) {
>    return (x==0)?0:x + mh[0].invokeGenerics(x-1);
> }
>
> MethodHandle mh = #$lambda$1(MethodHandle, int)
> MethodHandle[] array = {null};
> mh = mh.bind(array);
> array[0] = mh;
>
> Rather ugly, isn't it ?
> cheers,
> Rémi
>
>
>


More information about the lambda-dev mailing list