Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #20870

Re: Why is that in JDK8: value used in lambda expression shuld be effectively final?

From Steven Simpson <ss@domain.invalid>
Newsgroups comp.lang.java.programmer
Subject Re: Why is that in JDK8: value used in lambda expression shuld be effectively final?
Date 2013-01-02 14:15 +0000
Organization A noiseless patient Spider
Message-ID <m0sdr9-0tg.ln1@s.simpson148.btinternet.com> (permalink)
References <c885bedb-977c-49b4-a10a-b9cdd3df1dd9@googlegroups.com>

Show all headers | View raw


On 02/01/13 12:51, jeti789@web.de wrote:
> I'm currently plaing with JDK8 and using lambda-8-b69-windows-i586-17_dec_2012. I wonder why this does not compile:
>
> List<Integer> ints = new ArrayList<>();
> ints.add(1);
> ints.add(2);
> ints.add(3);
>
> int sum = 0;
> ints.forEach(i -> {sum += i;});
>
> The compiler error is "value used in lambda expression shuld be effectively final"

It's the same reason why inner classes can't mutate local variables in 
the enclosing scope.  The method that accepts the lambda or inner class 
instance cannot formally make any guarantee not to invoke the supplied 
code in a non-serial way.

forEach could informally specify that it will execute its argument only 
on its calling thread, and not after it returns, but the compiler could 
not detect that guarantee and allow 'sum' to be modified.

(I'm using 'formal' to indicate something that can be detected by the 
compiler.)


> However, this here compiles:
>
> int sumArray[] = new int[] { 0 };
> ints.forEach(i -> {sumArray[0] += i;});

Ultimately, the compiler can't stop anyone from shooting themselves in 
the foot.  You can still access an instance variable unsafely via a 
lambda, for example.

Stopping the protection at the level of local variables could seem a bit 
arbitrary, but it is still useful, since you expect the use of local 
variables to be intrinsically thread-safe (and they remain so under this 
level of protection), and trying to provide more comprehensive 
protection would be increasingly difficult.


> I'm a bit confused now. Does this mean that JDK8 closures are no true closures or is this a bug in my IDE (IDEA 12)?

For some definition of closures (one including mutable local capture), 
JDK8 lambdas are not closures (hence, they are not called closures).  
AIUI, the main goal of lambdas was to reduce verbosity/overhead of 
anonymous classes used with algorithms that better exploit parallelism.  
These do not typically require or work well with shared variables, and 
supporting mutable locals efficiently would require considerable extra 
effort for something substantially beyond the main goal.

I'm sure you can get a more authoritative explanation by checking the 
lambda mailing-list archives:

<http://mail.openjdk.java.net/pipermail/lambda-dev/>

I suggest looking for terms such as 'mutable local capture', and 
'effectively final'.


-- 
ss at comp dot lancs dot ac dot uk

Back to comp.lang.java.programmer | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Why is that in JDK8: value used in lambda expression shuld be effectively final? jeti789@web.de - 2013-01-02 04:51 -0800
  Re: Why is that in JDK8: value used in lambda expression shuld be effectively final? Steven Simpson <ss@domain.invalid> - 2013-01-02 14:15 +0000
    Re: Why is that in JDK8: value used in lambda expression shuld be   effectively final? Robert Klemme <shortcutter@googlemail.com> - 2013-01-07 23:08 +0100
  Re: Why is that in JDK8: value used in lambda expression shuld be effectively final? Saxo <jeti789@web.de> - 2013-01-02 09:46 -0800
  Re: Why is that in JDK8: value used in lambda expression shuld be effectively final? Saxo <jeti789@web.de> - 2013-01-05 07:01 -0800

csiph-web