Implementing recursive lambda with MethodHandle

Alex Blewitt alex.blewitt at gmail.com
Mon Feb 22 10:11:21 PST 2010


On Feb 22, 2010, at 17:49, Joshua Bloch wrote:

> 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.

Remi wrote:

> 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);
>     };

If 'this' refers to the current lambda, you don't need to pollute the  
scope. The assignment to 'a' here has no effect; it could be used as a  
direct value, e.g.:

doSomethingWithLambda( #int(int x) { return (x==0)?0:x+this.(x-1) );

I'm not sure why a temporary assignment to 'thisFn' is an better than  
using 'this' in place - on the other hand, if one wanted to, one could  
do both the above and the below.

>    #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
> [not] pollute the surrounding scope with an unused local variable or  
> method
> declaration.


I personally agree that the assignment of the lambda to a variable in  
order to be able to use it recursively feels like clutter.

It's also worth noting that the recursion isn't the only form; it  
could be used as a dependency injection handle as well:

#(Object target,#() fn) { target.visit(this,fn); };

This could be used to e.g. implement a monad or a strategy for doing  
depth/breadth-first processing of a set of nodes:

interface INode {
   INode[] children();
}

headFirst = #(Node n, #(Node) process ) { process(n);  
for(child:n.children()) this.(child,process) }

headLast = #(Node n, #(Node) process ) { for(child:n.children()) this. 
(child,process); process(n) }

Finally, the code-search tools that Neal provided show what can be  
done with existing Java objects. However, in these cases, it's far  
more likely that they'd be captured as static methods on a named  
class, rather than being able to pass in (potentially recursive)  
functions as arguments to other processes. As well as considering how  
it might be used with existing code, it probably makes sense to look  
into how it might be used in the future as well.

Alex



More information about the lambda-dev mailing list