Recursive lambdas

Alex Blewitt alex.blewitt at gmail.com
Mon Feb 22 01:54:47 PST 2010


It has been suggested that recursive lambdas can be defined without any assumption of 'this' as follows:

#int(int) fac = #(int x)(x <= 1 ? 1 : x * fac.(x-1));

There may be confusion in the case of 'fac' being overwritten in the remainder of the body:

#int(int) fac = #(int x)(x <= 1 ? 1 : x * fac.(x-1));
#int(int) other = #(int x)( fac.(x) ); // Not used in this example, see below
#int(int) old = fac;
fac = #(int x)(0);
old.()//

What does (should) old.() result in? In the case of a lambda-this, the answer would be clear; it would return the factorial as before. However, ther are two ways of interpreting the execution of old.() here:

* The embedded 'fac' retains its old reference from when it was defined
* The embedded 'fac' is interpreted in the current scope, and so returns 0

This is a contrived example, but now let's hoist these to member variables of a class:

class Foo {
  #int(int) fac = #(int x)(x <= 1 ? 1 : x * fac.(x-1));
  #int(int) other = #(int x)( fac.(x) );
  Foo() {
    #int(int) old = fac;
    fac = #(int x)(0);
    old.(); // What does this return?
  }
}

One might argue that it's the same result. But in this case, 'fac' can refer to one of two things:

* The lambda-this
* The reference to this.fac as a field in the class

Under the first interpretation, the effect is the same as before - it prints the factorial correctly. However, under the second interpretation, it will print 0.

The 'other' here demonstrates the problem. We have two lambdas, both with recursive calls to fac.(x) in them; however, the 'other' will always refer to the field 'fac' in the enclosing scope by reference rather than by value (will it?) Mark's example yesterday suggests that it might:

class Foo {             
	Runnable r = new Runnable() {
		public void run() {
			r.run(); // refers to Foo.this.r, and so will see changes to r
		}
	};
}

One can special-case this (or treat it as an oddity that no-one will worry about) but I thought I'd bring it up in the result of Mark's post.

Alex


More information about the lambda-dev mailing list