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