Why is that in JDK8: value used in lambda expression shuld beeffectively final?

Discussion in 'Java' started by jeti789@web.de, Jan 2, 2013.

  1. Guest

    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"

    However, this here compiles:

    int sumArray[] = new int[] { 0 };
    ints.forEach(i -> {sumArray[0] += i;});

    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)?

    Thanks, Oliver
     
    , Jan 2, 2013
    #1
    1. Advertising

  2. On 02/01/13 12:51, 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
     
    Steven Simpson, Jan 2, 2013
    #2
    1. Advertising

  3. Stefan Ram Guest

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

    writes:
    >int sum = 0;
    >ints.forEach(i -> {sum += i;});
    >The compiler error is "value used in lambda expression shuld be effectively final"


    I have no knowledge about or experience with the Java 1.8
    lambdas, but my idea (made up by me right now) is:

    You are passing »i -> {sum += i;}« to »ints«, which (»ints«)
    is an object on the heap. This object »ints« may still hold
    a reference to »i -> {sum += i;}«, when the method that
    contained »int sum = 0;« already has expired. »sum« seems
    to be a stack variable. So »ints« then might still hold
    »i -> {sum += i;}«, but where is the variable »sum« then?

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


    This array lives on the heap and might outlive its function.

    The compiler error message sounds strange, because a »value«
    cannot be final, only a variable can be final. A value is
    something like »4« or »8«. Values never change, even without
    »final«.
     
    Stefan Ram, Jan 2, 2013
    #3
  4. Guest

    Hi Steven,

    thanks for your elaborte answer.

    >For some definition of closures (one including mutable local capture),
    >JDK8 lambdas are not closures (hence, they are not called closures).


    I see, I didn't know. I wished Sun/Oracle had made this more clear ...

    >AIUI, the main goal of lambdas was to reduce verbosity/overhead of
    >anonymous classes used with algorithms that better exploit >parallelism.


    Well, JDK8 lambdas how they must be called then do at least reduce the amount of boilerplate code ...

    Anyhow, this news does really put a smile on my face. Guess it's really time to look for another JVM-based language like Groovy or Scala ;-).

    Regards, Oliver
     
    , Jan 2, 2013
    #4
  5. Guest

    > Anyhow, this news does really put a smile on my face.

    .... does NOT put a smile on my face, of course. Guess this will give Groovy2.0 more momentum.
     
    , Jan 2, 2013
    #5
  6. On 02/01/13 15:08, wrote:
    > Anyhow, this news does [not] really put a smile on my face. Guess it's really time to look for another JVM-based language like Groovy or Scala ;-).


    For your particular case:

    List<Integer> ints = ...;
    int sum = 0;
    ints.forEach(i -> { sum += i; });

    ....the recommended way is to use something like:

    int sum = ints.reduce(0, (x, y) -> x + y);

    ....which is more parallel-friendly. Of course, if you don't care about
    the parallelism, it's simply:

    int sum = 0;
    for (int i : ints)
    sum += i;

    I'm sure you're just using this example to explore what's available, and
    I think it would be a mistake to discard Java based on it. So is there
    a more sophisticated case you were hoping would improve with lambdas?


    --
    ss at comp dot lancs dot ac dot uk
     
    Steven Simpson, Jan 2, 2013
    #6
  7. Saxo Guest

    Hm... Maybe it was done that way for backwards compatibility. JDK8 lambdas are like less verbose annonymous classes and nothing more ...
     
    Saxo, Jan 2, 2013
    #7
  8. Saxo Guest

    > I'm sure you're just using this example to explore what's available,

    Yes, exactly. This little code snippet to calcualate a sum is a very simplebut canonical case of a closure that has a free variable:

    "When a function refers to a variable defined outside it, it's called a free variable. A function that refers to a free lexical variable is called a closure.". Paul Graham, ANSI Common Lisp, Prentice Hall, 1996, p.107.

    So free variables aren't possible with JDK8 lambdas. For people used to closures, this is surely surprising. Well, this does not render JDK8 lambdas useless. On the contrary, an imense amount of boilerplate code that is necessary without them can be removed with them. Once the JDK8 gets released this will be an eye-opener to about 95% of all Java developers (the ratio of Java developers not understanding closures ...).

    > I think it would be a mistake to discard Java based on it.


    If I could I would have done that a long time ago. But not going with a M$ language was a deliberate decision and on the JVM nothing will rival Java (only be a complement like Groovy, or scratch on it like Scala or Kotlin).

    > int sum = ints.reduce(0, (x, y) -> x + y);


    Nice, but it does not compile with me. I use IDEA 12 and the lambda-8-b69-windows-i586-17_dec_2012 JDK. Seems like reduce does not exist in Iterator or Collection!?

    -- Oliver
     
    Saxo, Jan 2, 2013
    #8
  9. Lew Guest

    Saxo wrote:
    > So free variables aren't possible with JDK8 lambdas. For people used to closures, this is surely
    > surprising. Well, this does not render JDK8 lambdas useless. On the contrary, an imense amount of
    > boilerplate code that is necessary without them can be removed with them. Once the JDK8 gets
    > released this will be an eye-opener to
    > about 95% of all Java developers (the ratio of Java developers not understanding closures ...).


    The ratio of Java developers who do not understand closures is probably pretty close to the
    ratio of Java developers who do not understand Java.

    Aside from that your comment is unsupportable. Or do you have evidence?

    ....

    I thought not.

    --
    Lew
     
    Lew, Jan 2, 2013
    #9
  10. On 02/01/13 19:31, Saxo wrote:
    >> int sum = ints.reduce(0, (x, y) -> x + y);

    > Nice, but it does not compile with me. I use IDEA 12 and the lambda-8-b69-windows-i586-17_dec_2012 JDK. Seems like reduce does not exist in Iterator or Collection!?


    I figured, if forEach is on Collection, reduce likely would be too. I
    did try to have a look for it in source, but wasn't sure if I had the
    right branch. I also didn't find the javadoc on-line. Based on the
    source, try:

    ints.stream().reduce(0, (x, y) -> x + y)

    --
    ss at comp dot lancs dot ac dot uk
     
    Steven Simpson, Jan 2, 2013
    #10
  11. On 01/02/2013 04:52 PM, Lew wrote:
    > Saxo wrote:
    >> So free variables aren't possible with JDK8 lambdas. For people used to closures, this is surely
    >> surprising. Well, this does not render JDK8 lambdas useless. On the contrary, an imense amount of
    >> boilerplate code that is necessary without them can be removed with them. Once the JDK8 gets
    >> released this will be an eye-opener to
    >> about 95% of all Java developers (the ratio of Java developers not understanding closures ...).

    >
    > The ratio of Java developers who do not understand closures is probably pretty close to the
    > ratio of Java developers who do not understand Java.

    [ SNIP ]

    I don't get that statement at all. A significant percentage of Java
    programmers don't use any other languages in a big way, including those
    that do have closures. And since Java itself doesn't have them (*), I
    just don't see why a programmer who understand Java really well can't
    also *not* know about closures.

    AHS

    * I'll wager that a lot of Java programmers - the ones with their hands
    full still doing their production work in JDK 1.6 and 1.7, say, don't
    have time to play with experimental features.
     
    Arved Sandstrom, Jan 3, 2013
    #11
  12. Lew Guest

    Steven Simpson wrote:
    > Saxo wrote:
    >>> int sum = ints.reduce(0, (x, y) -> x + y);

    >
    >> Nice, but it does not compile with me. I use IDEA 12 and the
    >> lambda-8-b69-windows-i586-17_dec_2012 JDK. Seems like reduce does not exist in
    >> Iterator or Collection!?

    >
    > I figured, if forEach is on Collection, reduce likely would be too. I


    'forEach' is not on Collection. It's on Collection's parent type.

    > did try to have a look for it in source, but wasn't sure if I had the
    > right branch. I also didn't find the javadoc on-line. Based on the
    > source, try:


    Javadoc for Java 8 is on line:
    http://download.java.net/jdk8/docs/api/index.html

    Not hard to find, but it doesn't contain the information you wanted.


    > ints.stream().reduce(0, (x, y) -> x + y)


    http://datumedge.blogspot.com/2012/06/java-8-lambdas.html
    gives a brief overview.

    --
    Lew
     
    Lew, Jan 3, 2013
    #12
  13. Lew Guest

    Arved Sandstrom wrote:
    > Lew wrote:
    >> Saxo wrote:
    >>> So free variables aren't possible with JDK8 lambdas. For people used to closures, this is surely
    >>> surprising. Well, this does not render JDK8 lambdas useless. On the contrary, an imense amount of
    >>> boilerplate code that is necessary without them can be removed with them. Once the JDK8 gets
    >>> released this will be an eye-opener to
    >>> about 95% of all Java developers (the ratio of Java developers not understanding closures ...).

    >
    >> The ratio of Java developers who do not understand closures is probably pretty close to the
    >> ratio of Java developers who do not understand Java.

    >
    > [ SNIP ]


    >
    > I don't get that statement at all. A significant percentage of Java


    You mean you don't agree with it. Apparently you do get it.

    > programmers don't use any other languages in a big way, including those


    How significant? What percentage? Aren't these the same ones I said don't understand
    Java either?

    How do you know they aren't?

    > that do have closures. And since Java itself doesn't have them (*), I
    > just don't see why a programmer who understand Java really well can't
    > also *not* know about closures.


    Can, certainly. But the statement was statistical, not possibilistic.

    Where does "95%" come from? Where does "significant percentage" come from?

    My point is that there are no data for these assertions. Likewise, I have no data, but
    unless you do you have nothing with which to refute my assertion.

    Plus there's the aforementioned matter of agreeing on definitions.
    >
    > * I'll wager that a lot of Java programmers - the ones with their hands


    How much is "a lot"? Does it approach 95%?

    > full still doing their production work in JDK 1.6 and 1.7, say, don't
    > have time to play with experimental features.


    I have my hands full doing production work in JDK 1.6 and 1.7. Yet I do play with
    experimental features, and even read about them beyond that.

    Doesn't everyone? Don't you?

    Anyone who doesn't, doesn't understand Java.

    --
    Lew
     
    Lew, Jan 3, 2013
    #13
  14. Saxo Guest

    > Aside from that your comment is unsupportable. Or do you have evidence?

    What I mean is that almost every Java developer I met during the last 10 years didn't know what I meant when I said it's a pitty that Java does not have closures. I can't remember anyone who asked anything else in return than"and what are closures?". Having worked some of these years as a consultant I did see places. Almost nobody are those famous 95%. Funny that people get that annoyed. For the older guys that have worked with some other language than Java before the difference f.ex. between Smalltalk developers and Java developers is striking in terms of intellectual reflection, general interest, etc. Probably a good place to be nowadays is the people from the Scala camp.

    -- Oliver
     
    Saxo, Jan 3, 2013
    #14
  15. Stefan Ram Guest

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

    Saxo <> writes:
    >What I mean is that almost every Java developer I met during
    >the last 10 years didn't know what I meant when I said it's a
    >pitty that Java does not have closures.


    Clojure already exists, and everyone who wants to program
    the LISP style is free to choose LISP or Clojure.

    Using LISP style in Java is not necessarily good Java style!

    For a Java programmer, good knowledge of Java is already
    sufficient. He does not need to know terminology of other
    languages!

    »Almost every English speaker I met didn't know what I
    meant, when I said it's a pitty that English does not
    have an ablative.«

    What in LISP is expressed by creating a new closure, in Java
    can be expressed by creating a new instance of a class.

    ( SETQ ADDER( LAMBDA( N )( LAMBDA( X )( + X N ))))

    becomes

    public class Adder
    { private final int n;
    public Adder( final int n ){ this.n = n; }
    public int add( final int x ){ return x + this.n; }}
     
    Stefan Ram, Jan 3, 2013
    #15
  16. Saxo Guest

    Am Mittwoch, 2. Januar 2013 22:46:00 UTC+1 schrieb Steven Simpson:
    > ints.stream().reduce(0, (x, y) -> x + y)


    This did it ;-). Thanks, good to know.
     
    Saxo, Jan 3, 2013
    #16
  17. Saxo Guest

    Saxo, Jan 3, 2013
    #17
  18. Lew Guest

    Patricia Shanahan wrote:
    > Stefan Ram wrote:
    >> Saxo writes:
    >>> What I mean is that almost every Java developer I met during
    >>> the last 10 years didn't know what I meant when I said it's a
    >>> pitty that Java does not have closures.


    On this newsgroup there've been spirited discussions on this topic for years.

    In my experience over the last ten years lots and lots of Java programmers, most
    of the ones with whom I've spoken, knew what closures were if they were reasonably
    competent Java programmers.

    But I don't claim statistical significance for my non-random idiosyncratic sample.
    You should not either.

    The fact that my experience is the opposite of yours should be evidence for that.

    For the record, I argued vehemently against the addition of closures to Java.

    I tend to agree with Stefan here.

    >> Clojure already exists, and everyone who wants to program
    >> the LISP style is free to choose LISP or Clojure.

    >
    >> Using LISP style in Java is not necessarily good Java style!

    >
    >> For a Java programmer, good knowledge of Java is already
    >> sufficient. He does not need to know terminology of other
    >> languages!


    Wrong.

    > ...
    > I would distinguish different levels of programming skill. If one is
    > going to be making decisions such as choosing the language for a
    > project, it is important to understand the capabilities and supported
    > programming styles for a wide variety of languages.
    >
    > Similarly, anyone working in programming language design and
    > standardization should understand the possibilities that have been
    > demonstrated by other languages.
    >
    > For someone who is just programming in one language, it is enough to
    > know that language well.


    Wrong.

    It is not enough.

    Because people who learn only Java tend not to even program Java well.

    That I've seen. I don't know if that has statistical significance.

    But based on my experience and much reading and the advice of mentors,
    I will state unequivocally that knowledge of only Java makes a terrible computer
    programmer.

    Simply terrible.

    Any real programmer would have learned at *least* one other language, usually
    prior to learning Java, and would understand things like computable pointers.

    Anyone who calls themselves a programmer and is unwilling to learn a second programming
    language is an ass and needs to switch to serving fries to fast-food customers.

    --
    Lew
     
    Lew, Jan 3, 2013
    #18
  19. On 01/02/2013 09:40 PM, Lew wrote:
    > Arved Sandstrom wrote:
    >> Lew wrote:
    >>> Saxo wrote:
    >>>> So free variables aren't possible with JDK8 lambdas. For people used to closures, this is surely
    >>>> surprising. Well, this does not render JDK8 lambdas useless. On the contrary, an imense amount of
    >>>> boilerplate code that is necessary without them can be removed with them. Once the JDK8 gets
    >>>> released this will be an eye-opener to
    >>>> about 95% of all Java developers (the ratio of Java developers not understanding closures ...).

    >>
    >>> The ratio of Java developers who do not understand closures is probably pretty close to the
    >>> ratio of Java developers who do not understand Java.

    >>
    >> [ SNIP ]

    >
    >>
    >> I don't get that statement at all. A significant percentage of Java

    >
    > You mean you don't agree with it. Apparently you do get it.
    >
    >> programmers don't use any other languages in a big way, including those

    >
    > How significant? What percentage? Aren't these the same ones I said don't understand
    > Java either?
    >
    > How do you know they aren't?
    >
    >> that do have closures. And since Java itself doesn't have them (*), I
    >> just don't see why a programmer who understand Java really well can't
    >> also *not* know about closures.

    >
    > Can, certainly. But the statement was statistical, not possibilistic.
    >
    > Where does "95%" come from? Where does "significant percentage" come from?
    >
    > My point is that there are no data for these assertions. Likewise, I have no data, but
    > unless you do you have nothing with which to refute my assertion.
    >
    > Plus there's the aforementioned matter of agreeing on definitions.
    >>
    >> * I'll wager that a lot of Java programmers - the ones with their hands

    >
    > How much is "a lot"? Does it approach 95%?
    >
    >> full still doing their production work in JDK 1.6 and 1.7, say, don't
    >> have time to play with experimental features.

    >
    > I have my hands full doing production work in JDK 1.6 and 1.7. Yet I do play with
    > experimental features, and even read about them beyond that.
    >
    > Doesn't everyone? Don't you?
    >
    > Anyone who doesn't, doesn't understand Java.
    >

    Well, we can agree on one thing - absent hard numbers - which I'm not
    sure exist - none of us have more than anecdotes.

    I'll say this - I've worked closely with hundreds of programmers over my
    career. Not just Java, obviously, everything under the sun. I've
    interviewed many dozens of developers. I've seen a humungous amount of
    code written by other people. I read professionally voraciously.

    These same statements are probably applicable to you and a bunch of
    other people in this NG too.

    _My_ takeaway from all that is that most professional working
    programmers are M-F 9-5. They don't actually spend time at home coding
    or doing professional development (with the exception of training or
    reading books that help them with the immediate technologies that they
    need *now*). They don't have more than an above-average grasp of
    anything, they aren't even that interested in the field.

    So no, I don't believe for a second that more than 5 or 10 percent of
    coders play with experimental features or learn languages that they may
    never use on the job...let alone teach themselves CS underpinnings of
    what they do.

    But this is all anecdotal. You may have all your career worked with
    young hard-chargers who absolutely live to code. You'd see things
    differently.

    As for *me*, the new _language_ features in Java 7 don't exactly take
    more than a few hours to read about and trial out in a simple test
    program. I spent rather more time investigating the new APIs in 7, so I
    know what's there and can plan to use it if appropriate.

    As for what is coming out in 8, I could not care less. I really could
    not. I'm not using 8 yet, and none of my Java work (which these days is
    a small bit of what I do) will even be on the Java 8 platform for years.
    So why waste my time? I'd rather hone up on Scala, Clojure, latest C#,
    and F#...to name a few.

    AHS
     
    Arved Sandstrom, Jan 4, 2013
    #19
  20. On 03/01/13 14:45, Saxo wrote:
    > http://objectscape.blogspot.de/2013/01/jdk8-lambdas-as-restrictive-as.html


    I'm still interested in seeing an example that you would normally write
    with free variables, demonstrating that lambdas are inadequate for the
    things you'd like to do. The example you provided of summing integers
    has two alternatives, so it only serves to show that free variables are
    not possible, not that free variables are necessary.

    Can you contrive something more sophisticated, as an exercise?

    --
    ss at comp dot lancs dot ac dot uk
     
    Steven Simpson, Jan 4, 2013
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roman Suzi
    Replies:
    13
    Views:
    608
    Bengt Richter
    Jan 7, 2005
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,004
    Smokey Grindel
    Dec 2, 2006
  3. Replies:
    1
    Views:
    385
    Peter Flynn
    Feb 18, 2007
  4. Steve Dogers

    lambda vs non-lambda proc

    Steve Dogers, Mar 30, 2009, in forum: Ruby
    Replies:
    1
    Views:
    178
    Sean O'Halpin
    Mar 30, 2009
  5. Haochen Xie
    Replies:
    4
    Views:
    245
    Haochen Xie
    Mar 17, 2013
Loading...

Share This Page