From pbenedict at apache.org Tue Dec 1 14:30:45 2009 From: pbenedict at apache.org (Paul Benedict) Date: Tue, 1 Dec 2009 16:30:45 -0600 Subject: The Philosophy of Nothing In-Reply-To: <15e8b9d20911302302q33c931dau637985a7108e9e8a@mail.gmail.com> References: <4B14A4D3.3060300@apache.org> <15e8b9d20911302153s5390b14g203501dd23bb79ef@mail.gmail.com> <4B14B82A.4070509@apache.org> <15e8b9d20911302302q33c931dau637985a7108e9e8a@mail.gmail.com> Message-ID: Neal, > Given that null is not a valid value for Nothing, and triggering the > "problem" requires working under the covers, I don't see much value in > adding to the platform another exception type.? I did have to diagnose this > kind of problem while writing the closures implementation, and I found it > easy with the null pointer exception.? I'd be interested to hear any > experience to the contrary. This was an interesting response. Up until now, I believed that a "void" method leaves the return value undefined. I know that in the x86 architecture, EAX is commonly used as the return value, and that the register is simply ignored for "void" methods. Because you said that an NPE would be generated, does that mean the JVM explicitly sets the return value of a "void" method to null? I can believe it. When I use reflection, "null" is the return value of a "void" method. Paul From neal at gafter.com Tue Dec 1 14:34:23 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 1 Dec 2009 14:34:23 -0800 Subject: The Philosophy of Nothing In-Reply-To: References: <4B14A4D3.3060300@apache.org> <15e8b9d20911302153s5390b14g203501dd23bb79ef@mail.gmail.com> <4B14B82A.4070509@apache.org> <15e8b9d20911302302q33c931dau637985a7108e9e8a@mail.gmail.com> Message-ID: <15e8b9d20912011434g6c0d7a78ibf65bdec93ef454c@mail.gmail.com> On Tue, Dec 1, 2009 at 2:30 PM, Paul Benedict wrote: > Because you said that an NPE would be generated, does that mean the > JVM explicitly sets the return value of a "void" method to null? No. We weren't talking about void methods. We were talking about methods declared to return Nothing. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091201/8ff395c3/attachment.html From pbenedict at apache.org Wed Dec 2 07:59:12 2009 From: pbenedict at apache.org (Paul Benedict) Date: Wed, 2 Dec 2009 09:59:12 -0600 Subject: The Philosophy of Nothing Message-ID: Neal, Does the spec prevent defining method that can neither return nor throw? public Nothing func() throws Nothing { } Paul From neal at gafter.com Wed Dec 2 08:07:46 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 2 Dec 2009 08:07:46 -0800 Subject: The Philosophy of Nothing In-Reply-To: References: Message-ID: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> On Wed, Dec 2, 2009 at 7:59 AM, Paul Benedict wrote: > Does the spec prevent defining method that can neither return nor throw? > > public Nothing func() throws Nothing { } > No, because Java has unchecked exceptions, and for other reasons that will be more clear when part b (0.6b) is published. I can't imagine what the value would be of adding such restrictions to the specification or compiler. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091202/2c090acb/attachment.html From pbenedict at apache.org Wed Dec 2 08:26:44 2009 From: pbenedict at apache.org (Paul Benedict) Date: Wed, 2 Dec 2009 10:26:44 -0600 Subject: The Philosophy of Nothing In-Reply-To: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> Message-ID: Neal, On Wed, Dec 2, 2009 at 10:07 AM, Neal Gafter wrote: > On Wed, Dec 2, 2009 at 7:59 AM, Paul Benedict wrote: >> >> Does the spec prevent defining method that can neither return nor throw? >> >> public Nothing func() throws Nothing { } > > No, because Java has unchecked exceptions, and for other reasons that will > be more clear when part b (0.6b) is published. > > I can't imagine what the value would be of adding such restrictions to the > specification or compiler. If a method cannot return nor throw, I would expect this to be an obvious compilation error. Note this example has nothing to do with closures, but just a normal method declaration. Well, I'll have to be patient and wait for 0.6b to explain. I am hoping that Nothing is used consistently. Thanks, Neal. Paul From markmahieu at googlemail.com Wed Dec 2 08:32:49 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 2 Dec 2009 16:32:49 +0000 Subject: The Philosophy of Nothing In-Reply-To: References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> Message-ID: <2D866418-5C40-46E7-88D1-771D7962EF64@googlemail.com> On 2 Dec 2009, at 16:26, Paul Benedict wrote: > Neal, > > On Wed, Dec 2, 2009 at 10:07 AM, Neal Gafter wrote: >> On Wed, Dec 2, 2009 at 7:59 AM, Paul Benedict wrote: >>> >>> Does the spec prevent defining method that can neither return nor throw? >>> >>> public Nothing func() throws Nothing { } >> >> No, because Java has unchecked exceptions, and for other reasons that will >> be more clear when part b (0.6b) is published. >> >> I can't imagine what the value would be of adding such restrictions to the >> specification or compiler. > > If a method cannot return nor throw, I would expect this to be an > obvious compilation error. Not sure I follow this. Your method declares that it cannot complete normally (ie. return explicitly or implicitly), but not that it doesn't throw. In fact, I believe you'd need a throw statement in there to get it to compile at all. Mark From jim.andreou at gmail.com Wed Dec 2 08:33:09 2009 From: jim.andreou at gmail.com (Dimitris Andreou) Date: Wed, 2 Dec 2009 16:33:09 +0000 Subject: The Philosophy of Nothing In-Reply-To: References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> Message-ID: <7d7138c10912020833u47661c61s3e36447a09a663b9@mail.gmail.com> 2009/12/2 Paul Benedict : > Neal, > > On Wed, Dec 2, 2009 at 10:07 AM, Neal Gafter wrote: >> On Wed, Dec 2, 2009 at 7:59 AM, Paul Benedict wrote: >>> >>> Does the spec prevent defining method that can neither return nor throw? >>> >>> public Nothing func() throws Nothing { } >> >> No, because Java has unchecked exceptions, and for other reasons that will >> be more clear when part b (0.6b) is published. >> >> I can't imagine what the value would be of adding such restrictions to the >> specification or compiler. > > If a method cannot return nor throw, I would expect this to be an > obvious compilation error. Note this example has nothing to do with > closures, but just a normal method declaration. > > Well, I'll have to be patient and wait for 0.6b to explain. I am > hoping that Nothing is used consistently. Thanks, Neal. > > Paul > Hi Paul, Note that a method can still throw exceptions it does not declare. But even if a method was required to list all possible thrown exceptions in its "throws clause", and it only declared Nothing so it couldn't throw any exceptions, then still this shouldn't be a compilation error, the code could simply enter an infinite loop. Dimitris From reinier at zwitserloot.com Wed Dec 2 08:45:19 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 2 Dec 2009 17:45:19 +0100 Subject: The Philosophy of Nothing In-Reply-To: References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> Message-ID: <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> The 'throws' clause of any method declaration lists *CHECKED* exceptions that you can't throw. Thus, "throws Nothing" indicates that the method may throw any unchecked exception, like all methods can, and may also throw any instance of Nothing. That last bit is trivially true for two reasons: 1. There are no instances of nothing. Therefore, granting any method the ability to throw instances of Nothing is irrelevant. 2. Nothing is an unchecked exception type, as it is a subtype of either RuntimeException or Error (it is in fact, both - Nothing is a subtype of everything). This is consistent with existing spec, see JLS 11.2: http://java.sun.com/docs/books/jls/second_edition/html/exceptions.doc.html#44121 : "The *unchecked exceptions classes* are the class RuntimeException and its subclasses, and the class Error and its subclasses." therefore, writing "throws Nothing" is as trivial as "throws NullPointerException". The compiler can run right past such a 'throws' clause, as it is effectively meaningless. If you're falling over the verbiage here (that "throws Nothing" seems to indicate that a method must not throw anything if you don't think about it for very long) I suggest you get over it. Confusion in frivolously constructed examples does not trump being compatible with other JVM languages that already have this concept, as well as having a natural term for situations where this type WILL see real-life usage, such as in return types and generics. --Reinier Zwitserloot On Wed, Dec 2, 2009 at 5:26 PM, Paul Benedict wrote: > Neal, > > On Wed, Dec 2, 2009 at 10:07 AM, Neal Gafter wrote: > > On Wed, Dec 2, 2009 at 7:59 AM, Paul Benedict > wrote: > >> > >> Does the spec prevent defining method that can neither return nor throw? > >> > >> public Nothing func() throws Nothing { } > > > > No, because Java has unchecked exceptions, and for other reasons that > will > > be more clear when part b (0.6b) is published. > > > > I can't imagine what the value would be of adding such restrictions to > the > > specification or compiler. > > If a method cannot return nor throw, I would expect this to be an > obvious compilation error. Note this example has nothing to do with > closures, but just a normal method declaration. > > Well, I'll have to be patient and wait for 0.6b to explain. I am > hoping that Nothing is used consistently. Thanks, Neal. > > Paul > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091202/925bd0ae/attachment.html From neal at gafter.com Wed Dec 2 09:00:22 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 2 Dec 2009 09:00:22 -0800 Subject: The Philosophy of Nothing In-Reply-To: References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> Message-ID: <15e8b9d20912020900u27f80692w7053ea0a1e9b6dc3@mail.gmail.com> On Wed, Dec 2, 2009 at 8:26 AM, Paul Benedict wrote: > If a method cannot return nor throw, I would expect this to be an > obvious compilation error. Note this example has nothing to do with > closures, but just a normal method declaration. > But this method CAN throw an unchecked exception. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091202/e4eee638/attachment-0001.html From pbenedict at apache.org Wed Dec 2 09:06:39 2009 From: pbenedict at apache.org (Paul Benedict) Date: Wed, 2 Dec 2009 11:06:39 -0600 Subject: The Philosophy of Nothing In-Reply-To: <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> Message-ID: Reinier, > If you're falling over the verbiage here (that "throws Nothing" seems to > indicate that a method must not throw anything if you don't think about it > for very long) I suggest you get over it. Confusion in frivolously > constructed examples... I think you're being a bit too harsh and panicky here. Maybe you're an expert in language design and can teach the whole subject, but I can only formulate my questions based on the spec, which, by the way, is incomplete. The first half is still in revision, and the second half isn't published. Neal has been very affable to field my questions, which won't win an award for great technical achievement, but I might give him an award for patience and virtuous responses. What you call "frivolously constructed" examples, I call "simple" for the sake of an easy conversation. Paul From neal at gafter.com Wed Dec 2 09:19:44 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 2 Dec 2009 09:19:44 -0800 Subject: The Philosophy of Nothing In-Reply-To: References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> Message-ID: <15e8b9d20912020919g4ec2b257q7812f2d790531805@mail.gmail.com> Paul- 0.6a is intended to stand on its own as a specification, which is why it was published first. It should not depend on anyhing in 0.6b to be understood. However, the details of 0.6a provide opportunities for the rest of the specification appearing in 0.6b. I can easily imagine disallowing "Nothing" in the explicit throws clause of a method to reduce this confusion. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091202/713b94c9/attachment.html From serge.boulay at gmail.com Wed Dec 2 09:53:11 2009 From: serge.boulay at gmail.com (Serge Boulay) Date: Wed, 2 Dec 2009 12:53:11 -0500 Subject: The Philosophy of Nothing In-Reply-To: <15e8b9d20912020919g4ec2b257q7812f2d790531805@mail.gmail.com> References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> <15e8b9d20912020919g4ec2b257q7812f2d790531805@mail.gmail.com> Message-ID: <855b507d0912020953l713fdd46i8e2c292dfee3042@mail.gmail.com> Is 0.6b something that you and Mark Reinhold are collaborating on or is the forthcoming spec to appear on his blog something all of his own? On Wed, Dec 2, 2009 at 12:19 PM, Neal Gafter wrote: > Paul- > > 0.6a is intended to stand on its own as a specification, which is why it > was published first. It should not depend on anyhing in 0.6b to be > understood. However, the details of 0.6a provide opportunities for the rest > of the specification appearing in 0.6b. > > I can easily imagine disallowing "Nothing" in the explicit throws clause of > a method to reduce this confusion. > > Cheers, > Neal > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091202/5aee104c/attachment.html From markmahieu at googlemail.com Wed Dec 2 10:09:51 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 2 Dec 2009 18:09:51 +0000 Subject: The Philosophy of Nothing In-Reply-To: <855b507d0912020953l713fdd46i8e2c292dfee3042@mail.gmail.com> References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> <15e8b9d20912020919g4ec2b257q7812f2d790531805@mail.gmail.com> <855b507d0912020953l713fdd46i8e2c292dfee3042@mail.gmail.com> Message-ID: Serge, Today's update to Mark's blog answers a few questions along those lines: http://blogs.sun.com/mr/entry/closures_qa Mark On 2 Dec 2009, at 17:53, Serge Boulay wrote: > Is 0.6b something that you and Mark Reinhold are collaborating on or is the forthcoming spec to appear on his blog something all of his own? > On Wed, Dec 2, 2009 at 12:19 PM, Neal Gafter wrote: > Paul- > > 0.6a is intended to stand on its own as a specification, which is why it was published first. It should not depend on anyhing in 0.6b to be understood. However, the details of 0.6a provide opportunities for the rest of the specification appearing in 0.6b. > > I can easily imagine disallowing "Nothing" in the explicit throws clause of a method to reduce this confusion. > > Cheers, > Neal > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091202/39c31e28/attachment.html From neal at gafter.com Wed Dec 2 10:59:37 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 2 Dec 2009 10:59:37 -0800 Subject: The Philosophy of Nothing In-Reply-To: <855b507d0912020953l713fdd46i8e2c292dfee3042@mail.gmail.com> References: <15e8b9d20912020807v7efb209ar8073758765135cd1@mail.gmail.com> <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> <15e8b9d20912020919g4ec2b257q7812f2d790531805@mail.gmail.com> <855b507d0912020953l713fdd46i8e2c292dfee3042@mail.gmail.com> Message-ID: <15e8b9d20912021059t8b6c91m66cf703a944d1738@mail.gmail.com> On Wed, Dec 2, 2009 at 9:53 AM, Serge Boulay wrote: > Is 0.6b something that you and Mark Reinhold are collaborating on or is the > forthcoming spec to appear on his blog something all of his own? > I know Mark has seen earlier revisions of the 0.6 work and that it influenced what he's preparing, but I don't really know anything more about the draft spec that he's preparing. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091202/c9b99ab6/attachment.html From peter.levart at gmail.com Sat Dec 5 02:46:47 2009 From: peter.levart at gmail.com (Peter Levart) Date: Sat, 5 Dec 2009 11:46:47 +0100 Subject: The Philosophy of Nothing In-Reply-To: <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> References: <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> Message-ID: <200912051146.48040.peter.levart@gmail.com> On Wednesday 02 December 2009 17:45:19 Reinier Zwitserloot wrote: > The 'throws' clause of any method declaration lists *CHECKED* exceptions > that you can't throw. Thus, "throws Nothing" indicates that the method may > throw any unchecked exception, like all methods can, and may also throw any > instance of Nothing. > > That last bit is trivially true for two reasons: > > 1. There are no instances of nothing. Therefore, granting any method the > ability to throw instances of Nothing is irrelevant. > > 2. Nothing is an unchecked exception type, as it is a subtype of either > RuntimeException or Error (it is in fact, both - Nothing is a subtype of > everything). This is consistent with existing spec, see JLS 11.2: > http://java.sun.com/docs/books/jls/second_edition/html/exceptions.doc.html# > 44121 > and 3. Nothing is also a checked exception type, as it is as subtype of say IOException, which is a checked exception (unless the definition of checked exceptions in new JLS excludes Nothing from checked exceptions types). :-) Peter From tronicek at fit.cvut.cz Sat Dec 5 04:33:19 2009 From: tronicek at fit.cvut.cz (tronicek at fit.cvut.cz) Date: Sat, 5 Dec 2009 13:33:19 +0100 Subject: m.invoke() vs. m() Message-ID: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> Hi, I noticed a discussion about m.invoke() and m() on Mark Reinhold's blog and although it is true that if m is in the variable name space, we need "invoke", if syntax fun void m(int x); is adopted, it seems natural to have m in the method name space and then the "invoke" is not needed. Z. -- Zdenek Tronicek FIT CTU in Prague From reinier at zwitserloot.com Sat Dec 5 04:46:28 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Sat, 5 Dec 2009 13:46:28 +0100 Subject: The Philosophy of Nothing In-Reply-To: <200912051146.48040.peter.levart@gmail.com> References: <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> <200912051146.48040.peter.levart@gmail.com> Message-ID: <560fb5ed0912050446n48d4a622k9ec2dd3b629dbbfc@mail.gmail.com> Nope, the JLS specifically states that an exception is unchecked if it is assignment compatible to RuntimeException or Error, and checked if it isn't. Therefore, an exception type that is a subtype of both IOException and RuntimeException is unambiguously unchecked. One could claim then that type casting causes weirdness to ensue, such as: Nothing x = getInstanceOfNothing(); throw (IOException)x; or even worse; IOException x = getInstanceOfNothing(); throw x; But this isn't very weird if you think about it a little more. Consider: RuntimeException x = new RuntimeException(); Exception y = x; throw y; unchecked exceptions can parade as checked exceptions with a simple silent upcast already. Nothing does not change the equation. checked / unchecked is a property of types, not of objects. It all works out nicely; Nothing, being a subtype of RuntimeException (and Error), is an unchecked throwable type. Therefore, something like: Nothing n = getNothing(); throw n; does not require you to catch or throw onwards the 'Nothing' type, and does compile, as instances of Nothing are Throwables. Of course, the 'throw n;' statement won't ever be executed; getNothing() must necessarily loop forever, or throw an exception itself as it can't return. There is nevertheless some weirdness inherent in having a nothing type. For example: Class c = someType(); if (String.class.isAssignableFrom(c) && Number.class.IsAssignableFrom(c)) { System.out.println("Hello, World!"); } one could argue that a sufficiently advanced style checker should flag this code as silly; no type is going to be both a subtype of Number and of String. It's analogous to the somewhat easier to realize as being silly code: if (x instanceof Number && x instanceof String) { ... } except of course that in the isAssignableFrom case, Nothing.class as a value for c will in fact make the boolean work. I guess we're somewhat lucky that no style checkers that I'm aware of actually go that far. --Reinier Zwitserloot On Sat, Dec 5, 2009 at 11:46 AM, Peter Levart wrote: > On Wednesday 02 December 2009 17:45:19 Reinier Zwitserloot wrote: > > The 'throws' clause of any method declaration lists *CHECKED* exceptions > > that you can't throw. Thus, "throws Nothing" indicates that the method > may > > throw any unchecked exception, like all methods can, and may also throw > any > > instance of Nothing. > > > > That last bit is trivially true for two reasons: > > > > 1. There are no instances of nothing. Therefore, granting any method the > > ability to throw instances of Nothing is irrelevant. > > > > 2. Nothing is an unchecked exception type, as it is a subtype of either > > RuntimeException or Error (it is in fact, both - Nothing is a subtype of > > everything). This is consistent with existing spec, see JLS 11.2: > > > http://java.sun.com/docs/books/jls/second_edition/html/exceptions.doc.html# > > 44121 > > > > and > > 3. Nothing is also a checked exception type, as it is as subtype of say > IOException, which is a > checked exception (unless the definition of checked exceptions in new JLS > excludes Nothing from > checked exceptions types). :-) > > Peter > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/66de70a9/attachment.html From reinier at zwitserloot.com Sat Dec 5 04:53:23 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Sat, 5 Dec 2009 13:53:23 +0100 Subject: m.invoke() vs. m() In-Reply-To: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> Message-ID: <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> Yes, I presumed Mark screwed up on that. The repercussions of being able to invoke any variable of a closure type simply by tossing parentheses after its mention are rather staggering. The closest you can get to something that is backwards and migration compatible and doesn't completely change the entire language is something like: when the parser sees something of this form: identifier(argslist[opt]) the parser will consider this a MethodCallOrClosureInvocation. During resolution, if identifier refers to a method name that is in scope, then this is a method invocation. If there is no such method name but there is a variable with that name, then it is a closure invocation. Meaning, if you create a new method, or one of your supertypes adds a new method, or something is statically imported, then a closure invocation can silently turn into a method invocation. The fun quadruples when you try to add some rule to the tune of: if 'identifier' is a legal method but the argslist doesn't fit any of that method's overloads, but it does fit the closure, then presumably, execute the closure instead. Yich. That's rather a lot of dancing the parser/resolver has to do in an area that's already extremely complicated (method resolution), all to avoid having to write '.invoke' in there. I'm not a fan of frivolous syntax merely to highlight something that your IDE can already tell you (that 'identifier' is a variable with a closure type), but in this case, the '.invoke' actually does impart something of significance that your parser/IDE cannot always infer for you: That the thing to the left of the invoke is a variable and not a method name. --Reinier Zwitserloot On Sat, Dec 5, 2009 at 1:33 PM, wrote: > Hi, > > I noticed a discussion about m.invoke() and m() on Mark Reinhold's blog > and although it is true that if m is in the variable name space, we need > "invoke", if syntax > > fun void m(int x); > > is adopted, it seems natural to have m in the method name space and then > the "invoke" is not needed. > > Z. > -- > Zdenek Tronicek > FIT CTU in Prague > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/6c3d7c30/attachment.html From ricky.clarkson at gmail.com Sat Dec 5 06:04:53 2009 From: ricky.clarkson at gmail.com (Ricky Clarkson) Date: Sat, 5 Dec 2009 14:04:53 +0000 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> Message-ID: <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> Whereas the only interpretation that actually makes sense is to choose the closest in lexical scope. In other words, f.invoke(args) and f(args) should never do different things to each other if you support the latter as shorthand for the former, unless you're deliberately making a language hard to follow. That is just as backward compatible, as no existing code contains closures, so no existing code's semantics is altered. I don't quite know what migration compatible means; I guess it's a woolly term. 2009/12/5 Reinier Zwitserloot : > Yes, I presumed Mark screwed up on that. The repercussions of being able to > invoke any variable of a closure type simply by tossing parentheses after > its mention are rather staggering. The closest you can get to something that > is backwards and migration compatible and doesn't completely change the > entire language is something like: > when the parser sees something of this form: > identifier(argslist[opt]) > the parser will consider this a MethodCallOrClosureInvocation. > During resolution, if identifier refers to a method name that is in scope, > then this is a method invocation. If there is no such method name but there > is a variable with that name, then it is a closure invocation. > Meaning, if you create a new method, or one of your supertypes adds a new > method, or something is statically imported, then a closure invocation can > silently turn into a method invocation. > The fun quadruples when you try to add some rule to the tune of: if > 'identifier' is a legal method but the argslist doesn't fit any of that > method's overloads, but it does fit the closure, then presumably, execute > the closure instead. Yich. > That's rather a lot of dancing the parser/resolver has to do in an area > that's already extremely complicated (method resolution), all to avoid > having to write '.invoke' in there. I'm not a fan of frivolous syntax merely > to highlight something that your IDE can already tell you (that 'identifier' > is a variable with a closure type), but in this case, the '.invoke' actually > does impart something of significance that your parser/IDE cannot always > infer for you: That the thing to the left of the invoke is a variable and > not a method name. > > --Reinier Zwitserloot > > > > On Sat, Dec 5, 2009 at 1:33 PM, wrote: >> >> Hi, >> >> I noticed a discussion about m.invoke() and m() on Mark Reinhold's blog >> and although it is true that if m is in the variable name space, we need >> "invoke", if syntax >> >> fun void m(int x); >> >> is adopted, it seems natural to have m in the method name space and then >> the "invoke" is not needed. >> >> Z. >> -- >> Zdenek Tronicek >> FIT CTU in Prague >> >> >> >> >> > > -- Ricky Clarkson Java and Scala Programmer, AD Holdings +44 1565 770804 Skype: ricky_clarkson Google Talk: ricky.clarkson at gmail.com Google Wave: ricky.clarkson at googlewave.com From vladimir.kirichenko at gmail.com Sat Dec 5 06:35:43 2009 From: vladimir.kirichenko at gmail.com (Vladimir Kirichenko) Date: Sat, 05 Dec 2009 16:35:43 +0200 Subject: m.invoke() vs. m() In-Reply-To: <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> Message-ID: <4B1A6FBF.40107@gmail.com> Ricky Clarkson wrote: > Whereas the only interpretation that actually makes sense is to choose > the closest in lexical scope. Or compiler should report an ambiguity error or shadowing warning. Any of these is better than "invoke". -- Best Regards, Vladimir Kirichenko -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 259 bytes Desc: OpenPGP digital signature Url : http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/d1affad7/attachment-0001.bin From ricky.clarkson at gmail.com Sat Dec 5 06:59:08 2009 From: ricky.clarkson at gmail.com (Ricky Clarkson) Date: Sat, 5 Dec 2009 14:59:08 +0000 Subject: m.invoke() vs. m() In-Reply-To: <4B1A6FBF.40107@gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> <4B1A6FBF.40107@gmail.com> Message-ID: <7eeb06460912050659m8040a26vbd812441c28c596@mail.gmail.com> Fine, but if it's a warning it shouldn't be active by default. Warnings that you cannot (or won't want to) program your way out of should not be enabled by default. This was a mistake Java 5 made, and look how long it took people to move to it, compared to the 1.3 -> 1.4 or 5 -> 6 moves. I don't count @SuppressWarnings as programming your way out of it. 2009/12/5 Vladimir Kirichenko : > Ricky Clarkson wrote: >> Whereas the only interpretation that actually makes sense is to choose >> the closest in lexical scope. > > Or compiler should report an ambiguity error or shadowing warning. > > Any of these is better than "invoke". > > > -- > Best Regards, > Vladimir Kirichenko > > -- Ricky Clarkson Java and Scala Programmer, AD Holdings +44 1565 770804 Skype: ricky_clarkson Google Talk: ricky.clarkson at gmail.com Google Wave: ricky.clarkson at googlewave.com From reinier at zwitserloot.com Sat Dec 5 07:51:51 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Sat, 5 Dec 2009 16:51:51 +0100 Subject: m.invoke() vs. m() In-Reply-To: <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> Message-ID: <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> Your idea is not going to work, Ricky. I can come up with a gajillion examples where your idea is either ambiguous or requires arbitrary ordering rules, and which would either way, as you so nicely put it, lead to a language that is 'deliberately hard to follow'. Problem #1: public class Test { private #()void x = #() {print("1");}; private void x() {print "2";} public static void main(String[] args) {x();} } What does this print? 1 or 2? Both 'x'es are in the same lexical scoping level. Problem #2: public class Test { public static void main(String[] args) {OtherClass.x();} } The only way you're going to make #2 work is by making the very meaning of this class change considerably depending on the structure of OtherClass. This is a very bad idea; instead of simply asserting that a language feature leads to confusion, here are the problems with that: (NB: gut instinct? Gut instinct has no place in discussions about language features. Please give actual reasons next time!) Code should remain generally parsable and resolvable even if there are syntax errors in it. This helps the compiler give error messages that state the problem clearly and point in the right locality, and it gives people writing code in IDEs a less jarring experience. For example, in eclipse, problems with an inner class sometimes blow up the entire local namespace resolution, meaning auto-complete doesn't work anymore. That should be avoided if at all possible. Having such far-reaching dependencies on other codes is a very bad thing for this concept; an error in OtherClass will now have a big impact on our code, and may lead our code to parse completely differently. Problem #3: It would also lead to problems with private API. Right now, java will resolve presuming all members are public, and then generate an error later when it realizes the method/field you're targeting is not visible. This isn't just a common strategy amongst java parsers, but it's a useful error mechanism as well; it catches problems where the code writer is confused about access levels with a clear error message (That method isn't visible, instead of That method doesn't exist). Your suggestion would mean that changing the type of a *private* field from a non-closure type to a closure-type has an impact on other code. Problem #4: Method Resolution is already one of the most complicated aspects of java, and you're suggesting that we make it even more complicated. I don't think saying that complicating the already extremely complicated is mere gut instinct. Right now, any parser that sees: ident(args); knows that this must mean: method invocation. It can tackle resolution by first trying to match 'ident' to the method namespace. Thus, if ident here is actually "x.y.z", then the compiler knows to look for a method named 'z' in a type 'x.y'. It'll have to consider both local variables and the global type namespace for 'x.y', which is already quite complicated, but at least it knows that the 'z' MUST be a method name. Not so in your proposal. In your proposal, we go from merely needing to sort out the method namespace in 'x.y', to knowing far, far more about x.y: - The entire variable namespace. - The TYPES of the variables in x.y. Type resolution is complex, and slow. IDEs avoid it as much as they can. If you turn type resolution on for all types in IDEs, they become slow as molasses even on multicore monsters. Solution: c.invoke(args) is the only legal closure invocation syntax. c(args) isn't. Is 'invoke' some serious curseword in programmese? Does it offend you so that this syntax just cannot stand? --Reinier Zwitserloot NB: Backwards compatibility is: Code written for javacX in mind still compiles into a class file with the same meaning when compiled in javacY, where Y is greater than X. Migration compatibility is: A class file produced by javacX still runs, and does what its supposed to do, on JVM Y, where Y is greater than X. The biggest issue here is most likely backwards and not migration compatibility. On Sat, Dec 5, 2009 at 3:04 PM, Ricky Clarkson wrote: > Whereas the only interpretation that actually makes sense is to choose > the closest in lexical scope. In other words, f.invoke(args) and > f(args) should never do different things to each other if you support > the latter as shorthand for the former, unless you're deliberately > making a language hard to follow. > > That is just as backward compatible, as no existing code contains > closures, so no existing code's semantics is altered. I don't quite > know what migration compatible means; I guess it's a woolly term. > > 2009/12/5 Reinier Zwitserloot : > > Yes, I presumed Mark screwed up on that. The repercussions of being able > to > > invoke any variable of a closure type simply by tossing parentheses after > > its mention are rather staggering. The closest you can get to something > that > > is backwards and migration compatible and doesn't completely change the > > entire language is something like: > > when the parser sees something of this form: > > identifier(argslist[opt]) > > the parser will consider this a MethodCallOrClosureInvocation. > > During resolution, if identifier refers to a method name that is in > scope, > > then this is a method invocation. If there is no such method name but > there > > is a variable with that name, then it is a closure invocation. > > Meaning, if you create a new method, or one of your supertypes adds a new > > method, or something is statically imported, then a closure invocation > can > > silently turn into a method invocation. > > The fun quadruples when you try to add some rule to the tune of: if > > 'identifier' is a legal method but the argslist doesn't fit any of that > > method's overloads, but it does fit the closure, then presumably, execute > > the closure instead. Yich. > > That's rather a lot of dancing the parser/resolver has to do in an area > > that's already extremely complicated (method resolution), all to avoid > > having to write '.invoke' in there. I'm not a fan of frivolous syntax > merely > > to highlight something that your IDE can already tell you (that > 'identifier' > > is a variable with a closure type), but in this case, the '.invoke' > actually > > does impart something of significance that your parser/IDE cannot always > > infer for you: That the thing to the left of the invoke is a variable and > > not a method name. > > > > --Reinier Zwitserloot > > > > > > > > On Sat, Dec 5, 2009 at 1:33 PM, wrote: > >> > >> Hi, > >> > >> I noticed a discussion about m.invoke() and m() on Mark Reinhold's blog > >> and although it is true that if m is in the variable name space, we need > >> "invoke", if syntax > >> > >> fun void m(int x); > >> > >> is adopted, it seems natural to have m in the method name space and then > >> the "invoke" is not needed. > >> > >> Z. > >> -- > >> Zdenek Tronicek > >> FIT CTU in Prague > >> > >> > >> > >> > >> > > > > > > > > -- > Ricky Clarkson > Java and Scala Programmer, AD Holdings > +44 1565 770804 > Skype: ricky_clarkson > Google Talk: ricky.clarkson at gmail.com > Google Wave: ricky.clarkson at googlewave.com > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/f265bde5/attachment.html From neal at gafter.com Sat Dec 5 09:03:48 2009 From: neal at gafter.com (Neal Gafter) Date: Sat, 5 Dec 2009 09:03:48 -0800 Subject: m.invoke() vs. m() In-Reply-To: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> Message-ID: <15e8b9d20912050903x572ec754jfe1a24d13789b6fd@mail.gmail.com> On Sat, Dec 5, 2009 at 4:33 AM, wrote: > I noticed a discussion about m.invoke() and m() on Mark Reinhold's blog > and although it is true that if m is in the variable name space, we need > "invoke", if syntax > > fun void m(int x); > > is adopted, it seems natural to have m in the method name space and then > the "invoke" is not needed. > I think Mark's idea is workable whatever he syntax. We had this in version 0.1 of the BGGA spec. We backed it out not because we thought it a bad idea, we just preferred to focus our attention on the other issues. The basic approach is to say that a variable of function type is in both the variable and the method namespaces. It is a bit funny to make the function interfaces special in this way, but I think it is sensible. You need to carefully define what it means to be "of function type" (e.g. does it include a variable of a type derived from a function type), and you need a whole bunch of additional rules (e.g. a variable of function type can't hide/override a method, etc) but I think it's all workable. It adds a moderate amount of complexity to the specification, but (like most of BGGA) that complexity is rarely surfaced to the developer. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/a625438f/attachment.html From neal at gafter.com Sat Dec 5 09:06:29 2009 From: neal at gafter.com (Neal Gafter) Date: Sat, 5 Dec 2009 09:06:29 -0800 Subject: The Philosophy of Nothing In-Reply-To: <560fb5ed0912050446n48d4a622k9ec2dd3b629dbbfc@mail.gmail.com> References: <560fb5ed0912020845n64f8407eh36fa7f687c3dd477@mail.gmail.com> <200912051146.48040.peter.levart@gmail.com> <560fb5ed0912050446n48d4a622k9ec2dd3b629dbbfc@mail.gmail.com> Message-ID: <15e8b9d20912050906me3d0028g11e49352b8b35b29@mail.gmail.com> On Sat, Dec 5, 2009 at 4:46 AM, Reinier Zwitserloot wrote: > One could claim then that type casting causes weirdness to ensue, such as: > > Nothing x = getInstanceOfNothing(); > throw (IOException)x; > I don't think you can declare a variable to be of type Nothing (any more than you can declare one to be of type void). It isn't useful to do so, and disallowing it doesn't prevent you from doing anything useful. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/1b4419c1/attachment.html From vladimir.kirichenko at gmail.com Sat Dec 5 11:31:06 2009 From: vladimir.kirichenko at gmail.com (Vladimir Kirichenko) Date: Sat, 05 Dec 2009 21:31:06 +0200 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> Message-ID: <4B1AB4FA.70408@gmail.com> Reinier Zwitserloot wrote: > Solution: > > c.invoke(args) is the only legal closure invocation syntax. c(args) > isn't. You're saying all the languages dealing with closures without any kind of "invoke" made by aliens? > Is 'invoke' some serious curseword in programmese? Does it offend > you so that this syntax just cannot stand? Yes it is. Why don't we use this syntax to invoke regular methods? It is a _function call_. One of the problems in todays java community I see is that lots of efforts wasted on reinventing the wheel or thinking that problems discovered have not been faced by others. Those are not new. Lambda is not something new. There are dozens of languages with lambdas or/and function types. There are syntax examples, the ways to deal with the problems you're describing. There is nothing new. Java is a follower in this case not a leader. For your example it's just enough to look at twin brother - C#: public class Test { public delegate void unit(); public unit x = () => Console.println(1); public void x() {Console.println(2);} } ./mcs -langversion:Future Test.cs Test.cs(5,21): error CS0102: The type `Test' already contains a definition for `x' Test.cs(4,21): (Location of the symbol related to previous error) Compilation failed: 1 error(s), 0 warnings Similar language, same problems - not an issue. Invocation syntax: x(); Scala: scala> class Test { | val x = println(1) | def x() = println(2) | } :6: error: value x is defined twice def x = println(2) Not a problem. Invocation syntax: x(); C++ #include using namespace std; class Test { void x() { cout << 1; } void (*x)(); }; g++ Test.cpp Test.cpp:7: error: declaration of ?void (* Test::x)()? Test.cpp:6: error: conflicts with previous declaration ?void Test::x()? Nothing new. Invocation syntax: x(); -- Best Regards, Vladimir Kirichenko -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 259 bytes Desc: OpenPGP digital signature Url : http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/e95f1aa9/attachment-0001.bin From reinier at zwitserloot.com Sat Dec 5 11:45:02 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Sat, 5 Dec 2009 20:45:02 +0100 Subject: m.invoke() vs. m() In-Reply-To: <4B1AB4FA.70408@gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> <4B1AB4FA.70408@gmail.com> Message-ID: <560fb5ed0912051145w6128962apaa85d3d0e69c0542@mail.gmail.com> On Sat, Dec 5, 2009 at 8:31 PM, Vladimir Kirichenko < vladimir.kirichenko at gmail.com> > > You're saying all the languages dealing with closures without any kind > of "invoke" made by aliens? > > What kind of comment is that? No, of course not. Java's choice of separate namespaces for methods and variables is relatively rare. Python, Ruby, and javascript, for example, all don't have this. And they all invoke 'closures' by just tagging any variable name with parentheses. Java isn't these languages. All the problems I posted are pretty much unique to a language that has separated these namespaces. > Yes it is. Why don't we use this syntax to invoke regular methods? It is > a _function call_. > > No it isn't. It's a closure invocation. Which is something you do to variables, not methods. Variables have a different namespace in java from methods. I also reiterate my point that everyone has a feel for style and gut instinct. Your woolly comments about how it feels like function call are irrelevant. They aren't the exact same thing, which is all that matters insofar as gut feeling goes. Show me either how we can leave off 'invoke' without a sizable set of changes to the JLS, or how the burden of typing ".invoke" is sufficiently heavy for it to be worth abolishing even with the serious repercussions I showed in my previous post. I'm not at all interested in your style sensitivities. [snip: List of languages with examples] > Java isn't any of those languages. Fortunately the folks who make the eventual decision on this (Mark Reinhold and crew) strongly dislike this kind of "Hey, look at language Y, we can just copy what they do" thinking. Your list of examples is an excellent case in point: All those languages DO NOT have multiple namespaces for the constructs that you posted. For example, in C#, friends that program in that language tell me you can't have a method named 'Foo' and a field also named 'Foo', which is collaborated by your example. So, for those languages, _duh_. Java isn't C#. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/dda719e8/attachment.html From vladimir.kirichenko at gmail.com Sat Dec 5 12:12:23 2009 From: vladimir.kirichenko at gmail.com (Vladimir Kirichenko) Date: Sat, 05 Dec 2009 22:12:23 +0200 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912051145w6128962apaa85d3d0e69c0542@mail.gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> <4B1AB4FA.70408@gmail.com> <560fb5ed0912051145w6128962apaa85d3d0e69c0542@mail.gmail.com> Message-ID: <4B1ABEA7.2050709@gmail.com> Reinier Zwitserloot wrote: > No it isn't. It's a closure invocation. Closure is a function. > Java isn't any of those languages. Fortunately the folks who make the > eventual decision on this (Mark Reinhold and crew) strongly dislike this > kind of "Hey, look at language Y, we can just copy what they do" > thinking. Considering existing solutions is a basic of engineering. And the question is not simple "hey look what my neighbor does". It "look what theory and practice in this area exist". > Your list of examples is an excellent case in point: All those > languages DO NOT have multiple namespaces for the constructs that you > posted. For example, in C#, friends that program in that language tell > me you can't have a method named 'Foo' and a field also named 'Foo', > which is collaborated by your example. So, for those languages, _duh_. > Java isn't C#. The question is: "does this make java better or worse". If it leads to the "invoke"-like solutions - I have no idea what good have java got from this. And even then there could be third namespace - for function types or we could not consider function types pure variable-space declaration. Let's dont stuck to something just because we call it some way. Especially if it gives us nothing good. -- Best Regards, Vladimir Kirichenko -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 259 bytes Desc: OpenPGP digital signature Url : http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/cbeb531a/attachment.bin From vladimir.kirichenko at gmail.com Sat Dec 5 12:38:05 2009 From: vladimir.kirichenko at gmail.com (Vladimir Kirichenko) Date: Sat, 05 Dec 2009 22:38:05 +0200 Subject: m.invoke() vs. m() In-Reply-To: <4B1ABEA7.2050709@gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> <4B1AB4FA.70408@gmail.com> <560fb5ed0912051145w6128962apaa85d3d0e69c0542@mail.gmail.com> <4B1ABEA7.2050709@gmail.com> Message-ID: <4B1AC4AD.9020106@gmail.com> Vladimir Kirichenko wrote: > The question is: "does this make java better or worse". If it leads to Even better question: does java closures looks better or worse comparing to other languages. If it worse - the question is: what is the point doing it worse. Doesn't this code look weird? m(); m1.invoke(); x.y(); x.z.invoke(); One of the points of adopting closures in java was simplification of syntax for cases where anonymous classes now applyed: Threads, Filters, Comparators. Why do we need it in the half-completed way - in the place of declaration it looks better, in the case of using it looks the same? The next request of enhancement would be to make it simpler. -- Best Regards, Vladimir Kirichenko -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 259 bytes Desc: OpenPGP digital signature Url : http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091205/36d0d080/attachment.bin From ricky.clarkson at gmail.com Sun Dec 6 02:22:40 2009 From: ricky.clarkson at gmail.com (Ricky Clarkson) Date: Sun, 6 Dec 2009 10:22:40 +0000 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> Message-ID: <7eeb06460912060222h662565e1x90e672a7b447da08@mail.gmail.com> > Your idea is not going to work, Ricky. The idea was not mine. I was commenting on your statements about Mark's idea. > Problem #1: > public class Test { > ?? ?private #()void x = #() {print("1");}; > ?? ?private void x() {print "2";} > ?? ?public static void main(String[] args) {x();} > } The arbitrary rule I would choose would be to cause this to give a compile error. That is, variables whose types are function types would work differently in terms of namespacing. > Problem #2: > public class Test { > ?? ?public static void main(String[] args) {OtherClass.x();} > } I think I've answered this in the answer to problem #1. > (NB: gut instinct? Gut > instinct has no place in discussions about language features. Please give > actual reasons next time!) I did not use the term 'gut instinct'. > Code should remain generally parsable and resolvable [snip Agreed, but I'm not sure how that affects this discussion. > Problem #3: > It would also lead to problems with private API. Not with the rule I mentioned above. > Problem #4: > Method Resolution is already one of the most complicated aspects of java, > and you're suggesting that we make it even more complicated. Again, I'm not suggesting we do so. I'm responding to your comments about Mark's suggestion to do so, and correcting what to me are errors. I don't really mind whether I type f(x) or f.invoke(x). > Right now, any parser that sees: > ident(args); > knows that this must mean: method invocation. It can tackle resolution by > first trying to match 'ident' to the method namespace. Thus, if ident here > is actually "x.y.z", then the compiler knows to look for a method named 'z' > in a type 'x.y'. It'll have to consider both local variables and the global > type namespace for 'x.y', which is already quite complicated, but at least > it knows that the 'z' MUST be a method name > Not so in your proposal. In your proposal, we go from merely needing to sort > out the method namespace in 'x.y', to knowing far, far more about x.y: > ?- The entire variable namespace. > ?- The TYPES of the variables in x.y. No, I would deliberately make this knowable without knowing the types, lest we get into exponential memory/time to resolve types. > Solution: > c.invoke(args) is the only legal closure invocation syntax. c(args) isn't. > Is 'invoke' some serious curseword in programmese? Does it offend you so > that this syntax just cannot stand? Can you try to read the words? Nothing I said implied I was offended. -- Ricky Clarkson Java and Scala Programmer, AD Holdings +44 1565 770804 Skype: ricky_clarkson Google Talk: ricky.clarkson at gmail.com Google Wave: ricky.clarkson at googlewave.com From reinier at zwitserloot.com Sun Dec 6 19:28:01 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 7 Dec 2009 04:28:01 +0100 Subject: m.invoke() vs. m() In-Reply-To: <7eeb06460912060222h662565e1x90e672a7b447da08@mail.gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <560fb5ed0912050453g6acd1fa6q74024b77b033067b@mail.gmail.com> <7eeb06460912050604wf2584d8y3dafecf22ade8b4@mail.gmail.com> <560fb5ed0912050751p24489db0g893d787eaf7035ee@mail.gmail.com> <7eeb06460912060222h662565e1x90e672a7b447da08@mail.gmail.com> Message-ID: <560fb5ed0912061928q3dee80fdtfaed550c41b4ffd2@mail.gmail.com> inline. > > Code should remain generally parsable and resolvable [snip > > Agreed, but I'm not sure how that affects this discussion. > > I explained why making closure variables act differently affects parsability and resolvability. If the namespace of a field or variable depends on its type, then a parsing problem with its type causes more problems than it does now. > > Problem #3: > > It would also lead to problems with private API. > > Not with the rule I mentioned above. > > Yes, it still does, even if closure-typed fields are in a special namespace. > > Problem #4: > > Method Resolution is already one of the most complicated aspects of java, > > and you're suggesting that we make it even more complicated. > > Again, I'm not suggesting we do so. You may not have suggested it, but you were defending it. Whether you are an active supporter or merely on the fence but defending it, this is an excellent argument against convoluting method namespaces even more, and I haven't heard any serious retort of this particular issue. An issue that has also been raised repeatedly and for example the java7 BOF at devoxx. (That is, method resolution in general being very complex, not specifically about how this syntax meshes with that). > > No, I would deliberately make this knowable without knowing the types, > lest we get into exponential memory/time to resolve types. > > How? If all fields occupy this new namespace, then javac7 is no longer capable of compiling code that would compile just fine on javac6, which is not an option. --Reinier Zwitserloot -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/61ca2860/attachment.html From ewjordan at gmail.com Sun Dec 6 21:33:22 2009 From: ewjordan at gmail.com (Eric Jordan) Date: Mon, 7 Dec 2009 00:33:22 -0500 Subject: m.invoke() vs. m() Message-ID: On Sat, 5 Dec 2009 20:45:02 +0100?Reinier Zwitserloot wrote: > Show me either how we can leave off 'invoke' without a sizable set of > changes to the JLS, or how the burden of typing ".invoke" is sufficiently > heavy for it to be worth abolishing even with the serious repercussions I > showed in my previous post. I'm not at all interested in your style > sensitivities. Style sensitivities and removal of boilerplate are two of the primary reasons that closures are being added, so they both need to be an important part of the discussion. Java doesn't need the dubious distinction of having the most verbose closure invocation syntax of any popular language, even if it is just by a few characters. A pointlessly verbose call syntax (from a user standpoint, I mean - no programmer in his right mind would ever name a closure the same thing as a method, as I'm sure everyone would agree, so cluttering the syntax to allow for that possibility *is* pointless) will make it painfully clear that this was "bolted on", and that will not be well received. I suspect it would become one of the primary examples people point at to show how Java "got closures wrong." As far as I can tell, you already agree that the only problem with putting closures into both variable and method namespaces is that it complicates the spec/implementation, not that there's any useful reason to prefer the ".invoke" syntax. As long as the changes are feasible, and I seem to recall Neal indicating that they are, then I don't really see what the problem is: millions of people will be using the new syntax, surely a bit of work to do it "right" is worth considering, no? Is it your claim that the changes would not, in fact, be feasible to implement? In that case I'd be more inclined to let this one go (you're right, it's not too much extra work to type ".invoke", even if it is just line noise), but I'm getting the sense that you don't think it's important enough to waste any energy on at all, which I strongly disagree with. This is a very visible and core component of closures, and people will notice and criticize even the tiniest bit of bloat in the syntax. - Eric From reinier at zwitserloot.com Sun Dec 6 21:37:57 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 7 Dec 2009 06:37:57 +0100 Subject: m.invoke() vs. m() In-Reply-To: References: Message-ID: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> It's going to be bolted on. Simple as that. There are going to be concessions. Lots of them. There's limited budget for complexity. Getting rid of ".invoke" is not a good place to spend it. The price is far too high, and the gain is far too meager. Also, just to throw a wrench in the works, from a style perspective, I think '.invoke' is much cleaner. Which shows exactly why style sensitivities have no place in this discussion. We all have our own idea. We most certainly don't represent your average java programmer, so even a tally of votes for style choices is unlikely to lead to the right answer. --Reinier Zwitserloot On Mon, Dec 7, 2009 at 6:33 AM, Eric Jordan wrote: > On Sat, 5 Dec 2009 20:45:02 +0100 Reinier Zwitserloot > wrote: > > Show me either how we can leave off 'invoke' without a sizable set of > > changes to the JLS, or how the burden of typing ".invoke" is sufficiently > > heavy for it to be worth abolishing even with the serious repercussions I > > showed in my previous post. I'm not at all interested in your style > > sensitivities. > > Style sensitivities and removal of boilerplate are two of the primary > reasons that closures are being added, so they both need to be an > important part of the discussion. Java doesn't need the dubious > distinction of having the most verbose closure invocation syntax of > any popular language, even if it is just by a few characters. A > pointlessly verbose call syntax (from a user standpoint, I mean - no > programmer in his right mind would ever name a closure the same thing > as a method, as I'm sure everyone would agree, so cluttering the > syntax to allow for that possibility *is* pointless) will make it > painfully clear that this was "bolted on", and that will not be well > received. I suspect it would become one of the primary examples > people point at to show how Java "got closures wrong." > > As far as I can tell, you already agree that the only problem with > putting closures into both variable and method namespaces is that it > complicates the spec/implementation, not that there's any useful > reason to prefer the ".invoke" syntax. As long as the changes are > feasible, and I seem to recall Neal indicating that they are, then I > don't really see what the problem is: millions of people will be using > the new syntax, surely a bit of work to do it "right" is worth > considering, no? > > Is it your claim that the changes would not, in fact, be feasible to > implement? In that case I'd be more inclined to let this one go > (you're right, it's not too much extra work to type ".invoke", even if > it is just line noise), but I'm getting the sense that you don't think > it's important enough to waste any energy on at all, which I strongly > disagree with. This is a very visible and core component of closures, > and people will notice and criticize even the tiniest bit of bloat in > the syntax. > > - Eric > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/749b7052/attachment.html From neal at gafter.com Sun Dec 6 22:31:47 2009 From: neal at gafter.com (Neal Gafter) Date: Sun, 6 Dec 2009 22:31:47 -0800 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> Message-ID: <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> On Sun, Dec 6, 2009 at 9:37 PM, Reinier Zwitserloot wrote: > Also, just to throw a wrench in the works, from a style perspective, I > think '.invoke' is much cleaner. Which shows exactly why style sensitivities > have no place in this discussion. > I don't follow this logic. At best that shows why the style sensitivities of some particular participants have no place here*. I suspect there is a hidden premise in your argument that the style preferences of any one participant in this discussion is as important as any other's. That all very democratic and egalitarian of you, but it doesn't work that way in practice. Some participants may have style sensitivities that are likely to result in a more natural-feeling language for the majority of its users. Programming language design by democratic processes doesn't tend to work out very well. * You've already declared that the positions you're taking now on topics such as function types < http://mail.openjdk.java.net/pipermail/coin-dev/2009-November/002498.html> are "a rotten piece of idiocy that will ruin Java" < http://zwitserloot.com/2006/10/09/concise-instance-creation-expressions-dissection/>, and that if closures of the style currently being considered are added, you're switching to another language < http://zwitserloot.com/2006/08/26/alternatives-to-closures-java/>. The other participants in this discussion at least respect their own opinions, and haven't publicly voiced reasons that they might undermine this effort. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091206/0a159458/attachment.html From ewjordan at gmail.com Mon Dec 7 01:38:11 2009 From: ewjordan at gmail.com (Eric Jordan) Date: Mon, 7 Dec 2009 04:38:11 -0500 Subject: m.invoke() vs. m() In-Reply-To: <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> Message-ID: On Sun, Dec 6, 2009 at 9:37 PM, Reinier Zwitserloot wrote: > It's going to be bolted on. Simple as that. > > There are going to be concessions. Lots of them. > > There's limited budget for complexity. Agreed (mostly) on these points, as long as we agree that an important part of this discussion is to figure out how to hide the bolts as well as possible. As far as complexity, user-facing complexity is far more limited than implementation complexity, which is limited only by the resources devoted to implementation/maintenance. > Getting rid of ".invoke" is not a good place to spend it. The price is > far too high, and the gain is far too meager. Again, I have no personal idea what the implementation price is, it may be that the addition of closures to the language is going to require so much work that rough edges will have to be left in, and perhaps that's what the price that you're talking about relates to. In which case, c'est la vie, it can't be done. But such a change would not spend much, if any, of the user-facing complexity budget. Re: the gain, it's really a matter of speculation. I tend to think that people will be annoyed, and wonder why they can't just write m() given that it's obvious what they are trying to do almost 100% of the time. Further, leaving the namespace handling untouched could (will?) lead to really nasty bugs, mainly because people are used to other languages where closure calls can be made with (): class MyBase { public void doFoo() { System.out.println("Wrong answer"); } } class MyDerived extends MyBase { public #()void doFoo = #() {System.out.println("Right answer");} static public void main(String[] args) { MyDerived derived = new MyDerived(); derived.doFoo(); //prints "Wrong answer", should be derived.doFoo.invoke() to print "Right answer", as expected } } Now imagine that MyBase is actually hidden away in some far off package that you didn't write, and imagine trying to debug this. It looks perfectly correct to the eye, it compiles, the doFoo() even autocompleted, helpfully!, and you have no indication whatsoever that there's already a doFoo method because you didn't override it. Yet you keep getting the wrong answer... I know, the definition of the doFoo closure could cause a warning, and it definitely should if the .invoke syntax is required. But personally, I don't think this should be allowed at all, it's too prone to error, since people *are* going to try to invoke with () whether it's allowed or not. > Also, just to throw a wrench in the works, from a style perspective, I > think '.invoke' is much cleaner. I have no problem *allowing* it, I just have a problem with requiring it. Scala lets you use "apply" as long-hand for (), and I think that's just fine: scala> val func = ()=>println("Hello") func: () => Unit = scala> func() Hello scala> func.apply Hello Neal Gafter wrote (re: style sensitivities having no place in the discussion): > I don't follow this logic. At best that shows why the style > sensitivities of some particular participants have no place here*. Actually, I think that having people in the discussion that have been negative about the proposal as a whole is a useful thing, because a lot of the Java community as a whole is very skeptical about this, and it's going to be important to address as many concerns as can be addressed without making the design into a democracy (a very bad thing, for sure). On this issue, though, except for Reinier, everyone that's commented so far seems to think it is a style problem, or that it's at least worth thinking about workaround. So as far as it is a matter of preference, it's one where almost everyone agrees. Mark Reinhold even mentioned on his blog that this was one of the things that specifically bothered him about FCM: (http://blogs.sun.com/mr/entry/closures_qa#comment-1259782867000): "FCM contains many good ideas but I'm troubled by, among other things, the subtle distinction between method literals and method references, the necessity of writing "m.invoke()" rather than just "m()" to invoke a method, and the complexity of named inner methods." So I think the argument over whether this is worth thinking about is mostly settled, and what remains is to decide whether the solutions are feasible or not. - Eric -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/cd5f3354/attachment-0001.html From schulz at the-loom.de Mon Dec 7 02:13:55 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Mon, 07 Dec 2009 11:13:55 +0100 Subject: m.invoke() vs. m() In-Reply-To: References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> Message-ID: <4B1CD563.2060606@the-loom.de> Eric Jordan wrote: > > Getting rid of ".invoke" is not a good place to spend it. The price is > > far too high, and the gain is far too meager. > > [..] > Re: the gain, it's really a matter of speculation. I tend to think that > people will be annoyed, and wonder why they can't just write m() given > that it's obvious what they are trying to do almost 100% of the time. To me, integrating closures into Java not only is to please API designers and concurrency specialists, but to make them a technology intuitively and easy to use for the average developer. So the gain of getting not only the technology right, but also the syntax and use-site of such a feature makes the decision on whether to have it one or the other way quite important. That is, by means of usability, the gain could be seen as quite high (and not meager), if the way of how to invoke a closure feels natural to any developer. If we look back on how extensive and controverse discussions on a syntax for defining closures in Java have been, it seems obvious that syntax is a very important issue especially for the feature's acceptance. As in most applications, user interface design and usability design is one of the main parts of development. Here, the developer is the user, hence the design of a feature (it's syntax) should not be understimated. > Mark Reinhold even mentioned on > his blog that this was one of the things that specifically bothered him > about FCM: > > (http://blogs.sun.com/mr/entry/closures_qa#comment-1259782867000): > "FCM contains many good ideas but I'm troubled by, among other things, > the subtle distinction between method literals and method references, > the necessity of writing "m.invoke()" rather than just "m()" to invoke a > method, and the complexity of named inner methods." The style of invocation was never an FCM only topic, but was derived from BGGA. Stephen and I simply did not consider tweaking around with name spaces. As Neal mentioned recently on this list, it might be feasible to put function-typed variables in both, method and variable name spaces. Hence, I would surely prefer to use "m()", too, because it feels natural to me from all the other C-like programming languages I know of supporting closures. Stefan From reinier at zwitserloot.com Mon Dec 7 08:13:29 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 7 Dec 2009 17:13:29 +0100 Subject: m.invoke() vs. m() In-Reply-To: <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> Message-ID: <560fb5ed0912070813x7771c4f6j90fdf39941ea17eb@mail.gmail.com> Wow, Neal. If you had come to devoxx, you could have punched me in the face, that might have been more efficient than that piece of rude, ad-hominem douchebaggery. The fact that I've been thinking about how to add closures to java since at least early 2005 should if anything give me some credits in your supposed 'some of us are more equal than others' world. Also, people who are capable of changing their opinions should be listened to more than people who pick a side and are incapable of being swayed by experience or logic. Your argument is also flat out wrong. If, due to plenty of experience using a variety of languages, as well as using java _a lot_, someone has formed a feel for style that is better than others, than obviously such a person should be able to explain why a certain style is better than another. Which was my entire point: If such a person can't, then I don't think we should be listening to that particular argument. --Reinier Zwitserloot On Mon, Dec 7, 2009 at 7:31 AM, Neal Gafter wrote: > On Sun, Dec 6, 2009 at 9:37 PM, Reinier Zwitserloot < > reinier at zwitserloot.com> wrote: > >> Also, just to throw a wrench in the works, from a style perspective, I >> think '.invoke' is much cleaner. Which shows exactly why style sensitivities >> have no place in this discussion. >> > > I don't follow this logic. At best that shows why the style sensitivities > of some particular participants have no place here*. I suspect there is a > hidden premise in your argument that the style preferences of any one > participant in this discussion is as important as any other's. That all > very democratic and egalitarian of you, but it doesn't work that way in > practice. Some participants may have style sensitivities that are likely to > result in a more natural-feeling language for the majority of its users. > Programming language design by democratic processes doesn't tend to work out > very well. > > * You've already declared that the positions you're taking now on topics > such as function types < > http://mail.openjdk.java.net/pipermail/coin-dev/2009-November/002498.html> > are "a rotten piece of idiocy that will ruin Java" < > http://zwitserloot.com/2006/10/09/concise-instance-creation-expressions-dissection/>, > and that if closures of the style currently being considered are added, > you're switching to another language < > http://zwitserloot.com/2006/08/26/alternatives-to-closures-java/>. The > other participants in this discussion at least respect their own opinions, > and haven't publicly voiced reasons that they might undermine this effort. > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/dfc55c48/attachment.html From reinier at zwitserloot.com Mon Dec 7 08:24:13 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 7 Dec 2009 17:24:13 +0100 Subject: m.invoke() vs. m() In-Reply-To: References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> Message-ID: <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> Allowing m() instead of m.invoke() actually spends quite a bit of the user-facing complexity budget. I've gone over the reasons, but just to highlight the ones relevant to user-facing complexity: - Changing the type of a field from closure to non-closure or vice versa can change the resolution in other source files, and in your own source file. In all java releases so far, the only way to do that is to actually add or remove members, or rename them. - Any form of identifiers(args); is already extremely complicated, and ".invoke"-less closure invocation is adding more to it. This isn't just a complexity cost carried by those implementing method resolution. IDEs are a big help here (as they can unambiguously show you what such an expression resolves to), but that doesn't eliminate the user-facing complexity completely. Those helpful IDEs are also going to have more work cut out for them to make this resolution work. Java has been around for decades, the IDEs for a long time too, and yet, resoluton in files with syntax errors is STILL a big issue. Handwaving this away as a one-off cost that only a select few implementors have to carry is not a good idea. Your example with 'nasty bugs' doesn't apply. First of all, nasty is a gross overstatement. A nasty bug is a bug that is very hard to find. This one won't be. Race conditions, those are nasty. Also, if you have a closure named 'doFoo', and a method named 'doFoo', some people are going to be confused. Given that the majority of java programmers either know no other language or only know a very small set of other languages and not very well, this is if anything an argument against allowing closureVar(); invocation without .invoke. Java isn't scala. You and I may be familiar with this notion, but the number of java programmers who are familiar with java is tiny. --Reinier Zwitserloot On Mon, Dec 7, 2009 at 10:38 AM, Eric Jordan wrote: > On Sun, Dec 6, 2009 at 9:37 PM, Reinier Zwitserloot < > reinier at zwitserloot.com> wrote: > > It's going to be bolted on. Simple as that. > > > > There are going to be concessions. Lots of them. > > > > There's limited budget for complexity. > > Agreed (mostly) on these points, as long as we agree that an important part > of this discussion is to figure out how to hide the bolts as well as > possible. As far as complexity, user-facing complexity is far more limited > than implementation complexity, which is limited only by the resources > devoted to implementation/maintenance. > > > > Getting rid of ".invoke" is not a good place to spend it. The price is > > far too high, and the gain is far too meager. > > Again, I have no personal idea what the implementation price is, it may be > that the addition of closures to the language is going to require so much > work that rough edges will have to be left in, and perhaps that's what the > price that you're talking about relates to. In which case, c'est la vie, it > can't be done. > > But such a change would not spend much, if any, of the user-facing > complexity budget. > > Re: the gain, it's really a matter of speculation. I tend to think that > people will be annoyed, and wonder why they can't just write m() given that > it's obvious what they are trying to do almost 100% of the time. > > Further, leaving the namespace handling untouched could (will?) lead to > really nasty bugs, mainly because people are used to other languages where > closure calls can be made with (): > > class MyBase { > public void doFoo() { System.out.println("Wrong answer"); } > } > > class MyDerived extends MyBase { > public #()void doFoo = #() {System.out.println("Right answer");} > > static public void main(String[] args) { > MyDerived derived = new MyDerived(); > derived.doFoo(); //prints "Wrong answer", should be > derived.doFoo.invoke() to print "Right answer", as expected > } > } > > Now imagine that MyBase is actually hidden away in some far off package > that you didn't write, and imagine trying to debug this. It looks perfectly > correct to the eye, it compiles, the doFoo() even autocompleted, helpfully!, > and you have no indication whatsoever that there's already a doFoo method > because you didn't override it. Yet you keep getting the wrong answer... > > I know, the definition of the doFoo closure could cause a warning, and it > definitely should if the .invoke syntax is required. But personally, I > don't think this should be allowed at all, it's too prone to error, since > people *are* going to try to invoke with () whether it's allowed or not. > > > > Also, just to throw a wrench in the works, from a style perspective, I > > think '.invoke' is much cleaner. > > I have no problem *allowing* it, I just have a problem with requiring it. > Scala lets you use "apply" as long-hand for (), and I think that's just > fine: > > scala> val func = ()=>println("Hello") > func: () => Unit = > > scala> func() > Hello > > scala> func.apply > Hello > > > Neal Gafter wrote (re: style sensitivities having no place in the > discussion): > > > I don't follow this logic. At best that shows why the style > > sensitivities of some particular participants have no place here*. > > Actually, I think that having people in the discussion that have been > negative about the proposal as a whole is a useful thing, because a lot of > the Java community as a whole is very skeptical about this, and it's going > to be important to address as many concerns as can be addressed without > making the design into a democracy (a very bad thing, for sure). > > On this issue, though, except for Reinier, everyone that's commented so far > seems to think it is a style problem, or that it's at least worth thinking > about workaround. So as far as it is a matter of preference, it's one where > almost everyone agrees. Mark Reinhold even mentioned on his blog that this > was one of the things that specifically bothered him about FCM: > > (http://blogs.sun.com/mr/entry/closures_qa#comment-1259782867000): > "FCM contains many good ideas but I'm troubled by, among other things, the > subtle distinction between method literals and method references, the > necessity of writing "m.invoke()" rather than just "m()" to invoke a method, > and the complexity of named inner methods." > > So I think the argument over whether this is worth thinking about is mostly > settled, and what remains is to decide whether the solutions are feasible or > not. > > - Eric > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/9a29ed86/attachment.html From opinali at gmail.com Mon Dec 7 14:46:28 2009 From: opinali at gmail.com (Osvaldo Doederlein) Date: Mon, 7 Dec 2009 20:46:28 -0200 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> Message-ID: I'll take a chance with my $2c here. I'm in the side of eliminating ".invoke" and allowing a straight call with "()". Some people argued that closure call and method call are not the same operation; here the difference is only formal - closure invocation is ultimately compiled/executed as method invocation. But either way it's irrelevant because we can just overload the "()" operator to handle both method-call and closure-call, there's much worse precedent for that in Java (e.g. "+"). The problem of separate variable/method namespaces can be handled by making the conflict illegal - any given scope cannot see two methods, or variables of closure type, with the same signature. No problem if I have c(10) and c("a", "b") where the first c is a closure field and the second c is a method. IMHO (not being a javac developer or JLS expert) this doesn't make method resolution more complex, we are unifying closure-typed-vars and methods and using similar, perhaps exactly identical, rules for both. (We can overload methods but not variables in the same scope, so we can't have multiple closures with same name even if their parameter lists differ - but this is handled before resolution, by Java's rules for variable naming and hiding.) 2009/12/7 Reinier Zwitserloot > Allowing m() instead of m.invoke() actually spends quite a bit of the > user-facing complexity budget. I've gone over the reasons, but just to > highlight the ones relevant to user-facing complexity: > > - Changing the type of a field from closure to non-closure or vice versa > can change the resolution in other source files, and in your own source > file. In all java releases so far, the only way to do that is to actually > add or remove members, or rename them. > This problem, as well as others I can think, seem strawmen to me. For another example, if I have interface A that defines a closure-typed field c, and interface B that defines a method with the same name c, then I can't have a class C that implements both A and B. So what? This problem exists since Java 1.0, you can have this kind of screwup with two interfaces that define two methods of compatible signatures but unrelated meaning, which is even worse because compilation will succeed but your implementation C.c() can't possibly satisfy the incompatible specifications of A.c() and B.c(). And you can also have A.c and B.c being fields, then C can actually implement both and javac accepts this silently, it's an error only if some code (perhaps a subclass of C) tries to use C.c - this is an interesting API-design puzzler. Also you can change the resolution of existing calls if you mess with the parameters of existing methods. Overall, closures don't bring anything significant to the table. Finally, I consider that ".invoke" will also spend substantial part of our "complexity budget". Just think about reflection. When Java was new, reflection was an obscure feature that was used almost only in the core libs. Things change; today, I have business-level code - interbank transaction processing, no less - that uses reflection often enough that IT HURTS, and I'm very happy that JDK 7 will relieve some of that pain with multi-catch (possibly), a parent ReflectiveOperationException class, and perhaps some extra sugar from JSR-292. Now, closure invocations will be rare in 2010 when JDK 7 ships, but it may (and I hope it will) be EVERYWHERE in frameworks or apps that are [re]designed a few years down the road. The closure/single-method-interface conversion will help people migrate as fast as they want. And when this happens, all those ".invoke" will suck hard. A significant part of the power of closures is that closures can be used interchangeably with regular methods or functions. As soon as users learn to use closures effectively, they will appreciate this and consider very natural to call closures just like they call methods. It's not a quantum leap; Java's "working programmers" have cut their teeth with inner classes, so closures are really not a big deal conceptually, and not hard to master. Not even with the method-like invocation syntax, and not even with a couple corner cases and extra rules. A+ Osvaldo -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/4f21562f/attachment.html From neal at gafter.com Mon Dec 7 14:50:57 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 7 Dec 2009 14:50:57 -0800 Subject: m.invoke() vs. m() In-Reply-To: References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> Message-ID: <15e8b9d20912071450y5dc1561blce2caf02b0656a09@mail.gmail.com> On Mon, Dec 7, 2009 at 2:46 PM, Osvaldo Doederlein wrote: > The problem of separate variable/method namespaces can be handled by making > the conflict illegal - any given scope cannot see two methods, or variables > of closure type, with the same signature. Things are not that simple. What about nested scopes, or the scope of a class/interface versus its subclasses/subinterfaces? Hiding? Shadowing? Overloading? These all have to be worked out. I think it's worth doing, but it's not trivial. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/eba6d3fd/attachment.html From reinier at zwitserloot.com Mon Dec 7 15:21:15 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 8 Dec 2009 00:21:15 +0100 Subject: m.invoke() vs. m() In-Reply-To: References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> Message-ID: <560fb5ed0912071521rdb626d7ya6cb289193abd8fe@mail.gmail.com> On Mon, Dec 7, 2009 at 11:46 PM, Osvaldo Doederlein wrote: > compiled/executed as method invocation. But either way it's irrelevant > because we can just overload the "()" operator to handle both method-call > and closure-call, there's much worse precedent for that in Java (e.g. "+"). > > "Java already sucks worse in regards X in area Y" is not an excuse to pile on the hurt. > IMHO (not being a javac developer or JLS expert) this doesn't make method > resolution more complex It does become more complex. Nested classes, the type of all variables all of a sudden enters play, as unifying the namespace of fields and methods generally is not backwards compatible, and more. > > This problem, as well as others I can think, seem strawmen to me. > How is that strawman? Do you think that people in practice never change the types of variables, or that with closures, existing variables of SAM types won't be rewritten to closure types? That seems quite a stretch. [snip rant on reflection] > How is this in any way or form relevant to the presumed added complexity of '.invoke'? You're comparing the need to insert a gajillion casts and catch 4 separate exception types on every reflection call with adding the letters ".invoke" to invoking closures? That also seems quite a stretch. ".invoke" does not suffer from any added complexity for users; it's considerably simpler. Closures are represented at the system level as an object. The payload of this closure is represented as a method (named "invoke", as being compatible with other JVM languages is a good thing). There's no way to abstract this away without that abstraction leaking like a sieve. Closures will of course extend Object, meaning you can do the usual things to them, such as reflection. Which will at the very least have to reveal that invoke method. I haven't seen a proposal to get rid of this, and I doubt a good one exists, so, whatever complexity you think exists in having a closure payload exist as a method named "invoke" cannot be avoided. Thus, we have two choices. (A) .invoke is the only way to invoke a closure, and we get all the complexity (insofar as it exists) of abstracting closures as a method named "invoke" on some function type, or (B) we allow .invoke, *AND* we allow invoke-less straight parameter syntax. Now we get all the complexity of A, and in addition, we get all the complexity of B, including fields that occupy more or less namespaces depending on their type, for example. Clearly, choice B cannot possibly be less complex than choice A. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091208/bc8783bb/attachment.html From vladimir.kirichenko at gmail.com Mon Dec 7 15:44:10 2009 From: vladimir.kirichenko at gmail.com (Vladimir Kirichenko) Date: Tue, 08 Dec 2009 01:44:10 +0200 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> Message-ID: <4B1D934A.3000905@gmail.com> Reinier Zwitserloot wrote: > Allowing m() instead of m.invoke() actually spends quite a bit of the > user-facing complexity budget. I've gone over the reasons, but just to > highlight the ones relevant to user-facing complexity: > > - Changing the type of a field from closure to non-closure or vice > versa can change the resolution in other source files, and in your own > source file. In all java releases so far, the only way to do that is to > actually add or remove members, or rename them. Which causes compilation error. So where is the problem? And in what way that change will not cause same thing with invoke? > - Any form of identifiers(args); is already extremely complicated, and > ".invoke"-less closure invocation is adding more to it. This isn't just > a complexity cost carried by those implementing method resolution. IDEs > are a big help here (as they can unambiguously show you what such an > expression resolves to), but that doesn't eliminate the user-facing > complexity completely. Those helpful IDEs are also going to have more > work cut out for them to make this resolution work. Adopting generics made a lot of work in IDEs. In compare with this change it's a significantly bigger work. Or annotations! This strange things introduced to java causes a lot of pain in IDE developers asses. So? > Java has been around > for decades, the IDEs for a long time too, and yet, resoluton in files > with syntax errors is STILL a big issue. Let's stop world from moving forward before we bring java IDE's to level what they could read our minds. > Java isn't scala. And yet there are IDEs for scala! > You and I may be familiar with this notion, but the number of java programmers who are familiar with java is tiny. I'm sorry but your arguments have no realistic base at all. Noone was familiar with C# before it was made. Now look at the market. Closures is a basic thing. There is nothing new. If java stop moving forward it will be dead in couple of years. Do not think that java language is state of the art. Everything changes. Once it was COBOL. Then remember delphi which "allowed to write windows programs without knowing that complex stuff". Where are they now? Java is conceptually pretty old now. It have the only choice now - moving forward or, slowly yes, but digging in. -- Best Regards, Vladimir Kirichenko -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 259 bytes Desc: OpenPGP digital signature Url : http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091208/17b88d5b/attachment.bin From vladimir.kirichenko at gmail.com Mon Dec 7 16:02:44 2009 From: vladimir.kirichenko at gmail.com (Vladimir Kirichenko) Date: Tue, 08 Dec 2009 02:02:44 +0200 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912071521rdb626d7ya6cb289193abd8fe@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> <560fb5ed0912071521rdb626d7ya6cb289193abd8fe@mail.gmail.com> Message-ID: <4B1D97A4.5010104@gmail.com> Reinier Zwitserloot wrote: > Clearly, choice B cannot possibly be less complex than choice A. How do we survived with later stuff now? Same challenges. package x; import static x.S.m; public class Test { public void m() { class T { public void m() { new Test() { public void m() { m(); } }; } } } } class S { public static void m() { } } -- Best Regards, Vladimir Kirichenko -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 259 bytes Desc: OpenPGP digital signature Url : http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091208/41ac6770/attachment-0001.bin From opinali at gmail.com Mon Dec 7 16:27:57 2009 From: opinali at gmail.com (Osvaldo Doederlein) Date: Mon, 7 Dec 2009 22:27:57 -0200 Subject: m.invoke() vs. m() In-Reply-To: <15e8b9d20912071450y5dc1561blce2caf02b0656a09@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> <15e8b9d20912071450y5dc1561blce2caf02b0656a09@mail.gmail.com> Message-ID: Hi Neal, 2009/12/7 Neal Gafter > On Mon, Dec 7, 2009 at 2:46 PM, Osvaldo Doederlein wrote: > >> The problem of separate variable/method namespaces can be handled by >> making the conflict illegal - any given scope cannot see two methods, or >> variables of closure type, with the same signature. > > > Things are not that simple. What about nested scopes, or the scope of a > class/interface versus its subclasses/subinterfaces? Hiding? Shadowing? > Overloading? These all have to be worked out. I think it's worth doing, > but it's not trivial. > > I'm aware of these issues, that's why I wrote "see" not "contain". But we already have all the complexity of considering such issues to resolve variable and method references. I surely believe that adding transparent closure calls to the mix may create some additional questions that don't have a single, trivial and obvious answer. Perhaps somebody could illustrate the problem with some sketch of grammar changes or some other way. As mostly a language user (*) I don't care about implementation complexity, compiler writers are born to suffer :-) as long as the end-user's features/complexity tradeoff (if any) is ok. And everything I've read from this thread failed to convince me that transparent calls will turn Java into the next C++ monster or even 1% of that. (*) Ten years ago I implemented a reasonably complete reverse engineering tool, that would consume both Java sources and classfiles, building an UML metamodel enriched with partial understanding of method bodies. I still remember that type resolution was surprisingly hard due to all combinations of imports, nesting, inner classes etc. But the lesson learned for me today, is that implementation != usage; as a Java language user, I _never_ thought of type resolution as anything even _minimally_ complex. (Context alone is usually sufficient to disambiguate things even without the help from IDEs; for the classic example, List can be either a collection or a AWT control but I never have to look at the imports or the editor's hover to know.) I don't know how well this experience maps to the admittedly more complex case of method resolution with closures, but my gut feeling is that the current complexity is very small and adding closures can't possibly make it even remotely bad enough to make me not want transparent closure calls. A+ Osvaldo -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/4320e6d2/attachment.html From ricky.clarkson at gmail.com Mon Dec 7 16:44:55 2009 From: ricky.clarkson at gmail.com (Ricky Clarkson) Date: Tue, 8 Dec 2009 00:44:55 +0000 Subject: m.invoke() vs. m() In-Reply-To: References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> <15e8b9d20912071450y5dc1561blce2caf02b0656a09@mail.gmail.com> Message-ID: <7eeb06460912071644m54973ddaw3f0c4696844aabf1@mail.gmail.com> "As mostly a language user (*) I don't care about implementation complexity, compiler writers are born to suffer :-) as long as the end-user's features/complexity tradeoff (if any) is ok." The problems occur when the complexity is not entirely contained within the compiler/IDE implementation. If you can't follow which method/closure will be called, you are likely to write more bugs than otherwise. If you can't follow it, chances are at least one compiler or IDE will get it wrong for some period of time too. In case of determined misreaders, this is a general point, and does not serve to support or disagree with points made elsewhere in this thread. -- Ricky Clarkson Java and Scala Programmer, AD Holdings +44 1565 770804 Skype: ricky_clarkson Google Talk: ricky.clarkson at gmail.com Google Wave: ricky.clarkson at googlewave.com From opinali at gmail.com Mon Dec 7 16:48:56 2009 From: opinali at gmail.com (Osvaldo Doederlein) Date: Mon, 7 Dec 2009 22:48:56 -0200 Subject: m.invoke() vs. m() In-Reply-To: <560fb5ed0912071521rdb626d7ya6cb289193abd8fe@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> <560fb5ed0912071521rdb626d7ya6cb289193abd8fe@mail.gmail.com> Message-ID: 2009/12/7 Reinier Zwitserloot > On Mon, Dec 7, 2009 at 11:46 PM, Osvaldo Doederlein wrote: > >> compiled/executed as method invocation. But either way it's irrelevant >> because we can just overload the "()" operator to handle both method-call >> and closure-call, there's much worse precedent for that in Java (e.g. "+"). >> >> > "Java already sucks worse in regards X in area Y" is not an excuse to pile > on the hurt. > By "worse" I meant "bigger"; I don't think that the overloaded "+" operator sucks a single bit. ;-) The fact is that the language already has many cases of superficial ambiguity, and they are NOT a problem. In fact the only "unambiguous" languages I programmed were Assembly - and these were old-school ASMs without powerful macros or the bewildering ISAs of modern chips. > > This problem, as well as others I can think, seem strawmen to me. >> > > How is that strawman? Do you think that people in practice never change the > types of variables, or that with closures, existing variables of SAM types > won't be rewritten to closure types? That seems quite a stretch. > Yes people do these things and many others, there's a ton of ways to break backwards compatibility, see Vladimir's reply too. I doesn't matter that much, unless you picture unexperienced programmers posing as APIs designers - but these guys will shoot themselves in the foot no matter how much baby-sitting we provide in the language. Designing good APIs that can evolve well is extremely hard, and most of the difficulty does not lie in language syntax. On your last comments below: invoke-less calls would be just sugar for the explicit calls; if you want .invoke for any reason (language interop, reflection, disambiguation) you use it. Java already has similar examples. You can iterate over a collection with explicit .iterator(), .hasNext() and .next() calls, or you can use enhanced-for. I don't remember anyone complaining that this made the language more complex, or that "the abstraction leaked". A+ Osvaldo > > [snip rant on reflection] >> > > How is this in any way or form relevant to the presumed added complexity of > '.invoke'? You're comparing the need to insert a gajillion casts and catch 4 > separate exception types on every reflection call with adding the letters > ".invoke" to invoking closures? That also seems quite a stretch. > > ".invoke" does not suffer from any added complexity for users; it's > considerably simpler. Closures are represented at the system level as an > object. The payload of this closure is represented as a method (named > "invoke", as being compatible with other JVM languages is a good thing). > There's no way to abstract this away without that abstraction leaking like a > sieve. Closures will of course extend Object, meaning you can do the usual > things to them, such as reflection. Which will at the very least have to > reveal that invoke method. I haven't seen a proposal to get rid of this, and > I doubt a good one exists, so, whatever complexity you think exists in > having a closure payload exist as a method named "invoke" cannot be avoided. > > Thus, we have two choices. > > (A) .invoke is the only way to invoke a closure, and we get all the > complexity (insofar as it exists) of abstracting closures as a method named > "invoke" on some function type, > > or > > (B) we allow .invoke, *AND* we allow invoke-less straight parameter syntax. > Now we get all the complexity of A, and in addition, we get all the > complexity of B, including fields that occupy more or less namespaces > depending on their type, for example. > > Clearly, choice B cannot possibly be less complex than choice A. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091207/f866d66d/attachment.html From ewjordan at gmail.com Tue Dec 8 14:12:01 2009 From: ewjordan at gmail.com (Eric Jordan) Date: Tue, 8 Dec 2009 17:12:01 -0500 Subject: m.invoke() vs. m() In-Reply-To: <15e8b9d20912071450y5dc1561blce2caf02b0656a09@mail.gmail.com> References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> <15e8b9d20912071450y5dc1561blce2caf02b0656a09@mail.gmail.com> Message-ID: Neal Gafter wrote: > Things are not that simple. What about nested scopes, > or the scope of a class/interface versus its subclasses/subinterfaces? > Hiding? Shadowing? Overloading? These all have to be > worked out. I think it's worth doing, but it's not trivial. Just as a start, I want to pin down some of these things - as you've said, this is not nearly as straightforward as it seems at a glance, and I think it will help everyone to see exactly why. I myself thought "well, just put closures into BOTH namespaces" was enough to settle it, but realized that it's easier said than done. My first thought was that any class with a declared closure member: class Foo { #(arg types)ReturnType doFoo; } could be rewritten to an equivalent class with the "default" Java namespace rules (where closures are objects, not methods) that simply delegates the call to ".invoke": class Foo { #(arg types)ReturnType doFoo = (do something); ReturnType doFoo(args) { doFoo.invoke(args); } } That would give us the desired doFoo() syntax and piggyback off of the usual method resolution rules, seemingly giving us "obvious" behavior and error messages (which, even if unaltered, would still make sense since the generated method name matches the closure) for free, including inheritance/hiding/overloading, behavior in inner/anonymous classes, etc. Let's see what happens if we consider a second class that would usually shadow the closure: class Bar extends Foo { #(different arg types)ReturnType doFoo = (do something else); ReturnType doFoo(different args) { doFoo.invoke(args); } } Even though the closure is shadowed and replaced with a different signature closure with the same name, calls to doBar with arguments matching either the visible or the shadowed closure will pass to the correct closures and complete as usual - this could be either a positive or a negative, as it's now easier to call Foo's closure with the () syntax than with .invoke because we can omit the otherwise necessary cast, but that's kind of an odd quirk. Welcome to the difference between methods and members - as far as shadowing is concerned a method's signature is part of its name, so we can overload, whereas for variables having different types doesn't prevent shadowing. This goes deeper. With the closure equivalent of a typical method override, we'd have class Baz extends Foo { #(arg types)ReturnType doFoo = (do something weird); ReturnType doFoo(args) { doFoo.invoke(args); } } When called with (), Baz's doFoo will be used in preference to Foo's doFoo. The closure inherits the method polymorphism when we use (). However, when we invoke the closure directly, that's not the case, because direct variable access is based on the declared class of the reference, not the runtime class. In other words, there's now going to be a difference depending on how our reference looks: Baz myBaz = new Baz(); Foo myFoo = (Foo)myBaz; myBaz.doFoo(args); //Baz's doFoo myFoo.doFoo(args); //Baz's doFoo myBaz.doFoo.invoke(args); //Baz's doFoo myFoo.doFoo.invoke(args); //Foo's doFoo Oops. That's bad. Take a closer look if it doesn't bother you: myFoo.doFoo(args) does something different than myFoo.doFoo.invoke(args), and that's a direct result of Java's (pretty much unchangeable) rules about method and variable overriding/shadowing. That's why it's not quite as simple as "putting closures into both namespaces", the lookup rules are different in each one. Wanna take bets on whether *that* one's showing up in the post-closures round of Java-gotchas if the syntax works like this? Deciding what we even *mean* by myFoo.doFoo when doFoo is a closure and myFoo has subclasses (where doFoo might be defined as well, either with the same or different signature) depends on whether we take a closure's variable nature or its method nature more seriously. We just can't have it both ways in the face of possibly shadowed variables. If we really want () to be equivalent to syntax sugar for .invoke, the right thing to do would be to make sure that polymorphism does not apply to closure calls. That's probably possible, but it's not as simple as a quick source-rewrite rule, so I haven't worked out much about how it would work. And I haven't even started thinking about local variable closures, exceptions, or many other things that might complicate matters. So I'm not saying that this is impossible (and I still think it's worth some effort to figure out), but it's definitely not a problem with an obvious, simple solution. - Eric -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091208/52e5a04b/attachment.html From opinali at gmail.com Wed Dec 9 04:29:05 2009 From: opinali at gmail.com (Osvaldo Doederlein) Date: Wed, 9 Dec 2009 10:29:05 -0200 Subject: m.invoke() vs. m() In-Reply-To: References: <560fb5ed0912062137s4e5d7b3ahb1a7aad0b3599002@mail.gmail.com> <15e8b9d20912062231o6adb9d7byb75de4cc9594589a@mail.gmail.com> <560fb5ed0912070824g38c6533sea95a6af8dde7a18@mail.gmail.com> <15e8b9d20912071450y5dc1561blce2caf02b0656a09@mail.gmail.com> Message-ID: 2009/12/8 Eric Jordan > Neal Gafter wrote: > > Things are not that simple. What about nested scopes, > > or the scope of a class/interface versus its subclasses/subinterfaces? > > Hiding? Shadowing? Overloading? These all have to be > > worked out. I think it's worth doing, but it's not trivial. > > Just as a start, I want to pin down some of these things - as you've said, > this is not nearly as straightforward as it seems at a glance, and I think > it will help everyone to see exactly why. I myself thought "well, just put > closures into BOTH namespaces" was enough to settle it, but realized that > it's easier said than done. > > My first thought was that any class with a declared closure member: > > class Foo { > #(arg types)ReturnType doFoo; > } > > could be rewritten to an equivalent class with the "default" Java namespace > rules (where closures are objects, not methods) that simply delegates the > call to ".invoke": > > class Foo { > #(arg types)ReturnType doFoo = (do something); > ReturnType doFoo(args) { doFoo.invoke(args); } > } > > That would give us the desired doFoo() syntax and piggyback off of the > usual method resolution rules, seemingly giving us "obvious" behavior and > error messages (which, even if unaltered, would still make sense since the > generated method name matches the closure) for free, including > inheritance/hiding/overloading, behavior in inner/anonymous classes, etc. > > Let's see what happens if we consider a second class that would usually > shadow the closure: > > class Bar extends Foo { > #(different arg types)ReturnType doFoo = (do something else); > ReturnType doFoo(different args) { doFoo.invoke(args); } > } > > Even though the closure is shadowed and replaced with a different signature > closure with the same name, calls to doBar with arguments matching either > the visible or the shadowed closure will pass to the correct closures and > complete as usual - this could be either a positive or a negative, as it's > now easier to call Foo's closure with the () syntax than with .invoke > because we can omit the otherwise necessary cast, but that's kind of an odd > quirk. Welcome to the difference between methods and members - as far as > shadowing is concerned a method's signature is part of its name, so we can > overload, whereas for variables having different types doesn't prevent > shadowing. > I guess you did this only to explore the problem, because these wrapper methods are completely unnecessary. A straight closure call, like bar.doFoo(x), would be compiled by simple desugaring into bar.doFoo.invoke(x). You are artifically binding closures to methods, which forces closures to adopt all method resolution rules including shadowing and overloading; this obviously doesn't work. The disambiguation (when necessary - namespaces with a mix of closures and methods with same name) should be resolved by javac, with new rules as necessary. Then javac emits bytecode with a getfield that's hardwired to either Foo.bar or Bar.bar. Your further, worse examples below are also in the same strawman category; of course that's really bad but then it's just because you created this closure->method translation, that was never suggested, and not necessary. I have a better idea for everybody interested in this issue: let's pick some simple program that makes abundant usage of closures in several scopes, twist it to create naming coincidences, and we can analyze whether transparent () calls creates any significant problem, i.e. if we need new resolution rules that add significant user-facing complexity (repeating again: extra complexity in javac's implementation has zero importance). If this happens and we cannot find a solution with simpler rules, then I'll be convinced that transparent calls are not a good idea. And even in that case, I think this syntax facility is good enough to be implement anyway. We can just issue a warning for any closure that shadow other variables (of closure type or not) or shadow/overload any method (especially with compatible parameter lists). The warning tells the user "danger, this code uses new and complex resolution rules, if you're too dumb to learn it, please rename this closure". BTW, I'm a frequent user of Checkstyle/PMD/FindBugs and they have such warnings for much simpler thnings, including many types of shadowing. I usually "fix" my code to please the validation tools even when I don't think it's really confusing - code conventions have big value in a team, and every time I remove shadowing I usually enhance a identifier to be more specific, which is good. A+ Osvaldo > > This goes deeper. With the closure equivalent of a typical method > override, we'd have > > class Baz extends Foo { > #(arg types)ReturnType doFoo = (do something weird); > ReturnType doFoo(args) { doFoo.invoke(args); } > } > > When called with (), Baz's doFoo will be used in preference to Foo's doFoo. > The closure inherits the method polymorphism when we use (). However, when > we invoke the closure directly, that's not the case, because direct variable > access is based on the declared class of the reference, not the runtime > class. In other words, there's now going to be a difference depending on > how our reference looks: > > Baz myBaz = new Baz(); > Foo myFoo = (Foo)myBaz; > > myBaz.doFoo(args); //Baz's doFoo > myFoo.doFoo(args); //Baz's doFoo > > myBaz.doFoo.invoke(args); //Baz's doFoo > myFoo.doFoo.invoke(args); //Foo's doFoo > > Oops. That's bad. Take a closer look if it doesn't bother you: > myFoo.doFoo(args) does something different than myFoo.doFoo.invoke(args), > and that's a direct result of Java's (pretty much unchangeable) rules about > method and variable overriding/shadowing. That's why it's not quite as > simple as "putting closures into both namespaces", the lookup rules are > different in each one. > > Wanna take bets on whether *that* one's showing up in the post-closures > round of Java-gotchas if the syntax works like this? > > Deciding what we even *mean* by myFoo.doFoo when doFoo is a closure and > myFoo has subclasses (where doFoo might be defined as well, either with the > same or different signature) depends on whether we take a closure's variable > nature or its method nature more seriously. We just can't have it both ways > in the face of possibly shadowed variables. > > If we really want () to be equivalent to syntax sugar for .invoke, the > right thing to do would be to make sure that polymorphism does not apply to > closure calls. That's probably possible, but it's not as simple as a quick > source-rewrite rule, so I haven't worked out much about how it would work. > And I haven't even started thinking about local variable closures, > exceptions, or many other things that might complicate matters. > > So I'm not saying that this is impossible (and I still think it's worth > some effort to figure out), but it's definitely not a problem with an > obvious, simple solution. > > - Eric > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091209/7d83b3e6/attachment-0001.html From peter.levart at gmail.com Sun Dec 13 01:49:35 2009 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 13 Dec 2009 10:49:35 +0100 Subject: m.invoke() vs. m() vs. m#() In-Reply-To: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> Message-ID: <200912131049.35382.peter.levart@gmail.com> I was following the discussion about the syntax of invoking a function type (a closure) when I thought: We agree that a special syntax for specifying function types (they are after all just generic interfaces) is fine: #(String)Integer vs. Function1 So why not adding special syntax for "invoking" a function type (a closure), for example: #(String)Integer parseInt = #(String s) Integer.valueOf(s); parseInt#("3") vs. parseInt.invoke("3"); This has the benefit of: - being unambiguous (no need for special shadowing/name-space rules) - the programmers intent is human visible (as with .invoke) - still not so verbose as .invoke What do you think? Peter P.S. I didn't check if the above syntax clashes with the intended syntax for specifying method references as function types. From vladimir.kirichenko at gmail.com Sun Dec 13 03:25:22 2009 From: vladimir.kirichenko at gmail.com (Vladimir Kirichenko) Date: Sun, 13 Dec 2009 13:25:22 +0200 Subject: m.invoke() vs. m() vs. m#() In-Reply-To: <200912131049.35382.peter.levart@gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <200912131049.35382.peter.levart@gmail.com> Message-ID: <4B24CF22.2060804@gmail.com> Peter Levart wrote: > This has the benefit of: > - being unambiguous (no need for special shadowing/name-space rules) Why be unambiguous here? For what? Just to have ability to name everything with the same name? Why don't we have special syntax for making unambiguous: * interfaces: class X interface %X * enums: class X{} enum $X{}; * constructors (why not?): class X { ~X(){} } * final fields/variables: public static final String &CONST; * static methods: C.*m*(); * !this() * ^super() Every of above examples could be supported with every argument against ambiguity shown here. Why don't we have it? And having this things ambiguous we seem not have any problems with "ambiguity". Closure is a function. It's a natural to call function, any function(constructor, static method, this(), super()) without pointing out with verb "call it" or hieroglyph defining the same. -- Best Regards, Vladimir Kirichenko -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 259 bytes Desc: OpenPGP digital signature Url : http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091213/ec63d760/attachment.bin From forax at univ-mlv.fr Sun Dec 13 07:13:11 2009 From: forax at univ-mlv.fr (=?UTF-8?B?UsOpbWkgRm9yYXg=?=) Date: Sun, 13 Dec 2009 16:13:11 +0100 Subject: m.invoke() vs. m() vs. m#() In-Reply-To: <4B24CF22.2060804@gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <200912131049.35382.peter.levart@gmail.com> <4B24CF22.2060804@gmail.com> Message-ID: <4B250487.8020604@univ-mlv.fr> Le 13/12/2009 12:25, Vladimir Kirichenko a ?crit : > Peter Levart wrote: > > >> This has the benefit of: >> - being unambiguous (no need for special shadowing/name-space rules) >> > Why be unambiguous here? For what? Just to have ability to name > everything with the same name? > > Why don't we have special syntax for making unambiguous: > * interfaces: class X interface %X > * enums: class X{} enum $X{}; > * constructors (why not?): class X { ~X(){} } > * final fields/variables: public static final String&CONST; > * static methods: C.*m*(); > * !this() > * ^super() > > you forget + for public, _ for static, ? for transient. BTW, to make fun of Perl is not fair :) > Every of above examples could be supported with every argument against > ambiguity shown here. Why don't we have it? And having this things > ambiguous we seem not have any problems with "ambiguity". > > Closure is a function. It's a natural to call function, any > function(constructor, static method, this(), super()) without pointing > out with verb "call it" or hieroglyph defining the same. > > R?mi From opinali at gmail.com Sun Dec 13 07:38:59 2009 From: opinali at gmail.com (Osvaldo Pinali Doederlein) Date: Sun, 13 Dec 2009 13:38:59 -0200 Subject: m.invoke() vs. m() vs. m#() In-Reply-To: <4B24CF22.2060804@gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <200912131049.35382.peter.levart@gmail.com> <4B24CF22.2060804@gmail.com> Message-ID: <4B250A93.4060602@gmail.com> Well put Vladimir. You remember me the eighties when we had those primitive BASIC languages, often with different suffixes for each data type - A$ for a string variable, A% for integer, A# for float or something like that - because type-unambiguous variable references allowed a simpler interpreter and typechecker. (I presume many programmers though that to be more readable to... so they invented/abused idioms like Hungarian notation years later.) Java already allows for ambiguity in many important places; as we're discussing closures, I could mention existing method invocation - as we have polymorphism, which is ALL ABOUT introducting ambiguity, and that's a core tenet of OO! Where some people see ambiguity, others see simplicity and expressiveness. We could even talk about cleaning up some of the existing syntax... for example, why Java needs separate 'extends'/'implements' keywords? The separate 'class'/'interface' keywords are sufficient to make these concepts clearly separated; the extra 'extends'/'implements' redundancy is a clear violation of DRY. [This is just rhetorics; I'm not seriously suggesting to deprecate 'implements' (or both keywords - in favor of something neutral like C++'s ':').] OTOH, not all language changes that add ambiguity should be accepted, even if they demonstrably make the language more powerful. For one thing, dynamic typing is not in my wish list for Java, because Java is a static typed language and I like it that way; it's a fundamental part of the language's core values and paradigm. Dynamic typing carries significant tradeoffs in performance and remarkably compile-time checking; if I wanted a "dynamic language" I'd run to Groovy, JRuby, Clojure etc. In summary, ambiguity is a HIGHLY overrated issue. I cannot imagine any single programming language trait that produces more ambiguity than dynamic typing, remarkably with powerful MOPs; still, half of the world likes to program that way because (IMHO) they equate productivity & readability to "less lines of code" and in that case it's hard to beat a dynamic+meta language. But closures extend the current language design naturally - in fact, closures _fixes_ this design ( inner classes ). The only real issue is: would transparent closure invocations (sans .invoke or any custom syntax) make the language _significantly_ more complex, in a way that matters to _end users_? Previous language enhancements - generics, autoboxing and varargs - have accreted much more complexity in this area than closures could possibly do. In fact, from my (admittedly non-expert) reading of the JLS, I'd say ANY of those changes alone create more drama than closures would. Quick puzzler: if you have f(int,Double) and f(Integer,double...), which method is invoked by f(0,1)? A common programmer who's never read the JLS would likely expect the compiler to prefer f(int,Double) that only requires autoboxing 1; but the right answer is f(Integer,double...), requiring both autoboxing 0 and wrapping 1 in a single-element double[]. If the "old-style" resolution fails, the JLS says to try again with autoboxing but without varargs; only in a third step varargs are considered. The rationale is to privilege fixed arity, but this is not obvious/intuitive, I just demonstrated that it doesn't always result in the simpler invocation (requiring less parameters to be wrapped). This rule is arbitrary enough to be at least as bad as anything transparent closure calls could bring (as far as I can see - I could be wrong). Yet, I use varargs as much as I can, and never found the ambiguity to be an issue in the real world. A+ Osvaldo Em 13/12/2009 09:25, Vladimir Kirichenko escreveu: > Peter Levart wrote: > > >> This has the benefit of: >> - being unambiguous (no need for special shadowing/name-space rules) >> > Why be unambiguous here? For what? Just to have ability to name > everything with the same name? > > Why don't we have special syntax for making unambiguous: > * interfaces: class X interface %X > * enums: class X{} enum $X{}; > * constructors (why not?): class X { ~X(){} } > * final fields/variables: public static final String&CONST; > * static methods: C.*m*(); > * !this() > * ^super() > > Every of above examples could be supported with every argument against > ambiguity shown here. Why don't we have it? And having this things > ambiguous we seem not have any problems with "ambiguity". > > Closure is a function. It's a natural to call function, any > function(constructor, static method, this(), super()) without pointing > out with verb "call it" or hieroglyph defining the same. > > From peter.levart at gmail.com Sun Dec 13 07:44:34 2009 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 13 Dec 2009 16:44:34 +0100 Subject: m.invoke() vs. m() vs. m#() In-Reply-To: <4B24CF22.2060804@gmail.com> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <200912131049.35382.peter.levart@gmail.com> <4B24CF22.2060804@gmail.com> Message-ID: <200912131644.34598.peter.levart@gmail.com> On Sunday 13 December 2009 12:25:22 Vladimir Kirichenko wrote: > Why be unambiguous here? For what? Just to have ability to name > everything with the same name? Well, just to stay simple in case it happens that someone names different things with the same name. We know we can have a class, a method and a variable in context using same names, but there's no ambiguity in their usage since it is expressed using different parts of Java syntax. > > Why don't we have special syntax for making unambiguous: > * interfaces: class X interface %X > * enums: class X{} enum $X{}; > * constructors (why not?): class X { ~X(){} } > * final fields/variables: public static final String &CONST; > * static methods: C.*m*(); > * !this() > * ^super() > > Every of above examples could be supported with every argument against > ambiguity shown here. Why don't we have it? And having this things > ambiguous we seem not have any problems with "ambiguity". Your examples are not parallels to mine. You suggest having special syntax "additions" for specifying symbol names of "different" things. There's no ambiguity in current Java syntax for specifying symbol names of different things: class X ... vs. interface X ... The first example unambiguously declares a class and the second an interface. > > Closure is a function. It's a natural to call function, any > function(constructor, static method, this(), super()) without pointing > out with verb "call it" or hieroglyph defining the same. > Well, you're right this time. We're at least trying to make it seem like it is. It was just a thought. Peter From vladimir.kirichenko at gmail.com Sun Dec 13 10:06:49 2009 From: vladimir.kirichenko at gmail.com (Vladimir Kirichenko) Date: Sun, 13 Dec 2009 20:06:49 +0200 Subject: m.invoke() vs. m() vs. m#() In-Reply-To: <4B250487.8020604@univ-mlv.fr> References: <1a1e9aaf9362c1ffa997acabc02f1cfd.squirrel@imap.fit.cvut.cz> <200912131049.35382.peter.levart@gmail.com> <4B24CF22.2060804@gmail.com> <4B250487.8020604@univ-mlv.fr> Message-ID: <4B252D39.6060907@gmail.com> R?mi Forax wrote: > Le 13/12/2009 12:25, Vladimir Kirichenko a ?crit : >> Peter Levart wrote: >> >> >>> This has the benefit of: >>> - being unambiguous (no need for special shadowing/name-space rules) >>> >> Why be unambiguous here? For what? Just to have ability to name >> everything with the same name? >> >> Why don't we have special syntax for making unambiguous: >> * interfaces: class X interface %X >> * enums: class X{} enum $X{}; >> * constructors (why not?): class X { ~X(){} } >> * final fields/variables: public static final String&CONST; >> * static methods: C.*m*(); >> * !this() >> * ^super() > you forget + for public, _ for static, ? for transient. > BTW, to make fun of Perl is not fair :) You got me!:) -- Best Regards, Vladimir Kirichenko -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 259 bytes Desc: OpenPGP digital signature Url : http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091213/c3c3d45f/attachment.bin From neal at gafter.com Sun Dec 13 16:34:59 2009 From: neal at gafter.com (Neal Gafter) Date: Sun, 13 Dec 2009 16:34:59 -0800 Subject: Closures for Java (0.6) specification part b Message-ID: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> Part b of the Closures for Java 0.6 specification can now be found at http://www.javac.info/closures-v06b.html. Part b extends the specification of part a to support *control abstraction*. There are also some minor changes in part a of the specification(described in its change log) that do not justify bumping the version number, the most significant of which is the addition of Peter von der Ah? as a coauthor. I think the most interesting remaining issue is how to modify the specification to allow a variable of function type to be invoked using the syntax v(args) instead of v.invoke(args). The most promising approach is likely the addition of such variables to both the variable and method namespace, and a suitable modification of affected sections (meaning of names, scopes, hiding, shadowing, overriding, overloading, method invocation expressions, etc). These documents, as well as links to resources related to Sun's Openjdk Project Lambda, can be found at http://www.javac.info/. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091213/de711f2c/attachment.html From pbenedict at apache.org Sun Dec 13 19:00:31 2009 From: pbenedict at apache.org (Paul Benedict) Date: Sun, 13 Dec 2009 21:00:31 -0600 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> Message-ID: Neal, Your last section says: > In this case an exception of type UnmatchedNonlocalTransfer is thrown. But the code example shows type UnmatchedTransfer. PS: Are you introducing a new Jump type too? Paul On Sun, Dec 13, 2009 at 6:34 PM, Neal Gafter wrote: > Part b of the Closures for Java 0.6 specification can now be found at > http://www.javac.info/closures-v06b.html.? Part b extends the specification > of part a to support control abstraction.? There are also some minor changes > in part a of the specification (described in its change log) that do not > justify bumping the version number, the most significant of which is the > addition of Peter von der Ah? as a coauthor. > > I think the most interesting remaining issue is how to modify the > specification to allow a variable of function type to be invoked using the > syntax v(args) instead of v.invoke(args).? The most promising approach is > likely the addition of such variables to both the variable and method > namespace, and a suitable modification of affected sections (meaning of > names, scopes, hiding, shadowing, overriding, overloading, method invocation > expressions, etc). > > These documents, as well as links to resources related to Sun's Openjdk > Project Lambda, can be found at http://www.javac.info/. > > Cheers, > Neal > > From neal at gafter.com Sun Dec 13 20:23:29 2009 From: neal at gafter.com (Neal Gafter) Date: Sun, 13 Dec 2009 20:23:29 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> Message-ID: <15e8b9d20912132023v29f44938i69ac5c176609889f@mail.gmail.com> On Sun, Dec 13, 2009 at 7:00 PM, Paul Benedict wrote: > Your last section says: > > In this case an exception of type UnmatchedNonlocalTransfer is thrown. > > But the code example shows type UnmatchedTransfer. > meh. It should be UnmatchedTransfer in both places. > PS: Are you introducing a new Jump type too? > Since the underlying mechanism for implementing the transfer is a contract between the compiler and itself, it need not be specified. BGGA's prototype uses the Jump type, which could be used to implement this specfication as well, but it is not visible to Java programmers so it is not part of the specification. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091213/b6ae15e1/attachment.html From pbenedict at apache.org Mon Dec 14 04:22:13 2009 From: pbenedict at apache.org (Paul Benedict) Date: Mon, 14 Dec 2009 06:22:13 -0600 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912132023v29f44938i69ac5c176609889f@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <15e8b9d20912132023v29f44938i69ac5c176609889f@mail.gmail.com> Message-ID: Neal, >> PS: Are you introducing a new Jump type too? > > Since the underlying mechanism for implementing the transfer is a contract > between the compiler and itself, it need not be specified.? BGGA's prototype > uses the Jump type, which could be used to implement this specification as > well, but it is not visible to Java programmers so it is not part of the > specification. I don't know how you can keep that constructor public without also exposing the Jump type, but I guess it's there solely for demonstrative purposes. Isn't the only operand to a Jump instruction its offset? You could probably turn that constructor argument into an int primitive unless you think more information is required. Paul From diego at trusteagle.com Mon Dec 14 04:17:29 2009 From: diego at trusteagle.com (diego at trusteagle.com) Date: Mon, 14 Dec 2009 13:17:29 +0100 Subject: C++ functors and boost::bind Message-ID: <200912141217.nBECHTLu004404@vivaldi30.register.it> I may come from a different background, and also don't know the history and the full extent of the discussion (e.g. http://mail.openjdk.java.net/pipermail/closures-dev/2009-November/000267.html ), but I don't fully understand the syntax. I hope somebody will take my opinion into account still in this late stage. In C++ there is a nicer and more straight forward syntax for callbacks available with functors, an example is here: http://www.boost.org/doc/libs/1_41_0/libs/bind/bind.html#with_boost_function and you can also have playButton.onClick(param one,param two) with an implementation of void operator()(param one , param two) in the class button At that point you do have a full and extensible object interface and you don't need to have extra syntactic sugar. Cheers, D. From neal at gafter.com Mon Dec 14 07:16:32 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 07:16:32 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <15e8b9d20912132023v29f44938i69ac5c176609889f@mail.gmail.com> Message-ID: <15e8b9d20912140716n13c7043ajcef386e2e5fe6b53@mail.gmail.com> Yes, that's a good point. Either Jump has to be public or hidden in the subclasses. Cheers, Neal On Mon, Dec 14, 2009 at 4:22 AM, Paul Benedict wrote: > Neal, > > >> PS: Are you introducing a new Jump type too? > > > > Since the underlying mechanism for implementing the transfer is a > contract > > between the compiler and itself, it need not be specified. BGGA's > prototype > > uses the Jump type, which could be used to implement this specification > as > > well, but it is not visible to Java programmers so it is not part of the > > specification. > > I don't know how you can keep that constructor public without also > exposing the Jump type, but I guess it's there solely for > demonstrative purposes. Isn't the only operand to a Jump instruction > its offset? You could probably turn that constructor argument into an > int primitive unless you think more information is required. > > Paul > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/7f7f1465/attachment.html From pbenedict at apache.org Mon Dec 14 10:33:38 2009 From: pbenedict at apache.org (Paul Benedict) Date: Mon, 14 Dec 2009 12:33:38 -0600 Subject: Control invocation syntax Message-ID: The syntax reads: ControlInvocationStatement: foropt Primary ( FormalParameters : ExpressionListopt ) Statement foropt Primary ( ExpressionListopt ) Statement But the "with" method declaration does not use the "for" keyword. Am I misunderstanding? It is used in Loop Abstractions, which I expect. Paul From neal at gafter.com Mon Dec 14 10:48:00 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 10:48:00 -0800 Subject: Control invocation syntax In-Reply-To: References: Message-ID: <15e8b9d20912141048k5f0e51e5g9d72490c41bdeb90@mail.gmail.com> On Mon, Dec 14, 2009 at 10:33 AM, Paul Benedict wrote: > The syntax reads: > > ControlInvocationStatement: > foropt Primary ( FormalParameters : ExpressionListopt ) Statement > foropt Primary ( ExpressionListopt ) Statement > > But the "with" method declaration does not use the "for" keyword. Am I > misunderstanding? It is used in Loop Abstractions, which I expect. > The "for" keyword is optional when defining a method that is intended to be used with the contol invocation syntax. It is used when the method is intended to be used like a loop. The "with" method is not intended to be used as a loop, so it is not defined with the "for" keyword. That means that "break" and "continue" ignore a control invocation of the "with" method. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/833c76b1/attachment.html From Jonathan.Gibbons at Sun.COM Mon Dec 14 11:20:02 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Mon, 14 Dec 2009 11:20:02 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> Message-ID: <4B268FE2.9070908@sun.com> Neal, As much as I like control flow abstraction, it seems that your proposal 0.6b leaves us in a half-way house with respect to control flow keywords. Using the 'for' modifier, 'break' and 'continue' get to work as expected, but it would appear that 'return' is still local to the lambda function, which is mildly icky. Have you considered this issue? -- Jon From neal at gafter.com Mon Dec 14 11:22:42 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 11:22:42 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <4B268FE2.9070908@sun.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> Message-ID: <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> That's not the case. In a statement lambda, all three are local. In an expression lambda, they are nonlocal. Cheers, Neal On Mon, Dec 14, 2009 at 11:20 AM, Jonathan Gibbons wrote: > Neal, > > As much as I like control flow abstraction, it seems that your proposal > 0.6b leaves us in a half-way house with respect to control flow keywords. > Using the 'for' modifier, 'break' and 'continue' get to work as expected, > but it would appear that 'return' is still local to the lambda function, > which is mildly icky. Have you considered this issue? > > -- Jon > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/2ea84aa3/attachment-0001.html From Jonathan.Gibbons at Sun.COM Mon Dec 14 11:47:08 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Mon, 14 Dec 2009 11:47:08 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> Message-ID: <4B26963C.1060302@sun.com> Ouch. That's pretty subtle, especially as the statement in a control invocation form is defined to use an expression lambda instead of a statement lambda. -- Jon Neal Gafter wrote: > That's not the case. In a statement lambda, all three are local. In > an expression lambda, they are nonlocal. > > Cheers, > Neal > > On Mon, Dec 14, 2009 at 11:20 AM, Jonathan Gibbons > > wrote: > > Neal, > > As much as I like control flow abstraction, it seems that your > proposal 0.6b leaves us in a half-way house with respect to > control flow keywords. Using the 'for' modifier, 'break' and > 'continue' get to work as expected, but it would appear that > 'return' is still local to the lambda function, which is mildly > icky. Have you considered this issue? > > -- Jon > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/f40f5bf0/attachment.html From neal at gafter.com Mon Dec 14 11:50:25 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 11:50:25 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <4B26963C.1060302@sun.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> Message-ID: <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> On Mon, Dec 14, 2009 at 11:47 AM, Jonathan Gibbons wrote: > Ouch. That's pretty subtle, especially as the statement in a control > invocation form is defined to use an expression lambda instead of a > statement lambda. > Maybe subtle for the specification, but not subtle for the Java programmer, as you don't see a lambda when you're writing a control invocation. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/85d94224/attachment.html From Jonathan.Gibbons at Sun.COM Mon Dec 14 11:58:02 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Mon, 14 Dec 2009 11:58:02 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> Message-ID: <4B2698CA.10401@sun.com> Neal Gafter wrote: > On Mon, Dec 14, 2009 at 11:47 AM, Jonathan Gibbons > > wrote: > > Ouch. That's pretty subtle, especially as the statement in a > control invocation form is defined to use an expression lambda > instead of a statement lambda. > > > Maybe subtle for the specification, but not subtle for the Java > programmer, as you don't see a lambda when you're writing a control > invocation. > > Cheers, > Neal > That's true. -- Jon -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/320429a5/attachment.html From talden at gmail.com Mon Dec 14 12:42:51 2009 From: talden at gmail.com (Talden) Date: Tue, 15 Dec 2009 09:42:51 +1300 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> Message-ID: <738d207f0912141242k92e4136he0c79a7c548d57ac@mail.gmail.com> On Tue, Dec 15, 2009 at 8:50 AM, Neal Gafter wrote: > On Mon, Dec 14, 2009 at 11:47 AM, Jonathan Gibbons > wrote: >> >> Ouch. That's pretty subtle, especially as the statement in a control >> invocation form is defined to use an expression lambda instead of a >> statement lambda. > > Maybe subtle for the specification, but not subtle for the Java programmer, > as you don't see a lambda when you're writing a control invocation. I think that's a really significant point that warrants clear mention in the documentation. It comes up frequently yet, as you say, this is a subtle point of confusion for reading the specification not reading and writing java code. >From the developers perspective they're not writing a lambda, they're writing a local block of code - continue, break and return should act as though they're local. -- Aaron Scott-Boddendijk From neal at gafter.com Mon Dec 14 12:55:49 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 12:55:49 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <738d207f0912141242k92e4136he0c79a7c548d57ac@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <738d207f0912141242k92e4136he0c79a7c548d57ac@mail.gmail.com> Message-ID: <15e8b9d20912141255y74346b13k36421685a6927586@mail.gmail.com> Talden- Good point. I'll add the following note as a clarification at the end of the *control invocation syntax *section in the next revision: Note that a consequence of this specification is that a break, continue, or return within the body of a control invocation can transfer to a target outside the control invocation statement. That is not a separate language rule, but a consequence of the meaning of the individual language elements that make up the specification of the control invocation statement. Can this be said more clearly? You can see working drafts of the 0.7 documents by guessing the URLs. Cheers, Neal On Mon, Dec 14, 2009 at 12:42 PM, Talden wrote: > On Tue, Dec 15, 2009 at 8:50 AM, Neal Gafter wrote: > > On Mon, Dec 14, 2009 at 11:47 AM, Jonathan Gibbons > > wrote: > >> > >> Ouch. That's pretty subtle, especially as the statement in a control > >> invocation form is defined to use an expression lambda instead of a > >> statement lambda. > > > > Maybe subtle for the specification, but not subtle for the Java > programmer, > > as you don't see a lambda when you're writing a control invocation. > > I think that's a really significant point that warrants clear mention > in the documentation. It comes up frequently yet, as you say, this is > a subtle point of confusion for reading the specification not reading > and writing java code. > > From the developers perspective they're not writing a lambda, they're > writing a local block of code - continue, break and return should act > as though they're local. > > -- > Aaron Scott-Boddendijk > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/42dc1cad/attachment.html From talden at gmail.com Mon Dec 14 13:39:07 2009 From: talden at gmail.com (Talden) Date: Tue, 15 Dec 2009 10:39:07 +1300 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912141255y74346b13k36421685a6927586@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <738d207f0912141242k92e4136he0c79a7c548d57ac@mail.gmail.com> <15e8b9d20912141255y74346b13k36421685a6927586@mail.gmail.com> Message-ID: <738d207f0912141339v69356eedi67857a3c6e643693@mail.gmail.com> That seems reasonable. Also, thanks for pointing out the obvious URL fiddling of 0.7. -- Aaron Scott-Boddendijk On Tue, Dec 15, 2009 at 9:55 AM, Neal Gafter wrote: > Talden- > > Good point.? I'll add the following note as a clarification at the end of > the control invocation syntax section in the next revision: > > Note that a consequence of this specification is that a break, continue, or > return within the body of a control invocation can transfer to a target > outside the control invocation statement. That is not a separate language > rule, but a consequence of the meaning of the individual language elements > that make up the specification of the control invocation statement. > > Can this be said more clearly? > > You can see working drafts of the 0.7 documents by guessing the URLs. > > Cheers, > Neal > > On Mon, Dec 14, 2009 at 12:42 PM, Talden wrote: >> >> On Tue, Dec 15, 2009 at 8:50 AM, Neal Gafter wrote: >> > On Mon, Dec 14, 2009 at 11:47 AM, Jonathan Gibbons >> > wrote: >> >> >> >> Ouch. That's pretty subtle, especially as the statement in a control >> >> invocation form is defined to use an expression lambda instead of a >> >> statement lambda. >> > >> > Maybe subtle for the specification, but not subtle for the Java >> > programmer, >> > as you don't see a lambda when you're writing a control invocation. >> >> I think that's a really significant point that warrants clear mention >> in the documentation. It comes up frequently yet, as you say, this is >> a subtle point of confusion for reading the specification not reading >> and writing java code. >> >> From the developers perspective they're not writing a lambda, they're >> writing a local block of code - continue, break and return should act >> as though they're local. >> >> -- >> Aaron Scott-Boddendijk > > From Jonathan.Gibbons at Sun.COM Mon Dec 14 21:52:58 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Mon, 14 Dec 2009 21:52:58 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> Message-ID: <4B27243A.7080007@sun.com> Neal Gafter wrote: > On Mon, Dec 14, 2009 at 11:47 AM, Jonathan Gibbons > > wrote: > > Ouch. That's pretty subtle, especially as the statement in a > control invocation form is defined to use an expression lambda > instead of a statement lambda. > > > Maybe subtle for the specification, but not subtle for the Java > programmer, as you don't see a lambda when you're writing a control > invocation. > > Cheers, > Neal > There is still potential confusion for the programmer using lambda expressions however. Someone reading 0.6a might reasonably infer that an expression lambda could easily be converted to statement lambda by adding a "return" and changes parens to curlies. If 0.6a were all there was, that would work. But in 0.6b, you've added block expressions. They look great - I want to use them - but they've broken that "obvious" rule relating expression lambdas to statement lambdas. Suddenly, there is a substantial non-obvious difference between expression lambdas and statement lambdas. With the for loop invocation syntax, we get to add another modifier to the signature, which makes it very clear this is a different sort of function type. Is there any similar way we could mark the type of any function type that is to be used for control flow abstraction, not just for loops? This would then avoid the need for the subtle semantic difference between expression lambdas and statement lambdas, and avoid the downstream puzzlers comparing the behavior of the two. -- Jon P.S. It wouldn't be quite so bad if the difference were the other way around, with local return, no break/continue in expression lambdas, and non-local return in statement lambdas, but it would still be even better if we could make the difference more explicit, somehow. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/860b4ce1/attachment.html From neal at gafter.com Mon Dec 14 22:44:56 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 22:44:56 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <4B27243A.7080007@sun.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> Message-ID: <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> On Mon, Dec 14, 2009 at 9:52 PM, Jonathan Gibbons wrote: > There is still potential confusion for the programmer using lambda > expressions however. > > Someone reading 0.6a might reasonably infer that an expression lambda could > easily be converted to statement lambda by adding a "return" and changes > parens to curlies. > I think that issue is mainly academic. I'd be surprised to find someone trying to use an expression lambda with a block expression (i.e. statements in the parens). Given the existence of statement lambdas, the code would be awkward for no apparent reason. The only real reason to do so would be to be able to use the nonlocal transfers in a context where you can't use the control invocation syntax (e.g. there are two controlled blocks to pass to a method). If you try to change a lambda from expression lambda to statement lambda, the transfers become compilation errors (except for a return statement in the unlikely event that the enclosing method and the lambda have the same return type). Most people nowadays make such local transformations using IDEs, and the IDE would presumably know how to do it correctly. If 0.6a were all there was, that would work. But in 0.6b, you've added > block expressions. They look great - I want to use them - but they've broken > that "obvious" rule relating expression lambdas to statement lambdas. > Suddenly, there is a substantial non-obvious difference between expression > lambdas and statement lambdas. > I think it's pretty obvious that "return" means something different. That's the whole point of introducing statement lambdas. break and continue just turn into compile-time errors. With the for loop invocation syntax, we get to add another modifier to the > signature, which makes it very clear this is a different sort of function > type. > The for modifier doesn't affect the function type, but I see where you're going with this. > Is there any similar way we could mark the type of any function type that > is to be used for control flow abstraction, not just for loops? This would > then avoid the need for the subtle semantic difference between expression > lambdas and statement lambdas, and avoid the downstream puzzlers comparing > the behavior of the two. > Puzzlers are only worrisome if they bite you, and I believe this one doesn't. The "for" modifier on the method doesn't affect the interpretation of the lambda or its contents... it is the appearance of the "for" on the invocation that changes the labels that are in scope when the lambda occurs. I would be very concerned about having the target type affect the meaning of the lambda body. I believe you still need both kinds of lambdas: you need expression lambdas for things like concise aggregate operations, and some people have insisted that you need statement lambdas where returning early is important for structuring the computation. So you're probably talking about a third lambda form. It is the lambda that needs another form, not the function type, even if you are saying that you like the restricted versus unrestricted function type distinction from BGGA, and want to bring that back into this revision of the spec. P.S. It wouldn't be quite so bad if the difference were the other way > around, with local return, no break/continue in expression lambdas, and > non-local return in statement lambdas, but it would still be even better if > we could make the difference more explicit, somehow. > I think the current spec is a worthwhile simplification versus BGGA, but I'd be happy to entertain further revisions. Maybe you like BGGA's lambda syntax for these "blocks" ? Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/bcb0255a/attachment-0001.html From neal at gafter.com Mon Dec 14 22:54:21 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 22:54:21 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> Message-ID: <15e8b9d20912142254l39980599wd1de69b251e2ad14@mail.gmail.com> On Mon, Dec 14, 2009 at 10:44 PM, Neal Gafter wrote: > I think the current spec is a worthwhile simplification versus BGGA, but > I'd be happy to entertain further revisions. Maybe you like BGGA's lambda > syntax for these "blocks" ? > Incidentally, if we do that then we don't need block expressions, and we can use a slightly different lambda conversion that allows boxing and unboxing when matching lambda parameters to the interface function (Josh Bloch expressed his preference for that in "Closures Controversy," slide 48). Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091214/36b5c7c9/attachment.html From peter.levart at marand.si Mon Dec 14 23:18:40 2009 From: peter.levart at marand.si (Peter Levart) Date: Tue, 15 Dec 2009 08:18:40 +0100 Subject: 0.6a, section "Closure Conversion" In-Reply-To: <15e8b9d20912142254l39980599wd1de69b251e2ad14@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <15e8b9d20912142254l39980599wd1de69b251e2ad14@mail.gmail.com> Message-ID: <200912150818.40260.peter.levart@marand.si> reads... "A lambda expression may be converted to any compatible interface type by the lambda conversion, which is a kind of widening reference conversion. There is a lambda conversion from a lambda expression to every interface type that has a single method m such that the lambda expression is compatible with m. A lambda expression is compatible with a method m iff all of the following hold: Either The lambda expression is an expression lambda, and there is an assignment conversion from the type of its result expression to the return type of m; or The lambda expression is a statement lambda, and either its body cannot complete normally *and* there is an assignment conversion from the type of the expression in each of its return statements to the return type of m; or all of its return statements yield no return value, and the method m has return type void or java.lang.Void ... " Shouldn't the bolded *and* really be *or* ? Peter -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/9eaffb33/attachment.html From neal at gafter.com Tue Dec 15 08:09:32 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 15 Dec 2009 08:09:32 -0800 Subject: 0.6a, section "Closure Conversion" In-Reply-To: <200912150818.40260.peter.levart@marand.si> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <15e8b9d20912142254l39980599wd1de69b251e2ad14@mail.gmail.com> <200912150818.40260.peter.levart@marand.si> Message-ID: <15e8b9d20912150809v42cbeea8ie55ebfbb1ea19064@mail.gmail.com> No, it should be "and". Think of it this way: if the body completes normally, the compiler inserts a "return;" statement at the end (without an expression). On Mon, Dec 14, 2009 at 11:18 PM, Peter Levart wrote: > reads... > > "A lambda expression may be converted to any compatible interface type by > the lambda conversion, which is a kind of widening reference conversion. > > There is a lambda conversion from a lambda expression to every interface > type that has a single method m such that the lambda expression is > compatible with m. A lambda expression is compatible with a method m iff > all of the following hold: > > - Either > - The lambda expression is an expression lambda, and there is an > assignment conversion from the type of its result expression to the return > type of m; or > - The lambda expression is a statement lambda, and either > - its body cannot complete normally *and* there is an assignment > conversion from the type of the expression in each of its return statements > to the return type of m; or > - all of its return statements yield no return value, and the method > m has return type void or java.lang.Void > - ... > > " > > Shouldn't the bolded *and* really be *or* ? > > Peter > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/e8cd78cc/attachment.html From Jonathan.Gibbons at Sun.COM Tue Dec 15 09:10:46 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Tue, 15 Dec 2009 09:10:46 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> Message-ID: <4B27C316.8020604@sun.com> Neal Gafter wrote: > On Mon, Dec 14, 2009 at 9:52 PM, Jonathan Gibbons > > wrote: > > There is still potential confusion for the programmer using lambda > expressions however. > > Someone reading 0.6a might reasonably infer that an expression > lambda could easily be converted to statement lambda by adding a > "return" and changes parens to curlies. > > > I think that issue is mainly academic. I'd be surprised to find > someone trying to use an expression lambda with a block expression > (i.e. statements in the parens). Given the existence of statement > lambdas, the code would be awkward for no apparent reason. The only > real reason to do so would be to be able to use the nonlocal transfers > in a context where you can't use the control invocation syntax (e.g. > there are two controlled blocks to pass to a method). If you try to > change a lambda from expression lambda to statement lambda, the > transfers become compilation errors (except for a return statement in > the unlikely event that the enclosing method and the lambda have the > same return type). > > Most people nowadays make such local transformations using IDEs, and > the IDE would presumably know how to do it correctly. > > If 0.6a were all there was, that would work. But in 0.6b, you've > added block expressions. They look great - I want to use them - > but they've broken that "obvious" rule relating expression lambdas > to statement lambdas. Suddenly, there is a substantial non-obvious > difference between expression lambdas and statement lambdas. > > > I think it's pretty obvious that "return" means something different. > That's the whole point of introducing statement lambdas. break and > continue just turn into compile-time errors. > > With the for loop invocation syntax, we get to add another > modifier to the signature, which makes it very clear this is a > different sort of function type. > > > The for modifier doesn't affect the function type, but I see where > you're going with this. > > > Is there any similar way we could mark the type of any function > type that is to be used for control flow abstraction, not just for > loops? This would then avoid the need for the subtle semantic > difference between expression lambdas and statement lambdas, and > avoid the downstream puzzlers comparing the behavior of the two. > > > Puzzlers are only worrisome if they bite you, and I believe this one > doesn't. > > The "for" modifier on the method doesn't affect the interpretation of > the lambda or its contents... it is the appearance of the "for" on the > invocation that changes the labels that are in scope when the lambda > occurs. I would be very concerned about having the target type affect > the meaning of the lambda body. > > I believe you still need both kinds of lambdas: you need expression > lambdas for things like concise aggregate operations, and some people > have insisted that you need statement lambdas where returning early is > important for structuring the computation. So you're probably talking > about a third lambda form. It is the lambda that needs another form, > not the function type, even if you are saying that you like the > restricted versus unrestricted function type distinction from BGGA, > and want to bring that back into this revision of the spec. > > P.S. It wouldn't be quite so bad if the difference were the other > way around, with local return, no break/continue in expression > lambdas, and non-local return in statement lambdas, but it would > still be even better if we could make the difference more > explicit, somehow. > > > I think the current spec is a worthwhile simplification versus BGGA, > but I'd be happy to entertain further revisions. Maybe you like > BGGA's lambda syntax for these "blocks" ? > > Cheers, > Neal > I don't think you need any new syntax for the invocation. If it looks like a lambda expression (as in Mark's proposal, or your 0.6a), it is a "standard" lambda expression, with local control flow (return is local, no break/continue). If it looks like control invocation syntax, it is an "extended" lambda expression, with non-local control flow (return is non-local, break/continue allowed depending on context.) The only thing I would suggest is a more explicit marker on the parameter type to indicate that an extended lambda expression is expected. -- Jon -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/683ec84b/attachment-0001.html From opinali at gmail.com Tue Dec 15 10:03:58 2009 From: opinali at gmail.com (Osvaldo Doederlein) Date: Tue, 15 Dec 2009 16:03:58 -0200 Subject: Closure implementation Message-ID: Hi, I was wondering about the implementation of closures (translation into Java bytecode), a topic that's not yet covered by any of the current proposals (CfJ 0.6a+b or the Strawman), although well illustrated by the BGGA prototype. It's perhaps early to worry about implementation, but the exception if some implementation requirement demand support from the language spec. I wish closures to be as lightweight as possible. This means: a) The classes that closures are translated to, should be as small and fast to load as possible. These classes could benefit from JSR-292's anonymous classes, so each synthetic closure class doesn't load unnecessary metadata. b) The compiler should be able to shortcut closure classes whenever possible. This is important for multiple use cases, from control structures (like in CfJ 0.6b) to Smalltalk-like extension methods for collections (select(), etc.). I'd expect a sufficiently smart compiler to translate the calls to such methods (and their literal-closure parameters) into fully inline code without any overhead of synthetic classes/methods. For control structures with non-local transfer, such optimization, when possible, would remove the bulky code and helper exceptions that we see in the BGGA prototype. c) For closures that cannot be optimized out and must be represented as runtime classes/objects, I'd expect a best-effort to optimize that representation. Remarkably, if the closure doesn't capture any state from the enclosing instance, I expect javac to generate a singleton object so there's no overhead to allocate a separate closure object at each execution. Item (b) is a hard call for source compilation because javac cannot inline methods generally, due to Java's compilation model. We could do this only for non-virtual calls to methods from the same class (like switch for enums does for ordinal numbers), but that would be too limited to be useful. On the other hand, such optimizations could be performed by the JIT compiler. This makes item (a) even more important, because all that class baggage would often be temporary: the VM loads and links it, runs it a while, and when the optimizer kicks in and gets rid of the class overhead, all that stuff can be unloaded and GC'd. Both (a) and (b) are only generally legal if the user code doesn't expect closures to be full-blown objects. CfJ already says "this [keyword] has the same meaning as it would where the lambda expression appears", so at least code inside the closure cannot easily manipulate the closure object. Closure conversion is also OK because the compiler wraps the closure code in a normal class implementing some interface, in this case there's no invoke() method. So the current proposal (and the BGGA prototype) already make no promises about the runtime nature of compiled closures. But in the general case, with closured-typed variables, we can reflect the closure class and its members, and lock on its monitor. We could make synchronized(someClosure) illegal at the source level, rejected by the verifier at the bytecode level, and (to deal with aliasing and casts) 'mark' all closure classes so their monitors will fail at runtime with a IllegalMonitorStateException. Item (c) is clear; the user just shouldn't expect the closure object to have separate identities for every usage, a rule we can impose without confusion as the closure syntax is free from the "new" operator. The demands of (b) can be addressed by inlining + Escape Analysis-driven scalar replacement + some specific optimizations for closures, e.g. to match the patterns of code generated for non-local returns in order to optimize that into straight local branches. Then we can expect optimally short and fast code to generated. EA and scalar replacement are advanced, bleeding edge optimizations in JDK7 (only C2), and extra optimizations for closures won't likely fit in the JDK7 schedule. But we can wait for the performance - right now I'm just worried to make sure that the language and bytecode won't make optimization any harder than necessary, ad maybe make it easy. The language should induce the user to not use closures as objects; (a) and (b) are important to enforce programming idioms and APIs that result in bytecode that's friendly to aggressive closure optimizations. And then, we could help the optimizer; for example, have bytecode attributes that mark closure bytecode semantically, so the JIT doesn't have to be tightly coupled to the patterns of code emitted by javac, remarkably for complex scenarios like non-local returns. Lightweight closures are very important for any usage that involves abundant, fine-grained closures. One of my old pet peeves with Java inner classes is that they're so bloated; closures (as powerful as BGGA or CfJ 0.6a+b) will be even more bloated. We could use this opportunity to provide lightweight closures/lambdas in the Java language. A sufficiently powerful and efficient bytecode/runtime representation (including helper classes in the core) would also be a great candidate for a universal representation of "full closures" for most language that support closures and target the JVM, so these languages have benefits in straight Java-interop and additional runtime footprint. A+ Osvaldo -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/9aad43a1/attachment.html From neal at gafter.com Tue Dec 15 11:20:59 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 15 Dec 2009 11:20:59 -0800 Subject: Closure implementation In-Reply-To: References: Message-ID: <15e8b9d20912151120p1da0f250ie61490cca2266631@mail.gmail.com> On Tue, Dec 15, 2009 at 10:03 AM, Osvaldo Doederlein wrote: > I was wondering about the implementation of closures (translation into Java > bytecode), a topic that's not yet covered by any of the current proposals > (CfJ 0.6a+b or the Strawman), although well illustrated by the BGGA > prototype. It's perhaps early to worry about implementation, but the > exception if some implementation requirement demand support from the > language spec. > The CFJ spec is clear that function types are interfaces. Other than that, the implementation of the interface generated by the compiler for a lambda is not constrained. It could even vary from compiler to compiler or from lambda to lambda. I wish closures to be as lightweight as possible. This means: > > a) The classes that closures are translated to, should be as small and fast > to load as possible. These classes could benefit from JSR-292's anonymous > classes, so each synthetic closure class doesn't load unnecessary metadata. > My understanding is that most of the cost comes from the methods, not the class. In any case, loading is a one-time thing. SE 7 will improve that with a new format for use instead of jar files. The 292 EDR doesn't describe anonymous classes. Do you mean method handles? It isn't clear that code generated to 292's method handles would actually be faster, but without a proposal on how to do it all we can do is guess. I strongly encourage you to suggest a form for the specification and implementation that would do that. b) The compiler should be able to shortcut closure classes whenever > possible. This is important for multiple use cases, from control structures > (like in CfJ 0.6b) to Smalltalk-like extension methods for collections > (select(), etc.). I'd expect a sufficiently smart compiler to translate the > calls to such methods (and their literal-closure parameters) into fully > inline code without any overhead of synthetic classes/methods. For control > structures with non-local transfer, such optimization, when possible, would > remove the bulky code and helper exceptions that we see in the BGGA > prototype. > Inlining is possible either in the VM, or by javac for methods specified as part of Java SE. The latter would be useful in conjunction with CFJ part b for things like ARM blocks, which could then be platform-provided APIs instead of a language extension. c) For closures that cannot be optimized out and must be represented as > runtime classes/objects, I'd expect a best-effort to optimize that > representation. Remarkably, if the closure doesn't capture any state from > the enclosing instance, I expect javac to generate a singleton object so > there's no overhead to allocate a separate closure object at each execution. > Agreed. That was why I took issue with Mark's assertion to the contrary (that each evaluation of a lambda would produce a distinct object). > Lightweight closures are very important for any usage that involves > abundant, fine-grained closures. One of my old pet peeves with Java inner > classes is that they're so bloated; closures (as powerful as BGGA or CfJ > 0.6a+b) will be even more bloated. I'm not sure in what sense you see those specifications as requiring weight in the implementation. Inner classes are certainly bloated in source, and have some start-up-time impact, but the objects themselves are small and fast to create and invoke. It isn't clear how to use jsr292's method handles to specify and implement a language construct compatible with the strawman, or what the overhead of such a solution would be. I think such a research project would be a very worthy undertaking, though I'm afraid I can't allocate my own time to the task. If it is to be done in time for SE 7 (specified, implemented, and integrated by the beginning of June), then whoever wants to make it happen (is that you, Osvaldo?) should probably start immediately. I will be happy to provide as much feeedback as my time allows. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/95084262/attachment.html From neal at gafter.com Tue Dec 15 11:27:18 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 15 Dec 2009 11:27:18 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <4B27C316.8020604@sun.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> Message-ID: <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> On Tue, Dec 15, 2009 at 9:10 AM, Jonathan Gibbons wrote: > I don't think you need any new syntax for the invocation. If it looks like > a lambda expression (as in Mark's proposal, or your 0.6a), it is a > "standard" lambda expression, with local control flow (return is local, no > break/continue). If it looks like control invocation syntax, it is an > "extended" lambda expression, with non-local control flow (return is > non-local, break/continue allowed depending on context.) The only thing I > would suggest is a more explicit marker on the parameter type to indicate > that an extended lambda expression is expected. > I think it would be a mistake to have no lambda form that is transparent. The control invocation shorthand is convenient for some, but not all useful control APIs. Your suggestion would only allow one transparent block per invocation, which must be the last parameter, which cannot have its own return value, and only in an invocation with no result value. Because the language features are not orthogonal in that formulation, those restrictions prevent expressing many kinds of useful control APIs and code refactorings. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/46366880/attachment.html From Jonathan.Gibbons at Sun.COM Tue Dec 15 14:09:03 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Tue, 15 Dec 2009 14:09:03 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> Message-ID: <4B2808FF.4020601@sun.com> Neal Gafter wrote: > On Tue, Dec 15, 2009 at 9:10 AM, Jonathan Gibbons > > wrote: > > I don't think you need any new syntax for the invocation. If it > looks like a lambda expression (as in Mark's proposal, or your > 0.6a), it is a "standard" lambda expression, with local control > flow (return is local, no break/continue). If it looks like > control invocation syntax, it is an "extended" lambda expression, > with non-local control flow (return is non-local, break/continue > allowed depending on context.) The only thing I would suggest is > a more explicit marker on the parameter type to indicate that an > extended lambda expression is expected. > > > I think it would be a mistake to have no lambda form that is > transparent. The control invocation shorthand is convenient for some, > but not all useful control APIs. Your suggestion would only allow one > transparent block per invocation, which must be the last parameter, > which cannot have its own return value, and only in an invocation with > no result value. Because the language features are not orthogonal in > that formulation, those restrictions prevent expressing many kinds of > useful control APIs and code refactorings. > > Cheers, > Neal > All fair enough, but wouldn't it be clearer to have some explicit syntax to indicate transparent rules, rather than (ab)using the difference between expression lambdas and statement lambdas. It seems to me that control flow abstraction is more likely to involve statement forms, and so anyone wanting to build control flow abstraction using explicit lambdas is more likely to try and use statement lambdas, and be surprised at the need to use the somewhat less obvious expression lambdas, with the somewhat curious "(Void) null" at the end. I guess I'm still trying to find some suggestions for explicit syntax to use, that is somewhat more obvious than round vs curly parens. Maybe some variant of "#" can be used, so that simple # means simple/standard lambda, and ## or #word or word# (for some word tbd) could mean a transparent lambda. -- Jon -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/57b836a5/attachment.html From neal at gafter.com Tue Dec 15 14:30:14 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 15 Dec 2009 14:30:14 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <4B2808FF.4020601@sun.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> Message-ID: <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> On Tue, Dec 15, 2009 at 2:09 PM, Jonathan Gibbons wrote: > All fair enough, but wouldn't it be clearer to have some explicit syntax > to indicate transparent rules, rather than (ab)using the difference between > expression lambdas and statement lambdas. > I don't think it is abuse. Expression lambdas are always transparent. Statement lambdas are not. They already have different syntax. It seems to me that control flow abstraction is more likely to involve > statement forms, and so anyone wanting to build control flow abstraction > using explicit lambdas is more likely to try and use statement lambdas, > I think this is confusing the API with the API client. The abstractions are written as methods and don't involve closures. They might not even use function types (they could use interfaces instead). The client, on the other hand, can use whichever form best expresses the purpose in the client. I guess I'm still trying to find some suggestions for explicit syntax to > use, that is somewhat more obvious than round vs curly parens. Maybe some > variant of "#" can be used, so that simple # means simple/standard lambda, > and ## or #word or word# (for some word tbd) could mean a transparent > lambda. > That was the restricted versus unrestricted function type distinction in BGGA. Perhaps you'd like both of the lambda forms in 0.6a to have returns treated locally, and add a third form that provides transparency? *#( FormalParameters ) => ( **Statementsopt Expression **) * As I pointed out previously, if we do that then we don't need block expressions, and we can use a slightly different lambda conversion for transparent lambdas that allows boxing and unboxing when matching lambda parameters to the interface function. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/2e6c5827/attachment.html From markmahieu at googlemail.com Tue Dec 15 14:33:14 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 15 Dec 2009 22:33:14 +0000 Subject: Closures for Java (0.6) specification part b In-Reply-To: <4B2808FF.4020601@sun.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> Message-ID: <229D056A-2E8E-4DB0-B8F8-AB0D8934D012@googlemail.com> On 15 Dec 2009, at 22:09, Jonathan Gibbons wrote: > Neal Gafter wrote: >> >> On Tue, Dec 15, 2009 at 9:10 AM, Jonathan Gibbons wrote: >> I don't think you need any new syntax for the invocation. If it looks like a lambda expression (as in Mark's proposal, or your 0.6a), it is a "standard" lambda expression, with local control flow (return is local, no break/continue). If it looks like control invocation syntax, it is an "extended" lambda expression, with non-local control flow (return is non-local, break/continue allowed depending on context.) The only thing I would suggest is a more explicit marker on the parameter type to indicate that an extended lambda expression is expected. >> >> I think it would be a mistake to have no lambda form that is transparent. The control invocation shorthand is convenient for some, but not all useful control APIs. Your suggestion would only allow one transparent block per invocation, which must be the last parameter, which cannot have its own return value, and only in an invocation with no result value. Because the language features are not orthogonal in that formulation, those restrictions prevent expressing many kinds of useful control APIs and code refactorings. >> >> Cheers, >> Neal >> > > All fair enough, but wouldn't it be clearer to have some explicit syntax to indicate transparent rules, rather than (ab)using the difference between expression lambdas and statement lambdas. > > It seems to me that control flow abstraction is more likely to involve statement forms, and so anyone wanting to build control flow abstraction using explicit lambdas is more likely to try and use statement lambdas, and be surprised at the need to use the somewhat less obvious expression lambdas, with the somewhat curious "(Void) null" at the end. I guess I'm still trying to find some suggestions for explicit syntax to use, that is somewhat more obvious than round vs curly parens. Maybe some variant of "#" can be used, so that simple # means simple/standard lambda, and ## or #word or word# (for some word tbd) could mean a transparent lambda. > > -- Jon I think the "(Void) null" is intended to be added by the compiler, and isn't something the programmer would see. But I agree people might think they should use 'statement lambdas' to build control 'statements'. It threw me when I first read it. This could well be just an case of finding alternative terminology though. Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/545939b8/attachment.html From Jonathan.Gibbons at Sun.COM Tue Dec 15 14:47:33 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Tue, 15 Dec 2009 14:47:33 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <229D056A-2E8E-4DB0-B8F8-AB0D8934D012@googlemail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <229D056A-2E8E-4DB0-B8F8-AB0D8934D012@googlemail.com> Message-ID: <4B281205.2000903@sun.com> Mark Mahieu wrote: > > On 15 Dec 2009, at 22:09, Jonathan Gibbons wrote: > >> Neal Gafter wrote: >>> On Tue, Dec 15, 2009 at 9:10 AM, Jonathan Gibbons >>> > wrote: >>> >>> I don't think you need any new syntax for the invocation. If it >>> looks like a lambda expression (as in Mark's proposal, or your >>> 0.6a), it is a "standard" lambda expression, with local control >>> flow (return is local, no break/continue). If it looks like >>> control invocation syntax, it is an "extended" lambda >>> expression, with non-local control flow (return is non-local, >>> break/continue allowed depending on context.) The only thing I >>> would suggest is a more explicit marker on the parameter type to >>> indicate that an extended lambda expression is expected. >>> >>> >>> I think it would be a mistake to have no lambda form that is >>> transparent. The control invocation shorthand is convenient for >>> some, but not all useful control APIs. Your suggestion would only >>> allow one transparent block per invocation, which must be the last >>> parameter, which cannot have its own return value, and only in an >>> invocation with no result value. Because the language features are >>> not orthogonal in that formulation, those restrictions prevent >>> expressing many kinds of useful control APIs and code refactorings. >>> >>> Cheers, >>> Neal >>> >> >> All fair enough, but wouldn't it be clearer to have some explicit >> syntax to indicate transparent rules, rather than (ab)using the >> difference between expression lambdas and statement lambdas. >> >> It seems to me that control flow abstraction is more likely to >> involve statement forms, and so anyone wanting to build control flow >> abstraction using explicit lambdas is more likely to try and use >> statement lambdas, and be surprised at the need to use the somewhat >> less obvious expression lambdas, with the somewhat curious "(Void) >> null" at the end. I guess I'm still trying to find some suggestions >> for explicit syntax to use, that is somewhat more obvious than round >> vs curly parens. Maybe some variant of "#" can be used, so that >> simple # means simple/standard lambda, and ## or #word or word# (for >> some word tbd) could mean a transparent lambda. >> >> -- Jon > > I think the "(Void) null" is intended to be added by the compiler, and > isn't something the programmer would see. > > But I agree people might think they should use 'statement lambdas' to > build control 'statements'. It threw me when I first read it. This > could well be just an case of finding alternative terminology though. > > Mark > Mark, "(Void) null" will be added by the compiler when the user is using control invocation syntax, but Neal was saying that won't be enough for all cases, implying that sometimes, the user will want to explicitly create their own lambdas with transparent control flow semantics. -- Jon -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/84be917f/attachment-0001.html From markmahieu at googlemail.com Tue Dec 15 15:04:07 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 15 Dec 2009 23:04:07 +0000 Subject: Closures for Java (0.6) specification part b In-Reply-To: <4B281205.2000903@sun.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <229D056A-2E8E-4DB0-B8F8-AB0D8934D012@googlemail.com> <4B281205.2000903@sun.com> Message-ID: <30C3CC13-D023-4CB0-B451-86E46B3B0A30@googlemail.com> On 15 Dec 2009, at 22:47, Jonathan Gibbons wrote: > > Mark, > > "(Void) null" will be added by the compiler when the user is using control invocation syntax, but Neal was saying that won't be enough for all cases, implying that sometimes, the user will want to explicitly create their own lambdas with transparent control flow semantics. > > -- Jon Oh I see - I'd missed that. Thanks, Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/e07becaf/attachment.html From markmahieu at googlemail.com Tue Dec 15 17:30:06 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 16 Dec 2009 01:30:06 +0000 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> Message-ID: <92CF177C-39B9-4BDD-85A5-B7A9899760F6@googlemail.com> On 15 Dec 2009, at 22:30, Neal Gafter wrote: > On Tue, Dec 15, 2009 at 2:09 PM, Jonathan Gibbons wrote: > I guess I'm still trying to find some suggestions for explicit syntax to use, that is somewhat more obvious than round vs curly parens. Maybe some variant of "#" can be used, so that simple # means simple/standard lambda, and ## or #word or word# (for some word tbd) could mean a transparent lambda. > > That was the restricted versus unrestricted function type distinction in BGGA. > > Perhaps you'd like both of the lambda forms in 0.6a to have returns treated locally, and add a third form that provides transparency? Bit of a long shot this, but is there any value in revisiting the old idea of using a different syntax for yielding a value from a lambda? I realise that's not without its own problems, but I wonder if it would permit an alternative option: keep expression and statement lambdas as the two forms, with expression lambdas remaining as defined in v0.6a. Then allow statement lambdas to contain 'return/break/continue' (nonlocal) *and* 'yield' (local) statements, and use statement lambdas with control abstraction APIs. It also implies that 'return' would retain the same meaning everywhere as it has now; it returns from the nearest enclosing method or constructor. Regards, Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091216/b23e1f03/attachment.html From Jonathan.Gibbons at Sun.COM Tue Dec 15 17:53:53 2009 From: Jonathan.Gibbons at Sun.COM (Jonathan Gibbons) Date: Tue, 15 Dec 2009 17:53:53 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B268FE2.9070908@sun.com> <15e8b9d20912141122i2dca6cbfp8a612dd6eecccc9@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> Message-ID: <4B283DB1.7020201@sun.com> Neal Gafter wrote: > On Tue, Dec 15, 2009 at 2:09 PM, Jonathan Gibbons > > wrote: > > All fair enough, but wouldn't it be clearer to have some explicit > syntax to indicate transparent rules, rather than (ab)using the > difference between expression lambdas and statement lambdas. > > > I don't think it is abuse. Expression lambdas are always > transparent. Statement lambdas are not. They already have different > syntax. I accept that they have different syntax. They also have different and obvious meanings depending on whether you want a lambda to be a simple expression or not. Overloading that relatively simple difference with transparency semantics is ingeniously clever in a way that is not as intuitively obvious and clever as the rest of the proposals. My $0.02. > > It seems to me that control flow abstraction is more likely to > involve statement forms, and so anyone wanting to build control > flow abstraction using explicit lambdas is more likely to try and > use statement lambdas, > > > I think this is confusing the API with the API client. The > abstractions are written as methods and don't involve closures. They > might not even use function types (they could use interfaces > instead). The client, on the other hand, can use whichever form best > expresses the purpose in the client. > > I guess I'm still trying to find some suggestions for explicit > syntax to use, that is somewhat more obvious than round vs curly > parens. Maybe some variant of "#" can be used, so that simple # > means simple/standard lambda, and ## or #word or word# (for some > word tbd) could mean a transparent lambda. > > > That was the restricted versus unrestricted function type distinction > in BGGA. > > Perhaps you'd like both of the lambda forms in 0.6a to have returns > treated locally, and add a third form that provides transparency? Yes, I'm suggesting both of the lambda forms in 0.6a to have returns treated locally, and then to have another way, either a third form or variants of the other forms, that provide transparency. I phrase it that way to try and emphasize that transparency seems to be an othogonal property to the difference between expression and statement lambdas. > > *#( FormalParameters ) => ( */Statementsopt Expression /*) > * > > As I pointed out previously, if we do that then we don't need block > expressions, and we can use a slightly different lambda conversion for > transparent lambdas that allows boxing and unboxing when matching > lambda parameters to the interface function. > > Cheers, > Neal > -- Jon -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/a0cb964d/attachment.html From pbenedict at apache.org Tue Dec 15 18:35:21 2009 From: pbenedict at apache.org (Paul Benedict) Date: Tue, 15 Dec 2009 20:35:21 -0600 Subject: Closures for Java (0.6) specification part b In-Reply-To: <92CF177C-39B9-4BDD-85A5-B7A9899760F6@googlemail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> <92CF177C-39B9-4BDD-85A5-B7A9899760F6@googlemail.com> Message-ID: Neal, Back to our previous discussion about prohibiting "Nothing" in the explicit throws clause of a method... Are there any closure or lambda features (like SAM) such a restriction would prevent? Something comes to mind about the duality of interfaces and closures, but I can't remember. Paul From neal at gafter.com Tue Dec 15 19:21:54 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 15 Dec 2009 19:21:54 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <92CF177C-39B9-4BDD-85A5-B7A9899760F6@googlemail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> <92CF177C-39B9-4BDD-85A5-B7A9899760F6@googlemail.com> Message-ID: <15e8b9d20912151921w330c4da2yf90e472bd6be5c1d@mail.gmail.com> On Tue, Dec 15, 2009 at 5:30 PM, Mark Mahieu wrote: > Bit of a long shot this, but is there any value in revisiting the old idea > of using a different syntax for yielding a value from a lambda? > That doesn't work out so well, for reasons discussed in gory detail here: < http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html >. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091215/bc966440/attachment.html From markmahieu at googlemail.com Tue Dec 15 22:59:01 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 16 Dec 2009 06:59:01 +0000 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912151921w330c4da2yf90e472bd6be5c1d@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B26963C.1060302@sun.com> <15e8b9d20912141150n2859eec3ua5e24ccc9272130b@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> <92CF177C-39B9-4BDD-85A5-B7A9899760F6@googlemail.com> <15e8b9d20912151921w330c4da2yf90e472bd6be5c1d@mail.gmail.com> Message-ID: <569ECB8E-DC8C-46D5-B9AE-3EF7E4FF66EC@googlemail.com> On 16 Dec 2009, at 03:21, Neal Gafter wrote: > On Tue, Dec 15, 2009 at 5:30 PM, Mark Mahieu wrote: > Bit of a long shot this, but is there any value in revisiting the old idea of using a different syntax for yielding a value from a lambda? > > That doesn't work out so well, for reasons discussed in gory detail here: . > > Cheers, > Neal > OK, although I must admit I'm struggling to see how it doesn't also apply to the use of 'return' in statement lambdas. Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091216/c68a930d/attachment-0001.html From diego at trusteagle.com Wed Dec 16 02:49:37 2009 From: diego at trusteagle.com (diego at trusteagle.com) Date: Wed, 16 Dec 2009 11:49:37 +0100 Subject: C++ functors and boost bind Message-ID: <200912161049.nBGAnbCM006078@vivaldi19.register.it> I may come from a different background, and also don't know the history and the full extent of the discussion (e.g. http://mail.openjdk.java.net/pipermail/closures-dev/2009-November/000267.html ), but I don't fully understand the syntax. I hope somebody will take my opinion into account still in this late stage. In C++ there is a nicer and more straight forward syntax for callbacks available with functors, an example is here: http://www.boost.org/doc/libs/1_41_0/libs/bind/bind.html#with_boost_function and you can also have playButton.onClick(param one,param two) with an implementation of void operator()(param one , param two) in the class button At that point you do have a full and extensible object interface and you don't need to have extra syntactic sugar. This same stuff is used for threads, sockets and ui callbacks. Cheers, D. From opinali at gmail.com Wed Dec 16 03:21:53 2009 From: opinali at gmail.com (Osvaldo Pinali Doederlein) Date: Wed, 16 Dec 2009 09:21:53 -0200 Subject: Closure implementation In-Reply-To: <15e8b9d20912151120p1da0f250ie61490cca2266631@mail.gmail.com> References: <15e8b9d20912151120p1da0f250ie61490cca2266631@mail.gmail.com> Message-ID: <4B28C2D1.9000900@gmail.com> Em 15/12/2009 17:20, Neal Gafter escreveu: > On Tue, Dec 15, 2009 at 10:03 AM, Osvaldo Doederlein > > wrote: > > I wish closures to be as lightweight as possible. This means: > a) The classes that closures are translated to, should be as small > and fast to load as possible. These classes could benefit from > JSR-292's anonymous classes, so each synthetic closure class > doesn't load unnecessary metadata. > > > My understanding is that most of the cost comes from the methods, not > the class. In any case, loading is a one-time thing. SE 7 will > improve that with a new format for use instead of jar files. > > The 292 EDR doesn't describe anonymous classes. Do you mean method > handles? It isn't clear that code generated to 292's method handles > would actually be faster, but without a proposal on how to do it all > we can do is guess. I strongly encourage you to suggest a form for > the specification and implementation that would do that. I really meant anonymous classes, I just assumed this would be in the scope of 292 because the original motivation was support for dynamic-typed languages (long time since I've checked the EDR, not following 292's list...). I realize that the space & loading costs are small; but then, the same holds for the helper classes generated by many dynamic langs. Of course the latter tend to produce a much higher number of such classes; but then, I (somewhat optimistically) envision a future with next-generation frameworks and DSLs abusing closures... if I ever have five closures per method and fifty per class, even if that's just in niche usages, any savings are significant, even with a better packaging format. > Lightweight closures are very important for any usage that > involves abundant, fine-grained closures. One of my old pet peeves > with Java inner classes is that they're so bloated; closures (as > powerful as BGGA or CfJ 0.6a+b) will be even more bloated. > > > I'm not sure in what sense you see those specifications as requiring > weight in the implementation. Inner classes are certainly bloated in > source, and have some start-up-time impact, but the objects themselves > are small and fast to create and invoke. I didn't see any impediment to the desired optimizations; I was just worried that it could exist somewhere I didn't notice. But your feedback clears these worries. > It isn't clear how to use jsr292's method handles to specify and > implement a language construct compatible with the strawman, or what > the overhead of such a solution would be. I think such a research > project would be a very worthy undertaking, though I'm afraid I can't > allocate my own time to the task. If it is to be done in time for SE > 7 (specified, implemented, and integrated by the beginning of June), > then whoever wants to make it happen (is that you, Osvaldo?) should > probably start immediately. I will be happy to provide as much > feeedback as my time allows. I didn't took the time to consider MethodHandles, that was not among my suggestions. MHIs and closures are both special interfaces, so that's likely another item in the wish-list of optimizations that I hope somebody, sometime, will do - I'm not able to provide a significant contribution for this, certainly not in the current JDK7 schedule. A+ Osvaldo -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091216/e25d5737/attachment.html From neal at gafter.com Wed Dec 16 07:56:14 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 16 Dec 2009 07:56:14 -0800 Subject: Closures for Java (0.6) specification part b In-Reply-To: <569ECB8E-DC8C-46D5-B9AE-3EF7E4FF66EC@googlemail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> <92CF177C-39B9-4BDD-85A5-B7A9899760F6@googlemail.com> <15e8b9d20912151921w330c4da2yf90e472bd6be5c1d@mail.gmail.com> <569ECB8E-DC8C-46D5-B9AE-3EF7E4FF66EC@googlemail.com> Message-ID: <15e8b9d20912160756v4e0c0e24p7948c103433d8203@mail.gmail.com> On Tue, Dec 15, 2009 at 10:59 PM, Mark Mahieu wrote: > > On 16 Dec 2009, at 03:21, Neal Gafter wrote: > > On Tue, Dec 15, 2009 at 5:30 PM, Mark Mahieu wrote: > >> Bit of a long shot this, but is there any value in revisiting the old idea >> of using a different syntax for yielding a value from a lambda? >> > > That doesn't work out so well, for reasons discussed in gory detail here: < > http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html > >. > > Cheers, > Neal > > > OK, although I must admit I'm struggling to see how it doesn't also apply > to the use of 'return' in statement lambdas. > It does, which is why another lambda form is required that is transparent. In the current spec that is the expression lambda. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091216/bae324f5/attachment.html From neal at gafter.com Wed Dec 16 08:01:23 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 16 Dec 2009 08:01:23 -0800 Subject: C++ functors and boost bind In-Reply-To: <200912161049.nBGAnbCM006078@vivaldi19.register.it> References: <200912161049.nBGAnbCM006078@vivaldi19.register.it> Message-ID: <15e8b9d20912160801y458dd8f8k7fef812957f5c08b@mail.gmail.com> D- In C++, functions and variables are in the same namespace. That is exactly one of the approaches we're investigating. We can't do it generally because that would break backward compatibility, but since function types are being newly added to the language, we might be able to say that variables of function type are in the method namespace in Java. Cheers, Neal On Wed, Dec 16, 2009 at 2:49 AM, wrote: > I may come from a different background, and also don't know the history and > the full extent of the discussion (e.g. > http://mail.openjdk.java.net/pipermail/closures-dev/2009-November/000267.html), but I don't fully understand the syntax. I hope somebody will take my > opinion into account still in this late stage. > > In C++ there is a nicer and more straight forward syntax for callbacks > available with functors, an example is here: > > > http://www.boost.org/doc/libs/1_41_0/libs/bind/bind.html#with_boost_function > > and you can also have > > playButton.onClick(param one,param two) > > with an implementation of > void operator()(param one , param two) > in the class button > > At that point you do have a full and extensible object interface and you > don't need to have extra syntactic sugar. > > This same stuff is used for threads, sockets and ui callbacks. > > Cheers, > D. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091216/25fb4b8c/attachment.html From markmahieu at googlemail.com Wed Dec 16 11:13:10 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 16 Dec 2009 19:13:10 +0000 Subject: Closures for Java (0.6) specification part b In-Reply-To: <15e8b9d20912160756v4e0c0e24p7948c103433d8203@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B27243A.7080007@sun.com> <15e8b9d20912142244k79b42ebeua6c72be06f475a27@mail.gmail.com> <4B27C316.8020604@sun.com> <15e8b9d20912151127y48a186aeheba7548e1dc661e2@mail.gmail.com> <4B2808FF.4020601@sun.com> <15e8b9d20912151430k78061bb2j1f2726032269ee65@mail.gmail.com> <92CF177C-39B9-4BDD-85A5-B7A9899760F6@googlemail.com> <15e8b9d20912151921w330c4da2yf90e472bd6be5c1d@mail.gmail.com> <569ECB8E-DC8C-46D5-B9AE-3EF7E4FF66EC@googlemail.com> <15e8b9d20912160756v4e0c0e24p7948c103433d8203@mail.gmail.com> Message-ID: <340F33F3-4ECC-4AAB-A3C9-919D13901DC1@googlemail.com> Aha, yes I'm with you now. I'd interpreted that quite differently. Thanks for the explanation. Mark On 16 Dec 2009, at 15:56, Neal Gafter wrote: > On Tue, Dec 15, 2009 at 10:59 PM, Mark Mahieu wrote: > > On 16 Dec 2009, at 03:21, Neal Gafter wrote: > >> On Tue, Dec 15, 2009 at 5:30 PM, Mark Mahieu wrote: >> Bit of a long shot this, but is there any value in revisiting the old idea of using a different syntax for yielding a value from a lambda? >> >> That doesn't work out so well, for reasons discussed in gory detail here: . >> >> Cheers, >> Neal >> > > OK, although I must admit I'm struggling to see how it doesn't also apply to the use of 'return' in statement lambdas. > > It does, which is why another lambda form is required that is transparent. In the current spec that is the expression lambda. > > Cheers, > Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091216/f14ffb35/attachment.html From peter.levart at marand.si Fri Dec 18 06:17:12 2009 From: peter.levart at marand.si (Peter Levart) Date: Fri, 18 Dec 2009 15:17:12 +0100 Subject: Control Invocation Syntax++ In-Reply-To: <340F33F3-4ECC-4AAB-A3C9-919D13901DC1@googlemail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <15e8b9d20912160756v4e0c0e24p7948c103433d8203@mail.gmail.com> <340F33F3-4ECC-4AAB-A3C9-919D13901DC1@googlemail.com> Message-ID: <200912181517.12856.peter.levart@marand.si> I have written a draft of a proposal that would fit the "Coin". I'm posting it here first to discuss if it has the potential to be a valuable addition to Java syntax also and in particular in relation to enabling "Control Invocation Syntax" as specified in CfJ 0.6b to be extended with additional ability. See the attached HTML... Peter -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091218/b4b2f73e/attachment.html From peter.levart at marand.si Fri Dec 18 06:29:26 2009 From: peter.levart at marand.si (Peter Levart) Date: Fri, 18 Dec 2009 15:29:26 +0100 Subject: Control Invocation Syntax++ In-Reply-To: <200912181517.12856.peter.levart@marand.si> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <340F33F3-4ECC-4AAB-A3C9-919D13901DC1@googlemail.com> <200912181517.12856.peter.levart@marand.si> Message-ID: <200912181529.26961.peter.levart@marand.si> Uf, I already see the problem. The extended "Control Invocation Syntax" is ambiguous. It does not differentiate between a single invocation of a split method and two invocations of normal methods. Peter On Friday 18 December 2009 15:17:12 Peter Levart wrote: > I have written a draft of a proposal that would fit the "Coin". I'm posting it here first to discuss if it has the potential to be a valuable addition to Java syntax also and in particular in relation to enabling "Control Invocation Syntax" as specified in CfJ 0.6b to be extended with additional ability. > > See the attached HTML... > > Peter > From schulz at the-loom.de Fri Dec 18 06:30:24 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Fri, 18 Dec 2009 15:30:24 +0100 Subject: Control Invocation Syntax++ In-Reply-To: <200912181517.12856.peter.levart@marand.si> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <15e8b9d20912160756v4e0c0e24p7948c103433d8203@mail.gmail.com> <340F33F3-4ECC-4AAB-A3C9-919D13901DC1@googlemail.com> <200912181517.12856.peter.levart@marand.si> Message-ID: <4B2B9200.5020906@the-loom.de> Peter, Coin will not accept new proposals, as Joe lately said again. But you might be interested in a little blog post of mine from some years ago: http://jroller.com/jadda/entry/multipiece_method_names Cheers, Stefan Peter Levart: > I have written a draft of a proposal that would fit the "Coin". I'm > posting it here first to discuss if it has the potential to be a > valuable addition to Java syntax also and in particular in relation > to enabling "Control Invocation Syntax" as specified in CfJ 0.6b to > be extended with additional ability. > > See the attached HTML... > > Peter From neal at gafter.com Fri Dec 18 06:45:15 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 18 Dec 2009 06:45:15 -0800 Subject: Control Invocation Syntax++ In-Reply-To: <4B2B9200.5020906@the-loom.de> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <15e8b9d20912160756v4e0c0e24p7948c103433d8203@mail.gmail.com> <340F33F3-4ECC-4AAB-A3C9-919D13901DC1@googlemail.com> <200912181517.12856.peter.levart@marand.si> <4B2B9200.5020906@the-loom.de> Message-ID: <15e8b9d20912180645v5c4ebd8dv527680a0e78c7e5c@mail.gmail.com> On Fri, Dec 18, 2009 at 6:30 AM, Stefan Schulz wrote: > Coin will not accept new proposals, as Joe lately said again. > But you might be interested in a little blog post of mine from some years > ago: > http://jroller.com/jadda/entry/multipiece_method_names > I'll second that with my own ancient historical post: < http://gafter.blogspot.com/2007/01/methodnamesinpieces.html>. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091218/8bf1507e/attachment.html From peter.levart at marand.si Fri Dec 18 07:01:40 2009 From: peter.levart at marand.si (Peter Levart) Date: Fri, 18 Dec 2009 16:01:40 +0100 Subject: Control Invocation Syntax++ In-Reply-To: <15e8b9d20912180645v5c4ebd8dv527680a0e78c7e5c@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B2B9200.5020906@the-loom.de> <15e8b9d20912180645v5c4ebd8dv527680a0e78c7e5c@mail.gmail.com> Message-ID: <200912181601.40807.peter.levart@marand.si> It's interesting to see how same ideas are re-instantiated again and again. I, for example, was inspired by Neal's comments that "Control Invocation Syntax" in 0.6b is not enough for all problems and the fact that I programmed in Objective-C a long ago... Peter P.S. But I didn't notice the problem about ambiguity at first. This is a no-go without complicating method resolution any further. On Friday 18 December 2009 15:45:15 Neal Gafter wrote: > On Fri, Dec 18, 2009 at 6:30 AM, Stefan Schulz wrote: > > > Coin will not accept new proposals, as Joe lately said again. > > But you might be interested in a little blog post of mine from some years > > ago: > > http://jroller.com/jadda/entry/multipiece_method_names > > > > I'll second that with my own ancient historical post: < > http://gafter.blogspot.com/2007/01/methodnamesinpieces.html>. > From markmahieu at googlemail.com Fri Dec 18 07:05:49 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Fri, 18 Dec 2009 15:05:49 +0000 Subject: Control Invocation Syntax++ In-Reply-To: <4B2B9200.5020906@the-loom.de> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <15e8b9d20912160756v4e0c0e24p7948c103433d8203@mail.gmail.com> <340F33F3-4ECC-4AAB-A3C9-919D13901DC1@googlemail.com> <200912181517.12856.peter.levart@marand.si> <4B2B9200.5020906@the-loom.de> Message-ID: <55634792-98E1-4624-B25C-5E7BFECCCEA9@googlemail.com> It's a fascinating area to investigate. I once built a 'foreach...where...orderBy' construct using BGGA: List words = ... ExecutorService executor = ... for each (String word : words) where (word.contains("e") || word.contains("o")) orderBy (word.toLowerCase()) selectAsync (Integer calculatedValue : slowCalculation(word), executor) { // ... } Very awkward implementation, and a bunch of other limitations, but interesting to experiment with. Mark On 18 Dec 2009, at 14:30, Stefan Schulz wrote: > Peter, > > Coin will not accept new proposals, as Joe lately said again. > But you might be interested in a little blog post of mine from some years ago: > http://jroller.com/jadda/entry/multipiece_method_names > > Cheers, > Stefan > > Peter Levart: >> I have written a draft of a proposal that would fit the "Coin". I'm >> posting it here first to discuss if it has the potential to be a >> valuable addition to Java syntax also and in particular in relation >> to enabling "Control Invocation Syntax" as specified in CfJ 0.6b to >> be extended with additional ability. >> >> See the attached HTML... >> >> Peter From peter.levart at marand.si Tue Dec 22 07:54:57 2009 From: peter.levart at marand.si (Peter Levart) Date: Tue, 22 Dec 2009 16:54:57 +0100 Subject: Control Invocation Syntax++ In-Reply-To: <15e8b9d20912180645v5c4ebd8dv527680a0e78c7e5c@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B2B9200.5020906@the-loom.de> <15e8b9d20912180645v5c4ebd8dv527680a0e78c7e5c@mail.gmail.com> Message-ID: <200912221654.57061.peter.levart@marand.si> Hello Neal, I'm trying to understand the Control Invocation Syntax in CfJ 0.6b (or 0.7b) where you write (I'm using [] notation here for 0..1 occurences): "A new invocation statement syntax is added to make closures convenient for control abstraction: ControlInvocationStatement: [for] Primary ( FormalParameters [: ExpressionList] ) Statement [for] Primary ( [ExpressionList] ) Statement This syntax is a shorthand for the following statement: Primary ( [ExpressionList,] # ( [FormalParameters] ) ( Statement (Void)null ) ); " I assume you are refering to grammar rules specified in the content of JLS 3rd edition - not in chapter 18.1 where the whole grammar is specified on one page and has different production rules. In the "presentation friendly" grammar the "Primary" means a primary expression. JLS (15.2) describes one possible primary expression called "MethodInvocation": MethodInvocation: MethodName ( [ArgumentList] ) Primary [. NonWildTypeArguments] Identifier ( [ArgumentList] ) super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ClassName . super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) TypeName . NonWildTypeArguments Identifier ( [ArgumentList] ) In analogy with the above (by the way, I think there's an error in MethodInvocation's last production rule - "NonWildTypeArguments" should be optional there too) I assume your control invocation statement syntax was meant to be more or less like this: ControlInvocationStatement: [for] MethodName ( FormalParameters [: ArgumentList] ) Statement [for] Primary [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) Statement [for] super [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) Statement [for] ClassName . super [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) Statement [for] TypeName [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) Statement [for] MethodName ( [ArgumentList] ) Statement [for] Primary [. NonWildTypeArguments] Identifier ( [ArgumentList] ) Statement [for] super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) Statement [for] ClassName . super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) Statement [for] TypeName [. NonWildTypeArguments] Identifier ( [ArgumentList] ) Statement And that syntax being a shorthand for one of the following: MethodName ( [ArgumentList,] # ( [FormalParameters] ) ( Statement (Void)null ) ); Primary [. NonWildTypeArguments] Identifier ( [ArgumentList,] # ( [FormalParameters] ) ( Statement (Void)null ) ); super [. NonWildTypeArguments] Identifier ( [ArgumentList,] # ( [FormalParameters] ) ( Statement (Void)null ) ); ClassName . super [. NonWildTypeArguments] ( [ArgumentList,] # ( [FormalParameters] ) ( Statement (Void)null ) ); TypeName [. NonWildTypeArguments] Identifier ( [ArgumentList,] # ( [FormalParameters] ) ( Statement (Void)null ) ); I'm sure you meant that but it was to verbose to put into the spec. document. ... Ok, now to something different. I was thinking about an alternative syntax. First, the syntax of parenthesized expression migh allow the expression in it to be optional: ParExpression: ( [BlockStatements] Expression ) ( BlockStatements ) Meaning of Expressions: The specification for a parenthesized expression is modified to describe its new execution semantics: The block statements (if any) are executed in sequence, from left to right. The result of the block expression is: * The type Nothing if there are block statements and the last block statement cannot complete normally; otherwise * The value and type of the final expression if there is one; otherwise * The type Void Definite Assignment: The definite assignment rules for this construct are almost identical to that for the block statement. The definite assignment state before the first block statement is the definite assignment state before the parenthesized expression. The definite assignment state before the subexpression (if there is one) is the definite assignment state following the last block statement. The definite assignment state after the parenthesized expression is the definite assignment state after the contained expression if there is one or the definite assignment state following the last block statement if there is no contained expression. Next, instead of "ControlInvocationStatement" I would propose "ControlInvocation" expression (being one of possible "Primary" expressions): ControlInvocation: [for] MethodName ( FormalParameters [: ArgumentList] ) ParExpression [for] Primary [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression [for] super [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression [for] ClassName . super [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression [for] TypeName [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression [for] MethodName ( [ArgumentList] ) ParExpression [for] Primary [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression [for] super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression [for] ClassName . super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression [for] TypeName [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression Which would be a shortcut for one of the following: MethodName ( [ArgumentList,] # ( [FormalParameters] ) ParExpression ) Primary [. NonWildTypeArguments] Identifier ( [ArgumentList,] # ( [FormalParameters] ) ParExpression ) super [. NonWildTypeArguments] Identifier ( [ArgumentList,] # ( [FormalParameters] ) ParExpression ) ClassName . super [. NonWildTypeArguments] ( [ArgumentList,] # ( [FormalParameters] ) ParExpression ) TypeName [. NonWildTypeArguments] Identifier ( [ArgumentList,] # ( [FormalParameters] ) ParExpression ) Your "withLock" example: withLock(lock) { System.out.println("hello"); } Would then read like: withLock(lock) ( System.out.println("hello"); ); And would be a shorthand for: withLock(lock, #() ( System.out.println("hello"); )); This would enable other possiblilities like this (using chained methods): List someList = ...; String result = Parallel.list(someList) .filter(String s)(!s.isEmpty()) .map(String s)(s.toLowerCase()) .reduce(String s1, String s2)(s1 + ":" + s2) .execute(executor); Or for example this (if the syntax is ever extended to support method names in pieces: http://gafter.blogspot.com/2007/01/methodnamesinpieces.html): StringBuilder sb = new StringBuilder("["); for each(String s : someCollection) ( sb.append(s); ) inBetween ( sb.append(", "); ); sb.append("]"); ...and this syntax would not be ambigous any more. Maybe even Mark would be more satisfied with this syntax since it is using "(" and ")" which is consistent with syntax of "expression lambdas using paranthesized expression" that are transparent instead of "{" and "}" which might be associated with "statement lambdas" which are not transparent. What do you think? Peter From bruce.chapman at nec.co.nz Tue Dec 22 13:10:48 2009 From: bruce.chapman at nec.co.nz (Bruce Chapman) Date: Wed, 23 Dec 2009 10:10:48 +1300 Subject: Control Invocation Syntax++ In-Reply-To: <200912221654.57061.peter.levart@marand.si> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B2B9200.5020906@the-loom.de> <15e8b9d20912180645v5c4ebd8dv527680a0e78c7e5c@mail.gmail.com> <200912221654.57061.peter.levart@marand.si> Message-ID: <001b01ca834b$3c301390$d2291eac@necxp210> Peter Levart said: First, the syntax of parenthesized expression migh allow the expression in it to be optional: ParExpression: ( [BlockStatements] Expression ) ( BlockStatements ) I respond: But a ParExpression is a kind of expression, so in your second form, what would be the value and type of that expression since statements don't have value or type? I guess there is no answer which is why the expression is mandatory. Bruce Chapman From peter.levart at gmail.com Tue Dec 22 14:11:04 2009 From: peter.levart at gmail.com (Peter Levart) Date: Tue, 22 Dec 2009 23:11:04 +0100 Subject: Control Invocation Syntax++ In-Reply-To: <001b01ca834b$3c301390$d2291eac@necxp210> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <200912221654.57061.peter.levart@marand.si> <001b01ca834b$3c301390$d2291eac@necxp210> Message-ID: <200912222311.04872.peter.levart@marand.si> On Tuesday 22 December 2009 22:10:48 Bruce Chapman wrote: > Peter Levart said: > > First, the syntax of parenthesized expression migh allow the expression in > it to be optional: > > ParExpression: > ( [BlockStatements] Expression ) > ( BlockStatements ) > > > I respond: > > But a ParExpression is a kind of expression, so in your second form, what > would be the value and type of that expression since statements don't have > value or type? I guess there is no answer which is why the expression is > mandatory. > I meant value "null", type "Void". Just like the following expression: (Void)null; That is the expression Neal is proposing to be automatically inserted after block statements in 0.6b variant of Control Invocation Statement. Peter From peter.levart at gmail.com Tue Dec 22 14:36:39 2009 From: peter.levart at gmail.com (Peter Levart) Date: Tue, 22 Dec 2009 23:36:39 +0100 Subject: Control Invocation Syntax++ In-Reply-To: <200912222311.04872.peter.levart@marand.si> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <001b01ca834b$3c301390$d2291eac@necxp210> <200912222311.04872.peter.levart@marand.si> Message-ID: <200912222336.39148.peter.levart@gmail.com> On Tuesday 22 December 2009 23:11:04 Peter Levart wrote: > I meant value "null", type "Void". Just like the following expression: > (Void)null; > Correction: (Void)null Without the terminating ';' of course. Peter From bruce.chapman at nec.co.nz Tue Dec 22 16:00:34 2009 From: bruce.chapman at nec.co.nz (Bruce Chapman) Date: Wed, 23 Dec 2009 13:00:34 +1300 Subject: Control Invocation Syntax++ In-Reply-To: <200912222311.04872.peter.levart@marand.si> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <200912221654.57061.peter.levart@marand.si> <001b01ca834b$3c301390$d2291eac@necxp210> <200912222311.04872.peter.levart@marand.si> Message-ID: <001f01ca8362$f30b2cf0$d2291eac@necxp210> OK, got it. I remember Neal once blogged about BGGA and addressed why the control invocation was a statement not an expression. I am trying to find a link to that now. OK, got it. Not blogged but in BGGA v0.5 Rationale: This is not an expression form for a very good reason: it looks like a statement, and we expect it to be used most commonly as a statement for the purpose of writing APIs that abstract patterns of control. If it were an expression form, an invocation like this would require a trailing semicolon after the close curly brace of a controlled block. Forgetting the semicolon would probably be a common source of error. The syntax is convenient for both synchronous (e.g. see withLock) and asynchronous (e.g. see Executor.execute) use cases. I think the argument there about needing a terminal ';' when used as a statement makes sense, however I can also see how making it an expression enables the benefit of composition through method chaining. An obvious solution is to allow both statement form (using {}) AND expression form (using ()) but is that overkill? There is at least one other way to achieve composition and which does not require Control invocation to be an expression - maybe that is sufficient for the (presumably) rare cases where an API designer wants to allow composition of control invocation syntax as the best way for API users to interact with some part of the API. Bruce -----Original Message----- From: Peter Levart [mailto:peter.levart at gmail.com] Sent: Wednesday, 23 December 2009 11:11 a.m. To: Bruce Chapman; closures-dev at openjdk.java.net Subject: Re: Control Invocation Syntax++ On Tuesday 22 December 2009 22:10:48 Bruce Chapman wrote: > Peter Levart said: > > First, the syntax of parenthesized expression migh allow the expression in > it to be optional: > > ParExpression: > ( [BlockStatements] Expression ) > ( BlockStatements ) > > > I respond: > > But a ParExpression is a kind of expression, so in your second form, what > would be the value and type of that expression since statements don't have > value or type? I guess there is no answer which is why the expression is > mandatory. > I meant value "null", type "Void". Just like the following expression: (Void)null; That is the expression Neal is proposing to be automatically inserted after block statements in 0.6b variant of Control Invocation Statement. Peter From neal at gafter.com Tue Dec 22 22:26:28 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 22 Dec 2009 22:26:28 -0800 Subject: Control Invocation Syntax++ In-Reply-To: <200912221654.57061.peter.levart@marand.si> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <4B2B9200.5020906@the-loom.de> <15e8b9d20912180645v5c4ebd8dv527680a0e78c7e5c@mail.gmail.com> <200912221654.57061.peter.levart@marand.si> Message-ID: <15e8b9d20912222226q293c8aeex3144322d5a04d19@mail.gmail.com> On Tue, Dec 22, 2009 at 7:54 AM, Peter Levart wrote: > I'm sure you meant that but it was to verbose to put into the spec. document. I can easily believe you are correct, but I haven't reviewed your comment in detail. > Ok, now to something different. I was thinking about an alternative syntax. > > First, the syntax of parenthesized expression migh allow the expression in it to be optional: > > ? ?ParExpression: > ? ? ? ?( [BlockStatements] Expression ) > ? ? ? ?( BlockStatements ) Yes, that is different. Why would you make that suggestion? > Next, instead of "ControlInvocationStatement" I would propose "ControlInvocation" expression (being one of possible "Primary" expressions): > > ? ?ControlInvocation: > ? ? ? ?[for] MethodName ( FormalParameters [: ArgumentList] ) ParExpression > ? ? ? ?[for] Primary [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression > ? ? ? ?[for] super [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression > ? ? ? ?[for] ClassName . super [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression > ? ? ? ?[for] TypeName [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression > ? ? ? ?[for] MethodName ( [ArgumentList] ) ParExpression > ? ? ? ?[for] Primary [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression > ? ? ? ?[for] super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression > ? ? ? ?[for] ClassName . super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression > ? ? ? ?[for] TypeName [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression These are all ambiguous with the idea of being able to invoke an expression of function type without the ".invoke". Cheers, Neal From peter.levart at marand.si Wed Dec 23 00:00:13 2009 From: peter.levart at marand.si (Peter Levart) Date: Wed, 23 Dec 2009 09:00:13 +0100 Subject: Control Invocation Syntax++ In-Reply-To: <15e8b9d20912222226q293c8aeex3144322d5a04d19@mail.gmail.com> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <200912221654.57061.peter.levart@marand.si> <15e8b9d20912222226q293c8aeex3144322d5a04d19@mail.gmail.com> Message-ID: <200912230900.13294.peter.levart@marand.si> On Wednesday 23 December 2009 07:26:28 Neal Gafter wrote: > > Next, instead of "ControlInvocationStatement" I would propose "ControlInvocation" expression (being one of possible "Primary" expressions): > > > > ControlInvocation: > > [for] MethodName ( FormalParameters [: ArgumentList] ) ParExpression > > [for] Primary [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression > > [for] super [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression > > [for] ClassName . super [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression > > [for] TypeName [. NonWildTypeArguments] Identifier ( FormalParameters [: ArgumentList] ) ParExpression > > [for] MethodName ( [ArgumentList] ) ParExpression > > [for] Primary [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression > > [for] super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression > > [for] ClassName . super [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression > > [for] TypeName [. NonWildTypeArguments] Identifier ( [ArgumentList] ) ParExpression > > These are all ambiguous with the idea of being able to invoke an > expression of function type without the ".invoke". > Oh yes, I see. As much as ParExpression and ArgumentList are ambiguous. It seams we're out of good unambiguous syntax variations. But what about the idea of ParExpression alone: ParExpression: ( [BlockStatements] Expression ) ( BlockStatements ) It would simplify expression lambdas when they are not used as functions but only as transparent closures. That's something BGGA has and although it is perceived as "strange" syntax, I like it. Peter From neal at gafter.com Wed Dec 23 08:17:57 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 23 Dec 2009 08:17:57 -0800 Subject: Control Invocation Syntax++ In-Reply-To: <200912230900.13294.peter.levart@marand.si> References: <15e8b9d20912131634r1280e374x649d474dc725d319@mail.gmail.com> <200912221654.57061.peter.levart@marand.si> <15e8b9d20912222226q293c8aeex3144322d5a04d19@mail.gmail.com> <200912230900.13294.peter.levart@marand.si> Message-ID: <15e8b9d20912230817w7a4ba353oce3a1993c791ef20@mail.gmail.com> On Wed, Dec 23, 2009 at 12:00 AM, Peter Levart wrote: > But what about the idea of ParExpression alone: > > ? ParExpression: > ? ? ? ( [BlockStatements] Expression ) > ? ? ? ( BlockStatements ) > > It would simplify expression lambdas when they are not used as functions but only as transparent closures. That's something BGGA has and although it is perceived as "strange" syntax, I like it. There is a tradeoff here. On the one hand, you'd like it to be as simple as possible to write 'transparent' closures. The situation which you're simplifying is the one in which you need statements in the closure, need transparent control flow to the enclosing scope, don't have a result from the closure, and can't use the control invocation syntax. I think that is an uncommon situation, but I do believe it is important to support it. That is possible in 0.6b, but it requires a bit of boilerplate, which you're proposing to eliminate. On the other hand, you've reintroduced from BGGA the possibility that something as small as a missing (or added) semicolon can change the semantics of the code. I felt that this was enough of a downside to write the specification as I did. Cheers, Neal From neal at gafter.com Mon Dec 28 08:38:55 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 28 Dec 2009 08:38:55 -0800 Subject: transparent lambda In-Reply-To: References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> Message-ID: <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> [conversation moved from lambda-dev to closures-dev] On Mon, Dec 28, 2009 at 3:38 AM, Peter Levart wrote: > > Worse, your proposal breaks transparency. That is explained in detail in < >> http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html>, >> ... > > > Being able to return early from a lambda has inherent conflicts with lambda > transparency since it targets lambda's bounds - lambda becomes visible. In > spite of that, I think (but I may be persuaded to think otherwise) that it > is possible to combine transparency to other constructs and "additional > features" like early return (that break Tennent's principle) in one form, > provided that those additional features use unique statement forms - > re-usage of same statements (return, break, continue) among different kinds > of constructs is not allowed. > Yes, it is possible, by using a label. It is just a bit awkward. More on that later. That single lambda form is mostly transparent. Non-transparency is obvious > only when you nest same kind of constructs - features that target those > kinds then select the innermost one. That's true with loops and methods in > Java today - they are not transparent to their own kind. > The purpose of your proposal was to get transparency. If you don't mind being non-transparent, then you need not have proposed anything at all. Loops are not an abstraction mechanism (more on that later), and methods don't nest, so the reasons don't apply to them in the same way. I have read your blog (above link) where you say: "while *existing* code > doesn't use this new statement form, once we introduce it into the language > we should expect people to start using it in *new* code. And once they do, > any code that includes this statement cannot be wrapped in a closure without > changing its meaning. Once we identified the bad smell this way, it wasn't > hard to come up with realistic examples where it gets in the way of using > the language." > > What realistic example did you have in mind? Does it get in the way of > using the language any more than when you try to use nested loops with > unlabeled break/continue? > I don't remember exactly what the examples were, but I hesitate to bring up particular examples because I'm afraid they'd be used to drive the design (see < http://gafter.blogspot.com/2006/09/failure-of-imagination-in-language_17.html>). The basic property you want of an abstraction mechanism is that the combination of abstraction (building a lambda) and deabstracting (invoking it) doesn't change the meaning of what it abstracts. This is very useful for refactoring code to remove redundancy. Any nontransparency interferes with that kind of refactoring. Loops are not an abstraction mechanism. Loops are supposed to change the execution of the code within them, by repeating their execution. Nevertheless, there are two syntactic forms of loops: transparent loops and non-transparent loops, just as we've proposed two forms for lambda expressions. The transparent ones are the ones that use a label. You can nest these any way you want, and as long as you keep your labels unique and use labelled break and continue, nesting does not change the meaning of the statements that are placed within a loop. Your proposal, while purporting to introduce transparency, actually remove the transparent (expression lambda) form by making it non-transparent. One approach that could be used to have lambdas that are both transparent and allow early return would be to introduce some kind of labelling mechanism. The labelling mechanism could either be part of the lambda expression syntax or the block expression syntax. Then, introduce a labelled return statement, possibly something like this: *return label : expression;* I haven't found a way to do this that feels right, but it is an approach worth exploring. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091228/8d3deffd/attachment.html From markmahieu at googlemail.com Mon Dec 28 09:12:02 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Mon, 28 Dec 2009 17:12:02 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> Message-ID: <0C002F15-7F13-4AAE-A365-A184700A8298@googlemail.com> On 28 Dec 2009, at 16:38, Neal Gafter wrote: > > One approach that could be used to have lambdas that are both transparent and allow early return would be to introduce some kind of labelling mechanism. The labelling mechanism could either be part of the lambda expression syntax or the block expression syntax. Then, introduce a labelled return statement, possibly something like this: > > return label : expression; > > I haven't found a way to do this that feels right, but it is an approach worth exploring. > > Cheers, > Neal > Coincidentally I've just been pondering the same thing. I still think it's easier if there's a syntactic distinction between 'return'-ing from the enclosing method, and 'yield'-ing from the lambda; 'return' retains the same meaning it always had, and the difficulty is confined to the conceptual 'yield' statement which must cater for the lambda-specific complication of nested lambda expressions. Making labelling a requirement to use 'yield' certainly seems too awkward, but perhaps defining a non-labelled yield as transferring control from the 'outermost' lambda (ie. transparent semantics for yield by default as well) would combine the desired preservation of semantics with 'nice' syntactic for the '9 out of 10' cases (because it's probably not even nested). Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091228/f1e6cbe0/attachment.html From neal at gafter.com Mon Dec 28 09:18:48 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 28 Dec 2009 09:18:48 -0800 Subject: transparent lambda In-Reply-To: <0C002F15-7F13-4AAE-A365-A184700A8298@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <0C002F15-7F13-4AAE-A365-A184700A8298@googlemail.com> Message-ID: <15e8b9d20912280918x17156e6rf6cbcd1d2f7c90e4@mail.gmail.com> On Mon, Dec 28, 2009 at 9:12 AM, Mark Mahieu wrote: > Making labelling a requirement to use 'yield' certainly seems too awkward, > but perhaps defining a non-labelled yield as transferring control from the > 'outermost' lambda (ie. transparent semantics for yield by default as well) > would combine the desired preservation of semantics with 'nice' syntactic > for the '9 out of 10' cases (because it's probably not even nested). > I can't tell if you're joking or not. That would mean that apparently simple code such as this *#(){ yield 3; }* could not be understood without looking at all of the enclosing context. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091228/17ffb825/attachment.html From markmahieu at googlemail.com Mon Dec 28 10:05:35 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Mon, 28 Dec 2009 18:05:35 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912280918x17156e6rf6cbcd1d2f7c90e4@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <0C002F15-7F13-4AAE-A365-A184700A8298@googlemail.com> <15e8b9d20912280918x17156e6rf6cbcd1d2f7c90e4@mail.gmail.com> Message-ID: <5EEAEC0A-D96F-4043-A422-BC03027CEB09@googlemail.com> On 28 Dec 2009, at 17:18, Neal Gafter wrote: > On Mon, Dec 28, 2009 at 9:12 AM, Mark Mahieu wrote: > Making labelling a requirement to use 'yield' certainly seems too awkward, but perhaps defining a non-labelled yield as transferring control from the 'outermost' lambda (ie. transparent semantics for yield by default as well) would combine the desired preservation of semantics with 'nice' syntactic for the '9 out of 10' cases (because it's probably not even nested). > > I can't tell if you're joking or not. That would mean that apparently simple code such as this > > #(){ yield 3; } > > could not be understood without looking at all of the enclosing context. > > Cheers, > Neal > No I'm not joking, but my wording could probably have been clearer; I'm suggesting that the non-labelled form would *only* be valid in the 'outermost' lambda; in a nested lambda the labelled form would be required. It's a bit of a cheat regarding Tennent's C.P, in that your example could not be refactored to equivalent code simply by wrapping the 'yield' in a (nested) lambda and invoking it - a label would have to be added to make it valid. Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091228/c2752175/attachment.html From neal at gafter.com Mon Dec 28 10:18:31 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 28 Dec 2009 10:18:31 -0800 Subject: transparent lambda In-Reply-To: <5EEAEC0A-D96F-4043-A422-BC03027CEB09@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <0C002F15-7F13-4AAE-A365-A184700A8298@googlemail.com> <15e8b9d20912280918x17156e6rf6cbcd1d2f7c90e4@mail.gmail.com> <5EEAEC0A-D96F-4043-A422-BC03027CEB09@googlemail.com> Message-ID: <15e8b9d20912281018p7363c7aeyf0dfe0779c3d1ba6@mail.gmail.com> On Mon, Dec 28, 2009 at 10:05 AM, Mark Mahieu wrote: > It's a bit of a cheat regarding Tennent's C.P, in that your example could > not be refactored to equivalent code simply by wrapping the 'yield' in a > (nested) lambda and invoking it - a label would have to be added to make it > valid. > That was my point: the existence of an unlabelled yield statement breaks TCP. If the yield statement is labelled, this problem does not occur. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091228/bd55a878/attachment-0001.html From markmahieu at googlemail.com Mon Dec 28 12:09:25 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Mon, 28 Dec 2009 20:09:25 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912281018p7363c7aeyf0dfe0779c3d1ba6@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <0C002F15-7F13-4AAE-A365-A184700A8298@googlemail.com> <15e8b9d20912280918x17156e6rf6cbcd1d2f7c90e4@mail.gmail.com> <5EEAEC0A-D96F-4043-A422-BC03027CEB09@googlemail.com> <15e8b9d20912281018p7363c7aeyf0dfe0779c3d1ba6@mail.gmail.com> Message-ID: <7AA4764B-95E3-4B71-8D01-4652C42658AE@googlemail.com> On 28 Dec 2009, at 18:18, Neal Gafter wrote: > On Mon, Dec 28, 2009 at 10:05 AM, Mark Mahieu wrote: > It's a bit of a cheat regarding Tennent's C.P, in that your example could not be refactored to equivalent code simply by wrapping the 'yield' in a (nested) lambda and invoking it - a label would have to be added to make it valid. > > That was my point: the existence of an unlabelled yield statement breaks TCP. If the yield statement is labelled, this problem does not occur. Hmm. Wouldn't it only *break* TCP if it were also valid in a nested lambda but with a different semantic meaning, or if there were no corresponding form for when the statement is wrapped in a lambda? To put it another way: if we view use of an unlabelled yield statement, such as your example: #() { yield 3; } as a) legal only in a non-nested lambda b) sugar for the more formal but equivalent labelled form, whereby the yield statement is bound to some compiler-generated label: someLabel: #() { yield someLabel : 3; } then the equivalences and correspondences required by TCP appear to me to remain intact. But perhaps I am misinterpreting Tennent's text. Anyway, I agree that using labels is worth exploring. Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091228/df1b1672/attachment.html From neal at gafter.com Mon Dec 28 12:18:24 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 28 Dec 2009 12:18:24 -0800 Subject: transparent lambda In-Reply-To: <7AA4764B-95E3-4B71-8D01-4652C42658AE@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <0C002F15-7F13-4AAE-A365-A184700A8298@googlemail.com> <15e8b9d20912280918x17156e6rf6cbcd1d2f7c90e4@mail.gmail.com> <5EEAEC0A-D96F-4043-A422-BC03027CEB09@googlemail.com> <15e8b9d20912281018p7363c7aeyf0dfe0779c3d1ba6@mail.gmail.com> <7AA4764B-95E3-4B71-8D01-4652C42658AE@googlemail.com> Message-ID: <15e8b9d20912281218l1cdd945dmdf6920b563813bf8@mail.gmail.com> On Mon, Dec 28, 2009 at 12:09 PM, Mark Mahieu wrote: > Hmm. Wouldn't it only *break* TCP if it were also valid in a nested lambda > but with a different semantic meaning, or if there were no corresponding > form for when the statement is wrapped in a lambda? > I'd say "syntax error" is a pretty serious breakage. To put it another way, the correspondence principle applied to lambda expressions says the meaning of a (nested) expression should not change when wrapped in a lambda. Changing the meaning from "allowed" to "not allowed" is therefore not transparent. Any expression form that has subexpressions should be capable of being nested. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091228/6d7d3b92/attachment.html From markmahieu at googlemail.com Mon Dec 28 12:30:10 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Mon, 28 Dec 2009 20:30:10 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912281218l1cdd945dmdf6920b563813bf8@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <0C002F15-7F13-4AAE-A365-A184700A8298@googlemail.com> <15e8b9d20912280918x17156e6rf6cbcd1d2f7c90e4@mail.gmail.com> <5EEAEC0A-D96F-4043-A422-BC03027CEB09@googlemail.com> <15e8b9d20912281018p7363c7aeyf0dfe0779c3d1ba6@mail.gmail.com> <7AA4764B-95E3-4B71-8D01-4652C42658AE@googlemail.com> <15e8b9d20912281218l1cdd945dmdf6920b563813bf8@mail.gmail.com> Message-ID: <41363581-BEB8-421E-B3BD-CB9C034F8327@googlemail.com> On 28 Dec 2009, at 20:18, Neal Gafter wrote: > On Mon, Dec 28, 2009 at 12:09 PM, Mark Mahieu wrote: > Hmm. Wouldn't it only *break* TCP if it were also valid in a nested lambda but with a different semantic meaning, or if there were no corresponding form for when the statement is wrapped in a lambda? > > I'd say "syntax error" is a pretty serious breakage. To put it another way, the correspondence principle applied to lambda expressions says the meaning of a (nested) expression should not change when wrapped in a lambda. Changing the meaning from "allowed" to "not allowed" is therefore not transparent. > > Any expression form that has subexpressions should be capable of being nested. > > Cheers, > Neal > I see - that certainly clears things up. I should probably revisit Tennent's text with a stricter interpretation of 'equivalent', 'analogous mechanism' etc :) Thanks for your patience. Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091228/529cd056/attachment.html From peter.levart at marand.si Tue Dec 29 04:03:15 2009 From: peter.levart at marand.si (Peter Levart) Date: Tue, 29 Dec 2009 13:03:15 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> Message-ID: <200912291303.15668.peter.levart@marand.si> On Monday 28 December 2009 17:38:55 Neal Gafter wrote: > Loops are not an abstraction mechanism. Loops are supposed to change the > execution of the code within them, by repeating their execution. > Nevertheless, there are two syntactic forms of loops: transparent loops and > non-transparent loops, just as we've proposed two forms for lambda > expressions. The transparent ones are the ones that use a label. You can > nest these any way you want, and as long as you keep your labels unique and > use labelled break and continue, nesting does not change the meaning of the > statements that are placed within a loop. Your proposal, while purporting > to introduce transparency, actually remove the transparent (expression > lambda) form by making it non-transparent. My proposal, with mentioned flaws, was an attempt at merging the two forms of lambdas into one. I aggree that the idea of a block expression with early yield has the problems and is not so valuable per se. But, as you say below, merging two forms into one is worth exploring. Let me explain what I mean by two forms. Not syntactical forms. I now think that two syntactical forms are actually useful. The expression lambda form is a very useful syntactical shortcut. I mean the transparent/nontransparent form defined by different syntax. I think worth exploring further is how to make statement lambda transparent, so that the meaning of statements in statement lambda would be the same as the meaning of statements in 0.6b block expression. 0.6b block expression might then lose the value and control invocation syntax could be defined in terms of statement lambda. > > One approach that could be used to have lambdas that are both transparent > and allow early return would be to introduce some kind of labelling > mechanism. The labelling mechanism could either be part of the lambda > expression syntax or the block expression syntax. Then, introduce a > labelled return statement, possibly something like this: > > *return label : expression;* > > I haven't found a way to do this that feels right, but it is an approach > worth exploring. What about the following syntax (another use-case for optionally naming the lambda - the other being predictable serializable class names): #int(int, int) adder = #Adder(int a, int b) { yield#Adder a + b; } When wrapped in lambda and executed: #int(int, int) adder = #Adder(int a, int b) { #() { yield#Adder a + b; }.invoke(); } ...it retains the meaning. The we can have two variations: - yield has a mandatory label, therefore the referenced lambda must have a name. In that case 0.6b block expression still has it's value by providing a kind of "unlabeled yield" as the last expression - though not an early yield. - yield has an optional label. The set of yields that belong to particular lambda (and define the return type) is then the union of labeled yields with label being equal to the lambda name and the unlabeled yields for which the lambda is their innermost lambda. Regarding the use of unlabeled yield: Should we be pragmatic? If one is not concerned about serializing lambdas and is writing lambdas that will never have to be simplified by introducing nested lambdas, why should (s)he be forced to label each lambda and only use labeled yields? The distinction is: enabling transparent lambda vs. supporting only transparent lambda. Would unlabeled yields cause to many problems? Regards, Peter From neal at gafter.com Tue Dec 29 08:53:04 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 29 Dec 2009 08:53:04 -0800 Subject: transparent lambda In-Reply-To: <200912291303.15668.peter.levart@marand.si> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> Message-ID: <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> On Tue, Dec 29, 2009 at 4:03 AM, Peter Levart wrote: > What about the following syntax (another use-case for optionally naming the > lambda - the other being predictable serializable class names): > > #int(int, int) adder = #Adder(int a, int b) { yield#Adder a + b; } > > When wrapped in lambda and executed: > > #int(int, int) adder = #Adder(int a, int b) { #() { yield#Adder a + b; > }.invoke(); } > > ...it retains the meaning. > > The we can have two variations: > > - yield has a mandatory label, therefore the referenced lambda must have a > name. In that case 0.6b block expression still has it's value by providing a > kind of "unlabeled yield" as the last expression - though not an early > yield. > > - yield has an optional label. The set of yields that belong to particular > lambda (and define the return type) is then the union of labeled yields with > label being equal to the lambda name and the unlabeled yields for which the > lambda is their innermost lambda. > > Regarding the use of unlabeled yield: Should we be pragmatic? If one is not > concerned about serializing lambdas and is writing lambdas that will never > have to be simplified by introducing nested lambdas, why should (s)he be > forced to label each lambda and only use labeled yields? The distinction is: > enabling transparent lambda vs. supporting only transparent lambda. Would > unlabeled yields cause to many problems? > The existence of unlabelled yields makes lambdas non-transparent. The consequence of that is that refactorings involving lambdas cannot be performed locally, but may require transformation of the enclosed code. If you look at the control invocation form, for example, it is defined in terms of a lambda expression. That means that placing a control invocation statement inside of a lambda would cause any unlabelled yield statements in the control invocation to go to "the wrong place": *#() { withLock(lock) { yield 23; // oops, yields to the withLock, not the enclosing lambda } } * I therefore think the variation in which the label is mandatory is more promising. It also has the advantage that we can use a context-sensitive keyword for "yield". However, I don't think you've perfected it yet. Two issues come to mind: 1. I'm afraid there might be some ambiguity with function types. Specifically, is "#X() Y" the declaration of a variable Y of function type "#X()", or is it a lambda labelled X whose value is Y? Adding mandatory parens around the expression part of a lambda expression might help. 2. I think the labelled yield syntax could be improved. I suspect something like "yield label : expression;" would be easier on the eyes. If we do this, I would want to drop the block expression from the closures proposal. If block expressions are added, they would no longer have anything to do with closures. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/613bfc16/attachment-0001.html From markmahieu at googlemail.com Tue Dec 29 11:50:39 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 29 Dec 2009 19:50:39 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> Message-ID: <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> On 29 Dec 2009, at 16:53, Neal Gafter wrote: > > I therefore think the variation in which the label is mandatory is more promising. It also has the advantage that we can use a context-sensitive keyword for "yield". That's something I'm definitely in favour of, if it turns out to be workable; at the risk of sounding like a broken record, yielding from a lambda and returning from the enclosing method are related but distinct mechanisms which are easily confused, and I believe that mirroring the distinction with an obvious difference in surface syntax would help greatly in avoiding that confusion. > However, I don't think you've perfected it yet. Two issues come to mind: > I'm afraid there might be some ambiguity with function types. Specifically, is "#X() Y" the declaration of a variable Y of function type "#X()", or is it a lambda labelled X whose value is Y? Adding mandatory parens around the expression part of a lambda expression might help. The JLS already declares that statements may be prefixed by a label, so isn't there already a natural position for the label to occur in a StatementLambda? #() label: { /* block */ } That doesn't seem too bad to me. > I think the labelled yield syntax could be improved. I suspect something like "yield label : expression;" would be easier on the eyes. Yes that looks ok. There might be a slight readability issue when the expression contains a conditional ?: operator, but that's probably no big deal. Presumably you'd also want to support using this in lambdas with a void result type, which might then be as simple as: yield label; With a new 'yield' keyword, I think that gives us a nice (syntactic) relationship with the use of labels and break/continue. It's notable that it would not work out so well with 'return'. Regards, Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/ef980c24/attachment.html From neal at gafter.com Tue Dec 29 12:02:56 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 29 Dec 2009 12:02:56 -0800 Subject: transparent lambda In-Reply-To: <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> Message-ID: <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> On Tue, Dec 29, 2009 at 11:50 AM, Mark Mahieu wrote: > However, I don't think you've perfected it yet. Two issues come to mind: > > 1. I'm afraid there might be some ambiguity with function types. > Specifically, is "#X() Y" the declaration of a variable Y of function type > "#X()", or is it a lambda labelled X whose value is Y? Adding mandatory > parens around the expression part of a lambda expression might help. > > > The JLS already declares that statements may be prefixed by a label, so > isn't there already a natural position for the label to occur in a > StatementLambda? > > #() label: { /* block */ } > > That doesn't seem too bad to me. > That's ambiguous with an expression lambda in the middle part of a ?: expression (because "#()ID" looks like an expression lambda). Requiring parens in an expression lambda might help. > > 1. I think the labelled yield syntax could be improved. I suspect > something like "yield label : expression;" would be easier on the eyes. > > Yes that looks ok. There might be a slight readability issue when the > expression contains a conditional ?: operator, but that's probably no big > deal. > > Presumably you'd also want to support using this in lambdas with a void > result type, which might then be as simple as: > > yield label; > > With a new 'yield' keyword, I think that gives us a nice (syntactic) > relationship with the use of labels and break/continue. It's notable that > it would not work out so well with 'return'. > Not so well in the sense that the colon would be required: "return label:;". On the other hand, labeled returns could be used with the method name as a label too. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/c884ef45/attachment.html From markmahieu at googlemail.com Tue Dec 29 13:02:44 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 29 Dec 2009 21:02:44 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> Message-ID: <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> On 29 Dec 2009, at 20:02, Neal Gafter wrote: >> I think the labelled yield syntax could be improved. I suspect something like "yield label : expression;" would be easier on the eyes. > > Yes that looks ok. There might be a slight readability issue when the expression contains a conditional ?: operator, but that's probably no big deal. > > Presumably you'd also want to support using this in lambdas with a void result type, which might then be as simple as: > > yield label; > > With a new 'yield' keyword, I think that gives us a nice (syntactic) relationship with the use of labels and break/continue. It's notable that it would not work out so well with 'return'. > > Not so well in the sense that the colon would be required: "return label:;". Indeed. Potentially quite a subtle visual difference between "return foo:;" and "return foo;", I'd say. > On the other hand, labeled returns could be used with the method name as a label too. Maybe... labels don't currently shadow method names though, so what would be the meaning of "return foo:;" inside a lambda labeled "foo" inside a method called "foo"? Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/76deaf69/attachment.html From neal at gafter.com Tue Dec 29 13:11:38 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 29 Dec 2009 13:11:38 -0800 Subject: transparent lambda In-Reply-To: <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> Message-ID: <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> On Tue, Dec 29, 2009 at 1:02 PM, Mark Mahieu wrote: > > On the other hand, labeled returns could be used with the method name as > a label too. > > Maybe... labels don't currently shadow method names though, so what would > be the meaning of "return foo:;" inside a lambda labeled "foo" inside a > method called "foo"? > These aren't ordinary labels that appear in the label namespace. I'd suggest making it an error to use a lambda label corresponding to the name of the enclosing method. By the way, instead of using a new keyword-ish thing, you could also use "break". -Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/9b2051fe/attachment.html From markmahieu at googlemail.com Tue Dec 29 13:32:52 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 29 Dec 2009 21:32:52 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> Message-ID: <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> On 29 Dec 2009, at 21:11, Neal Gafter wrote: > On Tue, Dec 29, 2009 at 1:02 PM, Mark Mahieu wrote: > > On the other hand, labeled returns could be used with the method name as a label too. > > Maybe... labels don't currently shadow method names though, so what would be the meaning of "return foo:;" inside a lambda labeled "foo" inside a method called "foo"? > > These aren't ordinary labels that appear in the label namespace. I'd suggest making it an error to use a lambda label corresponding to the name of the enclosing method. Fair enough I suppose. > By the way, instead of using a new keyword-ish thing, you could also use "break". I tried that one out on a few examples earlier today. It's a great fit for void-result lambdas, but I couldn't make up my mind whether I liked it quite so much when there's an actual result. It has potential, I think. Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/d2198603/attachment.html From schulz at the-loom.de Tue Dec 29 14:00:16 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Tue, 29 Dec 2009 23:00:16 +0100 Subject: transparent lambda In-Reply-To: <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> Message-ID: <4B3A7BF0.2040208@the-loom.de> On 29.12.2009 22:32, Mark Mahieu wrote: > On 29 Dec 2009, at 21:11, Neal Gafter wrote: >> By the way, instead of using a new keyword-ish thing, you could also >> use "break". > > I tried that one out on a few examples earlier today. It's a great fit > for void-result lambdas, but I couldn't make up my mind whether I liked > it quite so much when there's an actual result. It has potential, I think. break foo return bar; ;) I'm not sure about the namespace issue, though. What would this code do? Or is transparency limited here? void foo() { foo: { #void() bar = #() bar: { break foo; } bar(); } } Cheers Stefan From neal at gafter.com Tue Dec 29 14:21:04 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 29 Dec 2009 14:21:04 -0800 Subject: transparent lambda In-Reply-To: <4B3A7BF0.2040208@the-loom.de> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> Message-ID: <15e8b9d20912291421s19e47530xe9b3f2b456f3d099@mail.gmail.com> On Tue, Dec 29, 2009 at 2:00 PM, Stefan Schulz wrote: > I'm not sure about the namespace issue, though. What would this code do? Or > is transparency limited here? > > void foo() { > foo: { > #void() bar = #() bar: { > break foo; > } > bar(); > } > } > The syntax for a named lambda we've been discussing is *#name(args) { statements }* in other words, the controlled statement must be a block statement. If we use labelled break for returning early from a lambda, I would expect it to be illegal to use a lambda label with the same name as a label in the enclosing method. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/324d16b9/attachment.html From schulz at the-loom.de Tue Dec 29 14:28:28 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Tue, 29 Dec 2009 23:28:28 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912291421s19e47530xe9b3f2b456f3d099@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <15e8b9d20912291421s19e47530xe9b3f2b456f3d099@mail.gmail.com> Message-ID: <4B3A828C.3080904@the-loom.de> On 29.12.2009 23:21, Neal Gafter wrote: > The syntax for a named lambda we've been discussing is > > *#name(args) { statements }* Ok, so the example would become: void foo() { foo: { #void() bar = #bar() { break foo; }; bar(); } } > If we use labelled break for returning early from a lambda, I would > expect it to be illegal to use a lambda label with the same name as a > label in the enclosing method. The example does not define a lambda label conflicting with a normal label. I was refering to the "may return from the enclosing method" using the method's name as label idea. Stefan From neal at gafter.com Tue Dec 29 14:45:54 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 29 Dec 2009 14:45:54 -0800 Subject: transparent lambda In-Reply-To: <4B3A828C.3080904@the-loom.de> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <15e8b9d20912291421s19e47530xe9b3f2b456f3d099@mail.gmail.com> <4B3A828C.3080904@the-loom.de> Message-ID: <15e8b9d20912291445m34a5fec2pba00121adec55174@mail.gmail.com> On Tue, Dec 29, 2009 at 2:28 PM, Stefan Schulz wrote: > The example does not define a lambda label conflicting with a normal label. > I was refering to the "may return from the enclosing method" using the > method's name as label idea. > I expect if we also allowed breaking from a method, we would not allow a lambda label to conflict with the enclosing method's name. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/c222a7db/attachment.html From schulz at the-loom.de Tue Dec 29 14:49:48 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Tue, 29 Dec 2009 23:49:48 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912291445m34a5fec2pba00121adec55174@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <15e8b9d20912291421s19e47530xe9b3f2b456f3d099@mail.gmail.com> <4B3A828C.3080904@the-loom.de> <15e8b9d20912291445m34a5fec2pba00121adec55174@mail.gmail.com> Message-ID: <4B3A878C.2040003@the-loom.de> On 29.12.2009 23:45, Neal Gafter wrote: > On Tue, Dec 29, 2009 at 2:28 PM, Stefan Schulz > wrote: > > The example does not define a lambda label conflicting with a normal > label. I was refering to the "may return from the enclosing method" > using the method's name as label idea. > > > I expect if we also allowed breaking from a method, we would not allow a > lambda label to conflict with the enclosing method's name. In the example the conflict is a "normal" label having the same name as the enclosing method, which, by now, is legal in Java. The question is, whether break within a lambda may refer to a "normal" label. Stefan From neal at gafter.com Tue Dec 29 14:56:02 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 29 Dec 2009 14:56:02 -0800 Subject: transparent lambda In-Reply-To: <4B3A878C.2040003@the-loom.de> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <15e8b9d20912291421s19e47530xe9b3f2b456f3d099@mail.gmail.com> <4B3A828C.3080904@the-loom.de> <15e8b9d20912291445m34a5fec2pba00121adec55174@mail.gmail.com> <4B3A878C.2040003@the-loom.de> Message-ID: <15e8b9d20912291456t3eb483a2o864f292b681dde3a@mail.gmail.com> On Tue, Dec 29, 2009 at 2:49 PM, Stefan Schulz wrote: > In the example the conflict is a "normal" label having the same name as the > enclosing method, which, by now, is legal in Java. The question is, whether > break within a lambda may refer to a "normal" label. I sure hope so. Otherwise it breaks transparency, which was the whole point of this exercise. -Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/e7e7c4ef/attachment.html From markmahieu at googlemail.com Tue Dec 29 14:57:33 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 29 Dec 2009 22:57:33 +0000 Subject: transparent lambda In-Reply-To: <4B3A7BF0.2040208@the-loom.de> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> Message-ID: <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> On 29 Dec 2009, at 22:00, Stefan Schulz wrote: > On 29.12.2009 22:32, Mark Mahieu wrote: >> On 29 Dec 2009, at 21:11, Neal Gafter wrote: >>> By the way, instead of using a new keyword-ish thing, you could also >>> use "break". >> >> I tried that one out on a few examples earlier today. It's a great fit >> for void-result lambdas, but I couldn't make up my mind whether I liked >> it quite so much when there's an actual result. It has potential, I think. > > break foo return bar; > > ;) I think it's the terminology I'm uneasy with - for example, how do I describe clearly and unambiguously what that statement does? A return statement is easy: it "returns a value", or "returns from a method" or whatever. A hypothetical 'yield' statement is similar: "yields a value", "yields from a lambda" etc. 'break' is fine when there's no value (it "breaks from the named lambda"), but when there is one? Your example suggests that I should say something like "breaks from the lambda named 'foo' returning 'bar'", but if its producing a result from the lambda then "return" is exactly the word I'd like to avoid here. "breaks bar from foo" maybe? (sorry for the pedantic rambling) From neal at gafter.com Tue Dec 29 15:15:48 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 29 Dec 2009 15:15:48 -0800 Subject: transparent lambda In-Reply-To: <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> Message-ID: <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> On Tue, Dec 29, 2009 at 2:57 PM, Mark Mahieu wrote: > Your example suggests that I should say something like "breaks from the > lambda named 'foo' returning 'bar'", but if its producing a result from the > lambda then "return" is exactly the word I'd like to avoid here. > I would use the word "result": The statement *break* *Identifier **: **Expression** **;* terminates execution of the body of the lambda with whose label is given by the identifier, with the result value given by the expression. -Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091229/1883816c/attachment.html From schulz at the-loom.de Tue Dec 29 15:17:46 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Wed, 30 Dec 2009 00:17:46 +0100 Subject: transparent lambda In-Reply-To: <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912280838la73e53dg5db924449302ebf@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> Message-ID: <4B3A8E1A.8080200@the-loom.de> On 29.12.2009 23:57, Mark Mahieu wrote: > I think it's the terminology I'm uneasy with - for example, how do I > describe clearly and unambiguously what that statement does? A > return statement is easy: it "returns a value", or "returns from a > method" or whatever. A hypothetical 'yield' statement is similar: > "yields a value", "yields from a lambda" etc. > > 'break' is fine when there's no value (it "breaks from the named > lambda"), but when there is one? > > Your example suggests that I should say something like "breaks from > the lambda named 'foo' returning 'bar'", but if its producing a > result from the lambda then "return" is exactly the word I'd like to > avoid here. > > "breaks bar from foo" maybe? > > > (sorry for the pedantic rambling) No worries. The wink was added on purpose. I'd just like to see something explicit rather than subtle and easy to forget/mistype. "break" is nothing I'd expect to yield anything. So any "break bar yield/answer/give/with foo" to me reads better than "break bar : foo" // reminds of assert, though or "break bar (foo)" Stefan From markmahieu at googlemail.com Tue Dec 29 16:15:46 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 30 Dec 2009 00:15:46 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> Message-ID: On 29 Dec 2009, at 23:15, Neal Gafter wrote: > On Tue, Dec 29, 2009 at 2:57 PM, Mark Mahieu wrote: > Your example suggests that I should say something like "breaks from the lambda named 'foo' returning 'bar'", but if its producing a result from the lambda then "return" is exactly the word I'd like to avoid here. > > I would use the word "result": > > The statement > > break Identifier : Expression ; > > terminates execution of the body of the lambda with whose label is given by the identifier, with the result value given by the expression. > > -Neal Yes, "result" is a superior choice. However, it's the informal, succinct, conversational description of what the statement does that I'm trying to pin down - the verb, perhaps - which ideally should be suggested by the statement itself. That's why 'yield' is tempting; it's the verb you use in the spec. In conversations about BGGA, it was often tricky to tell whether someone was talking about a local or nonlocal return because both would often be informally described as 'returning'. Maybe I'm looking at this the wrong way though, and it's not so much the *kind* of return/yield that should be emphasised, but *where* it is returning/yielding from. Which is certainly what this labelling idea suggests. Mark -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091230/ac5a3e3e/attachment.html From forax at univ-mlv.fr Wed Dec 30 06:40:00 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 30 Dec 2009 15:40:00 +0100 Subject: transparent lambda In-Reply-To: References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <200912291303.15668.peter.levart@marand.si> <15e8b9d20912290853n121f69c4m6f004b72aad57b88@mail.gmail.com> <628DA9F9-86BA-45E6-AEC9-A1317103D4CE@googlemail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> Message-ID: <4B3B6640.9000607@univ-mlv.fr> You can also use 'return' as a suffix and the name of the function (in a separate scope) as prefix. int f() { lambda() { f.return 42; }.invoke(); } R?mi Le 30/12/2009 01:15, Mark Mahieu a ?crit : > > On 29 Dec 2009, at 23:15, Neal Gafter wrote: > >> On Tue, Dec 29, 2009 at 2:57 PM, Mark Mahieu >> > wrote: >> >> Your example suggests that I should say something like "breaks >> from the lambda named 'foo' returning 'bar'", but if its >> producing a result from the lambda then "return" is exactly the >> word I'd like to avoid here. >> >> >> I would use the word "result": >> >> The statement >> >> *break* /Identifier* */*: */Expression// /*;* >> >> terminates execution of the body of the lambda with whose label is >> given by the identifier, with the result value given by the expression. >> >> -Neal > > Yes, "result" is a superior choice. > > However, it's the informal, succinct, conversational description of > what the statement does that I'm trying to pin down - the verb, > perhaps - which ideally should be suggested by the statement itself. > That's why 'yield' is tempting; it's the verb you use in the spec. > > In conversations about BGGA, it was often tricky to tell whether > someone was talking about a local or nonlocal return because both > would often be informally described as 'returning'. > > Maybe I'm looking at this the wrong way though, and it's not so much > the *kind* of return/yield that should be emphasised, but *where* it > is returning/yielding from. Which is certainly what this labelling > idea suggests. > > Mark > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091230/950dcc42/attachment-0001.html From neal at gafter.com Wed Dec 30 08:01:03 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 30 Dec 2009 08:01:03 -0800 Subject: transparent lambda In-Reply-To: <4B3B6640.9000607@univ-mlv.fr> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> Message-ID: <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> On Wed, Dec 30, 2009 at 6:40 AM, R?mi Forax wrote: > You can also use 'return' as a suffix and the name of the function (in a > separate scope) as prefix. > > int f() { > lambda() { > f.return 42; > }.invoke(); > } > You could, but the resulting construct is not TCP-transparent. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091230/6da72c4f/attachment.html From forax at univ-mlv.fr Wed Dec 30 08:30:35 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 30 Dec 2009 17:30:35 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912291202s18c0e53co94b173460847714d@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> Message-ID: <4B3B802B.40401@univ-mlv.fr> Le 30/12/2009 17:01, Neal Gafter a ?crit : > On Wed, Dec 30, 2009 at 6:40 AM, R?mi Forax > wrote: > > You can also use 'return' as a suffix and the name of the function > (in a separate scope) as prefix. > > int f() { > lambda() { > f.return 42; > }.invoke(); > } > > > You could, but the resulting construct is not TCP-transparent. Yes, I see a lambda as an anonymous function and not as an abstraction over a statement or an expression. That's why 'return' returns from the lambda and not from the function. In my opinion, lambda are more like anonymous class but for function. So like you use Outer.this in an inner class to access to the enclosing class, you should use f.return to return from a named function in an anonymous function. R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091230/2bacbf50/attachment.html From neal at gafter.com Wed Dec 30 08:38:20 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 30 Dec 2009 08:38:20 -0800 Subject: transparent lambda In-Reply-To: <4B3B802B.40401@univ-mlv.fr> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <4B3B802B.40401@univ-mlv.fr> Message-ID: <15e8b9d20912300838x117932e6pf44de0eea2f22c1c@mail.gmail.com> On Wed, Dec 30, 2009 at 8:30 AM, R?mi Forax wrote: > Yes, I see a lambda as an anonymous function and not as an abstraction > over a statement or an expression. > That's why 'return' returns from the lambda and not from the function. > > In my opinion, lambda are more like anonymous class but for function. > So like you use Outer.this in an inner class to access to the enclosing > class, > you should use f.return to return from a named function in an anonymous > function. > That's certainly a consistent position, but it's not as useful. Writing methods that act as control structures would require callers to reorganize their code to use these control APIs. If you're going to bother to support nonlocal transfers, you might as well make the lambdas transparent and get the full benefits. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091230/44dffddc/attachment.html From neal at gafter.com Wed Dec 30 08:42:23 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 30 Dec 2009 08:42:23 -0800 Subject: transparent lambda In-Reply-To: <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> Message-ID: <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> I'm trying to avoid a "solution" that allows this puzzler to be puzzling: *#int() two = null; synchronized int four() { if (two == null) two = #() { return 2; }; return two() + two(); } public static void main(String[] args) { System.out.println(four()); } * What does this do? 1. prints "4" 2. throws an exception 3. prints "2" 4. Sometimes prints "2", sometimes throws an exception 5. does not compile If you make statement lambdas transparent, the answer is choice 4: the method prints "2" on its first execution, and throws an exception (unmatched transfer) thereafter. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091230/5567bab5/attachment.html From schulz at the-loom.de Wed Dec 30 10:47:26 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Wed, 30 Dec 2009 19:47:26 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <37EA4171-1A61-4643-8F2B-97CD1D720535@googlemail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> Message-ID: <4B3BA03E.4020506@the-loom.de> On 30.12.2009 17:42, Neal Gafter wrote: > I'm trying to avoid a "solution" that allows this puzzler to be puzzling: > > *#int() two = null; > synchronized int four() { > if (two == null) two = #() { return 2; }; > return two() + two(); > } > public static void main(String[] args) { > System.out.println(four()); > } > * > > What does this do? > > 1. prints "4" > 2. throws an exception > 3. prints "2" > 4. Sometimes prints "2", sometimes throws an exception > 5. does not compile Choice 5, as four is not static ;) With the current syntax planned for lambdas, Choice 1 would be correct and to me the least surprising one (no puzzler at all). > If you make statement lambdas transparent, the answer is choice 4: the > method prints "2" on its first execution, and throws an exception > (unmatched transfer) thereafter. So you'd bind the creation of the lambda to the actual first run of the method? Why is that? IMHO, if it were the same instance and the same method, it should just work fine, as long as it is invoked from within the method's scope. Stefan From neal at gafter.com Wed Dec 30 11:03:41 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 30 Dec 2009 11:03:41 -0800 Subject: transparent lambda In-Reply-To: <4B3BA03E.4020506@the-loom.de> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> <4B3BA03E.4020506@the-loom.de> Message-ID: <15e8b9d20912301103p4a229f72n44c95c1ee842dfd7@mail.gmail.com> On Wed, Dec 30, 2009 at 10:47 AM, Stefan Schulz wrote: > On 30.12.2009 17:42, Neal Gafter wrote: >> What does this do? >> >> ? 1. prints "4" >> ? 2. throws an exception >> ? 3. prints "2" >> ? 4. Sometimes prints "2", sometimes throws an exception >> ? 5. does not compile > > Choice 5, as four is not static ;) > With the current syntax planned for lambdas, Choice 1 would be correct and to me the least surprising one (no puzzler at all). Right: statement lambdas are not transparent in project lambda.? I've taken that position in CfJ 0.6 as well.? The point of the present discussion is to determine if there is a (reasonable) way to have only one kind of lambda that is transparent. >> If you make statement lambdas transparent, the answer is choice 4: the >> method prints "2" on its first execution, and throws an exception >> (unmatched transfer) thereafter. > > So you'd bind the creation of the lambda to the actual first run of the method? Why is that? IMHO, if it were the same instance and the same method, it should just work fine, as long as it is invoked from within the method's scope. You bind a "return" statement to return from the *invocation* of the method the lambda was created within (analogously, when you capture local variables you capture them from the invocation at the time the lambda was created). In the sample program, the lambda from the first invocation is reused for the second invocation, after its enclosing method has already returned. You're advocating dynamic scoping, which pretty much died in the mid 1970's. Dynamic scoping interacts particularly badly with recursion. From peter.levart at gmail.com Wed Dec 30 13:00:01 2009 From: peter.levart at gmail.com (Peter Levart) Date: Wed, 30 Dec 2009 22:00:01 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912301103p4a229f72n44c95c1ee842dfd7@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> <4B3BA03E.4020506@the-loom.de> <15e8b9d20912301103p4a229f72n44c95c1ee842dfd7@mail.gmail.com> Message-ID: How is 'invocation of a method' defined? What would happen if method four was invoked multiple times from a loop: for (int i=0; i<2; i++) four(); Would it this also throw unmatched transfer? Regards, Peter On 12/30/09, Neal Gafter wrote: > On Wed, Dec 30, 2009 at 10:47 AM, Stefan Schulz wrote: >> On 30.12.2009 17:42, Neal Gafter wrote: >>> What does this do? >>> >>> ? 1. prints "4" >>> ? 2. throws an exception >>> ? 3. prints "2" >>> ? 4. Sometimes prints "2", sometimes throws an exception >>> ? 5. does not compile >> >> Choice 5, as four is not static ;) >> With the current syntax planned for lambdas, Choice 1 would be correct and >> to me the least surprising one (no puzzler at all). > > Right: statement lambdas are not transparent in project lambda.? I've > taken that position in CfJ 0.6 as well.? The point of the present > discussion is to determine if there is a (reasonable) way to have only > one kind of lambda that is transparent. > >>> If you make statement lambdas transparent, the answer is choice 4: the >>> method prints "2" on its first execution, and throws an exception >>> (unmatched transfer) thereafter. >> >> So you'd bind the creation of the lambda to the actual first run of the >> method? Why is that? IMHO, if it were the same instance and the same >> method, it should just work fine, as long as it is invoked from within the >> method's scope. > > You bind a "return" statement to return from the *invocation* of the > method the lambda was created within (analogously, when you capture > local variables you capture them from the invocation at the time the > lambda was created). In the sample program, the lambda from the first > invocation is reused for the second invocation, after its enclosing > method has already returned. > > You're advocating dynamic scoping, which pretty much died in the mid > 1970's. Dynamic scoping interacts particularly badly with recursion. > -- Sent from Gmail for mobile | mobile.google.com From neal at gafter.com Wed Dec 30 13:08:45 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 30 Dec 2009 13:08:45 -0800 Subject: transparent lambda In-Reply-To: References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> <4B3BA03E.4020506@the-loom.de> <15e8b9d20912301103p4a229f72n44c95c1ee842dfd7@mail.gmail.com> Message-ID: <15e8b9d20912301308v22161b1fib102dbdbd492ea8f@mail.gmail.com> On Wed, Dec 30, 2009 at 1:00 PM, Peter Levart wrote: > How is 'invocation of a method' defined? What would happen if method > four was invoked multiple times from a loop: for (int i=0; i<2; i++) > four(); Would it this also throw unmatched transfer? Regards, Peter The "invocation of a method" is the execution of a Method Invocation Expression (JLS 15.12). Technically, we should include constructor invocations as well (JLS 15.9), since you can return from those as well. The second and all subsequent invocations of method two() throw the unmatched transfer exception. Since method four() calls it twice, method four() would always throw that exception. Remember, this is only in a hypothetical closures specification in which statement closures are transparent. Cheers, Neal From peter.levart at gmail.com Wed Dec 30 13:45:34 2009 From: peter.levart at gmail.com (Peter Levart) Date: Wed, 30 Dec 2009 22:45:34 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912291311x270c1f42v755e03927590fdf1@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> Message-ID: Isn't it true that method 'four' only calls lambda 'two' once? Lambda 'two' returns from method 'four' (since lambda is transparent) before the second call. My question was about how can a program differentiate multiple invocations of a method from the same call site? Does it maintain a counter? Regards, peter 2009/12/30, Neal Gafter : > I'm trying to avoid a "solution" that allows this puzzler to be puzzling: > > *#int() two = null; > synchronized int four() { > if (two == null) two = #() { return 2; }; > return two() + two(); > } > public static void main(String[] args) { > System.out.println(four()); > } > * > > What does this do? > > 1. prints "4" > 2. throws an exception > 3. prints "2" > 4. Sometimes prints "2", sometimes throws an exception > 5. does not compile > > If you make statement lambdas transparent, the answer is choice 4: the > method prints "2" on its first execution, and throws an exception (unmatched > transfer) thereafter. > > Cheers, > Neal > -- Poslano z moje mobilne naprave From neal at gafter.com Wed Dec 30 13:57:47 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 30 Dec 2009 13:57:47 -0800 Subject: transparent lambda In-Reply-To: References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> Message-ID: <15e8b9d20912301357w6ed0cb0dh4002d142af43af6d@mail.gmail.com> On Wed, Dec 30, 2009 at 1:45 PM, Peter Levart wrote: > Isn't it true that method 'four' only calls lambda 'two' once? Lambda > 'two' returns from method 'four' (since lambda is transparent) before > the second call. Right (I stand corrected): four() returns 2 on its first invocation, and throws an exception on subsequent invocations. > My question was about how can a program differentiate multiple > invocations of a method from the same call site? Does it maintain a > counter? The javac compiler can use any technique suitable for implementing these semantics. A counter would work if there were some way to avoid having to worry about the value wrapping. When a closure captures some context from the enclosing scope, that context can be packaged up into a frame object. The identity of that frame object can be used to distinguish one invocation from another. -Neal From tronicek at fit.cvut.cz Thu Dec 31 00:21:08 2009 From: tronicek at fit.cvut.cz (tronicek at fit.cvut.cz) Date: Thu, 31 Dec 2009 09:21:08 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912301357w6ed0cb0dh4002d142af43af6d@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <3D7AED09-43CC-4FD1-8696-C3BCD89FE7DB@googlemail.com> <4B3A7BF0.2040208@the-loom.de> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> <15e8b9d20912301357w6ed0cb0dh4002d142af43af6d@mail.gmail.com> Message-ID: Neal Gafter napsal(a): >> My question was about how can a program differentiate multiple >> invocations of a method from the same call site? Does it maintain a >> counter? > > The javac compiler can use any technique suitable for implementing > these semantics. A counter would work if there were some way to avoid > having to worry about the value wrapping. Just to be sure I know what you are talking about: do you mean overflow? Another question, which was already here, is, whether such escape of closure would be allowed. If invocation of #() { return 2; } is always error after returning from the first four(), it would be better to forbid such escape. > static #int() two = null; > static synchronized int four() { > if (two == null) two = #() { return 2; }; > return two() + two(); > } > public static void main(String[] args) { > System.out.println(four()); > } -- Zdenek Tronicek FIT CTU in Prague From neal at gafter.com Thu Dec 31 09:50:24 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 31 Dec 2009 09:50:24 -0800 Subject: transparent lambda In-Reply-To: References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B81BD76-7872-493D-99C3-250865340CC1@googlemail.com> <15e8b9d20912291515s348c7f78y670f3e50e2db256c@mail.gmail.com> <4B3B6640.9000607@univ-mlv.fr> <15e8b9d20912300801x7f7a4eauc27076eaaeabd390@mail.gmail.com> <15e8b9d20912300842g6a55796eiba472ce168b13f4a@mail.gmail.com> <15e8b9d20912301357w6ed0cb0dh4002d142af43af6d@mail.gmail.com> Message-ID: <15e8b9d20912310950k67394a4axe5f6880a92f21ceb@mail.gmail.com> On Thu, Dec 31, 2009 at 12:21 AM, wrote: > Just to be sure I know what you are talking about: do you mean overflow? > Yes. > Another question, which was already here, is, whether such escape of > closure would be allowed. If invocation of #() { return 2; } is always > error after returning from the first four(), it would be better to forbid > such escape. > Yes, it would be better, if there existed a static flow analysis to enforce this restriction that is both conservative and strong enough to allow virtually all of the kind of safe code that you can write without the analysis. I spent some time looking for a way to do it, and I didn't find one. None of the existing languages that support nonlocal transfers implement such an analysis, so we'd be breaking new ground if we found a way to do it. I should also point out that the runtime exception that is caused by this failure is remarkably easy to track down. I think you'd be hard pressed to find reports of a smalltalk/ruby/scala/clisp programmer complaining about accidentally triggering these errors, or having a hard time tracking them down. They're about as debuggable as array-index-out-of-bounds errors. Cheers, Neal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20091231/10ee5692/attachment.html