From keith.mcguigan at oracle.com Thu Feb 2 11:48:11 2012 From: keith.mcguigan at oracle.com (keith.mcguigan at oracle.com) Date: Thu, 02 Feb 2012 19:48:11 +0000 Subject: hg: lambda/lambda/hotspot: 7136761: SolSparc64 Lambda build generation needs to be fixed Message-ID: <20120202194819.50B0847316@hg.openjdk.java.net> Changeset: 108d1e7220ee Author: kamg Date: 2012-02-02 01:53 -0500 URL: http://hg.openjdk.java.net/lambda/lambda/hotspot/rev/108d1e7220ee 7136761: SolSparc64 Lambda build generation needs to be fixed Summary: Generated method constant pool hash value fixed for 64-bit ! src/share/vm/classfile/bytecodeAssembler.hpp From maurizio.cimadamore at oracle.com Mon Feb 6 05:45:48 2012 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Mon, 06 Feb 2012 13:45:48 +0000 Subject: hg: lambda/lambda/langtools: Exception transparency fixes: Message-ID: <20120206134554.6F11647396@hg.openjdk.java.net> Changeset: cf479ef26252 Author: mcimadamore Date: 2012-02-06 13:45 +0000 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/cf479ef26252 Exception transparency fixes: *) Compiler complains when union types containing type-parameters are used outside of a catch block *) Missing erasure in generated code causes assertion errors when lambda contains catch clause with throws type-parameter ! src/share/classes/com/sun/tools/javac/comp/Attr.java ! src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java + test/tools/javac/transparency/Neg10.java + test/tools/javac/transparency/Neg10.out + test/tools/javac/transparency/Pos05.java From drconrad at gmail.com Mon Feb 6 12:55:42 2012 From: drconrad at gmail.com (David Conrad) Date: Mon, 6 Feb 2012 15:55:42 -0500 Subject: New Lambda Preview? Message-ID: Any plans to push out a new ea build? The last time I checked (a day or so ago), the Nov 2011 build was still the latest, and it is now Feb 2012 and a lot of changesets have passed under the bridge. Apologies if this message and a new push have crossed, and yes I do realize I could build it myself from the repo. World enough and time, and all that. David Conrad On Mon, 06 Feb 2012 13:45:48 Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > Subject: hg: lambda/lambda/langtools: Exception transparency fixes: > > Changeset: cf479ef26252 > Author: mcimadamore > Date: 2012-02-06 13:45 +0000 > URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/cf479ef26252 > > Exception transparency fixes: > *) Compiler complains when union types containing type-parameters are used outside of a catch block > *) Missing erasure in generated code causes assertion errors when lambda contains catch clause with throws type-parameter > > ! src/share/classes/com/sun/tools/javac/comp/Attr.java > ! src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java > + test/tools/javac/transparency/Neg10.java > + test/tools/javac/transparency/Neg10.out > + test/tools/javac/transparency/Pos05.java > From marcos_antonio_ps at hotmail.com Mon Feb 6 15:28:36 2012 From: marcos_antonio_ps at hotmail.com (Marcos Antonio) Date: Tue, 7 Feb 2012 02:28:36 +0300 Subject: New Lambda Preview? In-Reply-To: References: Message-ID: I also would like to know this. Marcos > Date: Mon, 6 Feb 2012 15:55:42 -0500 > Subject: New Lambda Preview? > From: drconrad at gmail.com > To: lambda-dev at openjdk.java.net > > Any plans to push out a new ea build? The last time I checked (a day or so > ago), the Nov 2011 build was still the latest, and it is now Feb 2012 and a > lot of changesets have passed under the bridge. Apologies if this message > and a new push have crossed, and yes I do realize I could build it myself > from the repo. World enough and time, and all that. > > David Conrad > > On Mon, 06 Feb 2012 13:45:48 Maurizio Cimadamore < > maurizio.cimadamore at oracle.com> wrote: > > Subject: hg: lambda/lambda/langtools: Exception transparency fixes: > > > > Changeset: cf479ef26252 > > Author: mcimadamore > > Date: 2012-02-06 13:45 +0000 > > URL: > http://hg.openjdk.java.net/lambda/lambda/langtools/rev/cf479ef26252 > > > > Exception transparency fixes: > > *) Compiler complains when union types containing type-parameters are > used outside of a catch block > > *) Missing erasure in generated code causes assertion errors when lambda > contains catch clause with throws type-parameter > > > > ! src/share/classes/com/sun/tools/javac/comp/Attr.java > > ! src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java > > + test/tools/javac/transparency/Neg10.java > > + test/tools/javac/transparency/Neg10.out > > + test/tools/javac/transparency/Pos05.java > > > From maurizio.cimadamore at oracle.com Tue Feb 7 01:49:45 2012 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 07 Feb 2012 09:49:45 +0000 Subject: new binary snapshot available Message-ID: <4F30F3B9.6020305@oracle.com> Dear lambditizens, After some delay (due to intracosmic turbolences), another lambda binary snapshot landed on planet JDK: http://jdk8.java.net/lambda/ This new promotion includes several compiler bug fixes and, most notably, a brand new VM support for extension methods (kudos to Keith!). As always, your feedback is very important to us - please keep reporting your experience with the lambda binary snapshot on this mailing list. Again thanks to Brian, Dan, Mike, Stuart, Mike, the SQE and RE team for their effort in making this happen. Enjoy. Maurizio From maurizio.cimadamore at oracle.com Tue Feb 7 01:51:54 2012 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 07 Feb 2012 09:51:54 +0000 Subject: New Lambda Preview? In-Reply-To: References: Message-ID: <4F30F43A.5050200@oracle.com> We have been working on it (see related email) - sorry for the delay ;-) Maurizio On 06/02/12 23:28, Marcos Antonio wrote: > I also would like to know this. Marcos> Date: Mon, 6 Feb 2012 15:55:42 -0500 >> Subject: New Lambda Preview? >> From: drconrad at gmail.com >> To: lambda-dev at openjdk.java.net >> >> Any plans to push out a new ea build? The last time I checked (a day or so >> ago), the Nov 2011 build was still the latest, and it is now Feb 2012 and a >> lot of changesets have passed under the bridge. Apologies if this message >> and a new push have crossed, and yes I do realize I could build it myself >> from the repo. World enough and time, and all that. >> >> David Conrad >> >> On Mon, 06 Feb 2012 13:45:48 Maurizio Cimadamore< >> maurizio.cimadamore at oracle.com> wrote: >>> Subject: hg: lambda/lambda/langtools: Exception transparency fixes: >>> >>> Changeset: cf479ef26252 >>> Author: mcimadamore >>> Date: 2012-02-06 13:45 +0000 >>> URL: >> http://hg.openjdk.java.net/lambda/lambda/langtools/rev/cf479ef26252 >>> Exception transparency fixes: >>> *) Compiler complains when union types containing type-parameters are >> used outside of a catch block >>> *) Missing erasure in generated code causes assertion errors when lambda >> contains catch clause with throws type-parameter >>> ! src/share/classes/com/sun/tools/javac/comp/Attr.java >>> ! src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java >>> + test/tools/javac/transparency/Neg10.java >>> + test/tools/javac/transparency/Neg10.out >>> + test/tools/javac/transparency/Pos05.java >>> > > From miles at milessabin.com Tue Feb 7 03:09:50 2012 From: miles at milessabin.com (Miles Sabin) Date: Tue, 7 Feb 2012 11:09:50 +0000 Subject: Generic lambdas In-Reply-To: References: Message-ID: I just tried this again with the latest snapshot, but still no joy. What's the current plan for generic lambdas? Are they still in? Cheers, Miles On Wed, Nov 16, 2011 at 5:59 PM, Miles Sabin wrote: > I've just been attempting to play with generic lambdas using the > binary JDK 8 snapshot posted a few days ago, > > miles at lewis:lambda$ /usr/java/lambda-jdk/bin/java -version > openjdk version "1.8.0-ea" > OpenJDK Runtime Environment (build 1.8.0-ea-b1314) > OpenJDK 64-Bit Server VM (build 23.0-b04, mixed mode) > > I took this example from the EDR, > > public class Lambda { > ?public static interface Picker { > ? ? T pick(T first, T second); > ?} > > ?public static void main(String[] args) { > ? ?Picker rand = (T first, T second) -> new > Random().nextBoolean() ? first : second ; > ? ?int i = rand.pick(1, 2); > ? ?String s = rand.pick("a", "b"); > ?} > } > > But this fails compilation as follows, > > miles at lewis:lambda$ /usr/java/lambda-jdk/bin/javac Lambda.java > Lambda.java:7: error: illegal start of expression > ? ?Picker rand = (T first, T second) -> new > Random().nextBoolean() ? first : second ; > > ? ? ? ? ? ? ? ? ?^ > 1 error > > Is this expected at present? > > Cheers, > > > Miles > > -- > Miles Sabin > tel: +44 7813 944 528 > gtalk: miles at milessabin.com > skype: milessabin > g+: http://www.milessabin.com > http://twitter.com/milessabin > http://www.chuusai.com/ -- Miles Sabin tel: +44 7813 944 528 gtalk: miles at milessabin.com skype: milessabin g+: http://www.milessabin.com http://twitter.com/milessabin http://www.chuusai.com/ From maurizio.cimadamore at oracle.com Tue Feb 7 03:37:12 2012 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 07 Feb 2012 11:37:12 +0000 Subject: differences between lambda binary vs. JSR 335 EDR (updated) Message-ID: <4F310CE8.5060205@oracle.com> Hi, Here's a list of the remaining outstanding differences between the compiler implementation (binary snapshot) and the spec EDR: *) Generic lambdas are not supported/generic functional descriptors are not supported (15.27 and 9.8) interface SAM { void m(X x, Y y); } SAM s = (x,y)->{}; *) Compiler supports a slightly less powerful analysis for detecting effectively final variables that only applies to variables with an initializer (4.12.4) void m() { int x; x = 2; SAM s = ()->x*2; //error } With respect to the previous binary snapshot, the following changes have been integrated: *) added support for inlined syntax for extension methods i.e. void m() default { ... } instead of: void m() default Foo.m *) added support for '::' for method references: i.e. SAM s1 = foo::bar; SAM s2 = Foo::new; SAM s3 = new Bar()::baz; *) new parser scheme for lambda expressions - now mix of explicit/implicit parameters is not accepted (as per EDR) i.e. SAM s1 = (int x1, x2)->x1 + x2; //error *) new parser scheme for method references - now explicit argument types on method references are not accepted (as per EDR) i.e. SAM s1 = foo::bar(String); //error SAM s2 = foo::new(Integer, List); //error *) added support for target-typing in conditional expressions i.e. SAM s = cond ? ()->true : ()->false; Maurizio From marcos_antonio_ps at hotmail.com Tue Feb 7 04:15:17 2012 From: marcos_antonio_ps at hotmail.com (Marcos Antonio) Date: Tue, 7 Feb 2012 15:15:17 +0300 Subject: new binary snapshot available In-Reply-To: <4F30F3B9.6020305@oracle.com> References: <4F30F3B9.6020305@oracle.com> Message-ID: Thank you. Marcos > Date: Tue, 7 Feb 2012 09:49:45 +0000 > From: maurizio.cimadamore at oracle.com > To: lambda-dev at openjdk.java.net > Subject: new binary snapshot available > > Dear lambditizens, > After some delay (due to intracosmic turbolences), another lambda binary snapshot landed on planet JDK: > > http://jdk8.java.net/lambda/ > > This new promotion includes several compiler bug fixes and, most notably, a brand new VM support for extension methods (kudos to Keith!). > As always, your feedback is very important to us - please keep reporting your experience with the lambda binary snapshot on this mailing list. > > Again thanks to Brian, Dan, Mike, Stuart, Mike, the SQE and RE team for their effort in making this happen. > > Enjoy. > Maurizio > > From sam at sampullara.com Tue Feb 7 08:24:21 2012 From: sam at sampullara.com (Sam Pullara) Date: Tue, 7 Feb 2012 08:24:21 -0800 Subject: new binary snapshot available In-Reply-To: References: <4F30F3B9.6020305@oracle.com> Message-ID: Is there any chance of a Mac build in the near future? It is pretty painful to help try out the builds without being able to use them in my normal development environment. Thanks, Sam On Tue, Feb 7, 2012 at 4:15 AM, Marcos Antonio wrote: > > Thank you. > > Marcos > > >> Date: Tue, 7 Feb 2012 09:49:45 +0000 >> From: maurizio.cimadamore at oracle.com >> To: lambda-dev at openjdk.java.net >> Subject: new binary snapshot available >> >> Dear lambditizens, >> After some delay (due to intracosmic turbolences), another lambda binary snapshot landed on planet JDK: >> >> http://jdk8.java.net/lambda/ >> >> This new promotion includes several compiler bug fixes and, most notably, a brand new VM support for extension methods (kudos to Keith!). >> As always, your feedback is very important to us - please keep reporting your experience with the lambda binary snapshot on this mailing list. >> >> Again thanks to Brian, Dan, Mike, Stuart, Mike, the SQE and RE team for their effort in making this happen. >> >> Enjoy. >> Maurizio >> >> > > From martijnverburg at gmail.com Tue Feb 7 08:37:10 2012 From: martijnverburg at gmail.com (Martijn Verburg) Date: Tue, 7 Feb 2012 16:37:10 +0000 Subject: new binary snapshot available In-Reply-To: References: <4F30F3B9.6020305@oracle.com> Message-ID: Hi Sam, Henri Gomez provides Mac builds at http://code.google.com/p/openjdk-osx-build/ I'm not sure if the very latest lambda build is there, but Henri usually knocks out the builds pretty quickly. Cheers, Martijn On 7 February 2012 16:24, Sam Pullara wrote: > Is there any chance of a Mac build in the near future? It is pretty > painful to help try out the builds without being able to use them in > my normal development environment. > > Thanks, > Sam > > On Tue, Feb 7, 2012 at 4:15 AM, Marcos Antonio > wrote: >> >> Thank you. >> >> Marcos >> >> >>> Date: Tue, 7 Feb 2012 09:49:45 +0000 >>> From: maurizio.cimadamore at oracle.com >>> To: lambda-dev at openjdk.java.net >>> Subject: new binary snapshot available >>> >>> Dear lambditizens, >>> After some delay (due to intracosmic turbolences), another lambda binary snapshot landed on planet JDK: >>> >>> http://jdk8.java.net/lambda/ >>> >>> This new promotion includes several compiler bug fixes and, most notably, a brand new VM support for extension methods (kudos to Keith!). >>> As always, your feedback is very important to us - please keep reporting your experience with the lambda binary snapshot on this mailing list. >>> >>> Again thanks to Brian, Dan, Mike, Stuart, Mike, the SQE and RE team for their effort in making this happen. >>> >>> Enjoy. >>> Maurizio >>> >>> >> >> > From bernard.traversat at oracle.com Tue Feb 7 17:29:37 2012 From: bernard.traversat at oracle.com (Bernard Traversat) Date: Tue, 7 Feb 2012 17:29:37 -0800 Subject: new binary snapshot available In-Reply-To: References: <4F30F3B9.6020305@oracle.com> Message-ID: We are still in the process of merging the new Lambda features in the main JDK8 repository. The provided Lambda build is from the Lambda repository. We are getting there. Cheers, B. On Feb 7, 2012, at 8:37 AM, Martijn Verburg wrote: > Hi Sam, > > Henri Gomez provides Mac builds at > http://code.google.com/p/openjdk-osx-build/ I'm not sure if the very > latest lambda build is there, but Henri usually knocks out the builds > pretty quickly. > > Cheers, > Martijn > > On 7 February 2012 16:24, Sam Pullara wrote: >> Is there any chance of a Mac build in the near future? It is pretty >> painful to help try out the builds without being able to use them in >> my normal development environment. >> >> Thanks, >> Sam >> >> On Tue, Feb 7, 2012 at 4:15 AM, Marcos Antonio >> wrote: >>> >>> Thank you. >>> >>> Marcos >>> >>> >>>> Date: Tue, 7 Feb 2012 09:49:45 +0000 >>>> From: maurizio.cimadamore at oracle.com >>>> To: lambda-dev at openjdk.java.net >>>> Subject: new binary snapshot available >>>> >>>> Dear lambditizens, >>>> After some delay (due to intracosmic turbolences), another lambda binary snapshot landed on planet JDK: >>>> >>>> http://jdk8.java.net/lambda/ >>>> >>>> This new promotion includes several compiler bug fixes and, most notably, a brand new VM support for extension methods (kudos to Keith!). >>>> As always, your feedback is very important to us - please keep reporting your experience with the lambda binary snapshot on this mailing list. >>>> >>>> Again thanks to Brian, Dan, Mike, Stuart, Mike, the SQE and RE team for their effort in making this happen. >>>> >>>> Enjoy. >>>> Maurizio >>>> >>>> >>> >>> >> > From bitterfoxc at gmail.com Wed Feb 8 06:21:26 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Wed, 8 Feb 2012 23:21:26 +0900 Subject: Using default implementation, I can compile Illegal Extending Class which is mistaking access modifiers or return-types. Message-ID: Hi, Using default implementation, I can compile Illegal Extending Class which is mistaking access modifiers or return-types. Compiler is the newest binary snapshot. For instance: interface I { void method() default {} // method is pubilc } class C1 { void method() {} // method is package private } class C2 extends C1 implements I { // this would be illegal, but I can compile this. } I i = new C2(); i.method(); // this calling causes IllegalAccessError The other pattern: interface I { String method() default { return "str"; } } class C1 { public Integer method() { return 0; } } class C2 extends C1 implements I { // this extending would be illegal } C2 c2 = new C2(); C1 c1 = c2; I i = c2; System.out.println(c2.method()); // 0 System.out.println(c1.method()); // 0 System.out.println(i.method()); // str Was this already known? Regards, bitter_fox From maurizio.cimadamore at oracle.com Wed Feb 8 07:10:16 2012 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 08 Feb 2012 15:10:16 +0000 Subject: Using default implementation, I can compile Illegal Extending Class which is mistaking access modifiers or return-types. In-Reply-To: References: Message-ID: <4F329058.6010305@oracle.com> Right - the check for compatible implementation is currently excluding default methods - the reason is a flag mismatch - default methods are not marked with ACC_ABSTRACT anymore - as a result those compiler checks need to be updated to check for ACC_DEFENDER instead. I will push a fix soon. Maurizio On 08/02/12 14:21, bitter_fox wrote: > Hi, > Using default implementation, I can compile Illegal Extending Class which > is mistaking access modifiers or return-types. > > Compiler is the newest binary snapshot. > > For instance: > interface I > { > void method() default {} // method is pubilc > } > > class C1 > { > void method() {} // method is package private > } > > class C2 extends C1 implements I > { > // this would be illegal, but I can compile this. > } > > I i = new C2(); > i.method(); // this calling causes IllegalAccessError > > The other pattern: > interface I > { > String method() default > { > return "str"; > } > } > > class C1 > { > public Integer method() > { > return 0; > } > } > > class C2 extends C1 implements I > { > // this extending would be illegal > } > > C2 c2 = new C2(); > C1 c1 = c2; > I i = c2; > > System.out.println(c2.method()); // 0 > System.out.println(c1.method()); // 0 > System.out.println(i.method()); // str > > Was this already known? > > Regards, > bitter_fox > From maurizio.cimadamore at oracle.com Wed Feb 8 09:17:35 2012 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Wed, 08 Feb 2012 17:17:35 +0000 Subject: hg: lambda/lambda/langtools: Fix: differences in method flags cause default method override to go unchecked Message-ID: <20120208171740.76055473EB@hg.openjdk.java.net> Changeset: 82513fdfa3f6 Author: mcimadamore Date: 2012-02-08 16:57 +0000 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/82513fdfa3f6 Fix: differences in method flags cause default method override to go unchecked ! src/share/classes/com/sun/tools/javac/comp/Check.java + test/tools/javac/defender/Neg07.java + test/tools/javac/defender/Neg07.out + test/tools/javac/defender/Neg08.java + test/tools/javac/defender/Neg08.out + test/tools/javac/defender/Neg09.java + test/tools/javac/defender/Neg09.out + test/tools/javac/defender/Neg10.java + test/tools/javac/defender/Neg10.out + test/tools/javac/defender/Neg11.java + test/tools/javac/defender/Neg11.out From bitterfoxc at gmail.com Wed Feb 8 17:37:33 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Thu, 9 Feb 2012 10:37:33 +0900 Subject: Using default implementation, I can compile Illegal Extending Class which is mistaking access modifiers or return-types. In-Reply-To: <4F329058.6010305@oracle.com> References: <4F329058.6010305@oracle.com> Message-ID: Oh, It was caused by that reason.I've understood. Thank you for the fix. I've just got it. Regards, bitter_fox 2012/2/9 Maurizio Cimadamore > Right - the check for compatible implementation is currently excluding > default methods - the reason is a flag mismatch - default methods are not > marked with ACC_ABSTRACT anymore - as a result those compiler checks need > to be updated to check for ACC_DEFENDER instead. > > I will push a fix soon. > > Maurizio > > > > On 08/02/12 14:21, bitter_fox wrote: > >> Hi, >> Using default implementation, I can compile Illegal Extending Class which >> is mistaking access modifiers or return-types. >> >> Compiler is the newest binary snapshot. >> >> For instance: >> interface I >> { >> void method() default {} // method is pubilc >> } >> >> class C1 >> { >> void method() {} // method is package private >> } >> >> class C2 extends C1 implements I >> { >> // this would be illegal, but I can compile this. >> } >> >> I i = new C2(); >> i.method(); // this calling causes IllegalAccessError >> >> The other pattern: >> interface I >> { >> String method() default >> { >> return "str"; >> } >> } >> >> class C1 >> { >> public Integer method() >> { >> return 0; >> } >> } >> >> class C2 extends C1 implements I >> { >> // this extending would be illegal >> } >> >> C2 c2 = new C2(); >> C1 c1 = c2; >> I i = c2; >> >> System.out.println(c2.method()**); // 0 >> System.out.println(c1.method()**); // 0 >> System.out.println(i.method())**; // str >> >> Was this already known? >> >> Regards, >> bitter_fox >> >> > From stellarspot at yandex.ru Wed Feb 8 23:41:42 2012 From: stellarspot at yandex.ru (Spot Al) Date: Thu, 09 Feb 2012 11:41:42 +0400 Subject: f(x) syntax sugar in Lambda Message-ID: <434691328773302@web155.yandex.ru> Hi, For example if there is an interface ----------------------------------------------- interface Exponent{ double calculate(double x); } ----------------------------------------------- and I have a lambda expression: ----------------------------------------------- Exponent exp = (x) -> 1 + x + x * x / 2; ----------------------------------------------- would it be possible to get a value like: double e = exp(1); instead of double e = exp.calculate(1); ? Where exp(1) just a syntax sugar for the exp.calculate(1). So if variable a has a lambda type (interface with one method) than a(val1,.., valN) means a.methodName(val1,.., valN)? Thanks, Alexander. From maurizio.cimadamore at oracle.com Thu Feb 9 01:46:09 2012 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 09 Feb 2012 09:46:09 +0000 Subject: f(x) syntax sugar in Lambda In-Reply-To: <434691328773302@web155.yandex.ru> References: <434691328773302@web155.yandex.ru> Message-ID: <4F3395E1.2090303@oracle.com> Hi, I think there might be few problems with this approach when unleashed in a more widespread way: *) Java has two separate namespaces for methods/fields - so the following would be ambiguous: Exponent exp = (x) -> 1 + x + x * x / 2; void exp(int x) { ... } exp(3) //? *) The language does not have such a thing as 'type of a lambda' so, there is no way to distinguish between: SAM s = ()-> { ... } and SAM s = new SAM() { ... } This means that your proposal will apply to all expressions whose type E is a functional interface. *) What if E is a method call? You end up with things like: Exponent makeExp() { ... } makeExp()(5); *) If you have a functional interface with default methods: interface Exponent { double calculate(double x); void foo() default { ... } void bar() default { ... } } then the fact that the syntactic sugar will rewire the method call to 'calculate' (as that's the only abstract method in Exponent) might result a bit surprising since there is more than one method available in the functional interface. Maurizio On 09/02/12 07:41, Spot Al wrote: > Hi, > > For example if there is an interface > ----------------------------------------------- > interface Exponent{ > double calculate(double x); > } > ----------------------------------------------- > > and I have a lambda expression: > ----------------------------------------------- > Exponent exp = (x) -> 1 + x + x * x / 2; > ----------------------------------------------- > > would it be possible to get a value like: > double e = ep(1); > instead of > double e = exp.calculate(1); ? > > Where exp(1) just a syntax sugar for the exp.calculate(1). > > So if variable a has a lambda type (interface with one method) than a(val1,.., valN) means a.methodName(val1,.., valN)? > > Thanks, > Alexander. > > > > > From stellarspot at yandex.ru Fri Feb 10 00:42:53 2012 From: stellarspot at yandex.ru (Spot Al) Date: Fri, 10 Feb 2012 12:42:53 +0400 Subject: f(x) syntax sugar in Lambda In-Reply-To: <4F3395E1.2090303@oracle.com> References: <434691328773302@web155.yandex.ru> <4F3395E1.2090303@oracle.com> Message-ID: <641251328863373@web7.yandex.ru> What I want to do is just answer on the question: If it is possible to create a functional interface without using the method name, why it needs to mention the method name using the functional interface? The most serious objection against using the f(x) invocation is the separate namespaces for methods/fields. In this case just an another syntax which does not mention the method name can be used. For example double e = exp.(1); // or any other better syntax What about the last case which use the default methods, creating the lambda expression and using it without mentioning the method name are the same things. So ------------------------------------------ interface Exponent { double calculate(double x); void foo() default { ... } void bar() default { ... } } Exponent exp = (x) -> 1 + x + x * x / 2; // which method is defined? double e = exp.(1) // which method is invoked? In both cases we should care about default methods. Thanks, Alexander. 09.02.2012, 13:46, "Maurizio Cimadamore" : > Hi, > I think there might be few problems with this approach when unleashed in > a more widespread way: > > *) Java has two separate namespaces for methods/fields - so the > following would be ambiguous: > > Exponent exp = (x) -> 1 + x + x * x / 2; > void exp(int x) { ... } > > exp(3) //? > > *) The language does not have such a thing as 'type of a lambda' so, > there is no way to distinguish between: > > SAM s = ()-> { ... } > > and > > SAM s = new SAM() { ... } > > This means that your proposal will apply to all expressions whose type E > is a functional interface. > > *) What if E is a method call? You end up with things like: > > Exponent makeExp() { ... } > > makeExp()(5); > > *) If you have a functional interface with default methods: > > interface Exponent { > ????double calculate(double x); > ????void foo() default { ... } > ????void bar() default { ... } > } > > then the fact that the syntactic sugar will rewire the method call to > 'calculate' (as that's the only abstract method in Exponent) might > result a bit surprising since there is more than one method available in > the functional interface. > > Maurizio > > On 09/02/12 07:41, Spot Al wrote: > >> ?Hi, >> >> ?For example if there is an interface >> ?----------------------------------------------- >> ???interface Exponent{ >> ???????double calculate(double x); >> ???} >> ?----------------------------------------------- >> >> ?and I have a lambda expression: >> ?----------------------------------------------- >> ?Exponent exp = (x) -> ?1 + x + x * x / 2; >> ?----------------------------------------------- >> >> ?would it be possible to get a value like: >> ????double e = ep(1); >> ?instead of >> ????double e = exp.calculate(1); ? >> >> ?Where exp(1) just a syntax sugar for the exp.calculate(1). >> >> ?So if variable a has a lambda type (interface with one method) than a(val1,.., valN) means a.methodName(val1,.., valN)? >> >> ?Thanks, >> ?Alexander. From maurizio.cimadamore at oracle.com Fri Feb 10 02:35:21 2012 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 10 Feb 2012 10:35:21 +0000 Subject: f(x) syntax sugar in Lambda In-Reply-To: <641251328863373@web7.yandex.ru> References: <434691328773302@web155.yandex.ru> <4F3395E1.2090303@oracle.com> <641251328863373@web7.yandex.ru> Message-ID: <4F34F2E9.3070301@oracle.com> On 10/02/12 08:42, Spot Al wrote: > What I want to do is just answer on the question: > If it is possible to create a functional interface without using the method name, why it needs to mention the method name using the functional interface? I think the potential ambiguities at the call-site would seriously undermine code readability. I think this is one of the cases in which, just because you can, it doesn't mean you should ;-) Moreover, we had some experience with the m.() syntax - the first version of the prototype supported it and, well, the reaction hasn't been exactly positive [1]. [1] - http://www.infoq.com/news/2010/06/lambda-syntax-debate Maurizio > > The most serious objection against using the f(x) invocation is the separate namespaces for methods/fields. > In this case just an another syntax which does not mention the method name can be used. For example > double e = exp.(1); // or any other better syntax > > What about the last case which use the default methods, creating the lambda expression and using it without mentioning the method name are the same things. So > ------------------------------------------ > interface Exponent { > double calculate(double x); > void foo() default { ... } > void bar() default { ... } > } > > Exponent exp = (x) -> 1 + x + x * x / 2; // which method is defined? > double e = exp.(1) // which method is invoked? > > In both cases we should care about default methods. > > Thanks, > Alexander. > > > 09.02.2012, 13:46, "Maurizio Cimadamore": >> Hi, >> I think there might be few problems with this approach when unleashed in >> a more widespread way: >> >> *) Java has two separate namespaces for methods/fields - so the >> following would be ambiguous: >> >> Exponent exp = (x) -> 1 + x + x * x / 2; >> void exp(int x) { ... } >> >> exp(3) //? >> >> *) The language does not have such a thing as 'type of a lambda' so, >> there is no way to distinguish between: >> >> SAM s = ()-> { ... } >> >> and >> >> SAM s = new SAM() { ... } >> >> This means that your proposal will apply to all expressions whose type E >> is a functional interface. >> >> *) What if E is a method call? You end up with things like: >> >> Exponent makeExp() { ... } >> >> makeExp()(5); >> >> *) If you have a functional interface with default methods: >> >> interface Exponent { >> double calculate(double x); >> void foo() default { ... } >> void bar() default { ... } >> } >> >> then the fact that the syntactic sugar will rewire the method call to >> 'calculate' (as that's the only abstract method in Exponent) might >> result a bit surprising since there is more than one method available in >> the functional interface. >> >> Maurizio >> >> On 09/02/12 07:41, Spot Al wrote: >> >>> Hi, >>> >>> For example if there is an interface >>> ----------------------------------------------- >>> interface Exponent{ >>> double calculate(double x); >>> } >>> ----------------------------------------------- >>> >>> and I have a lambda expression: >>> ----------------------------------------------- >>> Exponent exp = (x) -> 1 + x + x * x / 2; >>> ----------------------------------------------- >>> >>> would it be possible to get a value like: >>> double e = ep(1); >>> instead of >>> double e = exp.calculate(1); ? >>> >>> Where exp(1) just a syntax sugar for the exp.calculate(1). >>> >>> So if variable a has a lambda type (interface with one method) than a(val1,.., valN) means a.methodName(val1,.., valN)? >>> >>> Thanks, >>> Alexander. From brian.goetz at oracle.com Fri Feb 10 04:33:55 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 10 Feb 2012 07:33:55 -0500 Subject: f(x) syntax sugar in Lambda In-Reply-To: <641251328863373@web7.yandex.ru> References: <434691328773302@web155.yandex.ru> <4F3395E1.2090303@oracle.com> <641251328863373@web7.yandex.ru> Message-ID: <448D96D9-888B-4889-B36B-C622A7C1A8F3@oracle.com> I think, ultimately, this is just discomfort with the committment to functional interfaces instead of function types, and an attempt to backpedal towards a wishy-washy middle ground. I don't see this as offering a compelling enough benefit. On Feb 10, 2012, at 3:42 AM, Spot Al wrote: > What I want to do is just answer on the question: > If it is possible to create a functional interface without using the method name, why it needs to mention the method name using the functional interface? > > The most serious objection against using the f(x) invocation is the separate namespaces for methods/fields. > In this case just an another syntax which does not mention the method name can be used. For example > double e = exp.(1); // or any other better syntax > > What about the last case which use the default methods, creating the lambda expression and using it without mentioning the method name are the same things. So > ------------------------------------------ > interface Exponent { > double calculate(double x); > void foo() default { ... } > void bar() default { ... } > } > > Exponent exp = (x) -> 1 + x + x * x / 2; // which method is defined? > double e = exp.(1) // which method is invoked? > > In both cases we should care about default methods. > > Thanks, > Alexander. > > > 09.02.2012, 13:46, "Maurizio Cimadamore" : >> Hi, >> I think there might be few problems with this approach when unleashed in >> a more widespread way: >> >> *) Java has two separate namespaces for methods/fields - so the >> following would be ambiguous: >> >> Exponent exp = (x) -> 1 + x + x * x / 2; >> void exp(int x) { ... } >> >> exp(3) //? >> >> *) The language does not have such a thing as 'type of a lambda' so, >> there is no way to distinguish between: >> >> SAM s = ()-> { ... } >> >> and >> >> SAM s = new SAM() { ... } >> >> This means that your proposal will apply to all expressions whose type E >> is a functional interface. >> >> *) What if E is a method call? You end up with things like: >> >> Exponent makeExp() { ... } >> >> makeExp()(5); >> >> *) If you have a functional interface with default methods: >> >> interface Exponent { >> double calculate(double x); >> void foo() default { ... } >> void bar() default { ... } >> } >> >> then the fact that the syntactic sugar will rewire the method call to >> 'calculate' (as that's the only abstract method in Exponent) might >> result a bit surprising since there is more than one method available in >> the functional interface. >> >> Maurizio >> >> On 09/02/12 07:41, Spot Al wrote: >> >>> Hi, >>> >>> For example if there is an interface >>> ----------------------------------------------- >>> interface Exponent{ >>> double calculate(double x); >>> } >>> ----------------------------------------------- >>> >>> and I have a lambda expression: >>> ----------------------------------------------- >>> Exponent exp = (x) -> 1 + x + x * x / 2; >>> ----------------------------------------------- >>> >>> would it be possible to get a value like: >>> double e = ep(1); >>> instead of >>> double e = exp.calculate(1); ? >>> >>> Where exp(1) just a syntax sugar for the exp.calculate(1). >>> >>> So if variable a has a lambda type (interface with one method) than a(val1,.., valN) means a.methodName(val1,.., valN)? >>> >>> Thanks, >>> Alexander. > From yshavit at akiban.com Fri Feb 10 08:27:51 2012 From: yshavit at akiban.com (Yuval Shavit) Date: Fri, 10 Feb 2012 11:27:51 -0500 Subject: f(x) syntax sugar in Lambda In-Reply-To: <448D96D9-888B-4889-B36B-C622A7C1A8F3@oracle.com> References: <434691328773302@web155.yandex.ru> <4F3395E1.2090303@oracle.com> <641251328863373@web7.yandex.ru> <448D96D9-888B-4889-B36B-C622A7C1A8F3@oracle.com> Message-ID: This question seems to me to be orthogonal to lambdas. It would apply just as well to JDK 7. Basically, the request (if I understand it correctly) is that if you have a reference whose type is an interface that defines just one method, you should be able to omit the method name in invoking it. There's a certain symmetry that establishes with lambdas, sure -- but the call site doesn't know if the Exponent it got in was defined as a standard class, anonymous class, lambda, proxy, whatever. On Fri, Feb 10, 2012 at 7:33 AM, Brian Goetz wrote: > I think, ultimately, this is just discomfort with the committment to > functional interfaces instead of function types, and an attempt to > backpedal towards a wishy-washy middle ground. I don't see this as > offering a compelling enough benefit. > > On Feb 10, 2012, at 3:42 AM, Spot Al wrote: > > > What I want to do is just answer on the question: > > If it is possible to create a functional interface without using the > method name, why it needs to mention the method name using the functional > interface? > > > > The most serious objection against using the f(x) invocation is the > separate namespaces for methods/fields. > > In this case just an another syntax which does not mention the method > name can be used. For example > > double e = exp.(1); // or any other better syntax > > > > What about the last case which use the default methods, creating the > lambda expression and using it without mentioning the method name are the > same things. So > > ------------------------------------------ > > interface Exponent { > > double calculate(double x); > > void foo() default { ... } > > void bar() default { ... } > > } > > > > Exponent exp = (x) -> 1 + x + x * x / 2; // which method is defined? > > double e = exp.(1) // which method is invoked? > > > > In both cases we should care about default methods. > > > > Thanks, > > Alexander. > > > > > > 09.02.2012, 13:46, "Maurizio Cimadamore" >: > >> Hi, > >> I think there might be few problems with this approach when unleashed in > >> a more widespread way: > >> > >> *) Java has two separate namespaces for methods/fields - so the > >> following would be ambiguous: > >> > >> Exponent exp = (x) -> 1 + x + x * x / 2; > >> void exp(int x) { ... } > >> > >> exp(3) //? > >> > >> *) The language does not have such a thing as 'type of a lambda' so, > >> there is no way to distinguish between: > >> > >> SAM s = ()-> { ... } > >> > >> and > >> > >> SAM s = new SAM() { ... } > >> > >> This means that your proposal will apply to all expressions whose type E > >> is a functional interface. > >> > >> *) What if E is a method call? You end up with things like: > >> > >> Exponent makeExp() { ... } > >> > >> makeExp()(5); > >> > >> *) If you have a functional interface with default methods: > >> > >> interface Exponent { > >> double calculate(double x); > >> void foo() default { ... } > >> void bar() default { ... } > >> } > >> > >> then the fact that the syntactic sugar will rewire the method call to > >> 'calculate' (as that's the only abstract method in Exponent) might > >> result a bit surprising since there is more than one method available in > >> the functional interface. > >> > >> Maurizio > >> > >> On 09/02/12 07:41, Spot Al wrote: > >> > >>> Hi, > >>> > >>> For example if there is an interface > >>> ----------------------------------------------- > >>> interface Exponent{ > >>> double calculate(double x); > >>> } > >>> ----------------------------------------------- > >>> > >>> and I have a lambda expression: > >>> ----------------------------------------------- > >>> Exponent exp = (x) -> 1 + x + x * x / 2; > >>> ----------------------------------------------- > >>> > >>> would it be possible to get a value like: > >>> double e = ep(1); > >>> instead of > >>> double e = exp.calculate(1); ? > >>> > >>> Where exp(1) just a syntax sugar for the exp.calculate(1). > >>> > >>> So if variable a has a lambda type (interface with one method) than > a(val1,.., valN) means a.methodName(val1,.., valN)? > >>> > >>> Thanks, > >>> Alexander. > > > > > From forax at univ-mlv.fr Fri Feb 10 09:08:16 2012 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 10 Feb 2012 18:08:16 +0100 Subject: f(x) syntax sugar in Lambda In-Reply-To: References: <434691328773302@web155.yandex.ru> <4F3395E1.2090303@oracle.com> <641251328863373@web7.yandex.ru> <448D96D9-888B-4889-B36B-C622A7C1A8F3@oracle.com> Message-ID: <4F354F00.7030007@univ-mlv.fr> On 02/10/2012 05:27 PM, Yuval Shavit wrote: > This question seems to me to be orthogonal to lambdas. It would apply just > as well to JDK 7. Basically, the request (if I understand it correctly) is > that if you have a reference whose type is an interface that defines just > one method, you should be able to omit the method name in invoking it. > There's a certain symmetry that establishes with lambdas, sure -- but the > call site doesn't know if the Exponent it got in was defined as a standard > class, anonymous class, lambda, proxy, whatever. The syntax '.()' was already proposed as '.do()' and was rejected for several reasons. As I recall, the main argument was that Java is an OOP language so the idea is to try to integrate lambdas in the plain old OOP syntax, hence use a method call. JavaScript by example choose the other way, all is functions and methods are functions stored in objects. cheers, R?mi > > On Fri, Feb 10, 2012 at 7:33 AM, Brian Goetz wrote: > >> I think, ultimately, this is just discomfort with the committment to >> functional interfaces instead of function types, and an attempt to >> backpedal towards a wishy-washy middle ground. I don't see this as >> offering a compelling enough benefit. >> >> On Feb 10, 2012, at 3:42 AM, Spot Al wrote: >> >>> What I want to do is just answer on the question: >>> If it is possible to create a functional interface without using the >> method name, why it needs to mention the method name using the functional >> interface? >>> The most serious objection against using the f(x) invocation is the >> separate namespaces for methods/fields. >>> In this case just an another syntax which does not mention the method >> name can be used. For example >>> double e = exp.(1); // or any other better syntax >>> >>> What about the last case which use the default methods, creating the >> lambda expression and using it without mentioning the method name are the >> same things. So >>> ------------------------------------------ >>> interface Exponent { >>> double calculate(double x); >>> void foo() default { ... } >>> void bar() default { ... } >>> } >>> >>> Exponent exp = (x) -> 1 + x + x * x / 2; // which method is defined? >>> double e = exp.(1) // which method is invoked? >>> >>> In both cases we should care about default methods. >>> >>> Thanks, >>> Alexander. >>> >>> >>> 09.02.2012, 13:46, "Maurizio Cimadamore">> : >>>> Hi, >>>> I think there might be few problems with this approach when unleashed in >>>> a more widespread way: >>>> >>>> *) Java has two separate namespaces for methods/fields - so the >>>> following would be ambiguous: >>>> >>>> Exponent exp = (x) -> 1 + x + x * x / 2; >>>> void exp(int x) { ... } >>>> >>>> exp(3) //? >>>> >>>> *) The language does not have such a thing as 'type of a lambda' so, >>>> there is no way to distinguish between: >>>> >>>> SAM s = ()-> { ... } >>>> >>>> and >>>> >>>> SAM s = new SAM() { ... } >>>> >>>> This means that your proposal will apply to all expressions whose type E >>>> is a functional interface. >>>> >>>> *) What if E is a method call? You end up with things like: >>>> >>>> Exponent makeExp() { ... } >>>> >>>> makeExp()(5); >>>> >>>> *) If you have a functional interface with default methods: >>>> >>>> interface Exponent { >>>> double calculate(double x); >>>> void foo() default { ... } >>>> void bar() default { ... } >>>> } >>>> >>>> then the fact that the syntactic sugar will rewire the method call to >>>> 'calculate' (as that's the only abstract method in Exponent) might >>>> result a bit surprising since there is more than one method available in >>>> the functional interface. >>>> >>>> Maurizio >>>> >>>> On 09/02/12 07:41, Spot Al wrote: >>>> >>>>> Hi, >>>>> >>>>> For example if there is an interface >>>>> ----------------------------------------------- >>>>> interface Exponent{ >>>>> double calculate(double x); >>>>> } >>>>> ----------------------------------------------- >>>>> >>>>> and I have a lambda expression: >>>>> ----------------------------------------------- >>>>> Exponent exp = (x) -> 1 + x + x * x / 2; >>>>> ----------------------------------------------- >>>>> >>>>> would it be possible to get a value like: >>>>> double e = ep(1); >>>>> instead of >>>>> double e = exp.calculate(1); ? >>>>> >>>>> Where exp(1) just a syntax sugar for the exp.calculate(1). >>>>> >>>>> So if variable a has a lambda type (interface with one method) than >> a(val1,.., valN) means a.methodName(val1,.., valN)? >>>>> Thanks, >>>>> Alexander. >> >> From maurizio.cimadamore at oracle.com Wed Feb 15 22:19:54 2012 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Thu, 16 Feb 2012 06:19:54 +0000 Subject: hg: lambda/lambda/langtools: Fix: recursive lambda causes compiler crash in certain contexts Message-ID: <20120216061959.2FDC947515@hg.openjdk.java.net> Changeset: 8d1d019259da Author: mcimadamore Date: 2012-02-15 22:19 -0800 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/8d1d019259da Fix: recursive lambda causes compiler crash in certain contexts ! src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java + test/tools/javac/lambda/LambdaExpr13.java From bitterfoxc at gmail.com Mon Feb 20 02:03:28 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Mon, 20 Feb 2012 19:03:28 +0900 Subject: Is target-typing for conditional expressions in cast context supported? Message-ID: Hi, when I compile this program, the compiler which is the newest binary snapshot says it is illegal. class Main { interface SAM { void invoke(); } public static void main(String[] args) { Object obj = (SAM)(true ? () -> {} : () -> {}); // Illegal } } I know that there is a compiler option to enable target-typing in method invocation context: -XDcomplexinference But it does not work to this situation. Is there another compiler option to enable target-typing in cast context? Regards, bitter_fox From maurizio.cimadamore at oracle.com Mon Feb 20 04:10:01 2012 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 20 Feb 2012 12:10:01 +0000 Subject: Is target-typing for conditional expressions in cast context supported? In-Reply-To: References: Message-ID: <4F423819.7080004@oracle.com> Hi, target-typing in cast context is still an open issue in both the compiler and the language spec. Maurizio On 20/02/12 10:03, bitter_fox wrote: > Hi, > when I compile this program, the compiler which is the newest binary > snapshot says it is illegal. > > class Main > { > interface SAM > { > void invoke(); > } > > public static void main(String[] args) > { > Object obj = (SAM)(true ? () -> {} : () -> {}); // Illegal > } > } > > I know that there is a compiler option to enable target-typing in method > invocation context: > -XDcomplexinference > But it does not work to this situation. > Is there another compiler option to enable target-typing in cast context? > > Regards, > bitter_fox > From wupuyuan at gmail.com Mon Feb 20 17:22:25 2012 From: wupuyuan at gmail.com (=?GB2312?B?zuLosdSo?=) Date: Tue, 21 Feb 2012 09:22:25 +0800 Subject: How about the performance of lambda Message-ID: Hi, I'm from china and take care of lamdba project these days. I read the doc of http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html very carefully, the lambda spec is so simple, but there is a question about performance. In section 1 background , we get the information that the "callback interface" nearly can not increase the performance by multicore cpu. From wupuyuan at gmail.com Mon Feb 20 17:33:18 2012 From: wupuyuan at gmail.com (=?GB2312?B?zuLosdSo?=) Date: Tue, 21 Feb 2012 09:33:18 +0800 Subject: The question about lambda's performance Message-ID: Hi, I'm from china and take care of lamdba project these days. I'm sorry for last mail is not whole... so I send again. I read the doc of http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html very carefully, the lambda spec is so simple, but there is a question about performance. In section 1 background , we get the information that the "callback interface" nearly can not increase the performance by multicore cpu or parallel-programming. But there is no info in the follow part about the target of lambda. Is there some improvement of JVM about this? I test the "javap -c" to the classes , there are no "invokedynamic" created, and test the cost time of inner classes and lambda ,it seems lambda codes cost a little more time. Thx resd my question! If there are any unclear because my pool English please note me! B&R From brian.goetz at oracle.com Mon Feb 20 18:48:07 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 20 Feb 2012 21:48:07 -0500 Subject: The question about lambda's performance In-Reply-To: References: Message-ID: <4F4305E7.5030702@oracle.com> Thanks for trying out the implementation! We are still very much in the prototype stage of the development of the implementation. Currently the compiler generates inner classes, but that is definitely a temporary strategy. Our focus has been exclusively on delivering something that works, so people can try it out. Many shortcuts have been taken to get something in people's hands as early as possible, so that we could get feedback on the usability of the features. Any conclusions drawn from performance measurements at this time would definitely be premature. On 2/20/2012 8:33 PM, ??? wrote: > Hi, I'm from china and take care of lamdba project these days. > > I'm sorry for last mail is not whole... so I send again. > > I read the doc of > http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html very > carefully, the lambda spec is so simple, but there is a question about > performance. > > In section 1 background , we get the information that the "callback > interface" nearly can not increase the performance by multicore cpu or > parallel-programming. But there is no info in the follow part about the > target of lambda. Is there some improvement of JVM about this? > > I test the "javap -c" to the classes , there are no "invokedynamic" > created, and test the cost time of inner classes and lambda ,it seems > lambda codes cost a little more time. > > Thx resd my question! If there are any unclear because my pool English > please note me! > B&R > From wupuyuan at gmail.com Mon Feb 20 18:57:55 2012 From: wupuyuan at gmail.com (=?GB2312?B?zuLosdSo?=) Date: Tue, 21 Feb 2012 10:57:55 +0800 Subject: The question about lambda's performance In-Reply-To: <4F4305E7.5030702@oracle.com> References: <4F4305E7.5030702@oracle.com> Message-ID: Thx for your reply , are there some blogs or doces about the plan and so on ? 2012/2/21 Brian Goetz > Thanks for trying out the implementation! > > We are still very much in the prototype stage of the development of the > implementation. Currently the compiler generates inner classes, but that > is definitely a temporary strategy. Our focus has been exclusively on > delivering something that works, so people can try it out. Many shortcuts > have been taken to get something in people's hands as early as possible, so > that we could get feedback on the usability of the features. > > Any conclusions drawn from performance measurements at this time would > definitely be premature. > > > > On 2/20/2012 8:33 PM, ?????? wrote: > >> Hi, I'm from china and take care of lamdba project these days. >> >> I'm sorry for last mail is not whole... so I send again. >> >> I read the doc of >> http://cr.openjdk.java.net/~**briangoetz/lambda/lambda-**state-4.htmlvery >> carefully, the lambda spec is so simple, but there is a question about >> performance. >> >> In section 1 background , we get the information that the "callback >> interface" nearly can not increase the performance by multicore cpu or >> parallel-programming. But there is no info in the follow part about the >> target of lambda. Is there some improvement of JVM about this? >> >> I test the "javap -c" to the classes , there are no "invokedynamic" >> created, and test the cost time of inner classes and lambda ,it seems >> lambda codes cost a little more time. >> >> Thx resd my question! If there are any unclear because my pool English >> please note me! >> B&R >> >> From brian.goetz at oracle.com Mon Feb 20 20:31:40 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 20 Feb 2012 23:31:40 -0500 Subject: The question about lambda's performance In-Reply-To: References: <4F4305E7.5030702@oracle.com> Message-ID: <4F431E2C.1080700@oracle.com> We post docs here as they become available. Watch this space! On 2/20/2012 9:57 PM, ?????? wrote: > Thx for your reply , are there some blogs or doces about the plan and so > on ? > > 2012/2/21 Brian Goetz > > > Thanks for trying out the implementation! > > We are still very much in the prototype stage of the development of > the implementation. Currently the compiler generates inner classes, > but that is definitely a temporary strategy. Our focus has been > exclusively on delivering something that works, so people can try it > out. Many shortcuts have been taken to get something in people's > hands as early as possible, so that we could get feedback on the > usability of the features. > > Any conclusions drawn from performance measurements at this time > would definitely be premature. > > > > On 2/20/2012 8:33 PM, ?????? wrote: > > Hi, I'm from china and take care of lamdba project these days. > > I'm sorry for last mail is not whole... so I send again. > > I read the doc of > http://cr.openjdk.java.net/~__briangoetz/lambda/lambda-__state-4.html > > very > carefully, the lambda spec is so simple, but there is a question > about > performance. > > In section 1 background , we get the information that the "callback > interface" nearly can not increase the performance by multicore > cpu or > parallel-programming. But there is no info in the follow part > about the > target of lambda. Is there some improvement of JVM about this? > > I test the "javap -c" to the classes , there are no "invokedynamic" > created, and test the cost time of inner classes and lambda ,it > seems > lambda codes cost a little more time. > > Thx resd my question! If there are any unclear because my pool > English > please note me! > B&R > > From bitterfoxc at gmail.com Tue Feb 21 02:57:46 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Tue, 21 Feb 2012 19:57:46 +0900 Subject: Is target-typing for conditional expressions in cast context supported? In-Reply-To: <4F423819.7080004@oracle.com> References: <4F423819.7080004@oracle.com> Message-ID: Oh, I see it hasn't been implemented now. I wait for the specification and the implementation. Thank you. Regards, bitter_fox 2012/2/20 Maurizio Cimadamore > Hi, > target-typing in cast context is still an open issue in both the compiler > and the language spec. > > Maurizio > > > On 20/02/12 10:03, bitter_fox wrote: > >> Hi, >> when I compile this program, the compiler which is the newest binary >> snapshot says it is illegal. >> >> class Main >> { >> interface SAM >> { >> void invoke(); >> } >> >> public static void main(String[] args) >> { >> Object obj = (SAM)(true ? () -> {} : () -> {}); // Illegal >> } >> } >> >> I know that there is a compiler option to enable target-typing in method >> invocation context: >> -XDcomplexinference >> But it does not work to this situation. >> Is there another compiler option to enable target-typing in cast context? >> >> Regards, >> bitter_fox >> >> > From pholser at gmail.com Tue Feb 21 14:31:29 2012 From: pholser at gmail.com (Paul Holser) Date: Tue, 21 Feb 2012 16:31:29 -0600 Subject: method references: type inference, toString() Message-ID: Hi lambda-dev, Using JDK 8 Developer Preview with lambda support (http://download.java.net/lambda/b25/windows-i586/lambda-8-b25-windows-i586-05_feb_2012.zip), Guava 11.0, Hamcrest 1.3.RC2, and JUnit 4.10 (sans Hamcrest classes). org.hamcrest.Matcher is not a SAM type, whereas com.google.common.base.Predicate is. Compiling Main.java: ==== begin Main.java ==== import com.google.common.base.Predicate; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.Test; import static org.hamcrest.MatcherAssert.assertThat; interface Foo { boolean isBar(); } abstract class PredicateMatcher extends TypeSafeMatcher { protected final Predicate predicate; private PredicateMatcher(Predicate predicate) { this.predicate = predicate; } @Override public final boolean matchesSafely(T target) { return predicate.apply(target); } public static PredicateMatcher matches(Predicate predicate) { return new PredicateMatcher(predicate) { @Override public void describeTo(Description description) { description.appendText("a value acceptable to predicate "); description.appendValue(this.predicate); } }; } } class BarredUpFoo implements Foo { @Override public boolean isBar() { return true; } } class BarredUpFooTest { @Test public void bar() { assertThat(new BarredUpFoo(), PredicateMatcher.matches(Foo::isBar)); } } public class Main { public static void main(String... args) { Predicate bar = Foo::isBar; System.out.println(bar); } } ==== end Main.java ==== yields: ==== begin console output ==== Main.java:41: error: no suitable method found for matches(member reference) assertThat(new BarredUpFoo(), PredicateMatcher.matches(Foo::isBar)); ^ method PredicateMatcher.matches(Predicate) is not applicable (cyclic inference - cannot infer target type for given lambda/method refer ence expression) method TypeSafeMatcher.matches(Object) is not applicable (actual argument member reference cannot be converted to Object by method invocation conversion (the target type of a lambda conversion must be an interface)) where U is a type-variable: U extends Object declared in method matches(Predicate) 1 error ==== end console output ==== Couple of questions: 1) Should the usage of Foo::isBar as the predicate fed to PredicateMatcher.matches() compile successfully? I'm hoping not to have to perform the SAM conversion by hand: Predicate bar = Foo::isBar; assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); In Main.main(), I perform that SAM conversion by hand, as you can see -- otherwise, it won't know to choose PrintStream.println(Object), it says "(actual argument member reference cannot be converted to Object by method invocation conversion)". 2) Wondering if it wouldn't be too much trouble to have method references respond to toString() with something like "Foo::isBar" or "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd make the output of PredicateMatcher.matches() really slick. Thanks for the help, and the great work thus far! Cheers, Paul Holser From bitterfoxc at gmail.com Tue Feb 21 14:44:24 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Wed, 22 Feb 2012 07:44:24 +0900 Subject: Recursive lambda on field declarations in local classes and anonymous classes. Message-ID: Hi, To use recursive lambda expressions, we have to use that statement: SAM sam = () -> sam.invoke(); However, the newest compiler rejects it on field declarations in local classes and anonymous classes. Cannot we use recursive lambda expressions in these situations? public class Main { interface SAM { void invoke(); } SAM sam = () -> sam.invoke(); // Legal class Inner { SAM sam = () -> sam.invoke(); // Legal } Object obj = new Object() { SAM sam = () -> sam.invoke(); // Illegal }; public static void main(String[] args) { class Local { SAM sam = () -> sam.invoke(); // Illegal } new Object() { SAM sam = () -> sam.invoke(); // Illegal }; } public void method() { class Local { SAM sam = () -> sam.invoke(); // Illegal } new Object() { SAM sam = () -> sam.invoke(); // Illegal }; } } Regards, bitter_fox From brian.goetz at oracle.com Tue Feb 21 15:07:38 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 21 Feb 2012 18:07:38 -0500 Subject: method references: type inference, toString() In-Reply-To: References: Message-ID: <4F4423BA.7090203@oracle.com> > 1) Should the usage of Foo::isBar as the predicate fed to > PredicateMatcher.matches() compile successfully? I'm hoping not to > have to perform the SAM conversion by hand: > > Predicate bar = Foo::isBar; > assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); Without answering the question on whether the inference should succeed or not (the exact details of type inference are currently in flux), I'll point out that there is a less intrusive form of "by hand" that can be used to provide the needed additional type info to the compiler -- use a cast to provide the target type. This is less intrusive that having to name a local variable. assertThat(new BarredUpFoo(), PredicateMatcher.matches((Predicate) Foo::isBar)); > 2) Wondering if it wouldn't be too much trouble to have method > references respond to toString() with something like "Foo::isBar" or > "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd > make the output of PredicateMatcher.matches() really slick. Yes, the details of this are being actively discussed in the EG, and is a desirable goal. Lots of details to work out, of course. From maurizio.cimadamore at oracle.com Tue Feb 21 15:32:19 2012 From: maurizio.cimadamore at oracle.com (maurizio cimadamore) Date: Tue, 21 Feb 2012 23:32:19 +0000 Subject: Recursive lambda on field declarations in local classes and anonymous classes. In-Reply-To: References: Message-ID: <4F442983.9040005@oracle.com> I will look into this - thanks for the report. Maurizio On 21-Feb-12 10:44 PM, bitter_fox wrote: > Hi, > To use recursive lambda expressions, we have to use that statement: > SAM sam = () -> sam.invoke(); > > However, the newest compiler rejects it on field declarations in local > classes and anonymous classes. > Cannot we use recursive lambda expressions in these situations? > > public class Main > { > interface SAM > { > void invoke(); > } > > SAM sam = () -> sam.invoke(); // Legal > > class Inner > { > SAM sam = () -> sam.invoke(); // Legal > } > > Object obj = new Object() > { > SAM sam = () -> sam.invoke(); // Illegal > }; > > public static void main(String[] args) > { > class Local > { > SAM sam = () -> sam.invoke(); // Illegal > } > > new Object() > { > SAM sam = () -> sam.invoke(); // Illegal > }; > } > > public void method() > { > class Local > { > SAM sam = () -> sam.invoke(); // Illegal > } > > new Object() > { > SAM sam = () -> sam.invoke(); // Illegal > }; > } > } > > Regards, > bitter_fox > From forax at univ-mlv.fr Tue Feb 21 15:34:16 2012 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 22 Feb 2012 00:34:16 +0100 Subject: method references: type inference, toString() In-Reply-To: References: Message-ID: <4F4429F8.4000806@univ-mlv.fr> On 02/21/2012 11:31 PM, Paul Holser wrote: > Hi lambda-dev, > > Using JDK 8 Developer Preview with lambda support > (http://download.java.net/lambda/b25/windows-i586/lambda-8-b25-windows-i586-05_feb_2012.zip), > Guava 11.0, Hamcrest 1.3.RC2, and JUnit 4.10 (sans Hamcrest classes). > > org.hamcrest.Matcher is not a SAM type, whereas > com.google.common.base.Predicate is. > > Compiling Main.java: > > ==== begin Main.java ==== > import com.google.common.base.Predicate; > import org.hamcrest.Description; > import org.hamcrest.TypeSafeMatcher; > import org.junit.Test; > > import static org.hamcrest.MatcherAssert.assertThat; > > interface Foo { > boolean isBar(); > } > > abstract class PredicateMatcher extends TypeSafeMatcher { > protected final Predicate predicate; > > private PredicateMatcher(Predicate predicate) { > this.predicate = predicate; > } > > @Override public final boolean matchesSafely(T target) { > return predicate.apply(target); > } > > public static PredicateMatcher matches(Predicate > predicate) { > return new PredicateMatcher(predicate) { > @Override public void describeTo(Description description) { > description.appendText("a value acceptable to predicate "); > description.appendValue(this.predicate); > } > }; > } > } > > class BarredUpFoo implements Foo { > @Override public boolean isBar() { > return true; > } > } > > class BarredUpFooTest { > @Test public void bar() { > assertThat(new BarredUpFoo(), PredicateMatcher.matches(Foo::isBar)); > } > } > > public class Main { > public static void main(String... args) { > Predicate bar = Foo::isBar; > System.out.println(bar); > } > } > ==== end Main.java ==== > > yields: > > ==== begin console output ==== > Main.java:41: error: no suitable method found for matches(member reference) > assertThat(new BarredUpFoo(), PredicateMatcher.matches(Foo::isBar)); > ^ > method PredicateMatcher.matches(Predicate) is not applicable > (cyclic inference - cannot infer target type for given lambda/method refer > ence expression) > method TypeSafeMatcher.matches(Object) is not applicable > (actual argument member reference cannot be converted to Object by method > invocation conversion > (the target type of a lambda conversion must be an interface)) > where U is a type-variable: > U extends Object declared in methodmatches(Predicate) > 1 error > ==== end console output ==== > > Couple of questions: > > 1) Should the usage of Foo::isBar as the predicate fed to > PredicateMatcher.matches() compile successfully? I'm hoping not to > have to perform the SAM conversion by hand: > > Predicate bar = Foo::isBar; > assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); > > In Main.main(), I perform that SAM conversion by hand, as you can see > -- otherwise, it won't know to choose PrintStream.println(Object), it > says "(actual argument member reference cannot be converted to Object > by method invocation conversion)". I only answer easy question, I let this one to Maurizio :) > > 2) Wondering if it wouldn't be too much trouble to have method > references respond to toString() with something like "Foo::isBar" or > "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd > make the output of PredicateMatcher.matches() really slick. There are two major problems. First security, if toString() exposes declaring class and method name you may show to much information for an attacker. Don't forget that the class may be non public and the method private. Second, performance, we want a VM to be able to implement the SAM conversion as a kind of proxy around a function pointer, i.e something that may not carry around the fat Object data structure. One possible solution. Because we also want lambda/method reference to be Serializable we are discussing an opt-in mechanism that will allow lambdas to be Serializable by having a stable name (thus a meaningful toString). But this kind of lambda may be less thin (and perhaps less efficient). > > Thanks for the help, and the great work thus far! > > Cheers, > Paul Holser > cheers, R?mi From vitalyd at gmail.com Tue Feb 21 16:16:39 2012 From: vitalyd at gmail.com (Vitaly Davidovich) Date: Tue, 21 Feb 2012 19:16:39 -0500 Subject: method references: type inference, toString() In-Reply-To: <4F4429F8.4000806@univ-mlv.fr> References: <4F4429F8.4000806@univ-mlv.fr> Message-ID: As they say, security by obscurity is not security :). I can see performance as an argument, but the security aspect seems invalid. Sent from my phone On Feb 21, 2012 6:33 PM, "R?mi Forax" wrote: > On 02/21/2012 11:31 PM, Paul Holser wrote: > > Hi lambda-dev, > > > > Using JDK 8 Developer Preview with lambda support > > ( > http://download.java.net/lambda/b25/windows-i586/lambda-8-b25-windows-i586-05_feb_2012.zip > ), > > Guava 11.0, Hamcrest 1.3.RC2, and JUnit 4.10 (sans Hamcrest classes). > > > > org.hamcrest.Matcher is not a SAM type, whereas > > com.google.common.base.Predicate is. > > > > Compiling Main.java: > > > > ==== begin Main.java ==== > > import com.google.common.base.Predicate; > > import org.hamcrest.Description; > > import org.hamcrest.TypeSafeMatcher; > > import org.junit.Test; > > > > import static org.hamcrest.MatcherAssert.assertThat; > > > > interface Foo { > > boolean isBar(); > > } > > > > abstract class PredicateMatcher extends TypeSafeMatcher { > > protected final Predicate predicate; > > > > private PredicateMatcher(Predicate predicate) { > > this.predicate = predicate; > > } > > > > @Override public final boolean matchesSafely(T target) { > > return predicate.apply(target); > > } > > > > public static PredicateMatcher matches(Predicate > > predicate) { > > return new PredicateMatcher(predicate) { > > @Override public void describeTo(Description description) { > > description.appendText("a value acceptable to predicate > "); > > description.appendValue(this.predicate); > > } > > }; > > } > > } > > > > class BarredUpFoo implements Foo { > > @Override public boolean isBar() { > > return true; > > } > > } > > > > class BarredUpFooTest { > > @Test public void bar() { > > assertThat(new BarredUpFoo(), > PredicateMatcher.matches(Foo::isBar)); > > } > > } > > > > public class Main { > > public static void main(String... args) { > > Predicate bar = Foo::isBar; > > System.out.println(bar); > > } > > } > > ==== end Main.java ==== > > > > yields: > > > > ==== begin console output ==== > > Main.java:41: error: no suitable method found for matches(member > reference) > > assertThat(new BarredUpFoo(), > PredicateMatcher.matches(Foo::isBar)); > > ^ > > method PredicateMatcher.matches(Predicate) is not > applicable > > (cyclic inference - cannot infer target type for given > lambda/method refer > > ence expression) > > method TypeSafeMatcher.matches(Object) is not applicable > > (actual argument member reference cannot be converted to Object > by method > > invocation conversion > > (the target type of a lambda conversion must be an interface)) > > where U is a type-variable: > > U extends Object declared in methodmatches(Predicate) > > 1 error > > ==== end console output ==== > > > > Couple of questions: > > > > 1) Should the usage of Foo::isBar as the predicate fed to > > PredicateMatcher.matches() compile successfully? I'm hoping not to > > have to perform the SAM conversion by hand: > > > > Predicate bar = Foo::isBar; > > assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); > > > > In Main.main(), I perform that SAM conversion by hand, as you can see > > -- otherwise, it won't know to choose PrintStream.println(Object), it > > says "(actual argument member reference cannot be converted to Object > > by method invocation conversion)". > > I only answer easy question, I let this one to Maurizio :) > > > > > 2) Wondering if it wouldn't be too much trouble to have method > > references respond to toString() with something like "Foo::isBar" or > > "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd > > make the output of PredicateMatcher.matches() really slick. > > There are two major problems. > First security, if toString() exposes declaring class and method name > you may show to much information for an attacker. Don't forget that > the class may be non public and the method private. > Second, performance, we want a VM to be able to implement the SAM > conversion as a kind of proxy around a function pointer, i.e something > that may not carry around the fat Object data structure. > > One possible solution. > Because we also want lambda/method reference to be Serializable > we are discussing an opt-in mechanism that will allow lambdas to > be Serializable by having a stable name (thus a meaningful toString). > But this kind of lambda may be less thin (and perhaps less efficient). > > > > > Thanks for the help, and the great work thus far! > > > > Cheers, > > Paul Holser > > > > cheers, > R?mi > > > > > From forax at univ-mlv.fr Tue Feb 21 16:35:05 2012 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 22 Feb 2012 01:35:05 +0100 Subject: method references: type inference, toString() In-Reply-To: References: <4F4429F8.4000806@univ-mlv.fr> Message-ID: <4F443839.5070004@univ-mlv.fr> On 02/22/2012 01:16 AM, Vitaly Davidovich wrote: > > As they say, security by obscurity is not security :). I can see > performance as an argument, but the security aspect seems invalid. > I agree, here security == part of the Java security model like when you call Class.getDeclaredMethods http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getDeclaredMethods%28%29 cheers, R?mi > Sent from my phone > > On Feb 21, 2012 6:33 PM, "R?mi Forax" > wrote: > > On 02/21/2012 11:31 PM, Paul Holser wrote: > > Hi lambda-dev, > > > > Using JDK 8 Developer Preview with lambda support > > > (http://download.java.net/lambda/b25/windows-i586/lambda-8-b25-windows-i586-05_feb_2012.zip), > > Guava 11.0, Hamcrest 1.3.RC2, and JUnit 4.10 (sans Hamcrest > classes). > > > > org.hamcrest.Matcher is not a SAM type, whereas > > com.google.common.base.Predicate is. > > > > Compiling Main.java: > > > > ==== begin Main.java ==== > > import com.google.common.base.Predicate; > > import org.hamcrest.Description; > > import org.hamcrest.TypeSafeMatcher; > > import org.junit.Test; > > > > import static org.hamcrest.MatcherAssert.assertThat; > > > > interface Foo { > > boolean isBar(); > > } > > > > abstract class PredicateMatcher extends TypeSafeMatcher { > > protected final Predicate predicate; > > > > private PredicateMatcher(Predicate predicate) { > > this.predicate = predicate; > > } > > > > @Override public final boolean matchesSafely(T target) { > > return predicate.apply(target); > > } > > > > public static PredicateMatcher matches(Predicate super U> > > predicate) { > > return new PredicateMatcher(predicate) { > > @Override public void describeTo(Description > description) { > > description.appendText("a value acceptable to > predicate "); > > description.appendValue(this.predicate); > > } > > }; > > } > > } > > > > class BarredUpFoo implements Foo { > > @Override public boolean isBar() { > > return true; > > } > > } > > > > class BarredUpFooTest { > > @Test public void bar() { > > assertThat(new BarredUpFoo(), > PredicateMatcher.matches(Foo::isBar)); > > } > > } > > > > public class Main { > > public static void main(String... args) { > > Predicate bar = Foo::isBar; > > System.out.println(bar); > > } > > } > > ==== end Main.java ==== > > > > yields: > > > > ==== begin console output ==== > > Main.java:41: error: no suitable method found for matches(member > reference) > > assertThat(new BarredUpFoo(), > PredicateMatcher.matches(Foo::isBar)); > > ^ > > method PredicateMatcher.matches(Predicate) is > not applicable > > (cyclic inference - cannot infer target type for given > lambda/method refer > > ence expression) > > method TypeSafeMatcher.matches(Object) is not applicable > > (actual argument member reference cannot be converted to > Object by method > > invocation conversion > > (the target type of a lambda conversion must be an > interface)) > > where U is a type-variable: > > U extends Object declared in methodmatches(Predicate super U>) > > 1 error > > ==== end console output ==== > > > > Couple of questions: > > > > 1) Should the usage of Foo::isBar as the predicate fed to > > PredicateMatcher.matches() compile successfully? I'm hoping not to > > have to perform the SAM conversion by hand: > > > > Predicate bar = Foo::isBar; > > assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); > > > > In Main.main(), I perform that SAM conversion by hand, as you > can see > > -- otherwise, it won't know to choose > PrintStream.println(Object), it > > says "(actual argument member reference cannot be converted to > Object > > by method invocation conversion)". > > I only answer easy question, I let this one to Maurizio :) > > > > > 2) Wondering if it wouldn't be too much trouble to have method > > references respond to toString() with something like "Foo::isBar" or > > "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd > > make the output of PredicateMatcher.matches() really slick. > > There are two major problems. > First security, if toString() exposes declaring class and method name > you may show to much information for an attacker. Don't forget that > the class may be non public and the method private. > Second, performance, we want a VM to be able to implement the SAM > conversion as a kind of proxy around a function pointer, i.e something > that may not carry around the fat Object data structure. > > One possible solution. > Because we also want lambda/method reference to be Serializable > we are discussing an opt-in mechanism that will allow lambdas to > be Serializable by having a stable name (thus a meaningful toString). > But this kind of lambda may be less thin (and perhaps less efficient). > > > > > Thanks for the help, and the great work thus far! > > > > Cheers, > > Paul Holser > > > > cheers, > R?mi > > > > From vitalyd at gmail.com Tue Feb 21 16:38:11 2012 From: vitalyd at gmail.com (Vitaly Davidovich) Date: Tue, 21 Feb 2012 19:38:11 -0500 Subject: method references: type inference, toString() In-Reply-To: <4F443839.5070004@univ-mlv.fr> References: <4F4429F8.4000806@univ-mlv.fr> <4F443839.5070004@univ-mlv.fr> Message-ID: Sure but that returns a method handle whereas the conversation is just about pretty printing in the debugger/toString. Moreover, caller already has a lambda for the underlying method and so can invoke it - I just don't see what type of security concern we're talking about. Sent from my phone On Feb 21, 2012 7:33 PM, "R?mi Forax" wrote: > On 02/22/2012 01:16 AM, Vitaly Davidovich wrote: > >> >> As they say, security by obscurity is not security :). I can see >> performance as an argument, but the security aspect seems invalid. >> >> > I agree, here security == part of the Java security model > like when you call Class.getDeclaredMethods > http://docs.oracle.com/javase/**7/docs/api/java/lang/Class.** > html#getDeclaredMethods%28%29 > > cheers, > R?mi > > Sent from my phone >> >> On Feb 21, 2012 6:33 PM, "R?mi Forax" > forax at univ-mlv.fr>> wrote: >> >> On 02/21/2012 11:31 PM, Paul Holser wrote: >> > Hi lambda-dev, >> > >> > Using JDK 8 Developer Preview with lambda support >> > >> (http://download.java.net/**lambda/b25/windows-i586/** >> lambda-8-b25-windows-i586-05_**feb_2012.zip >> ), >> > Guava 11.0, Hamcrest 1.3.RC2, and JUnit 4.10 (sans Hamcrest >> classes). >> > >> > org.hamcrest.Matcher is not a SAM type, whereas >> > com.google.common.base.**Predicate is. >> > >> > Compiling Main.java: >> > >> > ==== begin Main.java ==== >> > import com.google.common.base.**Predicate; >> > import org.hamcrest.Description; >> > import org.hamcrest.TypeSafeMatcher; >> > import org.junit.Test; >> > >> > import static org.hamcrest.MatcherAssert.**assertThat; >> > >> > interface Foo { >> > boolean isBar(); >> > } >> > >> > abstract class PredicateMatcher extends TypeSafeMatcher { >> > protected final Predicate predicate; >> > >> > private PredicateMatcher(Predicate predicate) { >> > this.predicate = predicate; >> > } >> > >> > @Override public final boolean matchesSafely(T target) { >> > return predicate.apply(target); >> > } >> > >> > public static PredicateMatcher matches(Predicate> super U> >> > predicate) { >> > return new PredicateMatcher(predicate) { >> > @Override public void describeTo(Description >> description) { >> > description.appendText("a value acceptable to >> predicate "); >> > description.appendValue(this.**predicate); >> > } >> > }; >> > } >> > } >> > >> > class BarredUpFoo implements Foo { >> > @Override public boolean isBar() { >> > return true; >> > } >> > } >> > >> > class BarredUpFooTest { >> > @Test public void bar() { >> > assertThat(new BarredUpFoo(), >> PredicateMatcher.matches(Foo::**isBar)); >> > } >> > } >> > >> > public class Main { >> > public static void main(String... args) { >> > Predicate bar = Foo::isBar; >> > System.out.println(bar); >> > } >> > } >> > ==== end Main.java ==== >> > >> > yields: >> > >> > ==== begin console output ==== >> > Main.java:41: error: no suitable method found for matches(member >> reference) >> > assertThat(new BarredUpFoo(), >> PredicateMatcher.matches(Foo::**isBar)); >> > ^ >> > method PredicateMatcher.matches(**Predicate) is >> not applicable >> > (cyclic inference - cannot infer target type for given >> lambda/method refer >> > ence expression) >> > method TypeSafeMatcher.matches(**Object) is not applicable >> > (actual argument member reference cannot be converted to >> Object by method >> > invocation conversion >> > (the target type of a lambda conversion must be an >> interface)) >> > where U is a type-variable: >> > U extends Object declared in methodmatches(Predicate> super U>) >> > 1 error >> > ==== end console output ==== >> > >> > Couple of questions: >> > >> > 1) Should the usage of Foo::isBar as the predicate fed to >> > PredicateMatcher.matches() compile successfully? I'm hoping not to >> > have to perform the SAM conversion by hand: >> > >> > Predicate bar = Foo::isBar; >> > assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); >> > >> > In Main.main(), I perform that SAM conversion by hand, as you >> can see >> > -- otherwise, it won't know to choose >> PrintStream.println(Object), it >> > says "(actual argument member reference cannot be converted to >> Object >> > by method invocation conversion)". >> >> I only answer easy question, I let this one to Maurizio :) >> >> > >> > 2) Wondering if it wouldn't be too much trouble to have method >> > references respond to toString() with something like "Foo::isBar" or >> > "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd >> > make the output of PredicateMatcher.matches() really slick. >> >> There are two major problems. >> First security, if toString() exposes declaring class and method name >> you may show to much information for an attacker. Don't forget that >> the class may be non public and the method private. >> Second, performance, we want a VM to be able to implement the SAM >> conversion as a kind of proxy around a function pointer, i.e something >> that may not carry around the fat Object data structure. >> >> One possible solution. >> Because we also want lambda/method reference to be Serializable >> we are discussing an opt-in mechanism that will allow lambdas to >> be Serializable by having a stable name (thus a meaningful toString). >> But this kind of lambda may be less thin (and perhaps less efficient). >> >> > >> > Thanks for the help, and the great work thus far! >> > >> > Cheers, >> > Paul Holser >> > >> >> cheers, >> R?mi >> >> >> >> >> > From maurizio.cimadamore at oracle.com Wed Feb 22 05:41:38 2012 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Wed, 22 Feb 2012 13:41:38 +0000 Subject: hg: lambda/lambda/langtools: Fix: spurious errors for self-reference and forward references inside a lambda Message-ID: <20120222134145.119D547629@hg.openjdk.java.net> Changeset: 65deb983ecd7 Author: mcimadamore Date: 2012-02-22 13:41 +0000 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/65deb983ecd7 Fix: spurious errors for self-reference and forward references inside a lambda ! src/share/classes/com/sun/tools/javac/comp/Attr.java + test/tools/javac/lambda/TestSelfRef.java From pholser at gmail.com Wed Feb 22 06:50:11 2012 From: pholser at gmail.com (Paul Holser) Date: Wed, 22 Feb 2012 08:50:11 -0600 Subject: method references: type inference, toString() In-Reply-To: <4F4423BA.7090203@oracle.com> References: <4F4423BA.7090203@oracle.com> Message-ID: Thanks for the prompt response, and for the reminder about the cast. Eager to see how things shake out with type inference! --p On Tue, Feb 21, 2012 at 5:07 PM, Brian Goetz wrote: >> 1) Should the usage of Foo::isBar as the predicate fed to >> PredicateMatcher.matches() compile successfully? I'm hoping not to >> have to perform the SAM conversion by hand: >> >> ? ? Predicate ?bar = Foo::isBar; >> ? ? assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); > > > Without answering the question on whether the inference should succeed or > not (the exact details of type inference are currently in flux), I'll point > out that there is a less intrusive form of "by hand" that can be used to > provide the needed additional type info to the compiler -- use a cast to > provide the target type. ?This is less intrusive that having to name a local > variable. > > ?assertThat(new BarredUpFoo(), > ? ? ? ? ? ? PredicateMatcher.matches((Predicate) Foo::isBar)); > > >> 2) Wondering if it wouldn't be too much trouble to have method >> references respond to toString() with something like "Foo::isBar" or >> "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd >> make the output of PredicateMatcher.matches() really slick. > > > Yes, the details of this are being actively discussed in the EG, and is a > desirable goal. ?Lots of details to work out, of course. From bitterfoxc at gmail.com Wed Feb 22 07:24:32 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Thu, 23 Feb 2012 00:24:32 +0900 Subject: Recursive lambda on field declarations in local classes and anonymous classes. In-Reply-To: <4F442983.9040005@oracle.com> References: <4F442983.9040005@oracle.com> Message-ID: I've just got the fix. Thank you for the fix. Regards, bitter_fox 2012/2/22 maurizio cimadamore > I will look into this - thanks for the report. > > Maurizio > > > On 21-Feb-12 10:44 PM, bitter_fox wrote: > >> Hi, >> To use recursive lambda expressions, we have to use that statement: >> SAM sam = () -> sam.invoke(); >> >> However, the newest compiler rejects it on field declarations in local >> classes and anonymous classes. >> Cannot we use recursive lambda expressions in these situations? >> >> public class Main >> { >> interface SAM >> { >> void invoke(); >> } >> >> SAM sam = () -> sam.invoke(); // Legal >> >> class Inner >> { >> SAM sam = () -> sam.invoke(); // Legal >> } >> >> Object obj = new Object() >> { >> SAM sam = () -> sam.invoke(); // Illegal >> }; >> >> public static void main(String[] args) >> { >> class Local >> { >> SAM sam = () -> sam.invoke(); // Illegal >> } >> >> new Object() >> { >> SAM sam = () -> sam.invoke(); // Illegal >> }; >> } >> >> public void method() >> { >> class Local >> { >> SAM sam = () -> sam.invoke(); // Illegal >> } >> >> new Object() >> { >> SAM sam = () -> sam.invoke(); // Illegal >> }; >> } >> } >> >> Regards, >> bitter_fox >> >> > From bitterfoxc at gmail.com Wed Feb 22 07:26:09 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Thu, 23 Feb 2012 00:26:09 +0900 Subject: method references: type inference, toString() In-Reply-To: References: Message-ID: 2012/2/22 Paul Holser > Hi lambda-dev, > > 1) Should the usage of Foo::isBar as the predicate fed to > PredicateMatcher.matches() compile successfully? I'm hoping not to > have to perform the SAM conversion by hand: > > Predicate bar = Foo::isBar; > assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); Maybe in this case you don't need to convert by hand, if you help type inference: assertThat(new BarredUpFoo(), PredicateMatcher.matches(Foo::isBar); My sample works well: import java.util.functions.Predicate; public class Test extends SuperTest { interface Foo { boolean isBar(); } public static void create(Predicate p) {} public static void main(String[] args) { //Test.create(Foo::isBar); // Error Test.create(Foo::isBar); } } class SuperTest { public static void create(Object o) {} } Regards, bitter_fox From maurizio.cimadamore at oracle.com Wed Feb 22 08:28:28 2012 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 22 Feb 2012 16:28:28 +0000 Subject: method references: type inference, toString() In-Reply-To: References: <4F4423BA.7090203@oracle.com> Message-ID: <4F4517AC.3010502@oracle.com> On 22/02/12 14:50, Paul Holser wrote: > Thanks for the prompt response, and for the reminder about the cast. > Eager to see how things shake out with type inference! As Brian said, details of type-inference are being figured out as we speak. The design space is, as you can imagine, fairly big, and solutions might vary from a full-blown global type-inferencer (a la ML) to strategies that work in a more local environment. We think that the latter strategies have better chance of succeeding in the Java ecosystem - one important consequence of adopting a global inference scheme is that diagnostics are usually pretty bad when things go wrong, as some inference error in some nested expression might trigger a type-error at a later stage in a seemingly unrelated expression. We would also like to maintain the invariant that the outcome of overload resolution should _not_ depend on the target type - i.e. the process for selecting an overloaded method is defined independently from the target type - same applies for the most specific routine. This means that in your case, where you have the following expression: assertThat(new BarredUpFoo(), Predicates.matches(Foo::isBar)); A local type-inferencer will not, in the general case, be able to help you with this example, as inference constraints on the first arguments (new BarredUpFoo()) cannot be used to influence overload resolution for the call to Predicates.matches(...) - nor we can use the second formal of 'assertThat' in order to discard potential overload candidates for Predicates.matches. This is the price to pay for locality. Another problem in this particular example, is that the formal of Predicates.matches contains inference variable - that's why you are getting the 'cyclic inference error' messages: the compiler is waiting for info in the target type to be able to proceed with the attribution of the method reference (the same applies if a lambda has no explicit parameter types) - since the target type is not a concrete type, you have an inference cycle there. What happens when there's such a cycle? There are, again, several strategies that could be exploited - one could have the compiler to infer all inference variable in the target type, and then proceed with normal attribution of the lambda/method reference. An important point here, is that we should instantiate inference variable in the target type only _after_ we checked all other argument types, otherwise the inferred type will be dependent on the order in which arguments are checked. A simpler solution is to have the compiler reporting the error (cyclic inference), and perhaps give a detailed explanation of what is the type information that is missing. While this approach is significantly simpler (i.e. it avoids extra-complexity burden on overload resolution), we believe it has a good cost vs. benefit ratio. Moreover, there are things that we can do in order to minimize the occurrences of such messages - for example, in the case above, since Foo::isBar is unambiguous, the method reference could be type-checked even in the absence of concrete argument types from the target functional descriptor. Bottom line: as far as type-inference is concerned, our story can be summarized as follows: *) keep it simple *) enhance inference in 'obvious cases' *) provide enough info to the user so that it will be easy to recover from inference errors Maurizio > > --p > > On Tue, Feb 21, 2012 at 5:07 PM, Brian Goetz wrote: >>> 1) Should the usage of Foo::isBar as the predicate fed to >>> PredicateMatcher.matches() compile successfully? I'm hoping not to >>> have to perform the SAM conversion by hand: >>> >>> Predicate bar = Foo::isBar; >>> assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar); >> >> Without answering the question on whether the inference should succeed or >> not (the exact details of type inference are currently in flux), I'll point >> out that there is a less intrusive form of "by hand" that can be used to >> provide the needed additional type info to the compiler -- use a cast to >> provide the target type. This is less intrusive that having to name a local >> variable. >> >> assertThat(new BarredUpFoo(), >> PredicateMatcher.matches((Predicate) Foo::isBar)); >> >> >>> 2) Wondering if it wouldn't be too much trouble to have method >>> references respond to toString() with something like "Foo::isBar" or >>> "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd >>> make the output of PredicateMatcher.matches() really slick. >> >> Yes, the details of this are being actively discussed in the EG, and is a >> desirable goal. Lots of details to work out, of course. From bitterfoxc at gmail.com Fri Feb 24 07:51:42 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Sat, 25 Feb 2012 00:51:42 +0900 Subject: Not recursive lambda works like recursive lambda. Message-ID: Hi, "SAM sam = () -> () -> sam.invoke()" is not recursive lambda. However, if sam is a local variable, sam works like recursive lambda. // This program was compiled by the newest compiler(revision:1254) public class Main { interface SAM { SAM invoke(); } static SAM field = () -> () -> field.invoke(); public static void main(String[] args) { SAM local = () -> () -> local.invoke(); field.invoke().invoke(); // Success local.invoke().invoke(); // StackOverflowError } } This is the dis-compiled code by jad: // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://www.kpdus.com/jad.html // Decompiler options: packimports(3) // Source File Name: Main.java public class Main { static interface SAM { public abstract SAM invoke(); } public static void main(String args[]) { SAM sam = new SAM() { public SAM invoke() { return new SAM() { public SAM invoke() { return invoke(); // call not sam.invoke() but this.invoke() } final _cls2 this$0; { this$0 = _cls2.this; super(); } }; } }; field.invoke().invoke(); sam.invoke().invoke(); } static SAM field = new SAM() { public SAM invoke() { return new SAM() { public SAM invoke() { return Main.field.invoke(); } final _cls1 this$0; { this$0 = _cls1.this; super(); } }; } }; } Regards, bitter_fox From maurizio.cimadamore at oracle.com Fri Feb 24 08:59:31 2012 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Fri, 24 Feb 2012 16:59:31 +0000 Subject: hg: lambda/lambda/langtools: Fix: recursion from doubly nested lambda is not handled correctly Message-ID: <20120224165936.2BE9D47694@hg.openjdk.java.net> Changeset: 3b2646fc2440 Author: mcimadamore Date: 2012-02-24 16:58 +0000 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/3b2646fc2440 Fix: recursion from doubly nested lambda is not handled correctly ! src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java + test/tools/javac/lambda/LambdaExpr14.java From bitterfoxc at gmail.com Fri Feb 24 15:56:27 2012 From: bitterfoxc at gmail.com (bitter_fox) Date: Sat, 25 Feb 2012 08:56:27 +0900 Subject: Not recursive lambda works like recursive lambda. In-Reply-To: References: Message-ID: Thank you for the fix. Regards, bitter_fox 2012/2/25 bitter_fox > Hi, > "SAM sam = () -> () -> sam.invoke()" is not recursive lambda. > However, if sam is a local variable, sam works like recursive lambda. > > // This program was compiled by the newest compiler(revision:1254) > public class Main > { > interface SAM > { > SAM invoke(); > } > > static SAM field = () -> () -> field.invoke(); > > public static void main(String[] args) > { > SAM local = () -> () -> local.invoke(); > > field.invoke().invoke(); // Success > local.invoke().invoke(); // StackOverflowError > } > } > > This is the dis-compiled code by jad: > > // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. > // Jad home page: http://www.kpdus.com/jad.html > // Decompiler options: packimports(3) > // Source File Name: Main.java > > > public class Main > { > static interface SAM > { > public abstract SAM invoke(); > } > > public static void main(String args[]) > { > SAM sam = new SAM() { > public SAM invoke() > { > return new SAM() { > public SAM invoke() > { > return invoke(); // call not sam.invoke() but > this.invoke() > } > > final _cls2 this$0; > > { > this$0 = _cls2.this; > super(); > } > }; > } > }; > field.invoke().invoke(); > sam.invoke().invoke(); > } > > static SAM field = new SAM() { > public SAM invoke() > { > return new SAM() { > public SAM invoke() > { > return Main.field.invoke(); > } > > final _cls1 this$0; > > { > this$0 = _cls1.this; > super(); > } > }; > } > }; > } > > Regards, > bitter_fox > > From conrad at dz015.com Sun Feb 26 13:49:09 2012 From: conrad at dz015.com (Conrad Winchester) Date: Sun, 26 Feb 2012 21:49:09 +0000 Subject: Method Pointers Message-ID: Hi all, I'm getting a little confused about closures and lambdas - I originally posted this question to closures-dev, but somebody told me that that was the wrong list and the lambda-dev is the right list. To me this question crosses both concepts - anyway my name is Conrad Winchester and I am a long time developer. I am currently experimenting with the new lambdas and function pointers in the Java 8 developer preview. I have come across something that strikes me as a little inconsistent in the current way that they are handled and just wanted to see what other people think. I will try to be succinct: I wish to add and remove function pointers to collections. I refer to the functions using a this reference. Essentially the issue is this. If I use collection.add(this#methodName) then I can not use collection.remove(this#methodName) because the reference 'this#methodName' is different to the first one. I think this is due to the way that SAM interfaces are used to wrap the closures. A side effect of this is that this will return false public boolean checkConsistency() { SomeSAMInterface m1 = this#methodName; SomeSAMInterface m2 = this#methodName; return m1==m2; } I personally think that every time I use 'this#methodName' it should return the same reference. Is this correct? Are there any plans to make method pointers always point to the same thing. If not it makes it much more awkward to use them Thanks Conrad Winchester From david.holmes at oracle.com Sun Feb 26 14:10:16 2012 From: david.holmes at oracle.com (David Holmes) Date: Mon, 27 Feb 2012 08:10:16 +1000 Subject: Method Pointers In-Reply-To: References: Message-ID: <4F4AADC8.4020900@oracle.com> Hi Conrad, This query was raised last December in the "Method reference conversion" thread - see in particular Brian's response here: http://mail.openjdk.java.net/pipermail/lambda-dev/2011-December/004396.html Bottom line: it is highly unlikely that this#methodName == this#methodName David Holmes ------------- On 27/02/2012 7:49 AM, Conrad Winchester wrote: > Hi all, > > I'm getting a little confused about closures and lambdas - I originally posted this question to closures-dev, but somebody told me that that was the wrong list and the lambda-dev is the right list. To me this question crosses both concepts - anyway > > my name is Conrad Winchester and I am a long time developer. I am currently experimenting with the new lambdas and function pointers in the Java 8 developer preview. I have come across something that strikes me as a little inconsistent in the current way that they are handled and just wanted to see what other people think. I will try to be succinct: > > I wish to add and remove function pointers to collections. I refer to the functions using a this reference. Essentially the issue is this. If I use > > collection.add(this#methodName) > > then I can not use > > collection.remove(this#methodName) > > because the reference 'this#methodName' is different to the first one. I think this is due to the way that SAM interfaces are used to wrap the closures. > > A side effect of this is that this will return false > > public boolean checkConsistency() > { > SomeSAMInterface m1 = this#methodName; > SomeSAMInterface m2 = this#methodName; > return m1==m2; > } > > I personally think that every time I use 'this#methodName' it should return the same reference. Is this correct? > > Are there any plans to make method pointers always point to the same thing. If not it makes it much more awkward to use them > > > Thanks > > Conrad Winchester > From brian.goetz at oracle.com Sun Feb 26 14:30:42 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 26 Feb 2012 17:30:42 -0500 Subject: Method Pointers In-Reply-To: References: Message-ID: <4F4AB292.7020007@oracle.com> Good question. Agreed that all things being equal, this would be a desirable property. Unfortunately, guarantees like this come with a possibly significant cost, and the question comes down to: how much are we willing to pay for properties like this? Where things are currently is that the identity properties of SAM conversion are deliberately underspecified, to maximize flexibility / minimize costs for the runtime. The current implementation makes some attempts to fold together identical method references and lambdas, but does not make "heroic efforts" to do so. If you want identity equality for bound method references (this::name), this turns out to be extremely expensive; we would have to keep an interned table of captured "method m bound to receiver r" method references, using weak references to keep this table from causing memory leaks. Are we willing to pay that much in capture cost, implementation complexity, and dynamic footprint to preserve the property you are asking for? (This seems a pretty clear "no" to me; this is one of those properties that provides a small benefit for a few but a significant cost for everyone.) One weaker and less expensive option would be to provide this guarantee for unbound and static references only (though this is by no means free); another would be to commit only to making the two objects .equals to each other rather than identity-equals. This is under consideration, but even this may be cost-prohibitive and/or too full of holes to provide a sufficiently intuitive semantics to make it worth it. (Aside: computational physics tells us that in the general case, this problem is undecidable anyway (see Rice's theorem), so whatever we did would necessarily be limited, and its limitations might be surprising enough that it would be better to promise nothing than to promise something complicated and confusing.) On 2/26/2012 4:49 PM, Conrad Winchester wrote: > Hi all, > > I'm getting a little confused about closures and lambdas - I originally posted this question to closures-dev, but somebody told me that that was the wrong list and the lambda-dev is the right list. To me this question crosses both concepts - anyway > > my name is Conrad Winchester and I am a long time developer. I am currently experimenting with the new lambdas and function pointers in the Java 8 developer preview. I have come across something that strikes me as a little inconsistent in the current way that they are handled and just wanted to see what other people think. I will try to be succinct: > > I wish to add and remove function pointers to collections. I refer to the functions using a this reference. Essentially the issue is this. If I use > > collection.add(this#methodName) > > then I can not use > > collection.remove(this#methodName) > > because the reference 'this#methodName' is different to the first one. I think this is due to the way that SAM interfaces are used to wrap the closures. > > A side effect of this is that this will return false > > public boolean checkConsistency() > { > SomeSAMInterface m1 = this#methodName; > SomeSAMInterface m2 = this#methodName; > return m1==m2; > } > > I personally think that every time I use 'this#methodName' it should return the same reference. Is this correct? > > Are there any plans to make method pointers always point to the same thing. If not it makes it much more awkward to use them > > > Thanks > > Conrad Winchester > From scolebourne at joda.org Sun Feb 26 15:02:26 2012 From: scolebourne at joda.org (Stephen Colebourne) Date: Sun, 26 Feb 2012 23:02:26 +0000 Subject: Method Pointers In-Reply-To: <4F4AB292.7020007@oracle.com> References: <4F4AB292.7020007@oracle.com> Message-ID: On 26 February 2012 22:30, Brian Goetz wrote: > Good question. ?Agreed that all things being equal, this would be a > desirable property. > > Unfortunately, guarantees like this come with a possibly significant > cost, and the question comes down to: how much are we willing to pay for > properties like this? > > Where things are currently is that the identity properties of SAM > conversion are deliberately underspecified, to maximize flexibility / > minimize costs for the runtime. ?The current implementation makes some > attempts to fold together identical method references and lambdas, but > does not make "heroic efforts" to do so. > > If you want identity equality for bound method references (this::name), > this turns out to be extremely expensive; we would have to keep an > interned table of captured "method m bound to receiver r" method > references, using weak references to keep this table from causing memory > leaks. ?Are we willing to pay that much in capture cost, implementation > complexity, and dynamic footprint to preserve the property you are > asking for? ?(This seems a pretty clear "no" to me; this is one of those > properties that provides a small benefit for a few but a significant > cost for everyone.) > > One weaker and less expensive option would be to provide this guarantee > for unbound and static references only (though this is by no means > free); another would be to commit only to making the two objects .equals > to each other rather than identity-equals. ?This is under consideration, > but even this may be cost-prohibitive and/or too full of holes to > provide a sufficiently intuitive semantics to make it worth it. Have you considered (I'm sure you have...) a form of requesting the reference to have equals semantics? Some form of method call or wrapper that the user muist specifically use to get the equals or == behaviour. I think that a manual extra step would be fine on the user-side. I've no specific thoughts about whether it helps implementation beyond noting that it bounds the hash map you describe. Stephen From brian.goetz at oracle.com Sun Feb 26 15:29:30 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 26 Feb 2012 18:29:30 -0500 Subject: Method Pointers In-Reply-To: References: <4F4AB292.7020007@oracle.com> Message-ID: <4F4AC05A.3030706@oracle.com> > Have you considered (I'm sure you have...) a form of requesting the > reference to have equals semantics? Some form of method call or > wrapper that the user muist specifically use to get the equals or == > behaviour. Yes, there are a number of possible use-site opt-ins to conversion options we might want to support. One of these is giving a name to a lambda, which may be useful in a number of contexts. The syntactic front-runner for this is to put a label inside the enclosing parens: (aLabel: x, y) -> x + y but this is not yet decided. Names are a useful part of a number of possible features, including: more stable serialization, better toString implementations, supporting nonlocal return, and others. Another use-site opt-in would be explicit serialization support. While we plan to do at least as well as inner classes -- a lambda is serializable if its target type is -- we'd like to do better, and provide a way of opting in. This largely turns out to be a syntactic problem -- what is the syntactic form of the opt-in. (Lots of suggestions have been made, and so far they all suck. I will open this to suggestions at a future time, but until then, please hold your fire.) The primary syntactic challenge is that because the conversion is invisible, there is no obvious place to hang conversion-specific metadata. We don't want to abuse either the static type system, annotations, or "fake functions" for this purpose. With a small number of conversion options we can do something ad-hoc (like the naming example above) but as the number of conversion options increases, this starts to hit the wall. From sam at sampullara.com Sun Feb 26 15:43:11 2012 From: sam at sampullara.com (Sam Pullara) Date: Sun, 26 Feb 2012 15:43:11 -0800 Subject: Method Pointers In-Reply-To: <4F4AC05A.3030706@oracle.com> References: <4F4AB292.7020007@oracle.com> <4F4AC05A.3030706@oracle.com> Message-ID: <902200E2-1577-4DE9-A440-C365BB1518E5@sampullara.com> Since we are going to support it when the interface is Serializable, why not just require that you do something like: interface SerializableRunnable extends Runnable, Serializable {} and then cast it to that at the call site. Is this an option that sucks? Sam On Feb 26, 2012, at 3:29 PM, Brian Goetz wrote: > Another use-site opt-in would be explicit serialization support. While > we plan to do at least as well as inner classes -- a lambda is > serializable if its target type is -- we'd like to do better, and > provide a way of opting in. This largely turns out to be a syntactic > problem -- what is the syntactic form of the opt-in. (Lots of > suggestions have been made, and so far they all suck. I will open this > to suggestions at a future time, but until then, please hold your fire.) From brian.goetz at oracle.com Sun Feb 26 15:48:57 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 26 Feb 2012 18:48:57 -0500 Subject: Method Pointers In-Reply-To: <902200E2-1577-4DE9-A440-C365BB1518E5@sampullara.com> References: <4F4AB292.7020007@oracle.com> <4F4AC05A.3030706@oracle.com> <902200E2-1577-4DE9-A440-C365BB1518E5@sampullara.com> Message-ID: <4F4AC4E9.6090109@oracle.com> I would call this the "do nothing" option (which is certainly an option), because we already support this as part of the basic SAM conversion. You can use a cast to select a specific target type, and if the target type is serializable then the lambda will be. But, it still is in the sucky category as a use-site serialization opt-in because it requires the user to create a class just so they make a lambda serializable (and if this were the only option, which it currently is, the result would be an application has many otherwise useless "garbage" classes like this one.) On 2/26/2012 6:43 PM, Sam Pullara wrote: > Since we are going to support it when the interface is Serializable, why not just require that you do something like: > > interface SerializableRunnable extends Runnable, Serializable {} > > and then cast it to that at the call site. Is this an option that sucks? > > Sam > > On Feb 26, 2012, at 3:29 PM, Brian Goetz wrote: >> Another use-site opt-in would be explicit serialization support. While >> we plan to do at least as well as inner classes -- a lambda is >> serializable if its target type is -- we'd like to do better, and >> provide a way of opting in. This largely turns out to be a syntactic >> problem -- what is the syntactic form of the opt-in. (Lots of >> suggestions have been made, and so far they all suck. I will open this >> to suggestions at a future time, but until then, please hold your fire.) From forax at univ-mlv.fr Sun Feb 26 15:53:55 2012 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 27 Feb 2012 00:53:55 +0100 Subject: Method Pointers In-Reply-To: <902200E2-1577-4DE9-A440-C365BB1518E5@sampullara.com> References: <4F4AB292.7020007@oracle.com> <4F4AC05A.3030706@oracle.com> <902200E2-1577-4DE9-A440-C365BB1518E5@sampullara.com> Message-ID: <4F4AC613.3080107@univ-mlv.fr> On 02/27/2012 12:43 AM, Sam Pullara wrote: > Since we are going to support it when the interface is Serializable, why not just require that you do something like: > > interface SerializableRunnable extends Runnable, Serializable {} > > and then cast it to that at the call site. Is this an option that sucks? yes, because you also have to change the API, by example Executor should have also a new submit()/execute() that takes a SerializableRunnable. Serializable is a runtime flag, it's ortogonal to the type system. If annotations were present in the jdk 1.1, Serializable would be an annotation. > > Sam R?mi From sam at sampullara.com Sun Feb 26 16:27:22 2012 From: sam at sampullara.com (Sam Pullara) Date: Sun, 26 Feb 2012 16:27:22 -0800 Subject: Method Pointers In-Reply-To: <4F4AC613.3080107@univ-mlv.fr> References: <4F4AB292.7020007@oracle.com> <4F4AC05A.3030706@oracle.com> <902200E2-1577-4DE9-A440-C365BB1518E5@sampullara.com> <4F4AC613.3080107@univ-mlv.fr> Message-ID: <6C5E7917-A540-446E-A38D-AAA37C53A3FB@sampullara.com> Why would they have to be changed? A SerializableRunnable is still a Runnable... If you cast it to a SerializableRunnable at the submit()/execute() site, that should work, no? Sam On Feb 26, 2012, at 3:53 PM, R?mi Forax wrote: > On 02/27/2012 12:43 AM, Sam Pullara wrote: >> Since we are going to support it when the interface is Serializable, why not just require that you do something like: >> >> interface SerializableRunnable extends Runnable, Serializable {} >> >> and then cast it to that at the call site. Is this an option that sucks? > > yes, because you also have to change the API, by example > Executor should have also a new submit()/execute() that takes a > SerializableRunnable. > > Serializable is a runtime flag, it's ortogonal to the type system. > If annotations were present in the jdk 1.1, Serializable would be an > annotation. > >> >> Sam > > R?mi > > From gregg at wonderly.org Sun Feb 26 16:53:23 2012 From: gregg at wonderly.org (Gregg Wonderly) Date: Sun, 26 Feb 2012 18:53:23 -0600 Subject: Method Pointers In-Reply-To: <4F4AB292.7020007@oracle.com> References: <4F4AB292.7020007@oracle.com> Message-ID: It seems to me that it would be probable that anyone holding a this#method reference would at some point use it for a membership test/expression. I think that in the case of an InvocationHandler, in particular, that the method would be of interest and possibly used to key to other data. If there is no constant representation, it seems very problematic to me. Gregg Sent from my iPhone On Feb 26, 2012, at 4:30 PM, Brian Goetz wrote: > Good question. Agreed that all things being equal, this would be a > desirable property. > > Unfortunately, guarantees like this come with a possibly significant > cost, and the question comes down to: how much are we willing to pay for > properties like this? > > Where things are currently is that the identity properties of SAM > conversion are deliberately underspecified, to maximize flexibility / > minimize costs for the runtime. The current implementation makes some > attempts to fold together identical method references and lambdas, but > does not make "heroic efforts" to do so. > > If you want identity equality for bound method references (this::name), > this turns out to be extremely expensive; we would have to keep an > interned table of captured "method m bound to receiver r" method > references, using weak references to keep this table from causing memory > leaks. Are we willing to pay that much in capture cost, implementation > complexity, and dynamic footprint to preserve the property you are > asking for? (This seems a pretty clear "no" to me; this is one of those > properties that provides a small benefit for a few but a significant > cost for everyone.) > > One weaker and less expensive option would be to provide this guarantee > for unbound and static references only (though this is by no means > free); another would be to commit only to making the two objects .equals > to each other rather than identity-equals. This is under consideration, > but even this may be cost-prohibitive and/or too full of holes to > provide a sufficiently intuitive semantics to make it worth it. > > (Aside: computational physics tells us that in the general case, this > problem is undecidable anyway (see Rice's theorem), so whatever we did > would necessarily be limited, and its limitations might be surprising > enough that it would be better to promise nothing than to promise > something complicated and confusing.) > > > On 2/26/2012 4:49 PM, Conrad Winchester wrote: >> Hi all, >> >> I'm getting a little confused about closures and lambdas - I originally posted this question to closures-dev, but somebody told me that that was the wrong list and the lambda-dev is the right list. To me this question crosses both concepts - anyway >> >> my name is Conrad Winchester and I am a long time developer. I am currently experimenting with the new lambdas and function pointers in the Java 8 developer preview. I have come across something that strikes me as a little inconsistent in the current way that they are handled and just wanted to see what other people think. I will try to be succinct: >> >> I wish to add and remove function pointers to collections. I refer to the functions using a this reference. Essentially the issue is this. If I use >> >> collection.add(this#methodName) >> >> then I can not use >> >> collection.remove(this#methodName) >> >> because the reference 'this#methodName' is different to the first one. I think this is due to the way that SAM interfaces are used to wrap the closures. >> >> A side effect of this is that this will return false >> >> public boolean checkConsistency() >> { >> SomeSAMInterface m1 = this#methodName; >> SomeSAMInterface m2 = this#methodName; >> return m1==m2; >> } >> >> I personally think that every time I use 'this#methodName' it should return the same reference. Is this correct? >> >> Are there any plans to make method pointers always point to the same thing. If not it makes it much more awkward to use them >> >> >> Thanks >> >> Conrad Winchester >> > From forax at univ-mlv.fr Sun Feb 26 17:06:14 2012 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 27 Feb 2012 02:06:14 +0100 Subject: Method Pointers In-Reply-To: References: <4F4AB292.7020007@oracle.com> Message-ID: <4F4AD706.10808@univ-mlv.fr> On 02/27/2012 01:53 AM, Gregg Wonderly wrote: > It seems to me that it would be probable that anyone holding a this#method reference would at some point use it for a membership test/expression. I think that in the case of an InvocationHandler, in particular, that the method would be of interest and possibly used to key to other data. If there is no constant representation, it seems very problematic to me. Foo#bar() is constant but with foo an instance of Foo, foo#bar () is not constant. I wonder if the best is not to do not allow the syntax instance#method_ref and only to allow the syntax Class#method_ref which is constant. > > Gregg > > Sent from my iPhone R?mi From vitalyd at gmail.com Sun Feb 26 17:37:18 2012 From: vitalyd at gmail.com (Vitaly Davidovich) Date: Sun, 26 Feb 2012 20:37:18 -0500 Subject: Method Pointers In-Reply-To: <4F4AB292.7020007@oracle.com> References: <4F4AB292.7020007@oracle.com> Message-ID: Brian, has there been any discussion to follow the .Net model where lambdas do have identity equality? They achieve this by having method references/pointers as proper types in the type system (i.e. System.Delegate). I can see how this is more involved than what java closures are, but perhaps it's the "right" thing to do? Sent from my phone On Feb 26, 2012 5:32 PM, "Brian Goetz" wrote: > Good question. Agreed that all things being equal, this would be a > desirable property. > > Unfortunately, guarantees like this come with a possibly significant > cost, and the question comes down to: how much are we willing to pay for > properties like this? > > Where things are currently is that the identity properties of SAM > conversion are deliberately underspecified, to maximize flexibility / > minimize costs for the runtime. The current implementation makes some > attempts to fold together identical method references and lambdas, but > does not make "heroic efforts" to do so. > > If you want identity equality for bound method references (this::name), > this turns out to be extremely expensive; we would have to keep an > interned table of captured "method m bound to receiver r" method > references, using weak references to keep this table from causing memory > leaks. Are we willing to pay that much in capture cost, implementation > complexity, and dynamic footprint to preserve the property you are > asking for? (This seems a pretty clear "no" to me; this is one of those > properties that provides a small benefit for a few but a significant > cost for everyone.) > > One weaker and less expensive option would be to provide this guarantee > for unbound and static references only (though this is by no means > free); another would be to commit only to making the two objects .equals > to each other rather than identity-equals. This is under consideration, > but even this may be cost-prohibitive and/or too full of holes to > provide a sufficiently intuitive semantics to make it worth it. > > (Aside: computational physics tells us that in the general case, this > problem is undecidable anyway (see Rice's theorem), so whatever we did > would necessarily be limited, and its limitations might be surprising > enough that it would be better to promise nothing than to promise > something complicated and confusing.) > > > On 2/26/2012 4:49 PM, Conrad Winchester wrote: > > Hi all, > > > > I'm getting a little confused about closures and lambdas - I originally > posted this question to closures-dev, but somebody told me that that was > the wrong list and the lambda-dev is the right list. To me this question > crosses both concepts - anyway > > > > my name is Conrad Winchester and I am a long time developer. I am > currently experimenting with the new lambdas and function pointers in the > Java 8 developer preview. I have come across something that strikes me as a > little inconsistent in the current way that they are handled and just > wanted to see what other people think. I will try to be succinct: > > > > I wish to add and remove function pointers to collections. I refer to > the functions using a this reference. Essentially the issue is this. If I > use > > > > collection.add(this#methodName) > > > > then I can not use > > > > collection.remove(this#methodName) > > > > because the reference 'this#methodName' is different to the first one. I > think this is due to the way that SAM interfaces are used to wrap the > closures. > > > > A side effect of this is that this will return false > > > > public boolean checkConsistency() > > { > > SomeSAMInterface m1 = this#methodName; > > SomeSAMInterface m2 = this#methodName; > > return m1==m2; > > } > > > > I personally think that every time I use 'this#methodName' it should > return the same reference. Is this correct? > > > > Are there any plans to make method pointers always point to the same > thing. If not it makes it much more awkward to use them > > > > > > Thanks > > > > Conrad Winchester > > > > From gdennis at alum.mit.edu Sun Feb 26 20:11:06 2012 From: gdennis at alum.mit.edu (Greg Dennis) Date: Sun, 26 Feb 2012 23:11:06 -0500 Subject: Method Pointers Message-ID: Have you considered allowing a cast to an intersection of types, e.g. allowing a cast to "(Runnable & Serializable)"? It's not the most succinct option, but it avoids the creation of the garbage class, and the concept of an intersection type already exists in generics. Greg > Date: Sun, 26 Feb 2012 18:48:57 -0500 > From: Brian Goetz > Subject: Re: Method Pointers > To: Sam Pullara > Cc: lambda-dev at openjdk.java.net > Message-ID: <4F4AC4E9.6090109 at oracle.com> > Content-Type: text/plain; charset=ISO-8859-1; format=flowed > > I would call this the "do nothing" option (which is certainly an > option), because we already support this as part of the basic SAM > conversion. You can use a cast to select a specific target type, and if > the target type is serializable then the lambda will be. But, it still > is in the sucky category as a use-site serialization opt-in because it > requires the user to create a class just so they make a lambda > serializable (and if this were the only option, which it currently is, > the result would be an application has many otherwise useless "garbage" > classes like this one.) > > > On 2/26/2012 6:43 PM, Sam Pullara wrote: > > Since we are going to support it when the interface is Serializable, why > not just require that you do something like: > > > > interface SerializableRunnable extends Runnable, Serializable {} > > > > and then cast it to that at the call site. Is this an option that sucks? > > > > Sam > > > > On Feb 26, 2012, at 3:29 PM, Brian Goetz wrote: > >> Another use-site opt-in would be explicit serialization support. While > >> we plan to do at least as well as inner classes -- a lambda is > >> serializable if its target type is -- we'd like to do better, and > >> provide a way of opting in. This largely turns out to be a syntactic > >> problem -- what is the syntactic form of the opt-in. (Lots of > >> suggestions have been made, and so far they all suck. I will open this > >> to suggestions at a future time, but until then, please hold your fire.) > From brian.goetz at oracle.com Sun Feb 26 21:05:01 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 27 Feb 2012 00:05:01 -0500 Subject: Method Pointers In-Reply-To: References: Message-ID: <4F4B0EFD.5000304@oracle.com> Yes, that was one of the many (sucking) options considered. (This one sucks for several reasons: (a) it teases the user into thinking we have first-class intersection types, and would be introducing an irregularity about the syntax of types; (b) is pretty verbose (you'd have to write out the whole target type, including type parameters.) As I said, we've examined a lot of syntax candidates, and have not yet found one that is very satisfying. I will write them up when I have the time -- and what's wrong with the ones we've considered -- and at that point it will be constructive to brainstorm for new ideas on this front. On 2/26/2012 11:11 PM, Greg Dennis wrote: > Have you considered allowing a cast to an intersection of types, e.g. > allowing a cast to "(Runnable& Serializable)"? It's not the most succinct > option, but it avoids the creation of the garbage class, and the concept of > an intersection type already exists in generics. > > Greg > > > > >> Date: Sun, 26 Feb 2012 18:48:57 -0500 >> From: Brian Goetz >> Subject: Re: Method Pointers >> To: Sam Pullara >> Cc: lambda-dev at openjdk.java.net >> Message-ID:<4F4AC4E9.6090109 at oracle.com> >> Content-Type: text/plain; charset=ISO-8859-1; format=flowed >> >> I would call this the "do nothing" option (which is certainly an >> option), because we already support this as part of the basic SAM >> conversion. You can use a cast to select a specific target type, and if >> the target type is serializable then the lambda will be. But, it still >> is in the sucky category as a use-site serialization opt-in because it >> requires the user to create a class just so they make a lambda >> serializable (and if this were the only option, which it currently is, >> the result would be an application has many otherwise useless "garbage" >> classes like this one.) >> >> >> On 2/26/2012 6:43 PM, Sam Pullara wrote: >>> Since we are going to support it when the interface is Serializable, why >> not just require that you do something like: >>> >>> interface SerializableRunnable extends Runnable, Serializable {} >>> >>> and then cast it to that at the call site. Is this an option that sucks? >>> >>> Sam >>> >>> On Feb 26, 2012, at 3:29 PM, Brian Goetz wrote: >>>> Another use-site opt-in would be explicit serialization support. While >>>> we plan to do at least as well as inner classes -- a lambda is >>>> serializable if its target type is -- we'd like to do better, and >>>> provide a way of opting in. This largely turns out to be a syntactic >>>> problem -- what is the syntactic form of the opt-in. (Lots of >>>> suggestions have been made, and so far they all suck. I will open this >>>> to suggestions at a future time, but until then, please hold your fire.) >> > From brian.goetz at oracle.com Sun Feb 26 21:25:17 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 27 Feb 2012 00:25:17 -0500 Subject: Method Pointers In-Reply-To: References: <4F4AB292.7020007@oracle.com> Message-ID: <4F4B13BD.5010500@oracle.com> Inner classes have the same problem, of course. But you can always do with lambdas what people have been doing with other sorts of "function objects" for years: Listener lst = e -> { action(e); } component.addListener(lst); ... component.removeListener(lst); On 2/26/2012 7:53 PM, Gregg Wonderly wrote: > It seems to me that it would be probable that anyone holding a this#method reference would at some point use it for a membership test/expression. I think that in the case of an InvocationHandler, in particular, that the method would be of interest and possibly used to key to other data. If there is no constant representation, it seems very problematic to me. > > Gregg > > Sent from my iPhone > > On Feb 26, 2012, at 4:30 PM, Brian Goetz wrote: > >> Good question. Agreed that all things being equal, this would be a >> desirable property. >> >> Unfortunately, guarantees like this come with a possibly significant >> cost, and the question comes down to: how much are we willing to pay for >> properties like this? >> >> Where things are currently is that the identity properties of SAM >> conversion are deliberately underspecified, to maximize flexibility / >> minimize costs for the runtime. The current implementation makes some >> attempts to fold together identical method references and lambdas, but >> does not make "heroic efforts" to do so. >> >> If you want identity equality for bound method references (this::name), >> this turns out to be extremely expensive; we would have to keep an >> interned table of captured "method m bound to receiver r" method >> references, using weak references to keep this table from causing memory >> leaks. Are we willing to pay that much in capture cost, implementation >> complexity, and dynamic footprint to preserve the property you are >> asking for? (This seems a pretty clear "no" to me; this is one of those >> properties that provides a small benefit for a few but a significant >> cost for everyone.) >> >> One weaker and less expensive option would be to provide this guarantee >> for unbound and static references only (though this is by no means >> free); another would be to commit only to making the two objects .equals >> to each other rather than identity-equals. This is under consideration, >> but even this may be cost-prohibitive and/or too full of holes to >> provide a sufficiently intuitive semantics to make it worth it. >> >> (Aside: computational physics tells us that in the general case, this >> problem is undecidable anyway (see Rice's theorem), so whatever we did >> would necessarily be limited, and its limitations might be surprising >> enough that it would be better to promise nothing than to promise >> something complicated and confusing.) >> >> >> On 2/26/2012 4:49 PM, Conrad Winchester wrote: >>> Hi all, >>> >>> I'm getting a little confused about closures and lambdas - I originally posted this question to closures-dev, but somebody told me that that was the wrong list and the lambda-dev is the right list. To me this question crosses both concepts - anyway >>> >>> my name is Conrad Winchester and I am a long time developer. I am currently experimenting with the new lambdas and function pointers in the Java 8 developer preview. I have come across something that strikes me as a little inconsistent in the current way that they are handled and just wanted to see what other people think. I will try to be succinct: >>> >>> I wish to add and remove function pointers to collections. I refer to the functions using a this reference. Essentially the issue is this. If I use >>> >>> collection.add(this#methodName) >>> >>> then I can not use >>> >>> collection.remove(this#methodName) >>> >>> because the reference 'this#methodName' is different to the first one. I think this is due to the way that SAM interfaces are used to wrap the closures. >>> >>> A side effect of this is that this will return false >>> >>> public boolean checkConsistency() >>> { >>> SomeSAMInterface m1 = this#methodName; >>> SomeSAMInterface m2 = this#methodName; >>> return m1==m2; >>> } >>> >>> I personally think that every time I use 'this#methodName' it should return the same reference. Is this correct? >>> >>> Are there any plans to make method pointers always point to the same thing. If not it makes it much more awkward to use them >>> >>> >>> Thanks >>> >>> Conrad Winchester >>> >> From conrad at dz015.com Sun Feb 26 23:54:49 2012 From: conrad at dz015.com (Conrad Winchester) Date: Mon, 27 Feb 2012 07:54:49 +0000 Subject: Method Pointers In-Reply-To: References: <4F4AB292.7020007@oracle.com> Message-ID: <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> Have to agree with Vitaly here, I think the SAM implementation should allow for equality or a different approach taken. I think that this lack of equality is a shame, because 1) other languages have dealt with this without this level of confusion. 2) it will cause the community to be plagued with exactly the same question over and over again - it feels like an incomplete implementation of method pointers. 3) as was stated in the other thread it makes the use of method pointers as listeners almost completely useless. I think it would be good, that if equality is not guaranteed, then we should have at least some test for 'sameness'. There may be some light - I noticed in my intellij debugger that the method pointer has two fields that in it rec$ and this$0. I was able to use these (in the debugger) to see that I could tell the difference between two different instances having pointers to the same method, but they are not accessible from the language to implement an equals() method - is this in the works? Conrad Winchester On 27 Feb 2012, at 01:37, Vitaly Davidovich wrote: > Brian, has there been any discussion to follow the .Net model where lambdas do have identity equality? They achieve this by having method references/pointers as proper types in the type system (i.e. System.Delegate). I can see how this is more involved than what java closures are, but perhaps it's the "right" thing to do? > > Sent from my phone > > On Feb 26, 2012 5:32 PM, "Brian Goetz" wrote: > Good question. Agreed that all things being equal, this would be a > desirable property. > > Unfortunately, guarantees like this come with a possibly significant > cost, and the question comes down to: how much are we willing to pay for > properties like this? > > Where things are currently is that the identity properties of SAM > conversion are deliberately underspecified, to maximize flexibility / > minimize costs for the runtime. The current implementation makes some > attempts to fold together identical method references and lambdas, but > does not make "heroic efforts" to do so. > > If you want identity equality for bound method references (this::name), > this turns out to be extremely expensive; we would have to keep an > interned table of captured "method m bound to receiver r" method > references, using weak references to keep this table from causing memory > leaks. Are we willing to pay that much in capture cost, implementation > complexity, and dynamic footprint to preserve the property you are > asking for? (This seems a pretty clear "no" to me; this is one of those > properties that provides a small benefit for a few but a significant > cost for everyone.) > > One weaker and less expensive option would be to provide this guarantee > for unbound and static references only (though this is by no means > free); another would be to commit only to making the two objects .equals > to each other rather than identity-equals. This is under consideration, > but even this may be cost-prohibitive and/or too full of holes to > provide a sufficiently intuitive semantics to make it worth it. > > (Aside: computational physics tells us that in the general case, this > problem is undecidable anyway (see Rice's theorem), so whatever we did > would necessarily be limited, and its limitations might be surprising > enough that it would be better to promise nothing than to promise > something complicated and confusing.) > > > On 2/26/2012 4:49 PM, Conrad Winchester wrote: > > Hi all, > > > > I'm getting a little confused about closures and lambdas - I originally posted this question to closures-dev, but somebody told me that that was the wrong list and the lambda-dev is the right list. To me this question crosses both concepts - anyway > > > > my name is Conrad Winchester and I am a long time developer. I am currently experimenting with the new lambdas and function pointers in the Java 8 developer preview. I have come across something that strikes me as a little inconsistent in the current way that they are handled and just wanted to see what other people think. I will try to be succinct: > > > > I wish to add and remove function pointers to collections. I refer to the functions using a this reference. Essentially the issue is this. If I use > > > > collection.add(this#methodName) > > > > then I can not use > > > > collection.remove(this#methodName) > > > > because the reference 'this#methodName' is different to the first one. I think this is due to the way that SAM interfaces are used to wrap the closures. > > > > A side effect of this is that this will return false > > > > public boolean checkConsistency() > > { > > SomeSAMInterface m1 = this#methodName; > > SomeSAMInterface m2 = this#methodName; > > return m1==m2; > > } > > > > I personally think that every time I use 'this#methodName' it should return the same reference. Is this correct? > > > > Are there any plans to make method pointers always point to the same thing. If not it makes it much more awkward to use them > > > > > > Thanks > > > > Conrad Winchester > > > From howard.lovatt at gmail.com Mon Feb 27 00:25:31 2012 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Mon, 27 Feb 2012 19:25:31 +1100 Subject: Method Pointers In-Reply-To: <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> Message-ID: <329BE84E-202C-4D3E-8B8C-CAC0955C43D7@gmail.com> When using inner classes in my own code I have used compare by value, including bound variables, rather than by location. This has worked well for me. Is it a possibility for lambdas? -- Howard Lovatt +61 419 971 263 (sent from my PDA) On 27/02/2012, at 6:54 PM, Conrad Winchester wrote: > Have to agree with Vitaly here, I think the SAM implementation should allow for equality or a different approach taken. > > I think that this lack of equality is a shame, because > > 1) other languages have dealt with this without this level of confusion. > 2) it will cause the community to be plagued with exactly the same question over and over again - it feels like an incomplete implementation of method pointers. > 3) as was stated in the other thread it makes the use of method pointers as listeners almost completely useless. > > I think it would be good, that if equality is not guaranteed, then we should have at least some test for 'sameness'. There may be some light - I noticed in my intellij debugger that the method pointer has two fields that in it rec$ and this$0. I was able to use these (in the debugger) to see that I could tell the difference between two different instances having pointers to the same method, but they are not accessible from the language to implement an equals() method - is this in the works? > > Conrad Winchester > > > On 27 Feb 2012, at 01:37, Vitaly Davidovich wrote: > >> Brian, has there been any discussion to follow the .Net model where lambdas do have identity equality? They achieve this by having method references/pointers as proper types in the type system (i.e. System.Delegate). I can see how this is more involved than what java closures are, but perhaps it's the "right" thing to do? >> >> Sent from my phone >> >> On Feb 26, 2012 5:32 PM, "Brian Goetz" wrote: >> Good question. Agreed that all things being equal, this would be a >> desirable property. >> >> Unfortunately, guarantees like this come with a possibly significant >> cost, and the question comes down to: how much are we willing to pay for >> properties like this? >> >> Where things are currently is that the identity properties of SAM >> conversion are deliberately underspecified, to maximize flexibility / >> minimize costs for the runtime. The current implementation makes some >> attempts to fold together identical method references and lambdas, but >> does not make "heroic efforts" to do so. >> >> If you want identity equality for bound method references (this::name), >> this turns out to be extremely expensive; we would have to keep an >> interned table of captured "method m bound to receiver r" method >> references, using weak references to keep this table from causing memory >> leaks. Are we willing to pay that much in capture cost, implementation >> complexity, and dynamic footprint to preserve the property you are >> asking for? (This seems a pretty clear "no" to me; this is one of those >> properties that provides a small benefit for a few but a significant >> cost for everyone.) >> >> One weaker and less expensive option would be to provide this guarantee >> for unbound and static references only (though this is by no means >> free); another would be to commit only to making the two objects .equals >> to each other rather than identity-equals. This is under consideration, >> but even this may be cost-prohibitive and/or too full of holes to >> provide a sufficiently intuitive semantics to make it worth it. >> >> (Aside: computational physics tells us that in the general case, this >> problem is undecidable anyway (see Rice's theorem), so whatever we did >> would necessarily be limited, and its limitations might be surprising >> enough that it would be better to promise nothing than to promise >> something complicated and confusing.) >> >> >> On 2/26/2012 4:49 PM, Conrad Winchester wrote: >>> Hi all, >>> >>> I'm getting a little confused about closures and lambdas - I originally posted this question to closures-dev, but somebody told me that that was the wrong list and the lambda-dev is the right list. To me this question crosses both concepts - anyway >>> >>> my name is Conrad Winchester and I am a long time developer. I am currently experimenting with the new lambdas and function pointers in the Java 8 developer preview. I have come across something that strikes me as a little inconsistent in the current way that they are handled and just wanted to see what other people think. I will try to be succinct: >>> >>> I wish to add and remove function pointers to collections. I refer to the functions using a this reference. Essentially the issue is this. If I use >>> >>> collection.add(this#methodName) >>> >>> then I can not use >>> >>> collection.remove(this#methodName) >>> >>> because the reference 'this#methodName' is different to the first one. I think this is due to the way that SAM interfaces are used to wrap the closures. >>> >>> A side effect of this is that this will return false >>> >>> public boolean checkConsistency() >>> { >>> SomeSAMInterface m1 = this#methodName; >>> SomeSAMInterface m2 = this#methodName; >>> return m1==m2; >>> } >>> >>> I personally think that every time I use 'this#methodName' it should return the same reference. Is this correct? >>> >>> Are there any plans to make method pointers always point to the same thing. If not it makes it much more awkward to use them >>> >>> >>> Thanks >>> >>> Conrad Winchester >>> >> > > From miles at milessabin.com Mon Feb 27 00:36:08 2012 From: miles at milessabin.com (Miles Sabin) Date: Mon, 27 Feb 2012 08:36:08 +0000 Subject: Method Pointers In-Reply-To: <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> Message-ID: On Mon, Feb 27, 2012 at 7:54 AM, Conrad Winchester wrote: > Have to agree with Vitaly here, I think the SAM implementation should allow for equality or a different approach taken. > > I think that this lack of equality is a shame, because > > 1) other languages have dealt with this without this level of confusion. > 2) ?it will cause the community to be plagued with exactly the same question over and over again - it feels like an incomplete implementation of method pointers. > 3) as was stated in the other thread it makes the use of method pointers as listeners almost completely useless. FYI, a quick illustration of the current semantics for the Scala equivalent, scala> class Foo { def foo(i : Int) = i } defined class Foo scala> val foo = new Foo foo: Foo = Foo at 49ab0137 scala> val f1 = foo.foo _ f1: Int => Int = scala> val f2 = foo.foo _ f2: Int => Int = scala> f1 eq f2 res0: Boolean = false scala> f1 == f2 res1: Boolean = false scala> f1.equals(f2) res2: Boolean = false I don't recall any serious objections to this behaviour. In practice if you use these things in a functional style the lack of identity or equality is a complete non-issue. Cheers, Miles -- Miles Sabin tel: +44 7813 944 528 gtalk: miles at milessabin.com skype: milessabin g+: http://www.milessabin.com http://twitter.com/milessabin http://www.chuusai.com/ From fdreger at gmail.com Mon Feb 27 03:03:21 2012 From: fdreger at gmail.com (Filip Dreger) Date: Mon, 27 Feb 2012 12:03:21 +0100 Subject: Method Pointers In-Reply-To: References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> Message-ID: > I think that this lack of equality is a shame, because > > 1) other languages have dealt with this without this level of confusion. I don't think so - there is always a lot of confusion (partially because in other languages many people use closures and very few actually understand or even notice them). Take this Javascript example: function Clazz(x){ this.x = x; } Clazz.prototype = { test: function() { alert(this.x) } } a = new Clazz(1) b = new Clazz(2) alert(a.test === b.test) // shows true We have two methods on two different objects, and yet they are equal. You might think that this is because "this" reference is not bound in JS, but there you go: function close_over(x){ return function(){alert(x)} } var example = {} a = close_over(example) b = close_over(example) alert(a===b) // shows false We have two instances of the same function with two equal closures, and they are NOT equal. I believe that the latter piece of code exactly mirrors your Java example (only in Java you would close over "this", not over "example"). What I wanted to say is that - in my opinion: - there is no "good solution that other languages use", - even Javascript, the language that embraces event-driven programming to the fullest, would not allow you to add and remove listeners as in your use case, - there is no point in paying a huge penalty (in terms of performance) for a doubtful gain. On the other hand, I really like Howard's proposition of comparing lambdas by checking equity of each captured value. If I understand correctly, it seems that a proper equals() method could be generated without any runtime costs, and this could lead to some interesting possibilities, like having two equal lambdas that are not the same object. The only problem I can think of is if someone had objects that - at the same time - can listen to events, and require some sort of equity (likely because of some external library). A contrived example - I use JPA entities in a project, - In my JPA classes I override equals() to use the primary key (many people do it), - Now I try to observe some object that is global to the whole application (or, actually, any scope wider than my current transaction, it could as well be session or conversation scoped), - Suddenly I run into all kinds of strange problems, because all listeners created by entities that represent the same table row are treated as equal. Hmmm. After writing it, I suddenly don't think the example is so contrived after all. Does anybody know how ActionScript 3 approaches this problem? Regards, Filip Dreger From brian.goetz at oracle.com Mon Feb 27 07:57:23 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 27 Feb 2012 10:57:23 -0500 Subject: Method Pointers In-Reply-To: References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> Message-ID: <4F4BA7E3.8040505@oracle.com> > On the other hand, I really like Howard's proposition of comparing > lambdas by checking equity of each captured value. If I understand > correctly, it seems that a proper equals() method could be generated > without any runtime costs The part about "no runtime costs" is not correct. Requiring a "proper" equals method imposes the requirement that the captured args be able to be reconstituted on demand, which likely has additional costs for capture and/or footprint. I'm not saying this is not desirable, I'm just saying don't kid yourself that its free. From howard.lovatt at gmail.com Mon Feb 27 11:51:38 2012 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Tue, 28 Feb 2012 06:51:38 +1100 Subject: Method Pointers In-Reply-To: <4F4BA7E3.8040505@oracle.com> References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> <4F4BA7E3.8040505@oracle.com> Message-ID: <6F5E0466-698C-424A-A63A-6D521C37F842@gmail.com> The method pointers are probably doing something I don't understand judging by your comment that arguments need to be reconstructed. Do you have time to expand on the comment? Cheers, -- Howard. Sent from my iPad On 28/02/2012, at 2:57 AM, Brian Goetz wrote: >> On the other hand, I really like Howard's proposition of comparing >> lambdas by checking equity of each captured value. If I understand >> correctly, it seems that a proper equals() method could be generated >> without any runtime costs > > The part about "no runtime costs" is not correct. Requiring a "proper" > equals method imposes the requirement that the captured args be able to > be reconstituted on demand, which likely has additional costs for > capture and/or footprint. > > I'm not saying this is not desirable, I'm just saying don't kid yourself > that its free. > > From brian.goetz at oracle.com Mon Feb 27 12:03:56 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 27 Feb 2012 15:03:56 -0500 Subject: Method Pointers In-Reply-To: <6F5E0466-698C-424A-A63A-6D521C37F842@gmail.com> References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> <4F4BA7E3.8040505@oracle.com> <6F5E0466-698C-424A-A63A-6D521C37F842@gmail.com> Message-ID: <4F4BE1AC.6090401@oracle.com> As background, check out the talk "From Lambdas to Bytecode" from JVMLS this year: http://medianetwork.oracle.com/video/player/1113272510001, which outlines the dynamic strategy for translation. I'm currently working on an updated document describing the translation strategy and options. One obvious translation strategy is inner classes, but it would be shameful if that's all we were ever able to do. Though inner classes can easily be tweaked to get direct access to captured variables since they are stored as fields, which is probably where the widespread "it would cost nothing" intuition is coming from. But another strategy is method handles, which offers the VM more latitude to perform optimizing translations without generating extra classes. So, for example, if you curry arguments onto a desugared lambda body with MethodHandles.insertArguments, the VM has the opportunity to use techniques like partial application to produce an optimized partially bound result. The cost of that is you cannot necessarily retrieve the arguments that were bound into the method handle, since they may no longer exist in a form that is retrievable. As an example, take the method boolean foo(String s) { if (s.isEmpty()) { return doSomething(s); } else return false; } If you have a method handle for foo, and do foo.insertArguments("") the VM is within its rights to simply hand you back a method handle for "return false" and does not hold onto the bound string argument, which then opens the doors to further optimizations. But if we saddle it with the requirement to remember everything that was bound to it, we lose that opportunity for optimization. On 2/27/2012 2:51 PM, Howard Lovatt wrote: > The method pointers are probably doing something I don't understand judging by your comment that arguments need to be reconstructed. Do you have time to expand on the comment? > > Cheers, > > -- Howard. > > Sent from my iPad > > On 28/02/2012, at 2:57 AM, Brian Goetz wrote: > >>> On the other hand, I really like Howard's proposition of comparing >>> lambdas by checking equity of each captured value. If I understand >>> correctly, it seems that a proper equals() method could be generated >>> without any runtime costs >> >> The part about "no runtime costs" is not correct. Requiring a "proper" >> equals method imposes the requirement that the captured args be able to >> be reconstituted on demand, which likely has additional costs for >> capture and/or footprint. >> >> I'm not saying this is not desirable, I'm just saying don't kid yourself >> that its free. >> >> From brian.goetz at oracle.com Mon Feb 27 12:19:19 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 27 Feb 2012 15:19:19 -0500 Subject: Method Pointers In-Reply-To: <4F4BE1AC.6090401@oracle.com> References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> <4F4BA7E3.8040505@oracle.com> <6F5E0466-698C-424A-A63A-6D521C37F842@gmail.com> <4F4BE1AC.6090401@oracle.com> Message-ID: <4F4BE547.3010106@oracle.com> Correction: example should be "if (!s.isEmpty()) ..." On 2/27/2012 3:03 PM, Brian Goetz wrote: > As background, check out the talk "From Lambdas to Bytecode" from JVMLS > this year: http://medianetwork.oracle.com/video/player/1113272510001, > which outlines the dynamic strategy for translation. I'm currently > working on an updated document describing the translation strategy and > options. > > One obvious translation strategy is inner classes, but it would be > shameful if that's all we were ever able to do. Though inner classes > can easily be tweaked to get direct access to captured variables since > they are stored as fields, which is probably where the widespread "it > would cost nothing" intuition is coming from. > > But another strategy is method handles, which offers the VM more > latitude to perform optimizing translations without generating extra > classes. So, for example, if you curry arguments onto a desugared > lambda body with MethodHandles.insertArguments, the VM has the > opportunity to use techniques like partial application to produce an > optimized partially bound result. The cost of that is you cannot > necessarily retrieve the arguments that were bound into the method > handle, since they may no longer exist in a form that is retrievable. > > As an example, take the method > > boolean foo(String s) { > if (s.isEmpty()) { return doSomething(s); } > else return false; > } > > If you have a method handle for foo, and do > foo.insertArguments("") > the VM is within its rights to simply hand you back a method handle for > "return false" and does not hold onto the bound string argument, which > then opens the doors to further optimizations. But if we saddle it with > the requirement to remember everything that was bound to it, we lose > that opportunity for optimization. > > > On 2/27/2012 2:51 PM, Howard Lovatt wrote: >> The method pointers are probably doing something I don't understand judging by your comment that arguments need to be reconstructed. Do you have time to expand on the comment? >> >> Cheers, >> >> -- Howard. >> >> Sent from my iPad >> >> On 28/02/2012, at 2:57 AM, Brian Goetz wrote: >> >>>> On the other hand, I really like Howard's proposition of comparing >>>> lambdas by checking equity of each captured value. If I understand >>>> correctly, it seems that a proper equals() method could be generated >>>> without any runtime costs >>> >>> The part about "no runtime costs" is not correct. Requiring a "proper" >>> equals method imposes the requirement that the captured args be able to >>> be reconstituted on demand, which likely has additional costs for >>> capture and/or footprint. >>> >>> I'm not saying this is not desirable, I'm just saying don't kid yourself >>> that its free. >>> >>> > From howard.lovatt at gmail.com Mon Feb 27 19:59:35 2012 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Tue, 28 Feb 2012 14:59:35 +1100 Subject: Method Pointers In-Reply-To: <4F4BE547.3010106@oracle.com> References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> <4F4BA7E3.8040505@oracle.com> <6F5E0466-698C-424A-A63A-6D521C37F842@gmail.com> <4F4BE1AC.6090401@oracle.com> <4F4BE547.3010106@oracle.com> Message-ID: I have seen your talk and was aware of the sort of code so I should have been more explicit with my question - sorry. If method handles were designed to compare by value then when you curry their argument you would also 'curry' their equals method, no need to retain the argument. Obviously there is some overhead in currying the equals, but maybe worth it. I am very unsure, and hence the original question, about what the overhead on currying equals would be for a lambda. On 28 February 2012 07:19, Brian Goetz wrote: > Correction: example should be "if (!s.isEmpty()) ..." > > > On 2/27/2012 3:03 PM, Brian Goetz wrote: > >> As background, check out the talk "From Lambdas to Bytecode" from JVMLS >> this year: http://medianetwork.oracle.**com/video/player/1113272510001 >> **, >> which outlines the dynamic strategy for translation. I'm currently >> working on an updated document describing the translation strategy and >> options. >> >> One obvious translation strategy is inner classes, but it would be >> shameful if that's all we were ever able to do. Though inner classes >> can easily be tweaked to get direct access to captured variables since >> they are stored as fields, which is probably where the widespread "it >> would cost nothing" intuition is coming from. >> >> But another strategy is method handles, which offers the VM more >> latitude to perform optimizing translations without generating extra >> classes. So, for example, if you curry arguments onto a desugared >> lambda body with MethodHandles.insertArguments, the VM has the >> opportunity to use techniques like partial application to produce an >> optimized partially bound result. The cost of that is you cannot >> necessarily retrieve the arguments that were bound into the method >> handle, since they may no longer exist in a form that is retrievable. >> >> As an example, take the method >> >> boolean foo(String s) { >> if (s.isEmpty()) { return doSomething(s); } >> else return false; >> } >> >> If you have a method handle for foo, and do >> foo.insertArguments("") >> the VM is within its rights to simply hand you back a method handle for >> "return false" and does not hold onto the bound string argument, which >> then opens the doors to further optimizations. But if we saddle it with >> the requirement to remember everything that was bound to it, we lose >> that opportunity for optimization. >> >> >> On 2/27/2012 2:51 PM, Howard Lovatt wrote: >> >>> The method pointers are probably doing something I don't understand >>> judging by your comment that arguments need to be reconstructed. Do you >>> have time to expand on the comment? >>> >>> Cheers, >>> >>> -- Howard. >>> >>> Sent from my iPad >>> >>> On 28/02/2012, at 2:57 AM, Brian Goetz wrote: >>> >>> On the other hand, I really like Howard's proposition of comparing >>>>> lambdas by checking equity of each captured value. If I understand >>>>> correctly, it seems that a proper equals() method could be generated >>>>> without any runtime costs >>>>> >>>> >>>> The part about "no runtime costs" is not correct. Requiring a "proper" >>>> equals method imposes the requirement that the captured args be able to >>>> be reconstituted on demand, which likely has additional costs for >>>> capture and/or footprint. >>>> >>>> I'm not saying this is not desirable, I'm just saying don't kid yourself >>>> that its free. >>>> >>>> >>>> >> -- -- Howard. From brian.goetz at oracle.com Mon Feb 27 20:16:06 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 27 Feb 2012 23:16:06 -0500 Subject: Method Pointers In-Reply-To: References: <4F4AB292.7020007@oracle.com> <4B78042E-E316-4BEF-A9AC-8A0647F3D10F@dz015.com> <4F4BA7E3.8040505@oracle.com> <6F5E0466-698C-424A-A63A-6D521C37F842@gmail.com> <4F4BE1AC.6090401@oracle.com> <4F4BE547.3010106@oracle.com> Message-ID: <4F4C5506.2080703@oracle.com> > If method handles were designed to compare by value Not sure what you mean by this. Method handles are not interned; two method handles that describe the same behavior are not necessarily == or .equals.