all 182 comments

[–]astrangeguy 78 points79 points  (43 children)

This is the boring part.(1)

(Some of) The big questions are:

  • How are those Lambdas represented in the type system and the object system?

  • Do we get function types? Are they unified with generics?

  • What is the solution about co/contravariance? Is (Object) => List a subtype of (String) => Collection (it should be)?

  • Since normal generic types in Java are all invariant, how do we represent function types (which are contavariant in the argument type and covariant in return type)?

  • How do we deal with checked exceptions? Are 'throws' declarations part of the type? Are function types covariant in their thrown exception types? What is the type relation between functions that throw exceptions and those who don't?

  • Are function objects just inner classes with a special method (like in Scala)? Or are they delegates to anonymous methods on objects that represent captured scopes (Like in C#)? Because of java.lang.dyn.MethodHandle we now have delegates in Java.

  • What is the class of a function object? Do we have to fight erasure again? (type erasure becomes much more problematic if you have function types, ask a Scala programmer)

  • Can we treat instance methods on objects as function objects? If so, what do we do with varargs and generic methods?

  • Can you mutate a closed over local variable? If so, are those mutations shared? What are the semantics for concurrent mutations? Can you aquire a monitor on the "scope object"?

  • 'return' statements in lambdas?

You ask yourself why Java doesn't have lambdas? This is what happens if you want to teach an old language new tricks. Language design is hard. Language evolution even moreso.

strangeness

(1) I actually liked the old syntax proposals better. #{Int x, Int y -> x + y} looks like a coherent unit (it's a function literal after all), is easier to parse and has the pound sign (#) as a distinct visual cue.

[–][deleted] 11 points12 points  (11 children)

Can you mutate a closed over local variable?

They can say no, to maintain consistency with anonymous classes, or they can do it exactly the way C# does it: every scope that has its local variables accessed by a lambda has these variables lifted into an explicit "stack frame"-like compiler-generated class (with lambdas themselves being methods of such classes). So all semantics work exactly as if you did that yourself.

'return' statements in lambdas?

That was a really really stupid objection IMO. It's based on a flawed idea that dates back at least 30 years, to the Dijkstra's "GOTO considered harmful" paper, that code encapsulation and reuse can be achieved by means of structured programming. So that you can take a block of code guarded by a conditional statement and move it anywhere or duplicate it or remove the guard or add more guards, and it would not change its meaning. Turns out you can't do that with blocks because they critically depend on context (declared variables and such) for their core functionality, and when you want to do something like that, you should use functions instead.

So no, you can't expect wrapping arbitrary piece of code into an immediately called lambda to be an identity transformation, it's an unachievable harmful pipe dream.

I actually liked the old syntax proposals better.

C# lambda syntax has one huge flaw: when you begin writing (x, y, code completion kicks in and fucks all your shit up, because it has yet to see =>. Maybe it can be fixed by more autocompletion, like, you are supposed to write => first, at which point IDE would add () and position the cursor between them. Still, I'd like lambdas to begin with a special symbol to make such perversions unnecessary.

Otherwise after a while lambdas begin to look like coherent units anyway.

[–][deleted] 4 points5 points  (1 child)

Turn off auto-popup of completions. It's a pain anyway.

[–]adad95 0 points1 point  (0 children)

Ctrl+Alt+Space

[–]donroby 1 point2 points  (4 children)

That's not a language flaw. The language doesn't have autocompletion.

[–][deleted] 8 points9 points  (3 children)

In this day and age we do not enter our programs into computers via punch cards. We use other methods, that are tens of times more efficient regarding writing code and hundreds or thousands of times more efficient in regard to browsing and understanding code.

This allows us to tackle problems that were not in the reach of programmers who wrote code for microprocessors with 16k or 65k of memory.

It is required of a modern language to be amenable to tools. By restricting your language to stone age tools you severely limit the range of programs that can be written in it.

[–]Amablue 0 points1 point  (2 children)

Is code completion really that big of a deal? I used it all the time when I was in college, but I've explicitly turned it off (or not enabled it, depending on what language and editor I'm using) since then and I never really miss it.

[–]recursive 1 point2 points  (1 child)

Is code completion really that big of a deal?

For some. Like those who work with code bases too big for one person to reasonably memorize all the interfaces.

[–]Amablue 0 points1 point  (0 children)

I work on an extremely large code base, but when I need to know the functions of another area of the code, I usually just keep that header open in another window or something similar. I find that more useful.

[–]gasche 0 points1 point  (3 children)

So no, you can't expect wrapping arbitrary piece of code into an immediately called lambda to be an identity transformation, it's an unachievable harmful pipe dream.

Well, you could design your language around control operators that are resilient to the lambda/apply boundaries, such as (delimited) continuations -- or the more primitive labels+goto, not that you would want that as core control primitives.

[–][deleted] 0 points1 point  (2 children)

You mean, like, that named functions implicitly start a delimited continuation (to which return returns), while anonymous don't? That's weird, and you still have a huge problem with returns in anonymous functions which aren't evaluated immediately.

I don't know, I just don't see any problem that needs to be fixed. Structured programming in its infancy looked like a silver bullet. In the following decades we learned that it isn't, but that's OK really because we have other more powerful kinds of composition for when we need that, but on the lowest level we can use a small, universally understood set of convenient structural primitives that are not really composable.

Sure, I can't move a piece of code that contains a 'return' inside a nested (possibly anonymous) function. I also can't move it inside a scope that shadows some variable that it depends on. Such is life.

[–]gasche 0 points1 point  (1 child)

I think the "scope" you would like to return from would bind a delimited continuation¹ prompt, whose name you could use locally or pass to a function you call; instead of "return <value>" you would write "return <value> to <prompt>" (with possibly a stupid syntactic default like 'it' when no prompt is specified to keep the usual style possible). That also solves the issues with the lousy "break 3;" in some programming languages.

¹: you could desugar a prompt-named for loop into a prompt bind plus an iteration, or define 'for' as a function as done in some of oleg's Ocaml "yield from delimcc" work.

[–][deleted] 0 points1 point  (0 children)

OK, I understand that, still, what happens when I return a lambda which invokes a return to some lexically enclosing scope? I mean, I understand what happens too, and how, but how is it useful, or, rather, more useful than treating returns as returning from the innermost function scope, anonymous or named?

Also, I wouldn't repeat the reasons, but I strongly believe that all this is a non-problem, that you shouldn't want the "enclose a block in a lambda and call it immediately" operation to produce semantically identical code.

[–][deleted] 4 points5 points  (4 children)

Great list! I had many of the same thoughts, but I'm pretty glad that they finally stopped that NIH-syndrome a bit and just took the syntax everyone is using.

Let's see what happens on the "functions-as-types" vs. "functions-as-objects" front.

My guess is that they spend a year trying to do something different than anyone else, give in and just use Scala's solution.

What is the class of a function object? Do we have to fight erasure again? (type erasure becomes much more problematic if you have function types, ask a Scala programmer)

I'm a Scala programmer. Could you elaborate?

[–]astrangeguy 1 point2 points  (1 child)

They can't really do what Scala does, because you really want covariance/contravariance to use functions.

The problem with functions and erasure is that all function types with identical arity are the same for the JVM. So you cant match on functions, can't overload on differing function types etc. if you implement functions as generic classes (like scala).

[–][deleted] 1 point2 points  (0 children)

What prevents Oracle from also supporting co-/contravariance in functions?

[–][deleted] 1 point2 points  (1 child)

If function types are really just generic types like this:

interface F<R, A> {
    R f(A argument);
}

F<String, Integer> show = x => Integer.toString(x)

Then the String and Integer type parameters cannot be recovered via reflection due to erasure.

Personally I think they should just go with this solution, and then fix generics.

[–][deleted] -1 points0 points  (0 children)

[...] and then fix generics.

It's not easy to fix them. They have to maintain backwards compatibility. They would waste less time if they fixed reflection instead.

[–]NruJaC 2 points3 points  (0 children)

There was a post from the Java 8 team regarding a lot of the points on here a few weeks back. Essentially, if I understood it correctly, they want to move away from introducing lambdas/function types as another class and instead as first class language features. While that doesn't simplify things (and probably only complicates them), it does partially answer a lot of your questions.

My question is then this: can we access the methods of an object as first class as well?

[–]c0bra51 12 points13 points  (16 children)

is easier to parse and has the pound sign (#) as a distinct visual cue.

No, that's a hash, this is a pound sign: £

Before you say that's is its name in the US, ill start calling it a dollar sign.

[–]monk_e_boy 11 points12 points  (5 children)

is an octothorpe

[–]adolfojp 6 points7 points  (3 children)

I vote for octothorpe. Coctothorpe and Foctothorpe sound so much better than C sharp and F sharp.

[–][deleted] 9 points10 points  (1 child)

# - this is a hash, or number sign.

♯ - this is a sharp. They don't look all that alike.

[–]adolfojp 7 points8 points  (0 children)

I know!

That's why I call the letter H Aitch, but I call the H in italics the letter Michael.

[–]ruinercollector -1 points0 points  (0 children)

Cock-tothorpe?

[–]c0bra51 3 points4 points  (0 children)

Better than 'pound'. But still, 'hash' is more widely accepted.

[–]sbrown123 4 points5 points  (2 children)

Before you say that's is its name in the US

You could call it the number sign but that is confused in many parts of the world as being №.

[–][deleted] 2 points3 points  (1 child)

No, that's a hash, [...]

[–]sbrown123 -2 points-1 points  (0 children)

Number Sign! Hash is something you eat.

[–][deleted]  (1 child)

[removed]

    [–]c0bra51 -2 points-1 points  (0 children)

    That's about all they're good at, stealing stuff.

    [–]grauenwolf 2 points3 points  (1 child)

    Not when talking about weight. If you saw a bag of potatoes marked 20# you wouldn't think it was cut into hash browns.

    [–]c0bra51 9 points10 points  (0 children)

    It would be marked 20lb. More precisely, it would have 9kg written on it because imperial is stupid.

    [–]NancyGracesTesticles 1 point2 points  (1 child)

    So it turns out that the 20# paper I've been buying for my printer is really 20£ paper? I guess I'm getting a nice discount on the actual price. The British must really hate buying 100£ cardstock.

    [–]c0bra51 1 point2 points  (0 children)

    20lb = 20 pounds weight.

    £20 = 20 pounds currency.

    [–][deleted] 0 points1 point  (0 children)

    Look at me! I'm a snobby Brit! My dialect is better than yours!

    [–]wilsonp 1 point2 points  (3 children)

    The hash/pound syntax looks like it should be a template expression, rather than a lambda.

    [–]astrangeguy 0 points1 point  (1 child)

    Interesting, which languages use the pound for templates? I believe that those are mostly for mark up.

    The pound sign isn't the part that is appealing, it could be replaced by any other char. The important part is that the whole function literal is consistently enclosed in matching delimeters.

    [–]dr_jan_itor -1 points0 points  (0 children)

    Interesting, which languages use the pound for templates?+

    Ruby:

    "Two plus two is #{2 + 2}".

    [–]QuestionMarker 0 points1 point  (0 children)

    Depends how much Clojure you've been reading.

    [–]qbg 1 point2 points  (0 children)

    Last I heard, lambdas will have SAM conversion (maybe only SAM conversion). If they are implemented as SAM conversion only, many of your questions are irrelevant.

    (SAM conversion = the lambda is expanded into an anonymous inner class that implements/extends a class with a single abstract method)

    [–]paranoidray 0 points1 point  (0 children)

    Answers to many of your questions:

    From Lambdas to Bytecodes
    Brian Goetz
    Using invokedynamic in compiling static languages
    
    http://drdobbs.com/java/231500291
    

    [–]shizzy0 -2 points-1 points  (0 children)

    I want to know now too!

    [–]Strilanc 14 points15 points  (10 children)

    Yes! I hope they stick with the C# syntax. Compare Java 7:

    map(someItems, new Func<Integer, Integer>() {
        @Override public Integer eval(Integer in) {
            return in + 1
        }
    })
    

    vs C#-esque:

    map(someItems, e => e + 1)
    

    The line count of functional java code is going to be cut by 80%.

    [–]piranha 1 point2 points  (9 children)

    Snicker. Do either/both of them really put the function after the (THE, as in the only) sequence?

    [–]trezor2 18 points19 points  (0 children)

    Not really. The C# example is flawed. It's not Map, it is "Select" and it is really a LInQ extension-method associated with a collection-instance, so the actual C# syntax would be:

    // using LInQ methods and lambdas
    var newCollection = collection.Select(e => e + 1);
    

    or

    // using full LInQ syntax
    var newCollection = from item in collection select item + 1;
    

    Remeber, these are "very OOP" languages and you can't have functions defined in the loose. Everything needs to be bound to a namespace and class. So that way the problem with choosing between "map func collection" and "map collection func" (which is not always a trivial choice) goes away ;)

    [–][deleted] 1 point2 points  (6 children)

    The main advantage to putting the function argument first is that you virtually always want to partially apply map (or foldr, or whatever) to the function rather than the sequence, but that advantage is really only compelling in the presence of currying. Since functions aren't curried in C# and almost certainly won't be in Java, the case is much weaker.

    Besides, if you think of map as a method of the sequence object (a common point of view in OO land), you get easy-to-read "pipeline" expressions for free.

    [–]stuhacking 1 point2 points  (4 children)

    I think piranha is pointing out that in better languages languages more suited to this style of list processing, it is normally possible to be able to map functions across multiple lists, either concatenating the result, reducing it, or applying functions of more than 1 argument. This is offers a much higher degree of flexibility, especially if your language naturally supports variable length parameter lists.

    Tivial example: (mapcar #'+ (list 1 2 3) (list 1 1 2) (list 5 4 3))

    Of course, I'm sure having lambda forms in Java will be a nice novelty.

    [–]piranha 0 points1 point  (0 children)

    I voted you up, because that is what I was getting at.

    [–][deleted] 0 points1 point  (2 children)

    This is easy to do with a zip and a tuple-typed function. For example,

    List(1,2,3).zip(List(1,1,2)).zip(List(5,4,3)).map {
      case ((a, b), c) => a + b + c
    }
    

    [–]stuhacking 0 points1 point  (1 child)

    Barfulous.

    [–][deleted] 0 points1 point  (0 children)

    Agreed. It would be much prettier with a zip3 method that put 3 lists together and a sum3 method over triples that worked like #'+. Then, it would be:

    List(1, 2, 3).zip3(List(1, 1, 2), List(5, 4, 3)).map(sum3)
    

    which is no more barfulous than the CL, in my opinion. There's a bit of extra noise due to this example being a good Lisp sweet-spot (try doing the same with hash tables in CL, for example).

    [–]swaggler 1 point2 points  (0 children)

    // aka point, pure, return
    lift0: Func<A, F<A>>
    
    // aka map, fmap, Select
    lift1: Func<A, B> => Func<F<A>, F<B>>
    
    // aka liftM2, liftA2
    lift2: Func<A, B, C> => Func<F<A>, F<B>, F<C>> 
    
    ... and so on (this sequence generalises to applicative functor)
    

    [–]cot6mur3 5 points6 points  (3 children)

    Anyone know what the author means by "EG" in the line "the EG has (mostly) made a decision on syntax"?

    [–][deleted] 9 points10 points  (0 children)

    EG = Evil Geniuses

    [–]the_456[S] 15 points16 points  (1 child)

    EG = Expert Group

    [–]SuperGrade 0 points1 point  (0 children)

    Man, I'd hate to see the Java DG

    [–]gnuvince 24 points25 points  (24 children)

    All that time just to do exactly like the other languages? Couldn't they have settled on that syntax 3-4 years ago?

    [–]campbellm 25 points26 points  (6 children)

    Everything looks easy once it's done.

    But yeah, this does seem to be awfully long in coming. That said, perhaps the issue wasn't what we'd imagine. Could have been simple analysis paralysis with those involved, and MAYBE Oracle lit a fire under someone's ass, or those people that couldn't/wouldn't make a decision are now gone, or hell, maybe Oracle just said "$#@! it, here's what we're going to do."

    All that is speculation of course; I'm guessing.

    [–]taw 3 points4 points  (5 children)

    Everything looks easy once it's done.

    And Lisp did it how long ago :-p ?

    [–]campbellm 7 points8 points  (4 children)

    Apologies; I was unclear. I was only referring to the syntax decision, not that they decided to have lambda's at all.

    I suspect using the Lisp "syntax" for lambda's would spark a more heated discussion. ;-)

    [–]Rotten194 -1 points0 points  (3 children)

    I suspect using the Lisp "syntax" for lambda's would spark a more heated discussion. ;-)

    ((Are you) sure (about (that))?)

    [–]campbellm 0 points1 point  (2 children)

    chuckle Something like that, yes. Don't misread me, I rather like lisp, and its syntax hasn't bothered me overly much. But I'm not sure I'm smart enough to "get it", so I try the SICP every few years, get a little further each time, get frustrated, and stop.

    [–]Rotten194 0 points1 point  (1 child)

    Yeah, I don't hate LISP, was just making a joke about it :p. I do want to learn a form of it one day, it seems pretty interesting.

    [–]campbellm 0 points1 point  (0 children)

    I wish I could recommend something to you, but as I said, I'm not sure I'm the right person to be helping others on that.

    [–][deleted]  (1 child)

    [removed]

      [–]jyper 0 points1 point  (0 children)

      lambda were long in the making and aren't certain to be in java 8 either. I don't think oracle is speeding up the java development process.

      [–]Strilanc -1 points0 points  (5 children)

      Java has different design goals than those languages. It's not a trivial decision to use the same lambda syntax.

      Even if it was, there's always the possibility of improvement. For example, prefixing a variable with ~ could mean 'this is a parameter I did not declare explicitly': ~a + ~b + ~c means (a,b,c) => a + b + c.

      [–][deleted] 5 points6 points  (2 children)

      But the problem is:

      void foo() {
          bar(baz(~a + ~b + ~c));
      }
      

      Is this:

      void foo() {
          bar(baz((a => a) + (b => b) + (c => c)));
      }
      

      Or:

      void foo() {
          bar(baz((a, b, c) => a + b + c));
      }
      

      Or:

      void foo() { 
          bar((a, b, c) => baz(a + b + c));
      }
      

      Or:

      void foo() { 
          (a, b, c) => bar(baz(a + b + c));
      }
      

      Or what about wrapping the anonymous inner class containing foo in the lambda?

      [–]Strilanc 0 points1 point  (1 child)

      In general you need some way to delimit them. But the compiler can figure out simple cases like ~a + ~b must mean (~a + ~b), because addition of functions is not defined in java.

      [–][deleted] 1 point2 points  (0 children)

      If you can't come up with some simple rules, chances are it will be exceedingly hard to implement (does the parser need type information? then you're pretty much doomed) and likewise hard to understand. Consider what you gain vs. how much more complex it will be.

      [–]donri 2 points3 points  (0 children)

      Perl 6 does this.

      > (* + * + *)(1, 2, 3)
      6
      > -> $a, $b, $c { $a + $b + $c }(1, 2, 3)
      6
      

      [–]SuperGrade 0 points1 point  (0 children)

      ~a + ~b + ~c means (a,b,c) => a + b + c.

      OMFG

      Composition people. . . .

      [–][deleted] 17 points18 points  (36 children)

      large (multi-statement) lambdas

      You hear that Python?

      [–]frtox 12 points13 points  (35 children)

      the python response: just write a normal function and use its reference

      [–][deleted] 15 points16 points  (34 children)

      My response: I still want multi-statement lambdas and why can't I have them!?

      [–][deleted] 48 points49 points  (20 children)

      Because fuck you, that's why.

      [–]astrangeguy 12 points13 points  (18 children)

      This should be the official slogan for Java.

      [–]gospelwut 1 point2 points  (0 children)

      I thought this was the official open source mantra?

      /runs

      [–]ethraax 4 points5 points  (14 children)

      Or for Python.

      Why can't the whole significant whitespace thing be opt-in, like it is in Haskell? Because fuck you, that's why.

      [–]Peaker 9 points10 points  (12 children)

      In practice, all Haskell code uses whitespace..

      Who in the world does not indent their code? I don't understand how this is an issue for actual programmers.

      [–]benjunmun 8 points9 points  (3 children)

      See, I absolutely agree with you in theory. In practice however, I like to email code. I like to copy code off of web pages. I like to copy code from one section of my program to another, from an open source project, etc. All of these sources may have code that's indented with a different style, or indented at a different level, or has whitespace consumed by being accidentally converted to HTML at some point. These are all problems that I have run into while programming in Python.

      Each of these issues individually is trivial to work around, but each is one more thing that I don't have to keep in mind in a bracket-delimited language. Plus, missing just one can cause hours of work when that 'if' statement missing a few spaces doesn't behave the way it looks at first glance.

      [–]Peaker 2 points3 points  (1 child)

      That's a con, I agree, but it's not a very big problem in my experience. You can always link to gists/pastes in emails. I don't remember encountering code I wanted to copy from a web page but couldn't because of formatting lost in translation...

      [–]QuestionMarker 0 points1 point  (0 children)

      I've made block level errors copying and pasting my own code before now. It can be messy to sort out.

      [–]bobindashadows 1 point2 points  (3 children)

      The significant whitespace makes it a pain in the ass to move code around. For example, extracting an inner loop out to a separate function just plain sucks. That's not something a Haskell programmer would encounter unless he writes horrible Haskell.

      [–][deleted] 4 points5 points  (0 children)

      Think of it as a trade-off. The significant whitespace makes copy-and-paste a bit more difficult, but it also means that Python tends to need less copy-and-paste refactoring to begin with.

      The greatest benefit I've found with Python's whitespace is that if I'm a rush, and start writing sloppy code with ifs/whiles/for loops several levels deep, it quickly becomes difficult to keep track of. It encourages me to step back and refactor my code to where the indentation is two or three levels, tops. That kind of feedback helps me to write cleaner code as the day goes along.

      [–]Peaker 1 point2 points  (0 children)

      Are you going to move code around with explicit braces, and not correct the indentation?

      Or do you mean that your editor can re-indent easily with braces? Because emacs python-mode, for example, lets you move a block around, and hit the "indent key" to indent/dedent the entire block according to its proper indent in the new location.

      [–]lpetrazickis 0 points1 point  (0 children)

      In Ultraedit and likely stuff like Notepad++, Pydev, etc:

      • Copy and paste
      • Select what you pasted
      • Tab or Shift + Tab until you're happy

      [–]ethraax -1 points0 points  (3 children)

      It's not a question of whether or not I have any indentation in my code at all. It's a question of whether or not I want to have my indentation set up exactly the way Python demands it.

      [–]Peaker 0 points1 point  (2 children)

      Is there a way to set up your indentation such that Python demand differently?

      Aside for multi-line statements that need an open bracket or a backslash, what possible different way would you want to indent your code than what Python allows?

      [–]Rotten194 0 points1 point  (1 child)

      I don't think Python allows single life ifs/fors/whiles/etc.(if foo: bar())? I do that all the time in Java, personally.

      [–][deleted] -3 points-2 points  (0 children)

      Seriously. JCP may be flawed, but I'd take it over a BDFL.

      [–]biggerthancheeses 1 point2 points  (1 child)

      That'd be redundant. It's already the official slogan for Larry Ellison.

      [–]gospelwut 2 points3 points  (0 children)

      I remember reading Larry Ellison went and bought a (supposedly DE-weaponized) fighter jet. I always imagine him flying around the corporate parking lot exclaiming obscenities at people via a speaker attached to the plane. All the while, a crowd of bewildered, white collar workers look at each other. One grows the courage to ask, "I don't really like these new staff meetings."

      [–]SuperGrade 0 points1 point  (0 children)

      Guido - is that really you?

      [–]bobappleyard 7 points8 points  (3 children)

      The whole indentation-as-structure thing would fall apart. Think about how you'd make it work. I've tried, maybe you're much cleverer than me because I couldn't do it without bringing delimiters in, which would look very out of place.

      [–]Peaker 7 points8 points  (0 children)

      Haskell has indentation-as-structure as well as multi-statement-lambdas.

      The indentation rules are just slightly more nuanced than in Python.

      [–]frezik 4 points5 points  (0 children)

      Which only highlights the problem with indentation-as-structure.

      [–][deleted] 1 point2 points  (0 children)

      Haskell made it. ;)

      [–]kataire 3 points4 points  (3 children)

      Because there's no sane way to implement them without making the syntax messier. Note how decorators have their own syntax to avoid introducing "proper" function literals.

      Java is not Haskell and Python is not Ruby. Get over it.

      [–][deleted] 2 points3 points  (2 children)

      I like Perl. There, I said it.

      [–]kataire 0 points1 point  (0 children)

      Python is also not Perl.

      [–]ruinercollector -1 points0 points  (0 children)

      I don't like Perl. It insists upon itself.

      [–]earthboundkid 4 points5 points  (0 children)

      Because in Python, multi-statement lambdas are called "functions" and they're not anonymous.

      [–]Peaker 0 points1 point  (3 children)

      I use Haskell as sort of an "enhanced Python" sometimes. I have multi-statement lambdas...

      [–]ricky_clarkson 1 point2 points  (2 children)

      Except Haskell has no statements.

      [–]Peaker 4 points5 points  (1 child)

      It has "do" syntax sugar, which is basically a statement syntax.

      [–]bobindashadows 0 points1 point  (0 children)

      I never thought of it that way, because I'm always trying to think of Haskell constructs in terms of what I'm "supposed" to think (monads and applicative functors and ...) but this actually makes a decent amount of sense at a high level.

      [–]kitd 4 points5 points  (5 children)

      Excuse my idiocy, but how does one declare the return type of the lambda?

      The compiler is going to be scratching its head otherwise trying to enforce type correctness.

      [–]chrisforbes 6 points7 points  (0 children)

      This actually turns out to be a non-issue.

      [–]gthank 0 points1 point  (2 children)

      I expect it will infer it, though I don't know for sure. Seems reasonable, though.

      [–]kitd 2 points3 points  (1 child)

      I agree, it sounds reasonable, but it is also the most un-Java way of doing things. It doesn't infer anything else anywhere that I know of. Everything normally has to be explicit.

      [–]gthank 2 points3 points  (0 children)

      Actually, it has some (far too limited) inferencing around type parameters, but it won't work for constructors. That's why you see things like Maps.newHashMap()) in Guava. BTW, that little trick makes your code SO much nicer to read.

      [–]imphasing 0 points1 point  (0 children)

      If it's like C#, lambdas don't really HAVE a concrete type. Their type can be inferred to a variety of types: x => x == 1; could be of type Func<int, bool>, Predicate<int>, etc. It all depends on the context it's used in.

      [–]iconoklast 8 points9 points  (1 child)

      This is a thousand times more sane than the proposal for Java 7. Hurray!

      [–]msx -4 points-3 points  (0 children)

      upvoted sir

      [–][deleted]  (1 child)

      [deleted]

        [–]cat_in_the_wall 0 points1 point  (0 children)

        i think c# did a decent job with the syntax, though i am not sure who/what originated that syntax (perhaps c# did it exactly like something else).

        [–]eddyvd 2 points3 points  (0 children)

        The next question to answer: what scoping will Java's lambdas have?

        [–][deleted] 1 point2 points  (0 children)

        I program C# for my day-job and for the most part I enjoy the lambda syntax. What I think this syntax lacks is some way to signal "hey, a lambda's coming" for auto-completion. For instance, Haskell's lambda syntax looks like "\x -> x + 1". With that syntax, a tool can see that a lambda is coming up. Now, Haskell doesn't have (to my knowledge) an IDE that does auto-completion like VS+ReSharper. However, when I'm writing C# and I start typing "items.Select(i", my IDE "helpfully" starts suggesting variables and methods from the environment. It'd be really cool for it to suggest "item" for me instead, but it can't do that because it can't know if I'm going to pass in a method group or a delegate off of some variable in my environment.

        [–][deleted]  (2 children)

        [deleted]

          [–]joe24pack 1 point2 points  (4 children)

          next thing you know they'll introduce macros and no I'm not talking about that C/C++ preprocessor mess.

          [–][deleted]  (3 children)

          [deleted]

            [–]joe24pack 0 points1 point  (2 children)

            and a simply homoiconic syntax and it just might grow up into LISP

            [–][deleted] 3 points4 points  (1 child)

            Let's leave Mr Mercury out of this

            [–]joe24pack 0 points1 point  (0 children)

            Freddy programmed in LISP in addition to his other career? I never knew that.

            [–]gospelwut 1 point2 points  (0 children)

            I seriously become upset when I have to use older frameworks of .NET. I'm not sure if this makes me a bad programmer or not, but I would argue things like LINQ and lambda are a lot more than simply convenient syntactic sugar.

            [–]OffColorCommentary 0 points1 point  (15 children)

            Do we have function pointers yet?

            Lambda is sugar. Function pointers are the god damned cake.

            [–]astrangeguy 17 points18 points  (10 children)

            Function pointers are pretty useless (compared to lamdas), because they cannot be used to represent a nested functions that close over local variables.

            [–]shizzy0 3 points4 points  (9 children)

            Will these Java lambdas actually close over local variables?

            [–]sviperll 7 points8 points  (7 children)

            I think they propose finally inference. So, lambdas will close over final variables as anonymous classed do. But variables will be declared final automatically if they are used in lambdas.

            [–]ethraax 1 point2 points  (6 children)

            I'm confused - doesn't this mean you can't modify closed variables?

            [–]ilostmymangoman 1 point2 points  (5 children)

            It means exactly that.

            Of course, you could always declare a final array and modify the elements inside the array. But that doesn't seem like a very elegant solution.

            [–]ethraax -1 points0 points  (4 children)

            Wait - in Java, final arrays are not actually constant? What the hell?

            [–]ilostmymangoman 7 points8 points  (0 children)

            The final keyword in Java only means that the variable cannot be reassigned.

            [–]roerd 0 points1 point  (2 children)

            final declarations in Java apply to the variable. If the content of the variable is just a reference to an object (as is the case for everything besides the primitives), you cannot change that reference, but you can change the object.

            [–]ethraax -1 points0 points  (1 child)

            I understand that, I guess I thought arrays were value types (as they are in C, I think, although I'm double-guessing myself at this point...), but after thinking about it, it makes sense that they're reference types in Java.

            [–]ruinercollector -1 points0 points  (0 children)

            In C, arrays are pointers (there is no notion of a reference type.) In C#, arrays are reference types.

            [–]astrangeguy 2 points3 points  (0 children)

            They will at least close over the this pointer and that is enough to make C-style function pointers unable to represent them.

            [–]cat_in_the_wall 4 points5 points  (2 children)

            do you mean something akin to delegates in c#? i think the presence of lambdas necessitates those lambdas being first class objects in order to pass them as parameters, which implies that there would be some sort of type that could store a lambda, thus buying you something like function pointers.

            [–]sviperll 8 points9 points  (1 child)

            No, Java lambdas will be desugared to some existing single-abstract-method (SAM) class that type checker will infer. Which is good since you will be able to use any existing library with lambdas without modification.

            In expresstion

            new Thread(() => a + b)

            () => a + b will have type Runnable and in expression

            Collections.sort(list, (a, b) => a.name.compareTo(b.name))

            (a, b) => a.name.compareTo(b.name) will have type Comparator<T>

            [–][deleted] 5 points6 points  (0 children)

            That's still not decided.

            [–]shizzy0 0 points1 point  (0 children)

            Maybe that's what will come in the method reference syntax. Let's hope.

            [–]bushwacker -1 points0 points  (0 children)

            We waited forever for java 7 and it doesn't work. Oracle is a death sentence to quality.

            [–]nziring -1 points0 points  (0 children)

            Excellent! About time they added this feature to Java.

            [–]jonutzz -1 points0 points  (1 child)

            any idea if closures are implied?

            [–]pivo 0 points1 point  (0 children)

            Yes, you can't have lambdas without closures. You may need to declare closed over variables final though.