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