Accessing non-final local variables from a lambda expression
Alex Buckley
Alex.Buckley at Sun.COM
Fri Feb 26 11:37:32 PST 2010
You appear to have missed shared variables in the project strawman. I
explicitly note in the draft spec that it does not yet incorporate
shared variables, so this discussion is moot.
Alex
Neal Gafter wrote:
> I experimented a bit with a lambda-ized version of a modified Google
> Collections. Specifically, I was playing with the method
>
> <T> Iterable<T> filter(
> Iterable<T> input,
> Predicate<T> predicate)
> { ... }
>
> Using this method and an anonymous inner class, one can write a method that
> returns every other value in its input sequence:
>
> // before
> <T> Iterable<T> everyOther(Iterable<T> input) {
> return filter(input, new Predicate<T>{
> boolean flag = true;
> public boolean apply(T input) {
> return (flag ^= true);
> }
> });
> }
>
> The equivalent function-ized version of the API would be (expressed in my
> preferred syntax):
>
> <T> Iterable<T> filter(
> Iterable<? extends T> input,
> (T)->boolean predicate)
> { ... }
>
> But now I have a problem implementing everyOther. The only way to create a
> value of function type is to write a lambda expression, but where to put the
> flag? In BGGA, CfJ, and other languages with lambdas, one could write it
> simply like this
>
> <T> Iterable<T> everyOther(Iterable<T> input) {
> boolean flag = true;
> return filter(input, (T t)->(flag ^= true));
> }
>
> But project lambda forbids access to mutable local variables from the
> enclosing scope. I came up with the following workable approach
>
> // after
> <T> Iterable<T> everyOther(Iterable<T> input) {
> class Alternator {
> boolean flag = true;
> boolean invoke() {
> return (flag ^= true);
> }
> }
> final Alternator alternate = new Alternator();
> return filter(input, #(T t)(alternate.invoke());
> }
>
> Comparing the before and the after, it appears that project lambda didn't do
> us any favors here. The "after" code is far worse. In our attempt to make
> the concurrent use cases "easier not to get wrong", we've placed a pile of
> obstacles before every programmer who uses function types in sequential
> code.
>
> It would be better to give a warning (not error) when a lambda accesses a
> mutable local variable from an enclosing scope, and provide one or more easy
> ways for programmers to suppress the warning. See CfJ <
> http://www.javac.info/closures-v06a.html> for my preferred approach.
>
More information about the lambda-dev
mailing list