From zhong.j.yu at gmail.com Sun Dec 1 19:03:56 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Sun, 1 Dec 2013 21:03:56 -0600 Subject: Closing the Stream returned from BufferedReader.lines() Message-ID: In this code BufferedReader br = ...; Stream stream = br.lines(); stream.close(); // does not close `br` `stream.close()` does not trigger `br.close()`. I for one find that rather counter-intuitive. Can you guys explain the design choice? When should a Stream forward close() to its source and when should it not? see http://stackoverflow.com/questions/20319417 Zhong Yu From mohan.radhakrishnan at polarisFT.com Mon Dec 2 01:12:12 2013 From: mohan.radhakrishnan at polarisFT.com (mohan.radhakrishnan at polarisFT.com) Date: Mon, 2 Dec 2013 14:42:12 +0530 Subject: Flatmap example Message-ID: Hi, Based on one of the suggestions by Paul Sandoz in the other thread "Basic functional style question" I coded this test. There are two unstructured lines of log that the code is trying to parse. Since I couldn't locate Java flatmap examples I looked at Scala code. I first tried the commented code which showed the error "Incompatible parameter types in lambda". But the combination of anonymous class and lambda worked. Is this how this type of problem is solved by using flatmap ? All of this is very exciting :-) Thanks, Mohan public class FlatMapTest { public static void main( String... argv ){ List source = new ArrayList(); source.add( "Peak Usage : init:2359296, used:13914944, committed:13959168, max:50331648Current Usage : init:2359296, used:13913536, committed:13959168, max:50331648|------------------| committed:13.31Mb+---------------------------------------------------------------------+|//////////////////| | max:48Mb+---------------------------------------------------------------------+|------------------| used:13.27Mb"); source.add( "Peak Usage : init:2359296, used:13916608, committed:13959168, max:50331648Current Usage : init:2359296, used:13915200, committed:13959168, max:50331648|------------------| committed:13.31Mb+---------------------------------------------------------------------+|//////////////////| | max:48Mb+---------------------------------------------------------------------+|------------------| used:13.27Mb"); List patterns = Arrays.asList(Pattern.compile("Current.*?[/|]"), Pattern.compile("[0-9]+(/,|/|)")); patterns.stream().flatMap(new Function() { @Override public Object apply(Pattern p1) { return source. stream(). map(p1::matcher). filter(Matcher::find).map(matcher -> matcher.group()); } }).forEach(x -> System.out.println(x)); // patterns.stream().flatMap(( Pattern p1 ) -> source. // stream(). // map(p1::matcher). // filter(Matcher::find).map(matcher -> matcher.group())).forEach(x -> System.out.println(x)); } } This e-Mail may contain proprietary and confidential information and is sent for the intended recipient(s) only. If by an addressing or transmission error this mail has been misdirected to you, you are requested to delete this mail immediately. You are also hereby notified that any use, any form of reproduction, dissemination, copying, disclosure, modification, distribution and/or publication of this e-mail message, contents or its attachment other than by its intended recipient/s is strictly prohibited. Visit us at http://www.polarisFT.com From Alan.Bateman at oracle.com Mon Dec 2 01:20:56 2013 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Mon, 02 Dec 2013 09:20:56 +0000 Subject: Closing the Stream returned from BufferedReader.lines() In-Reply-To: References: Message-ID: <529C50F8.6090503@oracle.com> On 02/12/2013 03:03, Zhong Yu wrote: > In this code > > BufferedReader br = ...; > Stream stream = br.lines(); > stream.close(); // does not close `br` > > `stream.close()` does not trigger `br.close()`. I for one find that > rather counter-intuitive. Can you guys explain the design choice? When > should a Stream forward close() to its source and when should it not? > See discussion on core-libs-dev from about a week ago on the same topic: http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023289.html From Sebastian.Millies at softwareag.com Mon Dec 2 04:02:33 2013 From: Sebastian.Millies at softwareag.com (Millies, Sebastian) Date: Mon, 2 Dec 2013 12:02:33 +0000 Subject: Closing the Stream returned from BufferedReader.lines() Message-ID: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6C8E@HQMBX5.eur.ad.sag> In that context, I'd be in favor either of Gernot Neppert's suggestion in http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023318.html to add a java.io.Closeable#closeUnchecked() default method, or of making the static utility method java.nio.file.Files#asUncheckedRunnable(Closeable) public somewhere. Otherwise many people will repeatedly have to write their own code in order to make the example suggested by Brian Goetz in that core-libs-dev discussion compile. Is it too late for such changes? -- Sebastian -----Original Message----- From: lambda-dev-bounces at openjdk.java.net [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Alan Bateman Sent: Monday, December 02, 2013 10:21 AM To: Zhong Yu Cc: lambda-dev at openjdk.java.net Subject: Re: Closing the Stream returned from BufferedReader.lines() On 02/12/2013 03:03, Zhong Yu wrote: > In this code > > BufferedReader br = ...; > Stream stream = br.lines(); > stream.close(); // does not close `br` > > `stream.close()` does not trigger `br.close()`. I for one find that > rather counter-intuitive. Can you guys explain the design choice? When > should a Stream forward close() to its source and when should it not? > See discussion on core-libs-dev from about a week ago on the same topic: http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023289.html Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com From paul.sandoz at oracle.com Mon Dec 2 04:33:52 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 2 Dec 2013 13:33:52 +0100 Subject: Flatmap example In-Reply-To: References: Message-ID: <102255F8-05FA-4B7F-A294-F96D4E8ADDC5@oracle.com> Hi, You are using a raw type for the List of Pattern, which is making it difficult for the compiler to infer types. Try this: List patterns = Arrays.asList(Pattern.compile("Current.*?[/|]"), Pattern.compile("[0-9]+(/,|/|)")); patterns.stream() .flatMap(new Function>() { @Override public Stream apply(Pattern p) { return source.stream() .map(p::matcher) .filter(Matcher::find) .map(Matcher::group); } }) .forEach(System.out::println); patterns.stream() .flatMap(p -> source.stream() .map(p::matcher) .filter(Matcher::find) .map(Matcher::group)) .forEach(System.out::println); Previously i thought you wanted to do layered matching e.g. match a line with pattern P1, then match the result of that with pattern P2 and so on. From your example i see that you wan to apply the pattern N times to the same source of lines to produce N different results (which may be getting into aspects of forked streams previously discussed). So i may have confused you with my suggestion of flatMap. A potential problem with your current use of flatMap is that it has munged the results so that the association of the Pattern to matched result is now lost. Paul. From Sebastian.Millies at softwareag.com Mon Dec 2 06:29:48 2013 From: Sebastian.Millies at softwareag.com (Millies, Sebastian) Date: Mon, 2 Dec 2013 14:29:48 +0000 Subject: b117: Self-reference in initializer does no longer work Message-ID: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D11@HQMBX5.eur.ad.sag> I just upgraded from b114 to b114. Self-references in initializers do no longer work, e. g. Zhong Yu's variation on the fix point operator: static Function fix2(Function, Function> f) { return new Object() { Function r = a -> f.apply(r).apply(a); }.r; } Why has this feature been dropped? Or is it a bug in b117? n Sebastian Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com From Sebastian.Millies at softwareag.com Mon Dec 2 06:31:55 2013 From: Sebastian.Millies at softwareag.com (Millies, Sebastian) Date: Mon, 2 Dec 2013 14:31:55 +0000 Subject: Flatmap example In-Reply-To: <102255F8-05FA-4B7F-A294-F96D4E8ADDC5@oracle.com> References: <102255F8-05FA-4B7F-A294-F96D4E8ADDC5@oracle.com> Message-ID: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D20@HQMBX5.eur.ad.sag> I can't get the second variant (without the inner class) to compile with b117. The method reference in ".map(p::matcher)" seems illegal, and explicitly typing the Lambda-Parameter "p" as "Pattern" leads to an Incompatible Types error. I have to cast the function that goes into the flatMap to "Function>". Why is that? -- Sebastian -----Original Message----- From: lambda-dev-bounces at openjdk.java.net [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Paul Sandoz Sent: Monday, December 02, 2013 1:34 PM Cc: lambda-dev at openjdk.java.net Subject: Re: Flatmap example Hi, You are using a raw type for the List of Pattern, which is making it difficult for the compiler to infer types. Try this: List patterns = Arrays.asList(Pattern.compile("Current.*?[/|]"), Pattern.compile("[0-9]+(/,|/|)")); patterns.stream() .flatMap(new Function>() { @Override public Stream apply(Pattern p) { return source.stream() .map(p::matcher) .filter(Matcher::find) .map(Matcher::group); } }) .forEach(System.out::println); patterns.stream() .flatMap(p -> source.stream() .map(p::matcher) .filter(Matcher::find) .map(Matcher::group)) .forEach(System.out::println); Previously i thought you wanted to do layered matching e.g. match a line with pattern P1, then match the result of that with pattern P2 and so on. From your example i see that you wan to apply the pattern N times to the same source of lines to produce N different results (which may be getting into aspects of forked streams previously discussed). So i may have confused you with my suggestion of flatMap. A potential problem with your current use of flatMap is that it has munged the results so that the association of the Pattern to matched result is now lost. Paul. Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com From Sebastian.Millies at softwareag.com Mon Dec 2 06:33:46 2013 From: Sebastian.Millies at softwareag.com (Millies, Sebastian) Date: Mon, 2 Dec 2013 14:33:46 +0000 Subject: Survey on Java erasure/reification In-Reply-To: <526329F1.7060706@oracle.com> References: <526329F1.7060706@oracle.com> Message-ID: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> Can anyone say anything about the outcome of this survey? Is this going to be important for Java 8, or is it a future thing? -- Sebastian -----Original Message----- From: lambda-dev-bounces at openjdk.java.net [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Brian Goetz Sent: Sunday, October 20, 2013 2:55 AM To: lambda-dev at openjdk.java.net; Core-Libs-Dev Subject: Survey on Java erasure/reification I've created a survey about people's attitudes towards erasure and reification. If you participate, please take the time to answer the free-response question; that's really what is going to help us. Survey here: https://www.surveymonkey.com/s/SCJC93R Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com From paul.sandoz at oracle.com Mon Dec 2 07:08:54 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 2 Dec 2013 16:08:54 +0100 Subject: Flatmap example In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D20@HQMBX5.eur.ad.sag> References: <102255F8-05FA-4B7F-A294-F96D4E8ADDC5@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D20@HQMBX5.eur.ad.sag> Message-ID: <12309D4F-32C1-4FF6-BF77-41B2E7033956@oracle.com> On Dec 2, 2013, at 3:31 PM, "Millies, Sebastian" wrote: > I can't get the second variant (without the inner class) to compile with b117. > Compiles and runs for me against the tip of tl. > The method reference in ".map(p::matcher)" seems illegal, and explicitly typing the Lambda-Parameter > "p" as "Pattern" leads to an Incompatible Types error. I have to cast the function that goes into the flatMap > to "Function>". Why is that? > I guess passing compile glitch or bug that was recently fixed. Paul. From ali.ebrahimi1781 at gmail.com Mon Dec 2 07:11:33 2013 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Mon, 2 Dec 2013 18:41:33 +0330 Subject: Survey on Java erasure/reification In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> References: <526329F1.7060706@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> Message-ID: May be java 10+ On Mon, Dec 2, 2013 at 6:03 PM, Millies, Sebastian < Sebastian.Millies at softwareag.com> wrote: > Can anyone say anything about the outcome of this survey? Is this going to > be important for Java 8, or is it > a future thing? -- Sebastian > > -----Original Message----- > From: lambda-dev-bounces at openjdk.java.net [mailto: > lambda-dev-bounces at openjdk.java.net] On Behalf Of Brian Goetz > Sent: Sunday, October 20, 2013 2:55 AM > To: lambda-dev at openjdk.java.net; Core-Libs-Dev > Subject: Survey on Java erasure/reification > > I've created a survey about people's attitudes towards erasure and > reification. > > If you participate, please take the time to answer the free-response > question; that's really what is going to help us. > > Survey here: > https://www.surveymonkey.com/s/SCJC93R > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, > Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - > Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), > Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of > the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > > > From ali.ebrahimi1781 at gmail.com Mon Dec 2 09:00:29 2013 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Mon, 2 Dec 2013 20:30:29 +0330 Subject: Survey on Java erasure/reification In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> References: <526329F1.7060706@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> Message-ID: Maybe java 10+ On Mon, Dec 2, 2013 at 6:03 PM, Millies, Sebastian < Sebastian.Millies at softwareag.com> wrote: > Can anyone say anything about the outcome of this survey? Is this going to > be important for Java 8, or is it > a future thing? -- Sebastian > > -----Original Message----- > From: lambda-dev-bounces at openjdk.java.net [mailto: > lambda-dev-bounces at openjdk.java.net] On Behalf Of Brian Goetz > Sent: Sunday, October 20, 2013 2:55 AM > To: lambda-dev at openjdk.java.net; Core-Libs-Dev > Subject: Survey on Java erasure/reification > > I've created a survey about people's attitudes towards erasure and > reification. > > If you participate, please take the time to answer the free-response > question; that's really what is going to help us. > > Survey here: > https://www.surveymonkey.com/s/SCJC93R > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, > Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - > Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), > Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of > the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > > > From zhong.j.yu at gmail.com Mon Dec 2 09:46:34 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Mon, 2 Dec 2013 11:46:34 -0600 Subject: b117: Self-reference in initializer does no longer work In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D11@HQMBX5.eur.ad.sag> References: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D11@HQMBX5.eur.ad.sag> Message-ID: See https://bugs.openjdk.java.net/browse/JDK-8024809 Basically a field cannot reference itself in the initializer, even if the reference occurs inside a lambda expression. However, you can bypass this kind of static analysis by using `this.r`. If that doesn't work in some context (where javac equates `this.r` and `r`) you can try `(this).r`. Zhong Yu On Mon, Dec 2, 2013 at 8:29 AM, Millies, Sebastian wrote: > I just upgraded from b114 to b114. Self-references in initializers do no longer work, e. g. > Zhong Yu's variation on the fix point operator: > > static Function fix2(Function, Function> f) > { > return new Object() > { > Function r = a -> f.apply(r).apply(a); > }.r; > } > > Why has this feature been dropped? Or is it a bug in b117? > > > n Sebastian > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > > From henry.jen at oracle.com Mon Dec 2 10:16:29 2013 From: henry.jen at oracle.com (Henry Jen) Date: Mon, 02 Dec 2013 10:16:29 -0800 Subject: BufferedReader::lines In-Reply-To: <5299B881.3040702@gmail.com> References: <5299B881.3040702@gmail.com> Message-ID: <529CCE7D.8000409@oracle.com> On Sat 30 Nov 2013 02:05:53 AM PST, Anthony Vanelverdinghe wrote: > Hi > > I have some questions concerning this method's implementation (in b117): > > * the Spliterator only has the ORDERED characteristic. Why aren't the > NONNULL and IMMUTABLE characteristics specified as well? > It's not IMMUTABLE because we cannot be sure that the source of BufferReader is immutable. I think it should have NONNULL as null is used as end of buffer. Cheers, Henry From brian.goetz at oracle.com Mon Dec 2 10:28:38 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 2 Dec 2013 13:28:38 -0500 Subject: Survey on Java erasure/reification In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> References: <526329F1.7060706@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> Message-ID: Java 8 is effectively done. But it is useful in gauging priorities for future platform evolution. Sent from my iPhone On Dec 2, 2013, at 9:33 AM, "Millies, Sebastian" wrote: > Can anyone say anything about the outcome of this survey? Is this going to be important for Java 8, or is it > a future thing? -- Sebastian > > -----Original Message----- > From: lambda-dev-bounces at openjdk.java.net [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Brian Goetz > Sent: Sunday, October 20, 2013 2:55 AM > To: lambda-dev at openjdk.java.net; Core-Libs-Dev > Subject: Survey on Java erasure/reification > > I've created a survey about people's attitudes towards erasure and reification. > > If you participate, please take the time to answer the free-response question; that's really what is going to help us. > > Survey here: > https://www.surveymonkey.com/s/SCJC93R > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > > From pbenedict at apache.org Mon Dec 2 10:37:22 2013 From: pbenedict at apache.org (Paul Benedict) Date: Mon, 2 Dec 2013 12:37:22 -0600 Subject: Survey on Java erasure/reification In-Reply-To: References: <526329F1.7060706@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> Message-ID: Are the results ever going to be made public or is it for Oracle's private consumption only? On Mon, Dec 2, 2013 at 12:28 PM, Brian Goetz wrote: > Java 8 is effectively done. But it is useful in gauging priorities for > future platform evolution. > > Sent from my iPhone > > On Dec 2, 2013, at 9:33 AM, "Millies, Sebastian" < > Sebastian.Millies at softwareag.com> wrote: > > > Can anyone say anything about the outcome of this survey? Is this going > to be important for Java 8, or is it > > a future thing? -- Sebastian > > > > -----Original Message----- > > From: lambda-dev-bounces at openjdk.java.net [mailto: > lambda-dev-bounces at openjdk.java.net] On Behalf Of Brian Goetz > > Sent: Sunday, October 20, 2013 2:55 AM > > To: lambda-dev at openjdk.java.net; Core-Libs-Dev > > Subject: Survey on Java erasure/reification > > > > I've created a survey about people's attitudes towards erasure and > reification. > > > > If you participate, please take the time to answer the free-response > question; that's really what is going to help us. > > > > Survey here: > > https://www.surveymonkey.com/s/SCJC93R > > > > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, > Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - > Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), > Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of > the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > > > > > > -- Cheers, Paul From zhong.j.yu at gmail.com Mon Dec 2 10:45:38 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Mon, 2 Dec 2013 12:45:38 -0600 Subject: Closing the Stream returned from BufferedReader.lines() In-Reply-To: <529C50F8.6090503@oracle.com> References: <529C50F8.6090503@oracle.com> Message-ID: On Mon, Dec 2, 2013 at 3:20 AM, Alan Bateman wrote: > On 02/12/2013 03:03, Zhong Yu wrote: >> >> In this code >> >> BufferedReader br = ...; >> Stream stream = br.lines(); >> stream.close(); // does not close `br` >> >> `stream.close()` does not trigger `br.close()`. I for one find that >> rather counter-intuitive. Can you guys explain the design choice? When >> should a Stream forward close() to its source and when should it not? >> > See discussion on core-libs-dev from about a week ago on the same topic: > > http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023289.html That discussion centers around the argument that `Stream.close()` should not be invoked anyway under the circumstance. However, what if it *is* invoked? What is the reason then that the stream does not close its data source when it is asked to close itself? The only reason I can think of is to punish the programmer for not following the best practice of open-close pairing so that they'll be whipped into having some good senses. That should only happen if the best practice is carved in stone, which is not the case here. It is perfectly legitimate, and occurring frequently in practice, that the ownership of a data source is transferred around through some predefined protocols, therefore the responsibility of `close` also changes hand. And we also want to write one liners like try(Stream lines = new BufferredReader(new MyWebReader()))) It's reasonable to expect that this should work, and `lines.close()` should propagate all the way to `MyWebReader.close`. And all the java.io wrapper classes forward `close` call to their sources, I don't see why the same strategy should not apply to `BufferredReader.lines()` which also creates a wrapper object. Zhong Yu From henry.jen at oracle.com Mon Dec 2 10:45:51 2013 From: henry.jen at oracle.com (Henry Jen) Date: Mon, 02 Dec 2013 10:45:51 -0800 Subject: Closing the Stream returned from BufferedReader.lines() In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6C8E@HQMBX5.eur.ad.sag> References: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6C8E@HQMBX5.eur.ad.sag> Message-ID: <529CD55F.1000107@oracle.com> On Mon 02 Dec 2013 04:02:33 AM PST, Millies, Sebastian wrote: > In that context, I'd be in favor > > either of Gernot Neppert's suggestion in > http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023318.html > to add a java.io.Closeable#closeUnchecked() default method, > > or of making the static utility method java.nio.file.Files#asUncheckedRunnable(Closeable) > public somewhere. > We thought about this before, but decided to leave it out because, 1. If a close method is known to throw exceptions, developer shoule deal with it. 2. It's trivial to add a static method to wrap up close if don't care consequences or add a utility class to cascade the exception. That said, I think a default method to simply close resource regardless would be convenient if name clashing is not a concern. Cheers, Henry > Otherwise many people will repeatedly have to write their own code in order to make > the example suggested by Brian Goetz in that core-libs-dev discussion compile. > Is it too late for such changes? > > -- Sebastian > > -----Original Message----- > From: lambda-dev-bounces at openjdk.java.net [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Alan Bateman > Sent: Monday, December 02, 2013 10:21 AM > To: Zhong Yu > Cc: lambda-dev at openjdk.java.net > Subject: Re: Closing the Stream returned from BufferedReader.lines() > > On 02/12/2013 03:03, Zhong Yu wrote: >> In this code >> >> BufferedReader br = ...; >> Stream stream = br.lines(); >> stream.close(); // does not close `br` >> >> `stream.close()` does not trigger `br.close()`. I for one find that >> rather counter-intuitive. Can you guys explain the design choice? When >> should a Stream forward close() to its source and when should it not? >> > See discussion on core-libs-dev from about a week ago on the same topic: > > http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023289.html > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > > From zhong.j.yu at gmail.com Mon Dec 2 10:50:13 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Mon, 2 Dec 2013 12:50:13 -0600 Subject: Closing the Stream returned from BufferedReader.lines() In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6C8E@HQMBX5.eur.ad.sag> References: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6C8E@HQMBX5.eur.ad.sag> Message-ID: Since `Stream.onClose` will almost always accept an action that may throw a checked exception under the hood, it is incorrect to use `Runnable` type here. The functional type should throw a checked Exception. And I think `propagateClose(AutoCloseable)` looks fine, and works nicely for 99% cases. On Mon, Dec 2, 2013 at 6:02 AM, Millies, Sebastian wrote: > In that context, I'd be in favor > > either of Gernot Neppert's suggestion in > http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023318.html > to add a java.io.Closeable#closeUnchecked() default method, > > or of making the static utility method java.nio.file.Files#asUncheckedRunnable(Closeable) > public somewhere. > > Otherwise many people will repeatedly have to write their own code in order to make > the example suggested by Brian Goetz in that core-libs-dev discussion compile. > Is it too late for such changes? > > -- Sebastian > > -----Original Message----- > From: lambda-dev-bounces at openjdk.java.net [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Alan Bateman > Sent: Monday, December 02, 2013 10:21 AM > To: Zhong Yu > Cc: lambda-dev at openjdk.java.net > Subject: Re: Closing the Stream returned from BufferedReader.lines() > > On 02/12/2013 03:03, Zhong Yu wrote: >> In this code >> >> BufferedReader br = ...; >> Stream stream = br.lines(); >> stream.close(); // does not close `br` >> >> `stream.close()` does not trigger `br.close()`. I for one find that >> rather counter-intuitive. Can you guys explain the design choice? When >> should a Stream forward close() to its source and when should it not? >> > See discussion on core-libs-dev from about a week ago on the same topic: > > http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023289.html > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > > From zhong.j.yu at gmail.com Mon Dec 2 10:57:46 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Mon, 2 Dec 2013 12:57:46 -0600 Subject: Closing the Stream returned from BufferedReader.lines() In-Reply-To: <529CD55F.1000107@oracle.com> References: <32F15738E8E5524DA4F01A0FA4A8E490C2FF6C8E@HQMBX5.eur.ad.sag> <529CD55F.1000107@oracle.com> Message-ID: On Mon, Dec 2, 2013 at 12:45 PM, Henry Jen wrote: > On Mon 02 Dec 2013 04:02:33 AM PST, Millies, Sebastian wrote: >> In that context, I'd be in favor >> >> either of Gernot Neppert's suggestion in >> http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023318.html >> to add a java.io.Closeable#closeUnchecked() default method, >> >> or of making the static utility method java.nio.file.Files#asUncheckedRunnable(Closeable) >> public somewhere. >> > > We thought about this before, but decided to leave it out because, > > 1. If a close method is known to throw exceptions, developer shoule > deal with it. The read methods of the data source also throw checked exceptions, which Stream uniformly rethrow as unchecked. It won't be surprising to do the same for the close method. The exception is not really neglected - it is propagated outwards, which is a legit way of "dealing with" it. (Though it is really dangerous that the exception is mucked as unchecked) > 2. It's trivial to add a static method to wrap up close if don't care > consequences or add a utility class to cascade the exception. > > That said, I think a default method to simply close resource regardless > would be convenient if name clashing is not a concern. > > Cheers, > Henry > >> Otherwise many people will repeatedly have to write their own code in order to make >> the example suggested by Brian Goetz in that core-libs-dev discussion compile. >> Is it too late for such changes? >> >> -- Sebastian >> >> -----Original Message----- >> From: lambda-dev-bounces at openjdk.java.net [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Alan Bateman >> Sent: Monday, December 02, 2013 10:21 AM >> To: Zhong Yu >> Cc: lambda-dev at openjdk.java.net >> Subject: Re: Closing the Stream returned from BufferedReader.lines() >> >> On 02/12/2013 03:03, Zhong Yu wrote: >>> In this code >>> >>> BufferedReader br = ...; >>> Stream stream = br.lines(); >>> stream.close(); // does not close `br` >>> >>> `stream.close()` does not trigger `br.close()`. I for one find that >>> rather counter-intuitive. Can you guys explain the design choice? When >>> should a Stream forward close() to its source and when should it not? >>> >> See discussion on core-libs-dev from about a week ago on the same topic: >> >> http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-November/023289.html >> >> >> Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com >> >> > From brian.goetz at oracle.com Mon Dec 2 14:22:44 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 2 Dec 2013 17:22:44 -0500 Subject: Survey on Java erasure/reification In-Reply-To: References: <526329F1.7060706@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> Message-ID: <104600AA-9680-4455-9CAE-936F881784F9@oracle.com> Yes, when I have time. Sent from my iPhone On Dec 2, 2013, at 1:37 PM, Paul Benedict wrote: > Are the results ever going to be made public or is it for Oracle's private consumption only? > > > On Mon, Dec 2, 2013 at 12:28 PM, Brian Goetz wrote: >> Java 8 is effectively done. But it is useful in gauging priorities for future platform evolution. >> >> Sent from my iPhone >> >> On Dec 2, 2013, at 9:33 AM, "Millies, Sebastian" wrote: >> >> > Can anyone say anything about the outcome of this survey? Is this going to be important for Java 8, or is it >> > a future thing? -- Sebastian >> > >> > -----Original Message----- >> > From: lambda-dev-bounces at openjdk.java.net [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Brian Goetz >> > Sent: Sunday, October 20, 2013 2:55 AM >> > To: lambda-dev at openjdk.java.net; Core-Libs-Dev >> > Subject: Survey on Java erasure/reification >> > >> > I've created a survey about people's attitudes towards erasure and reification. >> > >> > If you participate, please take the time to answer the free-response question; that's really what is going to help us. >> > >> > Survey here: >> > https://www.surveymonkey.com/s/SCJC93R >> > >> > >> > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com >> > >> > > > > > -- > Cheers, > Paul From forax at univ-mlv.fr Mon Dec 2 14:36:02 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 02 Dec 2013 23:36:02 +0100 Subject: Survey on Java erasure/reification In-Reply-To: References: <526329F1.7060706@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D33@HQMBX5.eur.ad.sag> Message-ID: <529D0B52.4070009@univ-mlv.fr> On 12/02/2013 06:00 PM, Ali Ebrahimi wrote: > Maybe java 10+ or never ... R?mi > > > On Mon, Dec 2, 2013 at 6:03 PM, Millies, Sebastian < > Sebastian.Millies at softwareag.com> wrote: > >> Can anyone say anything about the outcome of this survey? Is this going to >> be important for Java 8, or is it >> a future thing? -- Sebastian >> >> -----Original Message----- >> From: lambda-dev-bounces at openjdk.java.net [mailto: >> lambda-dev-bounces at openjdk.java.net] On Behalf Of Brian Goetz >> Sent: Sunday, October 20, 2013 2:55 AM >> To: lambda-dev at openjdk.java.net; Core-Libs-Dev >> Subject: Survey on Java erasure/reification >> >> I've created a survey about people's attitudes towards erasure and >> reification. >> >> If you participate, please take the time to answer the free-response >> question; that's really what is going to help us. >> >> Survey here: >> https://www.surveymonkey.com/s/SCJC93R >> >> >> Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, >> Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - >> Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), >> Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of >> the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com >> >> >> From Donald.Raab at gs.com Mon Dec 2 15:41:05 2013 From: Donald.Raab at gs.com (Raab, Donald) Date: Mon, 2 Dec 2013 18:41:05 -0500 Subject: GS Collections 4.2 Release Message-ID: <6712820CB52CFB4D842561213A77C0540531501976@GSCMAMP09EX.firmwide.corp.gs.com> I thought I would update this group on our latest release of GS Collections. For those who haven't heard of it, GS Collections is a comprehensive open source Java Collections library, featuring rich functional style interfaces and compatibility with JDK collections. Its features are fully lambda ready so you can try it out now with Java 8. Trying GS Collections with lambdas will also demonstrate the synergies between lambdas and this style of API: greatly increased code simplicity, readability and expressiveness as well as improved collection operation performance in some cases. As of the 4.1 release, GS Collections is now available in Maven Central. Release notes are available here: https://github.com/goldmansachs/gs-collections/releases GS Collections comes with a programming kata which is intended to help developers learn our APIs through a combination of educational material and hands-on exercises. The kata can be found in GitHub here: https://github.com/goldmansachs/gs-collections-kata We've updated our Java 8 kata solutions branch to leverage the latest features in GSC 4.2. We've also discovered a neat way to parameterize a method reference using our optimized (but lesser known) "With" methods (e.g. selectWith, collectWith, anySatisfyWith, detectWith, etc.). You can see two examples of this in the kata solutions. Method references are such a cool feature, our tendency is to want to use them as much as possible. Being able to parameterize a method reference gives us even more opportunities to leverage this wonderful Java 8 feature. Kudos and thanks to Oracle and the Java 8 Lambda developers on building this most excellent feature. Here's a link to our kata solutions branch that leverages Java 8 lambdas and method references: https://github.com/goldmansachs/gs-collections-kata/tree/solutions-java8 Several parameterized method reference examples are linked below. Look for methods that end in "With" and take a Java 8 method reference along with a second parameter. https://github.com/goldmansachs/gs-collections-kata/blob/solutions-java8/src/test/java/com/gs/collections/kata/Exercise1Test.java https://github.com/goldmansachs/gs-collections-kata/blob/solutions-java8/src/test/java/com/gs/collections/kata/Exercise3Test.java https://github.com/goldmansachs/gs-collections-kata/blob/solutions-java8/src/test/java/com/gs/collections/kata/Exercise5Test.java With the release of GSC 4.2 we now have support for all primitive types including mutable, immutable, unmodifiable, synchronized and lazy across primitive Lists, Sets, Maps, Bags and Stacks. You can transform from an object collection to any primitive collection type either eagerly or lazily, and back again. We do not support primitive to primitive type conversions yet. Our hope is that folks will further explore, test and provide feedback on the capabilities of Java 8 lambdas and method references with our extensive lambda ready APIs, especially with our primitive collections, before Java 8 is released in a few months. Cheers, Don The Goldman Sachs Group, Inc. All rights reserved. See http://www.gs.com/disclaimer/global_email for important risk disclosures, conflicts of interest and other terms and conditions relating to this e-mail and your reliance on information contained in it. This message may contain confidential or privileged information. If you are not the intended recipient, please advise us immediately and delete this message. See http://www.gs.com/disclaimer/email for further information on confidentiality and the risks of non-secure electronic communication. If you cannot access these links, please notify us by reply message and we will send the contents to you. From mohan.radhakrishnan at polarisFT.com Mon Dec 2 20:18:38 2013 From: mohan.radhakrishnan at polarisFT.com (mohan.radhakrishnan at polarisFT.com) Date: Tue, 3 Dec 2013 09:48:38 +0530 Subject: Flatmap example In-Reply-To: <12309D4F-32C1-4FF6-BF77-41B2E7033956@oracle.com> References: <102255F8-05FA-4B7F-A294-F96D4E8ADDC5@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D20@HQMBX5.eur.ad.sag> <12309D4F-32C1-4FF6-BF77-41B2E7033956@oracle.com> Message-ID: I am using 113 and it compiles.. But I realized there are 3 variants. //Style 1 patterns.stream() .flatMap(new Function>() { @Override public Stream apply(Pattern p) { return source.stream() .map(p::matcher) .filter(Matcher::find) .map(Matcher::group); } }) .forEach(System.out::println); //Style 2 patterns.stream().flatMap(( Pattern p1 ) -> source. stream(). map(p1::matcher). filter(Matcher::find).map(matcher -> matcher.group())).forEach(x -> System.out.println(x)); //Style 3 patterns.stream() .flatMap(new Function>() { @Override public Stream apply(Pattern p) { return source.stream() .map(p::matcher) .filter(Matcher::find) .map(Matcher::group); } }) .forEach(System.out::println); Thanks, Mohoan From: Paul Sandoz To: Cc: "lambda-dev at openjdk.java.net" Date: 12/02/2013 08:42 PM Subject: Re: Flatmap example Sent by: lambda-dev-bounces at openjdk.java.net On Dec 2, 2013, at 3:31 PM, "Millies, Sebastian" wrote: > I can't get the second variant (without the inner class) to compile with b117. > Compiles and runs for me against the tip of tl. > The method reference in ".map(p::matcher)" seems illegal, and explicitly typing the Lambda-Parameter > "p" as "Pattern" leads to an Incompatible Types error. I have to cast the function that goes into the flatMap > to "Function>". Why is that? > I guess passing compile glitch or bug that was recently fixed. Paul. This e-Mail may contain proprietary and confidential information and is sent for the intended recipient(s) only. If by an addressing or transmission error this mail has been misdirected to you, you are requested to delete this mail immediately. You are also hereby notified that any use, any form of reproduction, dissemination, copying, disclosure, modification, distribution and/or publication of this e-mail message, contents or its attachment other than by its intended recipient/s is strictly prohibited. Visit us at http://www.polarisFT.com From mohan.radhakrishnan at polarisFT.com Mon Dec 2 20:24:51 2013 From: mohan.radhakrishnan at polarisFT.com (mohan.radhakrishnan at polarisFT.com) Date: Tue, 3 Dec 2013 09:54:51 +0530 Subject: Flatmap example In-Reply-To: References: <102255F8-05FA-4B7F-A294-F96D4E8ADDC5@oracle.com> <32F15738E8E5524DA4F01A0FA4A8E490C2FF6D20@HQMBX5.eur.ad.sag> <12309D4F-32C1-4FF6-BF77-41B2E7033956@oracle.com> Message-ID: That are 2 variants that compile. I mistook code folding for a new pattern. Mohan From: Mohan Radhakrishnan/BSC31/polarisFT To: lambda-dev at openjdk.java.net Date: 12/03/2013 09:48 AM Subject: Re: Flatmap example I am using 113 and it compiles.. But I realized there are 3 variants. //Style 1 patterns.stream() .flatMap(new Function>() { @Override public Stream apply(Pattern p) { return source.stream() .map(p::matcher) .filter(Matcher::find) .map(Matcher::group); } }) .forEach(System.out::println); //Style 2 patterns.stream().flatMap(( Pattern p1 ) -> source. stream(). map(p1::matcher). filter(Matcher::find).map(matcher -> matcher.group())).forEach(x -> System.out.println(x)); //Style 3 patterns.stream() .flatMap(new Function>() { @Override public Stream apply(Pattern p) { return source.stream() .map(p::matcher) .filter(Matcher::find) .map(Matcher::group); } }) .forEach(System.out::println); Thanks, Mohoan From: Paul Sandoz To: Cc: "lambda-dev at openjdk.java.net" Date: 12/02/2013 08:42 PM Subject: Re: Flatmap example Sent by: lambda-dev-bounces at openjdk.java.net On Dec 2, 2013, at 3:31 PM, "Millies, Sebastian" wrote: > I can't get the second variant (without the inner class) to compile with b117. > Compiles and runs for me against the tip of tl. > The method reference in ".map(p::matcher)" seems illegal, and explicitly typing the Lambda-Parameter > "p" as "Pattern" leads to an Incompatible Types error. I have to cast the function that goes into the flatMap > to "Function>". Why is that? > I guess passing compile glitch or bug that was recently fixed. Paul. This e-Mail may contain proprietary and confidential information and is sent for the intended recipient(s) only. If by an addressing or transmission error this mail has been misdirected to you, you are requested to delete this mail immediately. You are also hereby notified that any use, any form of reproduction, dissemination, copying, disclosure, modification, distribution and/or publication of this e-mail message, contents or its attachment other than by its intended recipient/s is strictly prohibited. Visit us at http://www.polarisFT.com From mohan.radhakrishnan at polarisFT.com Tue Dec 3 03:37:49 2013 From: mohan.radhakrishnan at polarisFT.com (mohan.radhakrishnan at polarisFT.com) Date: Tue, 3 Dec 2013 17:07:49 +0530 Subject: Accumulating filtered values Message-ID: Hi, I have two streams. One is the log line and another stream is the pattern list. I was trying to accumulate the result of 'm.find()' in a List because this function returns multiple values in a while loop. I think here instead of a Predicate I need some type of accumulator ? I searched but didn't find an example. This code compiles and runs but I couldn't access the list of accumulated matches. The result now is a set of Matchers.But not the matches. Each Matcher is printed two times. [java.util.regex.Matcher[pattern=Current.*?[/|] region=0,447 lastmatch=]] java.util.regex.Matcher[pattern=Current.*?[/|] region=0,447 lastmatch=] [java.util.regex.Matcher[pattern=Current.*?[/|] region=0,447 lastmatch=]] java.util.regex.Matcher[pattern=Current.*?[/|] region=0,447 lastmatch=] [java.util.regex.Matcher[pattern=[0-9]+(/,|/|) region=0,447 lastmatch=]] java.util.regex.Matcher[pattern=[0-9]+(/,|/|) region=0,447 lastmatch=] [java.util.regex.Matcher[pattern=[0-9]+(/,|/|) region=0,447 lastmatch=]] java.util.regex.Matcher[pattern=[0-9]+(/,|/|) region=0,447 lastmatch=] Thanks. Predicate matches = m -> { List list = new ArrayList(); while(m.find()){ String match = m.group(); list.add(match); } return true; }; //Style 1 patterns.stream() .flatMap(new Function>() { @Override public Stream apply(Pattern p) { return source.stream() .map(p::matcher) .filter(matches).map(l -> { System.out.println( "[" + l + "]" ); return l; }); } }) .forEach(System.out::println); This e-Mail may contain proprietary and confidential information and is sent for the intended recipient(s) only. If by an addressing or transmission error this mail has been misdirected to you, you are requested to delete this mail immediately. You are also hereby notified that any use, any form of reproduction, dissemination, copying, disclosure, modification, distribution and/or publication of this e-mail message, contents or its attachment other than by its intended recipient/s is strictly prohibited. Visit us at http://www.polarisFT.com From samir at noodlesandwich.com Tue Dec 3 04:43:14 2013 From: samir at noodlesandwich.com (Samir Talwar) Date: Tue, 3 Dec 2013 12:43:14 +0000 Subject: Accumulating filtered values In-Reply-To: References: Message-ID: // Sending again. It appears I have to add "lambda-dev" manually to the reply list, even if I hit Reply All. It looks like you want to map over the matches, then filter out empty ones. This becomes clear when you realise you throw away the list you generate in the predicate. I'm not *sure* you want to throw away the empty ones, so if that's not true, just delete the appropriate line below. You also want to avoid printing inside the flatMap. You're already doing that outside. Finally, you can move more operations outside the flatMap. Anything that doesn't rely on the pattern itself is a candidate. Here's some untested code which should hopefully solve your problems: Function> matches = m -> { List list = new ArrayList(); while(m.find()) { list.add(m.group()); } return list; }; patterns.stream() .flatMap(p -> source.stream().map(p::matcher)) .map(matches) .filter(Predicates.not(List::isEmpty))) .forEach(System.out::println); ? Samir. On Tue, Dec 3, 2013 at 12:41 PM, Samir Talwar wrote: > It looks like you want to map over the matches, then filter out empty > ones. This becomes clear when you realise you throw away the list you > generate in the predicate. I'm not *sure* you want to throw away the empty > ones, so if that's not true, just delete the appropriate line below. > > You also want to avoid printing inside the flatMap. You're already doing > that outside. > > Finally, you can move more operations outside the flatMap. Anything that > doesn't rely on the pattern itself is a candidate. > > Here's some untested code which should hopefully solve your problems: > > Function> matches = m -> { > List list = new ArrayList(); > while(m.find()) { > list.add(m.group()); > } > return list; > }; > > patterns.stream() > .flatMap(p -> source.stream().map(p::matcher)) > .map(matches) > .filter(Predicates.not(List::isEmpty))) > .forEach(System.out::println); > > ? Samir. > > > > On Tue, Dec 3, 2013 at 11:37 AM, wrote: > >> Hi, >> I have two streams. One is the log line and another stream is >> the pattern list. I was trying to accumulate the result of 'm.find()' in a >> List because this function returns multiple values in a while loop. I >> think here instead of a Predicate I need some type of accumulator ? I >> searched but didn't find an example. >> >> This code compiles and runs but I couldn't access the list of accumulated >> matches. >> >> The result now is a set of Matchers.But not the matches. Each Matcher is >> printed two times. >> >> [java.util.regex.Matcher[pattern=Current.*?[/|] region=0,447 lastmatch=]] >> java.util.regex.Matcher[pattern=Current.*?[/|] region=0,447 lastmatch=] >> [java.util.regex.Matcher[pattern=Current.*?[/|] region=0,447 lastmatch=]] >> java.util.regex.Matcher[pattern=Current.*?[/|] region=0,447 lastmatch=] >> [java.util.regex.Matcher[pattern=[0-9]+(/,|/|) region=0,447 lastmatch=]] >> java.util.regex.Matcher[pattern=[0-9]+(/,|/|) region=0,447 lastmatch=] >> [java.util.regex.Matcher[pattern=[0-9]+(/,|/|) region=0,447 lastmatch=]] >> java.util.regex.Matcher[pattern=[0-9]+(/,|/|) region=0,447 lastmatch=] >> >> Thanks. >> >> Predicate matches = m -> { >> List list = new ArrayList(); >> while(m.find()){ >> String match = m.group(); >> list.add(match); >> } >> return true; >> }; >> >> //Style 1 >> patterns.stream() >> .flatMap(new Function>() { >> @Override >> public Stream apply(Pattern p) { >> return source.stream() >> .map(p::matcher) >> .filter(matches).map(l -> { >> System.out.println( "[" + l + "]" ); >> return l; >> }); >> } >> }) >> .forEach(System.out::println); >> >> >> This e-Mail may contain proprietary and confidential information and is >> sent for the intended recipient(s) only. If by an addressing or >> transmission error this mail has been misdirected to you, you are requested >> to delete this mail immediately. You are also hereby notified that any use, >> any form of reproduction, dissemination, copying, disclosure, modification, >> distribution and/or publication of this e-mail message, contents or its >> attachment other than by its intended recipient/s is strictly prohibited. >> >> Visit us at http://www.polarisFT.com >> >> > From henry.jen at oracle.com Tue Dec 3 10:36:16 2013 From: henry.jen at oracle.com (Henry Jen) Date: Tue, 03 Dec 2013 10:36:16 -0800 Subject: RFR: 8029434: Spliterator of Stream returned by BufferedReader.lines() should have NONNULL characteristic In-Reply-To: <529CCE7D.8000409@oracle.com> References: <5299B881.3040702@gmail.com> <529CCE7D.8000409@oracle.com> Message-ID: <529E24A0.9090604@oracle.com> Hi, Please review a small fix that add missing NONNULL characteristic and cleanup in javadoc. Thanks Anthony Vanelverdinghe for reporting of this bug. http://cr.openjdk.java.net/~henryjen/tl/8029434/0/webrev/ Cheers, Henry From henry.jen at oracle.com Tue Dec 3 11:49:34 2013 From: henry.jen at oracle.com (Henry Jen) Date: Tue, 03 Dec 2013 11:49:34 -0800 Subject: RFR: 8029434: Spliterator of Stream returned by BufferedReader.lines() should have NONNULL characteristic In-Reply-To: <77EB7336-4EDE-44C7-945A-99CB8C045B86@oracle.com> References: <5299B881.3040702@gmail.com> <529CCE7D.8000409@oracle.com> <529E24A0.9090604@oracle.com> <77EB7336-4EDE-44C7-945A-99CB8C045B86@oracle.com> Message-ID: <529E35CE.6010104@oracle.com> I have separated the fix into two part, 8029434: Spliterator of Stream returned by BufferedReader.lines() should have NONNULL characteristic 8029483: BufferedReader.lines() javadoc typo should be fixed So that we can at least fix the javadoc by jdk8 release if not the characteristic. Cheers, Henry On 12/03/2013 10:52 AM, Mike Duigou wrote: > Looks good to me. > > Mike > > On Dec 3 2013, at 10:36 , Henry Jen wrote: > >> Hi, >> >> Please review a small fix that add missing NONNULL characteristic and cleanup in javadoc. >> >> Thanks Anthony Vanelverdinghe for reporting of this bug. >> >> http://cr.openjdk.java.net/~henryjen/tl/8029434/0/webrev/ >> >> Cheers, >> Henry > From mike.duigou at oracle.com Tue Dec 3 11:48:49 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Tue, 3 Dec 2013 11:48:49 -0800 Subject: RFR: 8029434: Spliterator of Stream returned by BufferedReader.lines() should have NONNULL characteristic In-Reply-To: <529E35CE.6010104@oracle.com> References: <5299B881.3040702@gmail.com> <529CCE7D.8000409@oracle.com> <529E24A0.9090604@oracle.com> <77EB7336-4EDE-44C7-945A-99CB8C045B86@oracle.com> <529E35CE.6010104@oracle.com> Message-ID: Go ahead with pushing 8029483 as no approval is required for doc only change. Mike On Dec 3 2013, at 11:49 , Henry Jen wrote: > I have separated the fix into two part, > > 8029434: Spliterator of Stream returned by BufferedReader.lines() should have NONNULL characteristic > > 8029483: BufferedReader.lines() javadoc typo should be fixed > > So that we can at least fix the javadoc by jdk8 release if not the characteristic. > > Cheers, > Henry > > On 12/03/2013 10:52 AM, Mike Duigou wrote: >> Looks good to me. >> >> Mike >> >> On Dec 3 2013, at 10:36 , Henry Jen wrote: >> >>> Hi, >>> >>> Please review a small fix that add missing NONNULL characteristic and cleanup in javadoc. >>> >>> Thanks Anthony Vanelverdinghe for reporting of this bug. >>> >>> http://cr.openjdk.java.net/~henryjen/tl/8029434/0/webrev/ >>> >>> Cheers, >>> Henry >> From zhong.j.yu at gmail.com Tue Dec 3 12:05:25 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Tue, 3 Dec 2013 14:05:25 -0600 Subject: Javac Bug? In-Reply-To: <5287A669.1040006@oracle.com> References: <5286284B.8080608@oracle.com> <52863AA0.1050206@oracle.com> <528658F4.2080107@oracle.com> <52877DC8.3070008@univ-mlv.fr> <5287A669.1040006@oracle.com> Message-ID: Any update on this issue? My preference would be to fix the spec to remove the clauses that compare return types, which will only create confusions - sometimes it works, but very often it doesn't work - when lambda body is a statement expression. Zhong Yu On Sat, Nov 16, 2013 at 11:07 AM, David Holmes wrote: > On 17/11/2013 12:59 AM, Zhong Yu wrote: >> >> So this is a bug in the spec text, which indicates that the kind of >> return (void or value) plays a roles here? > > > Or a bug in javac as it doesn't implement the current spec? > > Either way there is a bug. Even if there is a desire to do something > different/better in 9, there should be consistency between the spec and > javac in 8. > > David > ----- > > >> Zhong Yu >> >> >> On Sat, Nov 16, 2013 at 8:14 AM, Remi Forax wrote: >>> >>> On 11/15/2013 06:25 PM, David Holmes wrote: >>>> >>>> On 16/11/2013 1:36 AM, Zhong Yu wrote: >>>>> >>>>> On Fri, Nov 15, 2013 at 9:15 AM, Vicente-Arturo Romero-Zaldivar >>>>> wrote: >>>>>> >>>>>> On 15/11/13 14:51, Zhong Yu wrote: >>>>>>> >>>>>>> The return type seems also play a role here, see >>>>>>> http://cr.openjdk.java.net/~dlsmith/jsr335-0.7.0/F.html >>>>>>> >>>>>>> "" >>>>>>> A lambda expression (15.27) is potentially compatible with a >>>>>>> functional interface type (9.8) if all of the following are true: >>>>>>> >>>>>>> The arity of the targeted type's function type is the same as the >>>>>>> arity of the lambda expression. >>>>>>> If the targeted type's function type has a void return, then the >>>>>>> lambda body is either a statement expression (14.8) or a >>>>>>> void-compatible block (15.27.2). >>>>>>> If the targeted type's function type has a (non-void) return type, >>>>>>> then the lambda body is either an expression or a value-compatible >>>>>>> block (15.27.2). >>>>>>> "" >>>>>>> >>>>>>> Therefore, method >>>>>>> public void forEach(Consumer consumer) >>>>>>> is not potentially applicable to invocation >>>>>>> forEach(v -> { return biPredicate.test(1, v); } ); >>>>>>> because the function type of Consumer has a void return, yet the >>>>>>> lambda body is a value-compatible block. >>>>>> >>>>>> >>>>>> The compiler analyze lambda expressions in several phases: >>>>>> >>>>>> first analysis is by arity, if there are two possible applicable >>>>>> methods by >>>>>> arity the compiler issues an error. If a method pass to the next >>>>>> phase, then >>>>>> the rest of the information is taken into account. >>>>> >>>>> But the spec text I quoted mentions both arity and return type in the >>>>> phase of identifying potentially applicable methods (15.12.2.1) >>>> >>>> I have to agree - the compiler needs to consider all of the conditions >>>> combined as is written in the spec. It should not declare ambiguity >>>> based on arity alone when the return type would have reduced things to a >>>> single applicable method. >>>> >>>> David >>>> ----- >>> >>> >>> Hi David, Hi all, >>> the lambda EG has decided that for 8 we will spec a very basic inference >>> algorithm >>> when overloading and lambdas are used at the same time, we have explored >>> many algorithms >>> and even found one that seems to work but we don't have the time to be >>> sure that it doesn't >>> introduce weird behavior (as the previous proposed algorithms). >>> So instead of releasing a half baked algorithm, we backoff to a simple >>> algorithm >>> that disambiguate using the arity only to be sure to not hamper our >>> chance to have a better one in 9. >>> >>> cheers, >>> R?mi >>> >>>> >>>>>> >>>>>>> >>>>>>> On Fri, Nov 15, 2013 at 7:57 AM, Vicente-Arturo Romero-Zaldivar >>>>>>> wrote: >>>>>>>> >>>>>>>> On 13/11/13 19:04, Zhong Yu wrote: >>>>>>>>> >>>>>>>>> This program does not compile in javac8 build 115. I think it >>>>>>>>> should >>>>>>>>> compile (but who knows really:) >>>>>>>>> >>>>>>>>> public class Bug { >>>>>>>>> public void forEach(Consumer consumer) { >>>>>>>>> // ... >>>>>>>>> } >>>>>>>>> public void forEach(Predicate predicate) { >>>>>>>>> // ... >>>>>>>>> } >>>>>>>>> public void forEach(BiConsumer >>>>>>>>> biConsumer) { >>>>>>>>> forEach((v) -> { biConsumer.accept(1, v); }); >>>>>>>>> } >>>>>>>>> public void forEach(BiPredicate>>>>>>>> T> >>>>>>>>> biPredicate) { >>>>>>>>> forEach(v -> { return biPredicate.test(1, v); } ); >>>>>>>>> } >>>>>>>>> } >>>>>>>> >>>>>>>> Hi Zhong Yu, >>>>>>>> >>>>>>>> No the compiler is right functional descriptors of Consumer and >>>>>>>> Predicate >>>>>>>> have the same arity, so the compiler determines that there is an >>>>>>>> ambiguity >>>>>>>> error. >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Vicente >>>>>>>> >>>>>>>>> >>>>>>>>> On Wed, Nov 13, 2013 at 12:59 PM, Zhong Yu >>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>> Here's my understanding how the process works. >>>>>>>>>> >>>>>>>>>> When javac sees >>>>>>>>>> >>>>>>>>>> forEach( v->... ) >>>>>>>>>> >>>>>>>>>> two pieces of information of the implicit lambda are used to prune >>>>>>>>>> overloading methods: >>>>>>>>>> 1. the arity. therefore BiConsumer/BiPredicate are excluded >>>>>>>>>> 2. whether the lambda body returns void or a real type. >>>>>>>>>> >>>>>>>>>> If the lambda body is a block, it's quite clear whether it's void >>>>>>>>>> or >>>>>>>>>> not. It seems to me that this would work: >>>>>>>>>> >>>>>>>>>> public void forEach(BiConsumer>>>>>>>>> T> >>>>>>>>>> biConsumer) { >>>>>>>>>> forEach((v) -> { biConsumer.accept(1, v); }); >>>>>>>>>> } >>>>>>>>>> public void forEach(BiPredicate>>>>>>>>> T> >>>>>>>>>> biPredicate) { >>>>>>>>>> forEach(v -> { return biPredicate.test(1, v); } ); >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> ( ... But it fails in javac build 115. javac bug?) >>>>>>>>>> >>>>>>>>>> If the lambda body is a "statement expression", like in your >>>>>>>>>> original >>>>>>>>>> example >>>>>>>>>> >>>>>>>>>> public void forEach(BiConsumer>>>>>>>>> T> >>>>>>>>>> biConsumer) { >>>>>>>>>> forEach((v) -> biConsumer.accept(1, v) ); >>>>>>>>>> } >>>>>>>>>> public void forEach(BiPredicate>>>>>>>>> T> >>>>>>>>>> biPredicate) { >>>>>>>>>> forEach(v -> biPredicate.test(1, v) ); >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> It's unclear what the return type is, so javac cannot use the >>>>>>>>>> return >>>>>>>>>> type to prune. Note that even though `biConsumer.accept(1, v)` >>>>>>>>>> obviously returns void, javac does not know that, because the type >>>>>>>>>> of >>>>>>>>>> `v` is not known yet. And even though `biPredicate.test(1, v)` >>>>>>>>>> obviously returns boolean, it is compatible to a function type >>>>>>>>>> that >>>>>>>>>> expects void return. >>>>>>>>>> >>>>>>>>>> Now, for each invocation, we have two potentially applicable >>>>>>>>>> methods. >>>>>>>>>> >>>>>>>>>> The next step tries to prune methods by checking argument types >>>>>>>>>> against method parameter types. Unfortunately, implicit lambda >>>>>>>>>> expressions are too vague, so they are simply ignored in this >>>>>>>>>> step. >>>>>>>>>> >>>>>>>>>> Therefore both methods are considered applicable methods. The most >>>>>>>>>> specific method is sought after. However neither method is more >>>>>>>>>> specific than the other, therefore we see the error message of >>>>>>>>>> ambiguity. >>>>>>>>>> >>>>>>>>>> If you use explicit lambda expressions, javac is able to do more >>>>>>>>>> pruning, so this works: >>>>>>>>>> >>>>>>>>>> public void forEach(BiConsumer>>>>>>>>> T> >>>>>>>>>> biConsumer) { >>>>>>>>>> forEach((T v) -> biConsumer.accept(1, v) ); >>>>>>>>>> } >>>>>>>>>> public void forEach(BiPredicate>>>>>>>>> T> >>>>>>>>>> biPredicate) { >>>>>>>>>> forEach( (T v) -> biPredicate.test(1, v) ); >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> So if you have overloading methods like this >>>>>>>>>> >>>>>>>>>> public void forEach(Consumer consumer) { >>>>>>>>>> // ... >>>>>>>>>> } >>>>>>>>>> public void forEach(Predicate predicate) { >>>>>>>>>> // ... >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> client code often cannot use implicit lambda expressions as >>>>>>>>>> arguments; >>>>>>>>>> and experts have advised against this kind of overloading scheme >>>>>>>>>> (two >>>>>>>>>> functional interfaces with the same arity) >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Zhong Yu >>>>>>>>>> >>>>>>>>>> On Wed, Nov 13, 2013 at 8:01 AM, D?vid Karnok >>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>> Hello, >>>>>>>>>>> >>>>>>>>>>> I'm rewriting a library and run into a strange ambiguity error >>>>>>>>>>> reported >>>>>>>>>>> by >>>>>>>>>>> javac in JDK 8 b115, Windows 7 x86: >>>>>>>>>>> >>>>>>>>>>> public class Bug { >>>>>>>>>>> public void forEach(Consumer consumer) { >>>>>>>>>>> // ... >>>>>>>>>>> } >>>>>>>>>>> public void forEach(BiConsumer>>>>>>>>>> T> >>>>>>>>>>> consumer) { >>>>>>>>>>> forEach((v) -> consumer.accept(1, v)); >>>>>>>>>>> } >>>>>>>>>>> public void forEach(Predicate >>>>>>>>>>> stoppableConsumer) { >>>>>>>>>>> // ... >>>>>>>>>>> } >>>>>>>>>>> public void forEach(BiPredicate>>>>>>>>>> T> >>>>>>>>>>> stoppableConsumer) { >>>>>>>>>>> forEach(v -> stoppableConsumer.test(1, v)); >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> error: reference to forEach is ambiguous >>>>>>>>>>> forEach((v) -> consumer.accept(1, v)); >>>>>>>>>>> both method forEach(Consumer) in Bug and method >>>>>>>>>>> forEach(Predicate) in Bug match >>>>>>>>>>> where T is a type-variable: >>>>>>>>>>> T extends Object declared in class Bug >>>>>>>>>>> >>>>>>>>>>> error: reference to forEach is ambiguous >>>>>>>>>>> forEach(v -> stoppableConsumer.test(1, v)); >>>>>>>>>>> both method forEach(Consumer) in Bug and method >>>>>>>>>>> forEach(Predicate) in Bug match >>>>>>>>>>> where T is a type-variable: >>>>>>>>>>> T extends Object declared in class Bug >>>>>>>>>>> >>>>>>>>>>> I'm using NetBeans 7.4 (Build 201310111528) which doesn't report >>>>>>>>>>> this >>>>>>>>>>> ambiguity in the editor, and the "highlight occurrences" >>>>>>>>>>> correctly >>>>>>>>>>> selects >>>>>>>>>>> the 3rd method when I select the forEach in the 4th method. >>>>>>>>>>> However, >>>>>>>>>>> the >>>>>>>>>>> clean and build fails with the errors above. I have to add >>>>>>>>>>> explicit >>>>>>>>>>> cast >>>>>>>>>>> to >>>>>>>>>>> the problematic places. >>>>>>>>>>> >>>>>>>>>>> So I'm a bit confused right now. Is it a bug with NetBeans' >>>>>>>>>>> editor, >>>>>>>>>>> with >>>>>>>>>>> javac or simply the artifact of how overload resolution works? >>>>>>>>>>> -- >>>>>>>>>>> Best regards, >>>>>>>>>>> David Karnok >>>>>>>>>>> >>> >>> >> > From mike.duigou at oracle.com Fri Dec 6 11:59:35 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Fri, 6 Dec 2013 11:59:35 -0800 Subject: RFR: 8029696 : (xs) Broken doc links to package-summary.html#NonInterference in java.util.stream Message-ID: Hello all; https://bugs.openjdk.java.net/browse/JDK-8029696 Michael McMahon noticed that some links to the anchor #NonInterference were not using the correct name for the anchor. He prepared a patch which I reviewed, tested. I also checked to make sure there were no other broken instances. I've prepared a webrev of the patch for anyone else who wishes to review. http://cr.openjdk.java.net/~mduigou/JDK-8029696/0/webrev/ Mike From robert.field at oracle.com Fri Dec 6 13:45:26 2013 From: robert.field at oracle.com (Robert Field) Date: Fri, 06 Dec 2013 13:45:26 -0800 Subject: RFR (javac) 8029558: VerifyError: Bad return type when lambda's body is in parentheses Message-ID: <52A24576.9000309@oracle.com> Please review compiler (javac) fix for: https://bugs.openjdk.java.net/browse/JDK-8029558 Webrev: http://cr.openjdk.java.net/~rfield/8029558v0/ Fix is to correctly treat the lambda body as a value returning entity rather than a void entity so that that the correct type converting casts are generated. This is done by passing the erased type rather than null as the expected type. Thanks, Robert From jonathan.gibbons at oracle.com Fri Dec 6 13:46:41 2013 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 06 Dec 2013 13:46:41 -0800 Subject: RFR (javac) 8029558: VerifyError: Bad return type when lambda's body is in parentheses In-Reply-To: <52A24576.9000309@oracle.com> References: <52A24576.9000309@oracle.com> Message-ID: <52A245C1.2010800@oracle.com> Robert, Is this for jdk8/tl? If so, then compiler-dev would be a better forum. The two tests look very similar. Are they materially different? -- Jon On 12/06/2013 01:45 PM, Robert Field wrote: > Please review compiler (javac) fix for: > > https://bugs.openjdk.java.net/browse/JDK-8029558 > > Webrev: > > http://cr.openjdk.java.net/~rfield/8029558v0/ > > > Fix is to correctly treat the lambda body as a value returning entity > rather than a void entity so that that the correct type converting > casts are generated. This is done by passing the erased type rather > than null as the expected type. > > Thanks, > Robert > From mike.duigou at oracle.com Fri Dec 6 14:18:55 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Fri, 6 Dec 2013 14:18:55 -0800 Subject: RFR: 8029055: Map.merge must refuse null values In-Reply-To: <63CE95FF-EBA9-4003-AFC2-4F8EBED9B807@oracle.com> References: <528E568D.8020909@oracle.com> <528EC28B.6040002@oracle.com> <528FF062.9030800@oracle.com> <52929A59.20204@oracle.com> <63CE95FF-EBA9-4003-AFC2-4F8EBED9B807@oracle.com> Message-ID: Hello all. I have updated the webrev with a final correction from Brian Goetz, the @throws NPE didn't reflect that it was thrown unconditionally if value is null. http://cr.openjdk.java.net/~mduigou/JDK-8029055/2/webrev/ Mike On Nov 25 2013, at 20:32 , Mike Duigou wrote: > > On Nov 24 2013, at 16:31 , David Holmes wrote: > >> Hi Mike, >> >> There is still no clear spec for what should happen if the param value is null. > > I feel very uncomfortable the status quo of with null being ignored, used for a sentinel and also as value. The relations between null and values in this method are just too complicated. > > Currently: > > - The provided value may be either null or non-null. Is null a legal value? It depends upon: > - Is there an existing value? > - Does the Map allow null values? > - Does the function allow null values? > - Existing null values are treated as absent. > - If a null value is passed should we remove this mapping or add it to the map? > - null might not be accepted by the map > - The associated value would still be regarded as absent for future operations. > - The function may return null to signal "remove". > > In particular I dislike adding a null entry to the map if there is no current mapping (or mapped to null). It seems like it should be invariant whether we end up with an associated value. If null is used to signify "remove" then map.contains(key) will return variable results depending upon the initial state. Having the behaviour vary based upon whether the map allows null values would be even worse. > > So I would like to suggest that we require value to be non-null. I have provisionally updated the spec and impls accordingly. > >> The parenthesized part is wrong. > > I think that's overzealous copying from compute(). I have removed it. > >> >> Also you have changed the method implementation not just the implDoc so the bug synopsis is somewhat misleading. > > I will correct this. More changes were made than I originally expected. New synopsis will be "Map.merge implementations should refuse null value param" > > I have updated the webrev. > > http://cr.openjdk.java.net/~mduigou/JDK-8029055/1/webrev/ > > Thanks, > > Mike > >> >> Thanks, >> David >> >> On 23/11/2013 10:25 AM, Mike Duigou wrote: >>> We'll be using https://bugs.openjdk.java.net/browse/JDK-8029055 for this issue. >>> >>> I've posted a webrev here: >>> >>> http://cr.openjdk.java.net/~mduigou/JDK-8029055/0/webrev/ >>> >>> There is an identical change in ConcurrentMap's merge(). >>> >>> Mike >>> >>> On Nov 22 2013, at 16:01 , Henry Jen wrote: >>> >>>> >>>> On 11/21/2013 06:33 PM, David Holmes wrote: >>>>> On 22/11/2013 5:02 AM, Louis Wasserman wrote: >>>>>> While I agree that case should be specified, I'm not certain I follow why >>>>>> that's what's going on here. >>>>>> >>>>>> The weird condition is that if oldValue is null, not value; oldValue >>>>>> is the >>>>>> old result of map.get(key). The Javadoc seems not just unspecified, but >>>>>> actively wrong. Here's a worked example: >>>>>> >>>>>> Map map = new HashMap<>(); >>>>>> map.merge("foo", 3, Integer::plus); >>>>>> Integer fooValue = map.get("foo"); >>>>>> >>>>>> Going through the Javadoc-specified default implementation: >>>>>> >>>>>> V oldValue = map.get(key); // oldValue is null >>>>>> V newValue = (oldValue == null) ? value : >>>>>> remappingFunction.apply(oldValue, value); >>>>>> // newValue is set to value, which is 3 >>>>>> if (newValue == null) // newValue is nonnull, branch not taken >>>>>> map.remove(key); >>>>>> else if (oldValue == null) // oldValue is null, branch taken >>>>>> map.remove(key); // removes the entry from the map >>>>>> else // else if was already triggered, branch not taken >>>>>> map.put(key, newValue); >>>>>> >>>> >>>> Seems like a document bug to me, we should fix this @implSpec. >>>> >>>> Cheers, >>>> Henry >>>> >>> > From bitterfoxc at gmail.com Fri Dec 6 16:23:19 2013 From: bitterfoxc at gmail.com (bitter_fox) Date: Sat, 7 Dec 2013 09:23:19 +0900 Subject: SOfError by Lambda expr in Local Class In-Reply-To: References: Message-ID: Hi, Does anyone know the state of this issue? Regards, bitter_fox 2013/12/1 bitter_fox > Hi, > When I compile the following code, StackOverflowError occur. > > public class Main > { > interface F {void f();} > > public static void main(String[] args) > { > class Local > { > public Local() > { > F f = () -> new Local(); > } > } > } > } > > It may be a cause that > c.s.t.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor#capturelocalClassDefs > is called recursively. > > void captureLocalClassDefs(Symbol csym, final > LambdaTranslationContext lambdaContext) { > JCClassDecl localCDef = localClassDefs.get(csym); > if (localCDef != null && localCDef.pos < > lambdaContext.tree.pos) { > BasicFreeVarCollector fvc = lower.new > BasicFreeVarCollector() { > @Override > void addFreeVars(ClassSymbol c) { > captureLocalClassDefs(c, lambdaContext); > } > // ... > }; > fvc.scan(localCDef); > } > } > > Following is a stack trace of the Error > java.lang.StackOverflowError > at com.sun.tools.javac.tree.JCTree$JCModifiers.accept(JCTree.java:2337) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitMethodDef(TreeScanner.java:84) > at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:772) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) > at > com.sun.tools.javac.tree.TreeScanner.visitClassDef(TreeScanner.java:80) > at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:687) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.captureLocalClassDefs(LambdaToMethod.java:1325) > at > com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor$1.addFreeVars(LambdaToMethod.java:1306) > at > com.sun.tools.javac.comp.Lower$BasicFreeVarCollector.visitNewClass(Lower.java:242) > at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1510) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitLambda(TreeScanner.java:221) > at com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1618) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitVarDef(TreeScanner.java:98) > at > com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:846) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) > at > com.sun.tools.javac.tree.TreeScanner.visitBlock(TreeScanner.java:105) > at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:903) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitMethodDef(TreeScanner.java:91) > at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:772) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) > at > com.sun.tools.javac.tree.TreeScanner.visitClassDef(TreeScanner.java:80) > at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:687) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.captureLocalClassDefs(LambdaToMethod.java:1325) > at > com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor$1.addFreeVars(LambdaToMethod.java:1306) > at > com.sun.tools.javac.comp.Lower$BasicFreeVarCollector.visitNewClass(Lower.java:242) > at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1510) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitLambda(TreeScanner.java:221) > at com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1618) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitVarDef(TreeScanner.java:98) > at > com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:846) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) > at > com.sun.tools.javac.tree.TreeScanner.visitBlock(TreeScanner.java:105) > at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:903) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitMethodDef(TreeScanner.java:91) > at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:772) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) > at > com.sun.tools.javac.tree.TreeScanner.visitClassDef(TreeScanner.java:80) > at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:687) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.captureLocalClassDefs(LambdaToMethod.java:1325) > at > com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor$1.addFreeVars(LambdaToMethod.java:1306) > at > com.sun.tools.javac.comp.Lower$BasicFreeVarCollector.visitNewClass(Lower.java:242) > at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1510) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitLambda(TreeScanner.java:221) > at com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1618) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitVarDef(TreeScanner.java:98) > at > com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:846) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) > at > com.sun.tools.javac.tree.TreeScanner.visitBlock(TreeScanner.java:105) > at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:903) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.tree.TreeScanner.visitMethodDef(TreeScanner.java:91) > at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:772) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) > at > com.sun.tools.javac.tree.TreeScanner.visitClassDef(TreeScanner.java:80) > at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:687) > at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) > at > com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.captureLocalClassDefs(LambdaToMethod.java:1325) > . > . > . > > > Regards, > bitter_fox > From daniel.smith at oracle.com Fri Dec 6 16:30:41 2013 From: daniel.smith at oracle.com (Dan Smith) Date: Fri, 6 Dec 2013 17:30:41 -0700 Subject: Javac Bug? In-Reply-To: References: <5286284B.8080608@oracle.com> <52863AA0.1050206@oracle.com> <528658F4.2080107@oracle.com> <52877DC8.3070008@univ-mlv.fr> <5287A669.1040006@oracle.com> Message-ID: Okay, we've had a change to confer on this and I've filed a javac bug: https://bugs.openjdk.java.net/browse/JDK-8029718 ?Dan On Dec 3, 2013, at 1:05 PM, Zhong Yu wrote: > Any update on this issue? > > My preference would be to fix the spec to remove the clauses that > compare return types, which will only create confusions - sometimes it > works, but very often it doesn't work - when lambda body is a > statement expression. > > Zhong Yu > > On Sat, Nov 16, 2013 at 11:07 AM, David Holmes wrote: >> On 17/11/2013 12:59 AM, Zhong Yu wrote: >>> >>> So this is a bug in the spec text, which indicates that the kind of >>> return (void or value) plays a roles here? >> >> >> Or a bug in javac as it doesn't implement the current spec? >> >> Either way there is a bug. Even if there is a desire to do something >> different/better in 9, there should be consistency between the spec and >> javac in 8. >> >> David >> ----- >> >> >>> Zhong Yu >>> >>> >>> On Sat, Nov 16, 2013 at 8:14 AM, Remi Forax wrote: >>>> >>>> On 11/15/2013 06:25 PM, David Holmes wrote: >>>>> >>>>> On 16/11/2013 1:36 AM, Zhong Yu wrote: >>>>>> >>>>>> On Fri, Nov 15, 2013 at 9:15 AM, Vicente-Arturo Romero-Zaldivar >>>>>> wrote: >>>>>>> >>>>>>> On 15/11/13 14:51, Zhong Yu wrote: >>>>>>>> >>>>>>>> The return type seems also play a role here, see >>>>>>>> http://cr.openjdk.java.net/~dlsmith/jsr335-0.7.0/F.html >>>>>>>> >>>>>>>> "" >>>>>>>> A lambda expression (15.27) is potentially compatible with a >>>>>>>> functional interface type (9.8) if all of the following are true: >>>>>>>> >>>>>>>> The arity of the targeted type's function type is the same as the >>>>>>>> arity of the lambda expression. >>>>>>>> If the targeted type's function type has a void return, then the >>>>>>>> lambda body is either a statement expression (14.8) or a >>>>>>>> void-compatible block (15.27.2). >>>>>>>> If the targeted type's function type has a (non-void) return type, >>>>>>>> then the lambda body is either an expression or a value-compatible >>>>>>>> block (15.27.2). >>>>>>>> "" >>>>>>>> >>>>>>>> Therefore, method >>>>>>>> public void forEach(Consumer consumer) >>>>>>>> is not potentially applicable to invocation >>>>>>>> forEach(v -> { return biPredicate.test(1, v); } ); >>>>>>>> because the function type of Consumer has a void return, yet the >>>>>>>> lambda body is a value-compatible block. >>>>>>> >>>>>>> >>>>>>> The compiler analyze lambda expressions in several phases: >>>>>>> >>>>>>> first analysis is by arity, if there are two possible applicable >>>>>>> methods by >>>>>>> arity the compiler issues an error. If a method pass to the next >>>>>>> phase, then >>>>>>> the rest of the information is taken into account. >>>>>> >>>>>> But the spec text I quoted mentions both arity and return type in the >>>>>> phase of identifying potentially applicable methods (15.12.2.1) >>>>> >>>>> I have to agree - the compiler needs to consider all of the conditions >>>>> combined as is written in the spec. It should not declare ambiguity >>>>> based on arity alone when the return type would have reduced things to a >>>>> single applicable method. >>>>> >>>>> David >>>>> ----- >>>> >>>> >>>> Hi David, Hi all, >>>> the lambda EG has decided that for 8 we will spec a very basic inference >>>> algorithm >>>> when overloading and lambdas are used at the same time, we have explored >>>> many algorithms >>>> and even found one that seems to work but we don't have the time to be >>>> sure that it doesn't >>>> introduce weird behavior (as the previous proposed algorithms). >>>> So instead of releasing a half baked algorithm, we backoff to a simple >>>> algorithm >>>> that disambiguate using the arity only to be sure to not hamper our >>>> chance to have a better one in 9. >>>> >>>> cheers, >>>> R?mi >>>> >>>>> >>>>>>> >>>>>>>> >>>>>>>> On Fri, Nov 15, 2013 at 7:57 AM, Vicente-Arturo Romero-Zaldivar >>>>>>>> wrote: >>>>>>>>> >>>>>>>>> On 13/11/13 19:04, Zhong Yu wrote: >>>>>>>>>> >>>>>>>>>> This program does not compile in javac8 build 115. I think it >>>>>>>>>> should >>>>>>>>>> compile (but who knows really:) >>>>>>>>>> >>>>>>>>>> public class Bug { >>>>>>>>>> public void forEach(Consumer consumer) { >>>>>>>>>> // ... >>>>>>>>>> } >>>>>>>>>> public void forEach(Predicate predicate) { >>>>>>>>>> // ... >>>>>>>>>> } >>>>>>>>>> public void forEach(BiConsumer >>>>>>>>>> biConsumer) { >>>>>>>>>> forEach((v) -> { biConsumer.accept(1, v); }); >>>>>>>>>> } >>>>>>>>>> public void forEach(BiPredicate>>>>>>>>> T> >>>>>>>>>> biPredicate) { >>>>>>>>>> forEach(v -> { return biPredicate.test(1, v); } ); >>>>>>>>>> } >>>>>>>>>> } >>>>>>>>> >>>>>>>>> Hi Zhong Yu, >>>>>>>>> >>>>>>>>> No the compiler is right functional descriptors of Consumer and >>>>>>>>> Predicate >>>>>>>>> have the same arity, so the compiler determines that there is an >>>>>>>>> ambiguity >>>>>>>>> error. >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Vicente >>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Wed, Nov 13, 2013 at 12:59 PM, Zhong Yu >>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>> Here's my understanding how the process works. >>>>>>>>>>> >>>>>>>>>>> When javac sees >>>>>>>>>>> >>>>>>>>>>> forEach( v->... ) >>>>>>>>>>> >>>>>>>>>>> two pieces of information of the implicit lambda are used to prune >>>>>>>>>>> overloading methods: >>>>>>>>>>> 1. the arity. therefore BiConsumer/BiPredicate are excluded >>>>>>>>>>> 2. whether the lambda body returns void or a real type. >>>>>>>>>>> >>>>>>>>>>> If the lambda body is a block, it's quite clear whether it's void >>>>>>>>>>> or >>>>>>>>>>> not. It seems to me that this would work: >>>>>>>>>>> >>>>>>>>>>> public void forEach(BiConsumer>>>>>>>>>> T> >>>>>>>>>>> biConsumer) { >>>>>>>>>>> forEach((v) -> { biConsumer.accept(1, v); }); >>>>>>>>>>> } >>>>>>>>>>> public void forEach(BiPredicate>>>>>>>>>> T> >>>>>>>>>>> biPredicate) { >>>>>>>>>>> forEach(v -> { return biPredicate.test(1, v); } ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> ( ... But it fails in javac build 115. javac bug?) >>>>>>>>>>> >>>>>>>>>>> If the lambda body is a "statement expression", like in your >>>>>>>>>>> original >>>>>>>>>>> example >>>>>>>>>>> >>>>>>>>>>> public void forEach(BiConsumer>>>>>>>>>> T> >>>>>>>>>>> biConsumer) { >>>>>>>>>>> forEach((v) -> biConsumer.accept(1, v) ); >>>>>>>>>>> } >>>>>>>>>>> public void forEach(BiPredicate>>>>>>>>>> T> >>>>>>>>>>> biPredicate) { >>>>>>>>>>> forEach(v -> biPredicate.test(1, v) ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> It's unclear what the return type is, so javac cannot use the >>>>>>>>>>> return >>>>>>>>>>> type to prune. Note that even though `biConsumer.accept(1, v)` >>>>>>>>>>> obviously returns void, javac does not know that, because the type >>>>>>>>>>> of >>>>>>>>>>> `v` is not known yet. And even though `biPredicate.test(1, v)` >>>>>>>>>>> obviously returns boolean, it is compatible to a function type >>>>>>>>>>> that >>>>>>>>>>> expects void return. >>>>>>>>>>> >>>>>>>>>>> Now, for each invocation, we have two potentially applicable >>>>>>>>>>> methods. >>>>>>>>>>> >>>>>>>>>>> The next step tries to prune methods by checking argument types >>>>>>>>>>> against method parameter types. Unfortunately, implicit lambda >>>>>>>>>>> expressions are too vague, so they are simply ignored in this >>>>>>>>>>> step. >>>>>>>>>>> >>>>>>>>>>> Therefore both methods are considered applicable methods. The most >>>>>>>>>>> specific method is sought after. However neither method is more >>>>>>>>>>> specific than the other, therefore we see the error message of >>>>>>>>>>> ambiguity. >>>>>>>>>>> >>>>>>>>>>> If you use explicit lambda expressions, javac is able to do more >>>>>>>>>>> pruning, so this works: >>>>>>>>>>> >>>>>>>>>>> public void forEach(BiConsumer>>>>>>>>>> T> >>>>>>>>>>> biConsumer) { >>>>>>>>>>> forEach((T v) -> biConsumer.accept(1, v) ); >>>>>>>>>>> } >>>>>>>>>>> public void forEach(BiPredicate>>>>>>>>>> T> >>>>>>>>>>> biPredicate) { >>>>>>>>>>> forEach( (T v) -> biPredicate.test(1, v) ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> So if you have overloading methods like this >>>>>>>>>>> >>>>>>>>>>> public void forEach(Consumer consumer) { >>>>>>>>>>> // ... >>>>>>>>>>> } >>>>>>>>>>> public void forEach(Predicate predicate) { >>>>>>>>>>> // ... >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> client code often cannot use implicit lambda expressions as >>>>>>>>>>> arguments; >>>>>>>>>>> and experts have advised against this kind of overloading scheme >>>>>>>>>>> (two >>>>>>>>>>> functional interfaces with the same arity) >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Zhong Yu >>>>>>>>>>> >>>>>>>>>>> On Wed, Nov 13, 2013 at 8:01 AM, D?vid Karnok >>>>>>>>>>> wrote: >>>>>>>>>>>> >>>>>>>>>>>> Hello, >>>>>>>>>>>> >>>>>>>>>>>> I'm rewriting a library and run into a strange ambiguity error >>>>>>>>>>>> reported >>>>>>>>>>>> by >>>>>>>>>>>> javac in JDK 8 b115, Windows 7 x86: >>>>>>>>>>>> >>>>>>>>>>>> public class Bug { >>>>>>>>>>>> public void forEach(Consumer consumer) { >>>>>>>>>>>> // ... >>>>>>>>>>>> } >>>>>>>>>>>> public void forEach(BiConsumer>>>>>>>>>>> T> >>>>>>>>>>>> consumer) { >>>>>>>>>>>> forEach((v) -> consumer.accept(1, v)); >>>>>>>>>>>> } >>>>>>>>>>>> public void forEach(Predicate >>>>>>>>>>>> stoppableConsumer) { >>>>>>>>>>>> // ... >>>>>>>>>>>> } >>>>>>>>>>>> public void forEach(BiPredicate>>>>>>>>>>> T> >>>>>>>>>>>> stoppableConsumer) { >>>>>>>>>>>> forEach(v -> stoppableConsumer.test(1, v)); >>>>>>>>>>>> } >>>>>>>>>>>> } >>>>>>>>>>>> >>>>>>>>>>>> error: reference to forEach is ambiguous >>>>>>>>>>>> forEach((v) -> consumer.accept(1, v)); >>>>>>>>>>>> both method forEach(Consumer) in Bug and method >>>>>>>>>>>> forEach(Predicate) in Bug match >>>>>>>>>>>> where T is a type-variable: >>>>>>>>>>>> T extends Object declared in class Bug >>>>>>>>>>>> >>>>>>>>>>>> error: reference to forEach is ambiguous >>>>>>>>>>>> forEach(v -> stoppableConsumer.test(1, v)); >>>>>>>>>>>> both method forEach(Consumer) in Bug and method >>>>>>>>>>>> forEach(Predicate) in Bug match >>>>>>>>>>>> where T is a type-variable: >>>>>>>>>>>> T extends Object declared in class Bug >>>>>>>>>>>> >>>>>>>>>>>> I'm using NetBeans 7.4 (Build 201310111528) which doesn't report >>>>>>>>>>>> this >>>>>>>>>>>> ambiguity in the editor, and the "highlight occurrences" >>>>>>>>>>>> correctly >>>>>>>>>>>> selects >>>>>>>>>>>> the 3rd method when I select the forEach in the 4th method. >>>>>>>>>>>> However, >>>>>>>>>>>> the >>>>>>>>>>>> clean and build fails with the errors above. I have to add >>>>>>>>>>>> explicit >>>>>>>>>>>> cast >>>>>>>>>>>> to >>>>>>>>>>>> the problematic places. >>>>>>>>>>>> >>>>>>>>>>>> So I'm a bit confused right now. Is it a bug with NetBeans' >>>>>>>>>>>> editor, >>>>>>>>>>>> with >>>>>>>>>>>> javac or simply the artifact of how overload resolution works? >>>>>>>>>>>> -- >>>>>>>>>>>> Best regards, >>>>>>>>>>>> David Karnok >>>>>>>>>>>> >>>> >>>> >>> >> From robert.field at oracle.com Fri Dec 6 20:42:40 2013 From: robert.field at oracle.com (Robert Field) Date: Fri, 06 Dec 2013 20:42:40 -0800 Subject: SOfError by Lambda expr in Local Class In-Reply-To: References: Message-ID: <52A2A740.3040805@oracle.com> I have created P2 issue 8029725: Lambda reference to containing local class causes javac infinite recursion -- https://bugs.openjdk.java.net/browse/JDK-8029725 and assigned it to myself. Thank you On 12/06/13 16:23, bitter_fox wrote: > Hi, > Does anyone know the state of this issue? > > Regards, > bitter_fox > > > 2013/12/1 bitter_fox > >> Hi, >> When I compile the following code, StackOverflowError occur. >> >> public class Main >> { >> interface F {void f();} >> >> public static void main(String[] args) >> { >> class Local >> { >> public Local() >> { >> F f = () -> new Local(); >> } >> } >> } >> } >> >> It may be a cause that >> c.s.t.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor#capturelocalClassDefs >> is called recursively. >> >> void captureLocalClassDefs(Symbol csym, final >> LambdaTranslationContext lambdaContext) { >> JCClassDecl localCDef = localClassDefs.get(csym); >> if (localCDef != null && localCDef.pos < >> lambdaContext.tree.pos) { >> BasicFreeVarCollector fvc = lower.new >> BasicFreeVarCollector() { >> @Override >> void addFreeVars(ClassSymbol c) { >> captureLocalClassDefs(c, lambdaContext); >> } >> // ... >> }; >> fvc.scan(localCDef); >> } >> } >> >> Following is a stack trace of the Error >> java.lang.StackOverflowError >> at com.sun.tools.javac.tree.JCTree$JCModifiers.accept(JCTree.java:2337) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitMethodDef(TreeScanner.java:84) >> at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:772) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) >> at >> com.sun.tools.javac.tree.TreeScanner.visitClassDef(TreeScanner.java:80) >> at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:687) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.captureLocalClassDefs(LambdaToMethod.java:1325) >> at >> com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor$1.addFreeVars(LambdaToMethod.java:1306) >> at >> com.sun.tools.javac.comp.Lower$BasicFreeVarCollector.visitNewClass(Lower.java:242) >> at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1510) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitLambda(TreeScanner.java:221) >> at com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1618) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitVarDef(TreeScanner.java:98) >> at >> com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:846) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) >> at >> com.sun.tools.javac.tree.TreeScanner.visitBlock(TreeScanner.java:105) >> at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:903) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitMethodDef(TreeScanner.java:91) >> at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:772) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) >> at >> com.sun.tools.javac.tree.TreeScanner.visitClassDef(TreeScanner.java:80) >> at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:687) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.captureLocalClassDefs(LambdaToMethod.java:1325) >> at >> com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor$1.addFreeVars(LambdaToMethod.java:1306) >> at >> com.sun.tools.javac.comp.Lower$BasicFreeVarCollector.visitNewClass(Lower.java:242) >> at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1510) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitLambda(TreeScanner.java:221) >> at com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1618) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitVarDef(TreeScanner.java:98) >> at >> com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:846) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) >> at >> com.sun.tools.javac.tree.TreeScanner.visitBlock(TreeScanner.java:105) >> at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:903) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitMethodDef(TreeScanner.java:91) >> at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:772) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) >> at >> com.sun.tools.javac.tree.TreeScanner.visitClassDef(TreeScanner.java:80) >> at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:687) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.captureLocalClassDefs(LambdaToMethod.java:1325) >> at >> com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor$1.addFreeVars(LambdaToMethod.java:1306) >> at >> com.sun.tools.javac.comp.Lower$BasicFreeVarCollector.visitNewClass(Lower.java:242) >> at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1510) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitLambda(TreeScanner.java:221) >> at com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1618) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitVarDef(TreeScanner.java:98) >> at >> com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:846) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) >> at >> com.sun.tools.javac.tree.TreeScanner.visitBlock(TreeScanner.java:105) >> at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:903) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.tree.TreeScanner.visitMethodDef(TreeScanner.java:91) >> at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:772) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57) >> at >> com.sun.tools.javac.tree.TreeScanner.visitClassDef(TreeScanner.java:80) >> at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:687) >> at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49) >> at >> com.sun.tools.javac.comp.LambdaToMethod$LambdaAnalyzerPreprocessor.captureLocalClassDefs(LambdaToMethod.java:1325) >> . >> . >> . >> >> >> Regards, >> bitter_fox >> From robert.field at oracle.com Sat Dec 7 12:04:31 2013 From: robert.field at oracle.com (Robert Field) Date: Sat, 07 Dec 2013 12:04:31 -0800 Subject: RFR (javac) 8029558: VerifyError: Bad return type when lambda's body is in parentheses In-Reply-To: <52A245C1.2010800@oracle.com> References: <52A24576.9000309@oracle.com> <52A245C1.2010800@oracle.com> Message-ID: <52A37F4F.4080700@oracle.com> On 12/06/13 13:46, Jonathan Gibbons wrote: > Robert, > > Is this for jdk8/tl? If so, then compiler-dev would be a better forum. I have sent it to compiler-dev as wqll. > > The two tests look very similar. Are they materially different? They are similar, however one is a lambda call within a lambda definition whereas the other is a generic constructor call. And they are, respectively, the original submitted test and the minimal test case. Especially with these squeaky little corner cases, I am more comfortable with both. They are small and non-repetitive, so test overhead should be insignificant. After several trials, the test duration for one vs both tests is deeply in the noise. Can I get a thumbs up from someone? -Robert > > -- Jon > > On 12/06/2013 01:45 PM, Robert Field wrote: >> Please review compiler (javac) fix for: >> >> https://bugs.openjdk.java.net/browse/JDK-8029558 >> >> Webrev: >> >> http://cr.openjdk.java.net/~rfield/8029558v0/ >> >> >> Fix is to correctly treat the lambda body as a value returning entity >> rather than a void entity so that that the correct type converting >> casts are generated. This is done by passing the erased type rather >> than null as the expected type. >> >> Thanks, >> Robert >> > From vicente.romero at oracle.com Sun Dec 8 11:49:26 2013 From: vicente.romero at oracle.com (Vicente-Arturo Romero-Zaldivar) Date: Sun, 08 Dec 2013 19:49:26 +0000 Subject: RFR (javac) 8029558: VerifyError: Bad return type when lambda's body is in parentheses - approved In-Reply-To: <52A37F4F.4080700@oracle.com> References: <52A24576.9000309@oracle.com> <52A245C1.2010800@oracle.com> <52A37F4F.4080700@oracle.com> Message-ID: <52A4CD46.4090408@oracle.com> Hi Robert, The patch is OK for me. Thanks, Vicente On 07/12/13 20:04, Robert Field wrote: > > On 12/06/13 13:46, Jonathan Gibbons wrote: >> Robert, >> >> Is this for jdk8/tl? If so, then compiler-dev would be a better forum. > > I have sent it to compiler-dev as wqll. > >> >> The two tests look very similar. Are they materially different? > > They are similar, however one is a lambda call within a lambda > definition whereas the other is a generic constructor call. And they > are, respectively, the original submitted test and the minimal test > case. Especially with these squeaky little corner cases, I am more > comfortable with both. They are small and non-repetitive, so test > overhead should be insignificant. After several trials, the test > duration for one vs both tests is deeply in the noise. > > Can I get a thumbs up from someone? > > -Robert > >> >> -- Jon >> >> On 12/06/2013 01:45 PM, Robert Field wrote: >>> Please review compiler (javac) fix for: >>> >>> https://bugs.openjdk.java.net/browse/JDK-8029558 >>> >>> Webrev: >>> >>> http://cr.openjdk.java.net/~rfield/8029558v0/ >>> >>> >>> Fix is to correctly treat the lambda body as a value returning >>> entity rather than a void entity so that that the correct type >>> converting casts are generated. This is done by passing the erased >>> type rather than null as the expected type. >>> >>> Thanks, >>> Robert >>> >> > From vicente.romero at oracle.com Tue Dec 10 14:26:29 2013 From: vicente.romero at oracle.com (Vicente-Arturo Romero-Zaldivar) Date: Tue, 10 Dec 2013 22:26:29 +0000 Subject: javac crash for annotation on lambda formal parameter type In-Reply-To: <52A771A9.3090809@oracle.com> References: <52A11E8E.5050908@oracle.com> <52A13B4B.2050103@oracle.com> <52A15738.7030803@gmail.com> <52A2598D.4050102@oracle.com> <52A50280.9010002@oracle.com> <52A75C21.8070505@oracle.com> <52A75F1D.8020704@gmail.com> <52A771A9.3090809@oracle.com> Message-ID: <52A79515.3000805@oracle.com> Hi all, Please review this public review for bug [1] which can be found at [2]. Some background: This bug was originally reported on the type-annotations-dev list. A code like this one: import java.lang.annotation.*; import java.util.function.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) @interface TA {} class LambdaFormal { IntUnaryOperator x = (@TAint y) -> 1; } is producing a NPE in javac. Type annotations code assumes that any lambda expression will always have a method as it's owner, which is not always true. Nevertheless this approach can be considered correct because the compiler is creating a method symbol in cases where a method is not present, field declarations. LambdaToMethod code was also expecting type annotations in one method, in the case of instance fields, in the first constructor, in the case of static fields in a fake method. What I have done here is to sync Attr with LTM so they use the same method depending on the particular case, see also the comments added in the patch. As a side result the method used by Attr and LTM classes is also used as a holder for type annotations, thus solving the current bug. Probably this is not the ultimate solution to the problem. It should be studied if both type annotations and lambda code can be made more flexible such that they don't assume that lambda expressions have a method as it's owner, but I think that this is a good solution for now. Thanks in advance for any comments, Vicente [1] https://bugs.openjdk.java.net/browse/JDK-8029721 [2] http://cr.openjdk.java.net/~vromero/8029721/webrev_01/ On 10/12/13 19:55, Vicente-Arturo Romero-Zaldivar wrote: > On 10/12/13 18:36, Werner Dietl wrote: >> >From Vicente's description I took away that the problem is too >> fundamental for me to work around in type-annotations. > > Hi Werner, > > I will submit a public webrev shortly. > >> >> Can we get the, admittedly ugly, hack I have in type-annotations into >> tl? It at least prevents this particular crash. >> I updated type-annotations/langtools to make diffing easier. > > I should push the patch by the end of this week so the crash should be > fixed. > > Thanks, > Vicente > >> >> It is a pity that this means that the compiler is not generating correct >> bytecode for type annotations within lambdas within field initializers. >> >> cu, WMD. >> >> On 13-12-10 01:23 PM, Alex Buckley wrote: >>> On 12/8/2013 3:36 PM, Vicente-Arturo Romero-Zaldivar wrote: >>>> I have created this bug entry to track this issue: >>>> https://bugs.openjdk.java.net/browse/JDK-8029787 >>>> >>>> I think this should be deferred for now, but Alex if you think that >>>> this >>>> should be fixed asap feel free to raise the priority to P2 and >>>> provide a >>>> justification. >>> Vicente, thanks for looking at the issue. I see that JDK-8029787 is now >>> closed as a duplicate of JDK-8029721, which is itself a P2. >>> >>> Werner, FYI, we (Oracle) are now only working on P2s and P1s for JDK 8, >>> and all P2s must be resolved by 12/13. After 12/13, it's P1s only; >>> everything else gets deferred to an update release or JDK 9. >>> >>> Alex > From mike.duigou at oracle.com Tue Dec 10 17:05:21 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Tue, 10 Dec 2013 17:05:21 -0800 Subject: RFR: 8029944: (xs) Primitive Stream reduce method documentation pseudo code misidentifies apply method Message-ID: <8D95DF8A-4AC1-4E98-BF19-CBDCDE512249@oracle.com> Hello all; This is a documentation only fix for a bug reported by Michael McMahon. The reduce methods of the primitive streams classes currently reference an "apply" method rather than the appropriate applyAsInt, applyAsLong or applyAsDouble methods. http://cr.openjdk.java.net/~mduigou/JDK-8029944/0/ Michael also suggested synchronizing the names accumulator and op but I declined (thus far) to make this change. If there is consensus that this would be helpful I can amend the changeset. Mike From joe.darcy at oracle.com Tue Dec 10 17:23:33 2013 From: joe.darcy at oracle.com (Joseph Darcy) Date: Tue, 10 Dec 2013 17:23:33 -0800 Subject: RFR: 8029944: (xs) Primitive Stream reduce method documentation pseudo code misidentifies apply method In-Reply-To: <8D95DF8A-4AC1-4E98-BF19-CBDCDE512249@oracle.com> References: <8D95DF8A-4AC1-4E98-BF19-CBDCDE512249@oracle.com> Message-ID: <52A7BE95.1060308@oracle.com> On 12/10/2013 5:05 PM, Mike Duigou wrote: > Hello all; > > This is a documentation only fix for a bug reported by Michael McMahon. The reduce methods of the primitive streams classes currently reference an "apply" method rather than the appropriate applyAsInt, applyAsLong or applyAsDouble methods. > > http://cr.openjdk.java.net/~mduigou/JDK-8029944/0/ > > Looks good; cheers, -Joe From joel.franck at oracle.com Wed Dec 11 02:10:28 2013 From: joel.franck at oracle.com (Joel Borggren-Franck) Date: Wed, 11 Dec 2013 11:10:28 +0100 Subject: javac crash for annotation on lambda formal parameter type In-Reply-To: <52A79515.3000805@oracle.com> References: <52A13B4B.2050103@oracle.com> <52A15738.7030803@gmail.com> <52A2598D.4050102@oracle.com> <52A50280.9010002@oracle.com> <52A75C21.8070505@oracle.com> <52A75F1D.8020704@gmail.com> <52A771A9.3090809@oracle.com> <52A79515.3000805@oracle.com> Message-ID: <20131211101028.GB4575@oracle.com> Hi Vicente, FWIW I think this looks fine, _but_ you should get a review from someone more experienced with the later phases of javac. Kudos for the well documented fix. Since code from Attr is frequently used in other phases, have you thought about the possibility to get into a racy situation, say if LTM calls back into Attr in an unexpected way? cheers /Joel On 2013-12-10, Vicente-Arturo Romero-Zaldivar wrote: > Hi all, > > Please review this public review for bug [1] which can be found at [2]. > > Some background: > > This bug was originally reported on the type-annotations-dev list. A > code like this one: > > import java.lang.annotation.*; > import java.util.function.*; > > @Retention(RetentionPolicy.RUNTIME) > @Target(ElementType.TYPE_USE) > @interface TA {} > > class LambdaFormal { > IntUnaryOperator x = (@TAint y) -> 1; > } > > > is producing a NPE in javac. Type annotations code assumes that any > lambda expression will always have a method as it's owner, which is > not always true. > Nevertheless this approach can be considered correct because the > compiler is creating a method symbol in cases where a method is not > present, field declarations. > > LambdaToMethod code was also expecting type annotations in one > method, in the case of instance fields, in the first constructor, in > the case of static fields in a fake method. > > What I have done here is to sync Attr with LTM so they use the same > method depending on the particular case, see also the comments added > in the patch. > As a side result the method used by Attr and LTM classes is also > used as a holder for type annotations, thus solving the current bug. > > Probably this is not the ultimate solution to the problem. It should > be studied if both type annotations and lambda code can be made more > flexible such that they don't assume that lambda expressions have a > method as it's owner, but I think that this is a good solution for > now. > > Thanks in advance for any comments, > > Vicente > > [1] https://bugs.openjdk.java.net/browse/JDK-8029721 > [2] http://cr.openjdk.java.net/~vromero/8029721/webrev_01/ > From vicente.romero at oracle.com Wed Dec 11 02:33:29 2013 From: vicente.romero at oracle.com (Vicente-Arturo Romero-Zaldivar) Date: Wed, 11 Dec 2013 10:33:29 +0000 Subject: javac crash for annotation on lambda formal parameter type In-Reply-To: <20131211101028.GB4575@oracle.com> References: <52A13B4B.2050103@oracle.com> <52A15738.7030803@gmail.com> <52A2598D.4050102@oracle.com> <52A50280.9010002@oracle.com> <52A75C21.8070505@oracle.com> <52A75F1D.8020704@gmail.com> <52A771A9.3090809@oracle.com> <52A79515.3000805@oracle.com> <20131211101028.GB4575@oracle.com> Message-ID: <52A83F79.2010304@oracle.com> Hi Joel, Thanks for your comments. On 11/12/13 10:10, Joel Borggren-Franck wrote: > Hi Vicente, > > FWIW I think this looks fine, _but_ you should get a review from someone > more experienced with the later phases of javac. I have this already covered, please check links in the bug entry. > > Kudos for the well documented fix. Thanks. > > Since code from Attr is frequently used in other phases, have you > thought about the possibility to get into a racy situation, say if LTM > calls back into Attr in an unexpected way? Right now this is not happening, it's true that if there are changes in the future then this code may fail, but that's part of the process. I was thinking about using a weak hash map in Attr, but this approach is probably too much for a, for the moment, simple issue. Vicente. > > cheers > /Joel > > On 2013-12-10, Vicente-Arturo Romero-Zaldivar wrote: >> Hi all, >> >> Please review this public review for bug [1] which can be found at [2]. >> >> Some background: >> >> This bug was originally reported on the type-annotations-dev list. A >> code like this one: >> >> import java.lang.annotation.*; >> import java.util.function.*; >> >> @Retention(RetentionPolicy.RUNTIME) >> @Target(ElementType.TYPE_USE) >> @interface TA {} >> >> class LambdaFormal { >> IntUnaryOperator x = (@TAint y) -> 1; >> } >> >> >> is producing a NPE in javac. Type annotations code assumes that any >> lambda expression will always have a method as it's owner, which is >> not always true. >> Nevertheless this approach can be considered correct because the >> compiler is creating a method symbol in cases where a method is not >> present, field declarations. >> >> LambdaToMethod code was also expecting type annotations in one >> method, in the case of instance fields, in the first constructor, in >> the case of static fields in a fake method. >> >> What I have done here is to sync Attr with LTM so they use the same >> method depending on the particular case, see also the comments added >> in the patch. >> As a side result the method used by Attr and LTM classes is also >> used as a holder for type annotations, thus solving the current bug. >> >> Probably this is not the ultimate solution to the problem. It should >> be studied if both type annotations and lambda code can be made more >> flexible such that they don't assume that lambda expressions have a >> method as it's owner, but I think that this is a good solution for >> now. >> >> Thanks in advance for any comments, >> >> Vicente >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8029721 >> [2] http://cr.openjdk.java.net/~vromero/8029721/webrev_01/ >> From joel.franck at oracle.com Wed Dec 11 02:41:36 2013 From: joel.franck at oracle.com (Joel Borggren-Franck) Date: Wed, 11 Dec 2013 11:41:36 +0100 Subject: javac crash for annotation on lambda formal parameter type In-Reply-To: <52A83F79.2010304@oracle.com> References: <52A15738.7030803@gmail.com> <52A2598D.4050102@oracle.com> <52A50280.9010002@oracle.com> <52A75C21.8070505@oracle.com> <52A75F1D.8020704@gmail.com> <52A771A9.3090809@oracle.com> <52A79515.3000805@oracle.com> <20131211101028.GB4575@oracle.com> <52A83F79.2010304@oracle.com> Message-ID: <20131211104136.GC4575@oracle.com> Hi, On 2013-12-11, Vicente-Arturo Romero-Zaldivar wrote: > >Since code from Attr is frequently used in other phases, have you > >thought about the possibility to get into a racy situation, say if LTM > >calls back into Attr in an unexpected way? > > Right now this is not happening, it's true that if there are changes > in the future then this code may fail, but that's part of the > process. I was thinking about using a weak hash map in Attr, but > this approach is probably too much for a, for the moment, simple > issue. > There is always a risk something breaks in the future, I'm satisfied with you having thought trough this. cheers /Joel From Jonathan.Ross at imc-chicago.com Fri Dec 13 12:38:18 2013 From: Jonathan.Ross at imc-chicago.com (Jonathan C. Ross) Date: Fri, 13 Dec 2013 14:38:18 -0600 Subject: Overload resolution regression In-Reply-To: References: <528B4BD3.2070906@univ-mlv.fr> <528B7804.5000404@univ-mlv.fr> Message-ID: Hi again, I thought I understood this issue after Remi?s explanation, but I have run into a couple of cases where I still don?t understand the outcome, One example is essentially para-phrased as follows: import java.util.Collection; abstract class Test { abstract > T build(); abstract void use(Collection n); abstract void use(Double s); void f() { use(build()); } } Works fine in 7, and my JDK-8-savvy IDE?s (IntelliJ, Netbeans) think it?s fine. However, ea-b119 thinks the overloading of ?use' is ambiguous. In what scenario could this behaviour be an enhancement? ? Jonathan Ross On 19 Nov 2013, at 10:43, Jonathan Ross wrote: > Or a pickMe(String) for that matter? > > Thanks for the explanation, Remi. Indeed, we were just using the > coincidence of the Object fallback; it seems to predominantly affect our > test fixtures - I hope, at least. The nasty thing about it is that it > leads to a runtime exception rather than a compilation error, so we may not > find out for certain for a while. > > > On Tue, Nov 19, 2013 at 9:02 AM, Paul Benedict wrote: > >> Ah, okay, that makes sense now. Filling me in on the background was a big >> helper. >> >> For the sake of clarity, what would happen to Jonathan's example if there >> was also a third pickMe(BigDecimal)? >> >> >> On Tue, Nov 19, 2013 at 8:39 AM, Remi Forax wrote: >> >>> On 11/19/2013 02:53 PM, Paul Benedict wrote: >>> >>>> I don't see how you can call the compiler "smarter" in this example. >>>> >>> >>> 'smarter' because this is not the only use case :) >>> Here is an example that fails to compile with 7 but compiles with 8 >>> (comparingByValue is also a method that only uses type variables to >>> specify the return type) >>> Map map = ... >>> map.entrySet().stream().sorted(Map.Entry.comparingByValue()); >>> >>> For pickMe(unsafe()) the inference fails in 7 and uses Object as a >>> fallback, >>> it appears that it's what the user want but that's just a coincidence. >>> >>> It is choosing pickMe(BigInteger) without >: BigInteger type being >>>> present. >>>> >>> >>> >>> Don't forget that pickMe(null) also choose pickMe(BigInteger), >>> it's the way the algorithm that choose the most specific method works >>> since the beginning. >>> here, the constraint is that T is a subtype of Object, so both >>> pickMe(Object) and pickMe(BigInteger) are applicable, >>> then the most specific algorithm chooses that pickMe(BigInteger) is >> better >>> than pickMe(Object). >>> >>> cheers, >>> R?mi >>> >>> >>>> >>>> On Tue, Nov 19, 2013 at 5:30 AM, Remi Forax >>> forax at univ-mlv.fr>> wrote: >>>> >>>> On 11/19/2013 01:43 AM, Jonathan Ross wrote: >>>>> Hi, >>>> >>>> Hi Johnathan, >>>> >>>>> >>>>> I recently started porting a 150k-line project to jdk 8 to try >>>> my hand at >>>>> the recent changes in the collection libraries. (Hadn't done >>>> this since >>>>> last year, my apologies!) >>>>> >>>>> I have run in to a large number of compilation errors: >>>> regressions in type >>>>> inference and overload resolution. A lot of these are in unit >>>> tests using >>>>> mockito and fest and other similar monadic apis that rely heavily >> on >>>>> overload resolution. >>>> >>>> It's not a regression, it's an enhancement :) >>>> >>>>> >>>>> The code snippet below is a distilled version of my typical >>>> compilation >>>>> error: our test code relying on the compiler choosing the Object >>>> overload >>>>> by default. >>>>> >>>>> >>>>> import java.math.BigInteger; >>>>> >>>>> public class OverloadingRegression { >>>>> >>>>> static T unsafeCast(Object anObject) { >>>>> return (T) anObject; >>>>> } >>>>> >>>>> public void showOverloadResolutionIssue() { >>>>> pickMe(unsafeCast(new String())); >>>>> } >>>>> >>>>> private void pickMe(BigInteger o) { /* ClassCastException in >>>>> 1.8.0-ea-b115 */ } >>>>> >>>>> private void pickMe(Object o) { /* fine, picked in 1.6 & >>>> 1.7 */ } >>>>> } >>>>> >>>>> >>>>> Obviously the unsafeCast is not going to win any beauty prizes, >> but >>>>> sometimes you just have to do this sort of thing. My main point >>>> is: it >>>>> used to work in java 7, it doesn't any more. >>>>> >>>>> Is this a known issue (or is it even expected behaviour)? >>>> >>>> Yes, it's the expected behavior, when you try do inference inside a >>>> method call, >>>> here unsafeCast is inside pickMe, in that case with jdk6 & 7, the >>>> inference >>>> is not done and T is replaceb by its bound (Object), with jdk8, the >>>> compiler is smarter, >>>> and find the most specific method first, here pickMe(BigInteger) >>>> is more >>>> specific than pickMe(Object) and then infers T (T = BigInteger). >>>> >>>>> >>>>> I'm using 1.8.0-ea-b115, but I verified that it fails with all >>>> 1.8 jdks I >>>>> have my box. When I pass in -source 1.7 it does work. And when >>>> I do an >>>>> explicit cast to Object (of course). >>>> >>>> so this is the correct behavior for 8, the new stream API heavily >>>> relies >>>> on that, >>>> and yes, this new semantics is not compatible with 1.7 in the case >> the >>>> inference was failing, >>>> this is a known compatibility issue. >>>> >>>>> >>>>> -- Jonathan Ross >>>>> >>>> >>>> cheers, >>>> R?mi >>>> >>>> >>>> >>>> >>>> >>>> -- >>>> Cheers, >>>> Paul >>>> >>> >>> >> >> >> -- >> Cheers, >> Paul >> >> >> ________________________________ >> >> The information in this e-mail is intended only for the person or entity >> to which it is addressed. >> >> It may contain confidential and /or privileged material. If someone other >> than the intended recipient should receive this e-mail, he / she shall not >> be entitled to read, disseminate, disclose or duplicate it. >> >> If you receive this e-mail unintentionally, please inform us immediately >> by "reply" and then delete it from your system. Although this information >> has been compiled with great care, neither IMC Financial Markets & Asset >> Management nor any of its related entities shall accept any responsibility >> for any errors, omissions or other inaccuracies in this information or for >> the consequences thereof, nor shall it be bound in any way by the contents >> of this e-mail or its attachments. In the event of incomplete or incorrect >> transmission, please return the e-mail to the sender and permanently delete >> this message and any attachments. >> >> Messages and attachments are scanned for all known viruses. Always scan >> attachments before opening them. >> > ________________________________ The information in this e-mail is intended only for the person or entity to which it is addressed. It may contain confidential and /or privileged material. If someone other than the intended recipient should receive this e-mail, he / she shall not be entitled to read, disseminate, disclose or duplicate it. If you receive this e-mail unintentionally, please inform us immediately by "reply" and then delete it from your system. Although this information has been compiled with great care, neither IMC Financial Markets & Asset Management nor any of its related entities shall accept any responsibility for any errors, omissions or other inaccuracies in this information or for the consequences thereof, nor shall it be bound in any way by the contents of this e-mail or its attachments. In the event of incomplete or incorrect transmission, please return the e-mail to the sender and permanently delete this message and any attachments. Messages and attachments are scanned for all known viruses. Always scan attachments before opening them. From forax at univ-mlv.fr Sat Dec 14 10:43:48 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 14 Dec 2013 19:43:48 +0100 Subject: Trouble with wildcards Message-ID: <52ACA6E4.3080109@univ-mlv.fr> Hi all, I've tried to explain in code how a Stream (here a Flow to avoid confusion) can be implemented (just filter/map, only a sequential stream) with consecutive operations, filter.filter or map.map optimized. I end up with the code below which compiles but if instead of return Flow.this.filter(/*predicate.and(predicate2)*/ t -> predicate.test(t) && predicate2.test(t)); I replace it by return Flow.this.filter(predicate.and(predicate2)); the compiler refuses to compile and I don't understand why :( Here predicate is a Predicate, so predicate2 should be a Predicate, because and() is declared like this: Predicate.and(Predicate) predicate2 is a Predicate so it should match Predicate but it doesn't. Is it a bug in the compiler or in my head ? cheers, R?mi @FunctionalInterface public interface Flow { public void forEach(Consumer consumer); public default Flow filter(Predicate predicate) { return new Flow() { @Override public void forEach(Consumer consumer) { Flow.this.forEach(u -> { if (predicate.test(u)) { consumer.accept(u); } }); } @Override public Flow filter(Predicate predicate2) { return Flow.this.filter(/*predicate.and(predicate2)*/ t -> predicate.test(t) && predicate2.test(t)); } }; } public default Flow map(Function function) { return new Flow() { @Override public void forEach(Consumer consumer) { Flow.this.forEach(t -> consumer.accept(function.apply(t))); } @Override public Flow map(Function function2) { return Flow.this.map(function.andThen(function2)); } }; } public static Flow create(Iterable iterable) { return iterable::forEach; } public static void main(String[] args) { List list = IntStream.range(0, 10).boxed().collect(Collectors.toList()); Flow flow = create(list); flow.filter(x -> x != 5).filter(x -> x != 2).forEach(System.out::println); flow.map(x -> x * 2).map(x -> x + 1).forEach(System.out::println); flow.filter(x -> x != 5).map(x -> x * 2).filter(x -> x != 2).map(x -> x / 2).forEach(System.out::println); } } From paul.sandoz at oracle.com Mon Dec 16 06:42:43 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 16 Dec 2013 15:42:43 +0100 Subject: Trouble with wildcards In-Reply-To: <52ACA6E4.3080109@univ-mlv.fr> References: <52ACA6E4.3080109@univ-mlv.fr> Message-ID: <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> Hi Remi, Reducing it down a little: import java.util.*; import java.util.function.*; class A { static class X {}; static class Y extends X {}; public static void main(String[] args) { Predicate px = x -> x instanceof X; Predicate py = y -> y instanceof Y; Predicate psy = px; Predicate superyandy = psy.and(py); // <-- error superyandy.test(new Y()); } } $ javac -Xdiags:verbose A.java A.java:15: error: method and in interface Predicate cannot be applied to given types; Predicate superyandy = psy.and(py); // <-- error ^ required: Predicate found: Predicate reason: argument mismatch; Predicate cannot be converted to Predicate where T is a type-variable: T extends Object declared in interface Predicate where CAP#1 is a fresh type-variable: CAP#1 extends Object super: Y from capture of ? super Y 1 error It's confusing... Paul. On Dec 14, 2013, at 7:43 PM, Remi Forax wrote: > Hi all, > I've tried to explain in code how a Stream (here a Flow to avoid > confusion) can be implemented (just filter/map, only a sequential > stream) with consecutive operations, filter.filter or map.map optimized. > > I end up with the code below which compiles but if instead of > return Flow.this.filter(/*predicate.and(predicate2)*/ t -> > predicate.test(t) && predicate2.test(t)); > I replace it by > return Flow.this.filter(predicate.and(predicate2)); > the compiler refuses to compile and I don't understand why :( > > Here predicate is a Predicate, so predicate2 should be a > Predicate, > because and() is declared like this: Predicate.and(Predicate) > predicate2 is a Predicate so it should match Predicate super ? super T> but > it doesn't. > > Is it a bug in the compiler or in my head ? > > cheers, > R?mi > > @FunctionalInterface > public interface Flow { > public void forEach(Consumer consumer); > > public default Flow filter(Predicate predicate) { > return new Flow() { > @Override > public void forEach(Consumer consumer) { > Flow.this.forEach(u -> { > if (predicate.test(u)) { > consumer.accept(u); > } > }); > } > @Override > public Flow filter(Predicate predicate2) { > return Flow.this.filter(/*predicate.and(predicate2)*/ t -> > predicate.test(t) && predicate2.test(t)); > } > }; > } > > public default Flow map(Function > function) { > return new Flow() { > @Override > public void forEach(Consumer consumer) { > Flow.this.forEach(t -> consumer.accept(function.apply(t))); > } > @Override > public Flow map(Function function2) { > return Flow.this.map(function.andThen(function2)); > } > }; > } > > public static Flow create(Iterable iterable) { > return iterable::forEach; > } > > public static void main(String[] args) { > List list = IntStream.range(0, > 10).boxed().collect(Collectors.toList()); > Flow flow = create(list); > flow.filter(x -> x != 5).filter(x -> x != > 2).forEach(System.out::println); > flow.map(x -> x * 2).map(x -> x + 1).forEach(System.out::println); > flow.filter(x -> x != 5).map(x -> x * 2).filter(x -> x != 2).map(x > -> x / 2).forEach(System.out::println); > } > } > From forax at univ-mlv.fr Mon Dec 16 13:38:22 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Mon, 16 Dec 2013 22:38:22 +0100 Subject: Trouble with wildcards In-Reply-To: <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> Message-ID: <52AF72CE.9020101@univ-mlv.fr> On 12/16/2013 03:42 PM, Paul Sandoz wrote: > Hi Remi, > > Reducing it down a little: > > import java.util.*; > import java.util.function.*; > > class A { > > static class X {}; > static class Y extends X {}; > > public static void main(String[] args) { > Predicate px = x -> x instanceof X; > Predicate py = y -> y instanceof Y; > > Predicate psy = px; > > Predicate superyandy = psy.and(py); // <-- error > superyandy.test(new Y()); > } > } > > $ javac -Xdiags:verbose A.java > A.java:15: error: method and in interface Predicate cannot be applied to given types; > Predicate superyandy = psy.and(py); // <-- error > ^ > required: Predicate > found: Predicate > reason: argument mismatch; Predicate cannot be converted to Predicate > where T is a type-variable: > T extends Object declared in interface Predicate > where CAP#1 is a fresh type-variable: > CAP#1 extends Object super: Y from capture of ? super Y > 1 error > > > It's confusing... > > Paul. indeed :) R?mi > > On Dec 14, 2013, at 7:43 PM, Remi Forax wrote: > >> Hi all, >> I've tried to explain in code how a Stream (here a Flow to avoid >> confusion) can be implemented (just filter/map, only a sequential >> stream) with consecutive operations, filter.filter or map.map optimized. >> >> I end up with the code below which compiles but if instead of >> return Flow.this.filter(/*predicate.and(predicate2)*/ t -> >> predicate.test(t) && predicate2.test(t)); >> I replace it by >> return Flow.this.filter(predicate.and(predicate2)); >> the compiler refuses to compile and I don't understand why :( >> >> Here predicate is a Predicate, so predicate2 should be a >> Predicate, >> because and() is declared like this: Predicate.and(Predicate) >> predicate2 is a Predicate so it should match Predicate> super ? super T> but >> it doesn't. >> >> Is it a bug in the compiler or in my head ? >> >> cheers, >> R?mi >> >> @FunctionalInterface >> public interface Flow { >> public void forEach(Consumer consumer); >> >> public default Flow filter(Predicate predicate) { >> return new Flow() { >> @Override >> public void forEach(Consumer consumer) { >> Flow.this.forEach(u -> { >> if (predicate.test(u)) { >> consumer.accept(u); >> } >> }); >> } >> @Override >> public Flow filter(Predicate predicate2) { >> return Flow.this.filter(/*predicate.and(predicate2)*/ t -> >> predicate.test(t) && predicate2.test(t)); >> } >> }; >> } >> >> public default Flow map(Function >> function) { >> return new Flow() { >> @Override >> public void forEach(Consumer consumer) { >> Flow.this.forEach(t -> consumer.accept(function.apply(t))); >> } >> @Override >> public Flow map(Function function2) { >> return Flow.this.map(function.andThen(function2)); >> } >> }; >> } >> >> public static Flow create(Iterable iterable) { >> return iterable::forEach; >> } >> >> public static void main(String[] args) { >> List list = IntStream.range(0, >> 10).boxed().collect(Collectors.toList()); >> Flow flow = create(list); >> flow.filter(x -> x != 5).filter(x -> x != >> 2).forEach(System.out::println); >> flow.map(x -> x * 2).map(x -> x + 1).forEach(System.out::println); >> flow.filter(x -> x != 5).map(x -> x * 2).filter(x -> x != 2).map(x >> -> x / 2).forEach(System.out::println); >> } >> } >> > > From zhong.j.yu at gmail.com Mon Dec 16 15:10:45 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Mon, 16 Dec 2013 17:10:45 -0600 Subject: Trouble with wildcards In-Reply-To: <52AF72CE.9020101@univ-mlv.fr> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <52AF72CE.9020101@univ-mlv.fr> Message-ID: Not exactly sure what you guys are talking about... but I guess it's a complaint about the signature of Predicate.and()? It might be changed to be more receptive, like Predicate and(Predicate other) then the previous examples could be compiled, as well as this one Predicate p1 = null; Predicate p2 = null; Predicate p3 = p1.and(p2); Zhong Yu On Mon, Dec 16, 2013 at 3:38 PM, Remi Forax wrote: > On 12/16/2013 03:42 PM, Paul Sandoz wrote: >> Hi Remi, >> >> Reducing it down a little: >> >> import java.util.*; >> import java.util.function.*; >> >> class A { >> >> static class X {}; >> static class Y extends X {}; >> >> public static void main(String[] args) { >> Predicate px = x -> x instanceof X; >> Predicate py = y -> y instanceof Y; >> >> Predicate psy = px; >> >> Predicate superyandy = psy.and(py); // <-- error >> superyandy.test(new Y()); >> } >> } >> >> $ javac -Xdiags:verbose A.java >> A.java:15: error: method and in interface Predicate cannot be applied to given types; >> Predicate superyandy = psy.and(py); // <-- error >> ^ >> required: Predicate >> found: Predicate >> reason: argument mismatch; Predicate cannot be converted to Predicate >> where T is a type-variable: >> T extends Object declared in interface Predicate >> where CAP#1 is a fresh type-variable: >> CAP#1 extends Object super: Y from capture of ? super Y >> 1 error >> >> >> It's confusing... >> >> Paul. > > indeed :) > > R?mi > >> >> On Dec 14, 2013, at 7:43 PM, Remi Forax wrote: >> >>> Hi all, >>> I've tried to explain in code how a Stream (here a Flow to avoid >>> confusion) can be implemented (just filter/map, only a sequential >>> stream) with consecutive operations, filter.filter or map.map optimized. >>> >>> I end up with the code below which compiles but if instead of >>> return Flow.this.filter(/*predicate.and(predicate2)*/ t -> >>> predicate.test(t) && predicate2.test(t)); >>> I replace it by >>> return Flow.this.filter(predicate.and(predicate2)); >>> the compiler refuses to compile and I don't understand why :( >>> >>> Here predicate is a Predicate, so predicate2 should be a >>> Predicate, >>> because and() is declared like this: Predicate.and(Predicate) >>> predicate2 is a Predicate so it should match Predicate>> super ? super T> but >>> it doesn't. >>> >>> Is it a bug in the compiler or in my head ? >>> >>> cheers, >>> R?mi >>> >>> @FunctionalInterface >>> public interface Flow { >>> public void forEach(Consumer consumer); >>> >>> public default Flow filter(Predicate predicate) { >>> return new Flow() { >>> @Override >>> public void forEach(Consumer consumer) { >>> Flow.this.forEach(u -> { >>> if (predicate.test(u)) { >>> consumer.accept(u); >>> } >>> }); >>> } >>> @Override >>> public Flow filter(Predicate predicate2) { >>> return Flow.this.filter(/*predicate.and(predicate2)*/ t -> >>> predicate.test(t) && predicate2.test(t)); >>> } >>> }; >>> } >>> >>> public default Flow map(Function >>> function) { >>> return new Flow() { >>> @Override >>> public void forEach(Consumer consumer) { >>> Flow.this.forEach(t -> consumer.accept(function.apply(t))); >>> } >>> @Override >>> public Flow map(Function function2) { >>> return Flow.this.map(function.andThen(function2)); >>> } >>> }; >>> } >>> >>> public static Flow create(Iterable iterable) { >>> return iterable::forEach; >>> } >>> >>> public static void main(String[] args) { >>> List list = IntStream.range(0, >>> 10).boxed().collect(Collectors.toList()); >>> Flow flow = create(list); >>> flow.filter(x -> x != 5).filter(x -> x != >>> 2).forEach(System.out::println); >>> flow.map(x -> x * 2).map(x -> x + 1).forEach(System.out::println); >>> flow.filter(x -> x != 5).map(x -> x * 2).filter(x -> x != 2).map(x >>> -> x / 2).forEach(System.out::println); >>> } >>> } >>> >> >> > > From mike.duigou at oracle.com Mon Dec 16 19:42:30 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Mon, 16 Dec 2013 19:42:30 -0800 Subject: RFR: 8029795 : LinkedHashMap.getOrDefault() doesn't update access order. (was Why doesn't new Map methods generate entry accesses on LinkedHashMap?) In-Reply-To: References: <77261386538162@web15j.yandex.ru> <9EEFC5AC-D87E-4676-9967-E190B0ED5041@oracle.com> <042FDEC2-D558-45D7-B416-754055549CA8@oracle.com> Message-ID: I've updated the documentation per Paul's suggestions. Specifically, in addition to the existing put() and get() methods the new Map methods putIfAbsent() getOrDefault() compute() computeIfAbsent() computeIfPresent() merge() are all documented to perform a single access of the entry (assuming that an entry is created or modified as a result). replace() is documented as accessing the entry, if it exists and a replacement is made. If no replacement is made then no access is recorded. http://cr.openjdk.java.net/~mduigou/JDK-8029795/2/webrev/ Mike On Dec 11 2013, at 02:32 , Paul Sandoz wrote: > > On Dec 11, 2013, at 1:27 AM, Mike Duigou wrote: > >> I have added tests and documentation for the other methods. >> >> http://cr.openjdk.java.net/~mduigou/JDK-8029795/1/webrev/ >> >> The documentation for some of the methods is ambiguous about how many access events are generated. For LRU cache is OK but other cases (counting based eviction) may care about the total number of accesses. > > + * invocation completes). Invoking the {@code replace}, {@code merge}, > + * {@code compute} or {@code computeIfPresent} methods results in one or more > + * accesses of the corresponding entry. The {@code putAll} method generates one > > If i look at the code for say replace it generates *at most one access* in terms of affecting last access order, if the entry exists and if the old/new value constraint holds: > > @Override > public boolean replace(K key, V oldValue, V newValue) { > Node e; V v; > if ((e = getNode(hash(key), key)) != null && > ((v = e.value) == oldValue || (v != null && v.equals(oldValue)))) { > e.value = newValue; > afterNodeAccess(e); > return true; > } > return false; > } > > > I have attempted to categorise the access behaviour of each method: > > get: > access to entry, if it exists > > put: > access to new entry > > putIfAbsent > access to entry, if it exists > otherwise access to new entry > > replace(K key, V value) > access to entry, if it exists > > replace(K key, V oldValue, V newValue) > access to entry, if it exists and it's value is updated > > computeIfAbsent: > access to entry, if it exists and it's value is non-null, or > access to entry, if it exists and it's null value is updated to a non-null value [*], > otherwise access to new entry, if created > > computeIfPresent > access to entry, if it exists and it's non-null value is updated to a non-null value > > compute > access to entry, if it exists and it's value is updated to a non-null value, > otherwise access to new entry, if created > > merge > access to entry, if it exists and it's value is updated to a non-null value, > otherwise access to new entry, if created > > > Patterns, to help group for documentation: > > get/put/putIfAbsent/replace(K key, V value): access to entry associated with the key, if entry exists after invocation completes > > replace(K key, V oldValue, V newValue): access to entry associated with the key, if returns true > > computeIfAbsent/computeIfPresent/compute/merge: access to entry associated with the key, if returns a non-null value. > > > -- > > [*] There is some ambiguity with computeIfAbsent. When the entry exists, it's value is null, and the value returned from the mapping function is null then, an access to that entry occurs: > > V v = mappingFunction.apply(key); > if (old != null) { > old.value = v; > afterNodeAccess(old); > return v; > } > else if (v == null) > return null; > > Is that a bug? I would have expected the returning of null from the mapping function to signal no-action to be taken. Thus computeIfPresent and computeIfAbsent have no side-effects for an existing entry whose value is null when the function returns null (same applies to merge, if the value parameter is null or the remapping function returns null, and to compute, if the remapping function returns null). > > So perhaps that code should be: > > V v = mappingFunction.apply(key); > if (v == null) > return null; > else if (old != null) { > old.value = v; > afterNodeAccess(old); > return v; > } > > Paul. From paul.sandoz at oracle.com Tue Dec 17 03:56:14 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 17 Dec 2013 12:56:14 +0100 Subject: Trouble with wildcards In-Reply-To: References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <52AF72CE.9020101@univ-mlv.fr> Message-ID: <08B92373-1C99-4CB5-873B-E47E8B4CF010@oracle.com> On Dec 17, 2013, at 12:10 AM, Zhong Yu wrote: > Not exactly sure what you guys are talking about... but I guess it's a > complaint about the signature of Predicate.and()? > > It might be changed to be more receptive, like > > Predicate and(Predicate other) > > then the previous examples could be compiled, as well as this one > > Predicate p1 = null; > Predicate p2 = null; > Predicate p3 = p1.and(p2); > Thanks, we used a similar trick with Comparator.thenComparing but removed it [1] and i can no longer recall why, perhaps Henry can though. Paul. [1] http://hg.openjdk.java.net/lambda/lambda/jdk/rev/20b3fd9c7d36 - default Comparator thenComparing(Comparator other) { + default Comparator thenComparing(Comparator other) { From vicente.romero at oracle.com Tue Dec 17 07:06:45 2013 From: vicente.romero at oracle.com (Vicente-Arturo Romero-Zaldivar) Date: Tue, 17 Dec 2013 15:06:45 +0000 Subject: Overload resolution regression In-Reply-To: References: <528B4BD3.2070906@univ-mlv.fr> <528B7804.5000404@univ-mlv.fr> Message-ID: <52B06885.6020105@oracle.com> Hi Jonathan, Thanks for the provided test case. I think that this is a bug in javac. The bug has been filed before, https://bugs.openjdk.java.net/browse/JDK-8028774, for similar cases. I have added your test case to the bug entry. Thanks, Vicente On 13/12/13 20:38, Jonathan C. Ross wrote: > Hi again, > > I thought I understood this issue after Remi?s explanation, but I have run into a couple of cases where I still don?t understand the outcome, One example is essentially para-phrased as follows: > > import java.util.Collection; > > abstract class Test { > abstract > T build(); > > abstract void use(Collection n); > abstract void use(Double s); > > void f() { > use(build()); > } > } > > Works fine in 7, and my JDK-8-savvy IDE?s (IntelliJ, Netbeans) think it?s fine. However, ea-b119 thinks the overloading of ?use' is ambiguous. In what scenario could this behaviour be an enhancement? > > ? Jonathan Ross > > > On 19 Nov 2013, at 10:43, Jonathan Ross wrote: > >> Or a pickMe(String) for that matter? >> >> Thanks for the explanation, Remi. Indeed, we were just using the >> coincidence of the Object fallback; it seems to predominantly affect our >> test fixtures - I hope, at least. The nasty thing about it is that it >> leads to a runtime exception rather than a compilation error, so we may not >> find out for certain for a while. >> >> >> On Tue, Nov 19, 2013 at 9:02 AM, Paul Benedict wrote: >> >>> Ah, okay, that makes sense now. Filling me in on the background was a big >>> helper. >>> >>> For the sake of clarity, what would happen to Jonathan's example if there >>> was also a third pickMe(BigDecimal)? >>> >>> >>> On Tue, Nov 19, 2013 at 8:39 AM, Remi Forax wrote: >>> >>>> On 11/19/2013 02:53 PM, Paul Benedict wrote: >>>> >>>>> I don't see how you can call the compiler "smarter" in this example. >>>>> >>>> 'smarter' because this is not the only use case :) >>>> Here is an example that fails to compile with 7 but compiles with 8 >>>> (comparingByValue is also a method that only uses type variables to >>>> specify the return type) >>>> Map map = ... >>>> map.entrySet().stream().sorted(Map.Entry.comparingByValue()); >>>> >>>> For pickMe(unsafe()) the inference fails in 7 and uses Object as a >>>> fallback, >>>> it appears that it's what the user want but that's just a coincidence. >>>> >>>> It is choosing pickMe(BigInteger) without >: BigInteger type being >>>>> present. >>>>> >>>> >>>> Don't forget that pickMe(null) also choose pickMe(BigInteger), >>>> it's the way the algorithm that choose the most specific method works >>>> since the beginning. >>>> here, the constraint is that T is a subtype of Object, so both >>>> pickMe(Object) and pickMe(BigInteger) are applicable, >>>> then the most specific algorithm chooses that pickMe(BigInteger) is >>> better >>>> than pickMe(Object). >>>> >>>> cheers, >>>> R?mi >>>> >>>> >>>>> On Tue, Nov 19, 2013 at 5:30 AM, Remi Forax >>>> forax at univ-mlv.fr>> wrote: >>>>> >>>>> On 11/19/2013 01:43 AM, Jonathan Ross wrote: >>>>>> Hi, >>>>> Hi Johnathan, >>>>> >>>>>> I recently started porting a 150k-line project to jdk 8 to try >>>>> my hand at >>>>>> the recent changes in the collection libraries. (Hadn't done >>>>> this since >>>>>> last year, my apologies!) >>>>>> >>>>>> I have run in to a large number of compilation errors: >>>>> regressions in type >>>>>> inference and overload resolution. A lot of these are in unit >>>>> tests using >>>>>> mockito and fest and other similar monadic apis that rely heavily >>> on >>>>>> overload resolution. >>>>> It's not a regression, it's an enhancement :) >>>>> >>>>>> The code snippet below is a distilled version of my typical >>>>> compilation >>>>>> error: our test code relying on the compiler choosing the Object >>>>> overload >>>>>> by default. >>>>>> >>>>>> >>>>>> import java.math.BigInteger; >>>>>> >>>>>> public class OverloadingRegression { >>>>>> >>>>>> static T unsafeCast(Object anObject) { >>>>>> return (T) anObject; >>>>>> } >>>>>> >>>>>> public void showOverloadResolutionIssue() { >>>>>> pickMe(unsafeCast(new String())); >>>>>> } >>>>>> >>>>>> private void pickMe(BigInteger o) { /* ClassCastException in >>>>>> 1.8.0-ea-b115 */ } >>>>>> >>>>>> private void pickMe(Object o) { /* fine, picked in 1.6 & >>>>> 1.7 */ } >>>>>> } >>>>>> >>>>>> >>>>>> Obviously the unsafeCast is not going to win any beauty prizes, >>> but >>>>>> sometimes you just have to do this sort of thing. My main point >>>>> is: it >>>>>> used to work in java 7, it doesn't any more. >>>>>> >>>>>> Is this a known issue (or is it even expected behaviour)? >>>>> Yes, it's the expected behavior, when you try do inference inside a >>>>> method call, >>>>> here unsafeCast is inside pickMe, in that case with jdk6 & 7, the >>>>> inference >>>>> is not done and T is replaceb by its bound (Object), with jdk8, the >>>>> compiler is smarter, >>>>> and find the most specific method first, here pickMe(BigInteger) >>>>> is more >>>>> specific than pickMe(Object) and then infers T (T = BigInteger). >>>>> >>>>>> I'm using 1.8.0-ea-b115, but I verified that it fails with all >>>>> 1.8 jdks I >>>>>> have my box. When I pass in -source 1.7 it does work. And when >>>>> I do an >>>>>> explicit cast to Object (of course). >>>>> so this is the correct behavior for 8, the new stream API heavily >>>>> relies >>>>> on that, >>>>> and yes, this new semantics is not compatible with 1.7 in the case >>> the >>>>> inference was failing, >>>>> this is a known compatibility issue. >>>>> >>>>>> -- Jonathan Ross >>>>>> >>>>> cheers, >>>>> R?mi >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> Cheers, >>>>> Paul >>>>> >>>> >>> >>> -- >>> Cheers, >>> Paul >>> >>> >>> ________________________________ >>> >>> The information in this e-mail is intended only for the person or entity >>> to which it is addressed. >>> >>> It may contain confidential and /or privileged material. If someone other >>> than the intended recipient should receive this e-mail, he / she shall not >>> be entitled to read, disseminate, disclose or duplicate it. >>> >>> If you receive this e-mail unintentionally, please inform us immediately >>> by "reply" and then delete it from your system. Although this information >>> has been compiled with great care, neither IMC Financial Markets & Asset >>> Management nor any of its related entities shall accept any responsibility >>> for any errors, omissions or other inaccuracies in this information or for >>> the consequences thereof, nor shall it be bound in any way by the contents >>> of this e-mail or its attachments. In the event of incomplete or incorrect >>> transmission, please return the e-mail to the sender and permanently delete >>> this message and any attachments. >>> >>> Messages and attachments are scanned for all known viruses. Always scan >>> attachments before opening them. >>> > > ________________________________ > > The information in this e-mail is intended only for the person or entity to which it is addressed. > > It may contain confidential and /or privileged material. If someone other than the intended recipient should receive this e-mail, he / she shall not be entitled to read, disseminate, disclose or duplicate it. > > If you receive this e-mail unintentionally, please inform us immediately by "reply" and then delete it from your system. Although this information has been compiled with great care, neither IMC Financial Markets & Asset Management nor any of its related entities shall accept any responsibility for any errors, omissions or other inaccuracies in this information or for the consequences thereof, nor shall it be bound in any way by the contents of this e-mail or its attachments. In the event of incomplete or incorrect transmission, please return the e-mail to the sender and permanently delete this message and any attachments. > > Messages and attachments are scanned for all known viruses. Always scan attachments before opening them. > From anna.kozlova at jetbrains.com Tue Dec 17 08:38:51 2013 From: anna.kozlova at jetbrains.com (Anna Kozlova) Date: Tue, 17 Dec 2013 17:38:51 +0100 Subject: javac 8 with target level 7 Message-ID: <02e801cefb46$77e37180$67aa5480$@jetbrains.com> Hi, The code compiles with java 8 (b. 119) target 7, but fails to compile with javac 7 target 7: import java.util.Comparator; class GenericMethod { > Comparator getComparator() { return null; } void useComparator(Comparator comparator) { } void test() { useComparator(this.getComparator()); } } Was that intended? Thanks, Anna From Jonathan.Ross at imc-chicago.com Tue Dec 17 09:19:44 2013 From: Jonathan.Ross at imc-chicago.com (Jonathan Ross) Date: Tue, 17 Dec 2013 17:19:44 +0000 Subject: Overload resolution regression In-Reply-To: <52B06885.6020105@oracle.com> References: <528B4BD3.2070906@univ-mlv.fr> <528B7804.5000404@univ-mlv.fr> <52B06885.6020105@oracle.com> Message-ID: Hi Vincente, Thanks for adding the test case. The original code example in JDK-8028774 was mine as well, by the way. It would appear to be a slightly different issue, at least the compiler error is different. With the new test case, we get: $ javac Test.java Test.java:10: error: reference to use is ambiguous use(build()); ^ both method use(Collection) in Test and method use(Double) in Test match 1 error What leads you to think it is the same issue? ? Jonathan On Dec 17, 2013, at 9:06 AM, Vicente-Arturo Romero-Zaldivar > wrote: Hi Jonathan, Thanks for the provided test case. I think that this is a bug in javac. The bug has been filed before, https://bugs.openjdk.java.net/browse/JDK-8028774, for similar cases. I have added your test case to the bug entry. Thanks, Vicente On 13/12/13 20:38, Jonathan C. Ross wrote: Hi again, I thought I understood this issue after Remi?s explanation, but I have run into a couple of cases where I still don?t understand the outcome, One example is essentially para-phrased as follows: import java.util.Collection; abstract class Test { abstract > T build(); abstract void use(Collection n); abstract void use(Double s); void f() { use(build()); } } Works fine in 7, and my JDK-8-savvy IDE?s (IntelliJ, Netbeans) think it?s fine. However, ea-b119 thinks the overloading of ?use' is ambiguous. In what scenario could this behaviour be an enhancement? ? Jonathan Ross On 19 Nov 2013, at 10:43, Jonathan Ross > wrote: Or a pickMe(String) for that matter? Thanks for the explanation, Remi. Indeed, we were just using the coincidence of the Object fallback; it seems to predominantly affect our test fixtures - I hope, at least. The nasty thing about it is that it leads to a runtime exception rather than a compilation error, so we may not find out for certain for a while. On Tue, Nov 19, 2013 at 9:02 AM, Paul Benedict > wrote: Ah, okay, that makes sense now. Filling me in on the background was a big helper. For the sake of clarity, what would happen to Jonathan's example if there was also a third pickMe(BigDecimal)? On Tue, Nov 19, 2013 at 8:39 AM, Remi Forax > wrote: On 11/19/2013 02:53 PM, Paul Benedict wrote: I don't see how you can call the compiler "smarter" in this example. 'smarter' because this is not the only use case :) Here is an example that fails to compile with 7 but compiles with 8 (comparingByValue is also a method that only uses type variables to specify the return type) Map map = ... map.entrySet().stream().sorted(Map.Entry.comparingByValue()); For pickMe(unsafe()) the inference fails in 7 and uses Object as a fallback, it appears that it's what the user want but that's just a coincidence. It is choosing pickMe(BigInteger) without >: BigInteger type being present. Don't forget that pickMe(null) also choose pickMe(BigInteger), it's the way the algorithm that choose the most specific method works since the beginning. here, the constraint is that T is a subtype of Object, so both pickMe(Object) and pickMe(BigInteger) are applicable, then the most specific algorithm chooses that pickMe(BigInteger) is better than pickMe(Object). cheers, R?mi On Tue, Nov 19, 2013 at 5:30 AM, Remi Forax >> wrote: On 11/19/2013 01:43 AM, Jonathan Ross wrote: Hi, Hi Johnathan, I recently started porting a 150k-line project to jdk 8 to try my hand at the recent changes in the collection libraries. (Hadn't done this since last year, my apologies!) I have run in to a large number of compilation errors: regressions in type inference and overload resolution. A lot of these are in unit tests using mockito and fest and other similar monadic apis that rely heavily on overload resolution. It's not a regression, it's an enhancement :) The code snippet below is a distilled version of my typical compilation error: our test code relying on the compiler choosing the Object overload by default. import java.math.BigInteger; public class OverloadingRegression { static T unsafeCast(Object anObject) { return (T) anObject; } public void showOverloadResolutionIssue() { pickMe(unsafeCast(new String())); } private void pickMe(BigInteger o) { /* ClassCastException in 1.8.0-ea-b115 */ } private void pickMe(Object o) { /* fine, picked in 1.6 & 1.7 */ } } Obviously the unsafeCast is not going to win any beauty prizes, but sometimes you just have to do this sort of thing. My main point is: it used to work in java 7, it doesn't any more. Is this a known issue (or is it even expected behaviour)? Yes, it's the expected behavior, when you try do inference inside a method call, here unsafeCast is inside pickMe, in that case with jdk6 & 7, the inference is not done and T is replaceb by its bound (Object), with jdk8, the compiler is smarter, and find the most specific method first, here pickMe(BigInteger) is more specific than pickMe(Object) and then infers T (T = BigInteger). I'm using 1.8.0-ea-b115, but I verified that it fails with all 1.8 jdks I have my box. When I pass in -source 1.7 it does work. And when I do an explicit cast to Object (of course). so this is the correct behavior for 8, the new stream API heavily relies on that, and yes, this new semantics is not compatible with 1.7 in the case the inference was failing, this is a known compatibility issue. -- Jonathan Ross cheers, R?mi -- Cheers, Paul -- Cheers, Paul ________________________________ The information in this e-mail is intended only for the person or entity to which it is addressed. It may contain confidential and /or privileged material. If someone other than the intended recipient should receive this e-mail, he / she shall not be entitled to read, disseminate, disclose or duplicate it. If you receive this e-mail unintentionally, please inform us immediately by "reply" and then delete it from your system. Although this information has been compiled with great care, neither IMC Financial Markets & Asset Management nor any of its related entities shall accept any responsibility for any errors, omissions or other inaccuracies in this information or for the consequences thereof, nor shall it be bound in any way by the contents of this e-mail or its attachments. In the event of incomplete or incorrect transmission, please return the e-mail to the sender and permanently delete this message and any attachments. Messages and attachments are scanned for all known viruses. Always scan attachments before opening them. ________________________________ The information in this e-mail is intended only for the person or entity to which it is addressed. It may contain confidential and /or privileged material. If someone other than the intended recipient should receive this e-mail, he / she shall not be entitled to read, disseminate, disclose or duplicate it. If you receive this e-mail unintentionally, please inform us immediately by "reply" and then delete it from your system. Although this information has been compiled with great care, neither IMC Financial Markets & Asset Management nor any of its related entities shall accept any responsibility for any errors, omissions or other inaccuracies in this information or for the consequences thereof, nor shall it be bound in any way by the contents of this e-mail or its attachments. In the event of incomplete or incorrect transmission, please return the e-mail to the sender and permanently delete this message and any attachments. Messages and attachments are scanned for all known viruses. Always scan attachments before opening them. ________________________________ The information in this e-mail is intended only for the person or entity to which it is addressed. It may contain confidential and /or privileged material. If someone other than the intended recipient should receive this e-mail, he / she shall not be entitled to read, disseminate, disclose or duplicate it. If you receive this e-mail unintentionally, please inform us immediately by "reply" and then delete it from your system. Although this information has been compiled with great care, neither IMC Financial Markets & Asset Management nor any of its related entities shall accept any responsibility for any errors, omissions or other inaccuracies in this information or for the consequences thereof, nor shall it be bound in any way by the contents of this e-mail or its attachments. In the event of incomplete or incorrect transmission, please return the e-mail to the sender and permanently delete this message and any attachments. Messages and attachments are scanned for all known viruses. Always scan attachments before opening them. From daniel.smith at oracle.com Tue Dec 17 10:21:39 2013 From: daniel.smith at oracle.com (Dan Smith) Date: Tue, 17 Dec 2013 11:21:39 -0700 Subject: Trouble with wildcards In-Reply-To: <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> Message-ID: <184D6EEE-18F0-4F1E-A25D-B024436F5793@oracle.com> On Dec 16, 2013, at 7:42 AM, Paul Sandoz wrote: > Hi Remi, > > Reducing it down a little: > > import java.util.*; > import java.util.function.*; > > class A { > > static class X {}; > static class Y extends X {}; > > public static void main(String[] args) { > Predicate px = x -> x instanceof X; > Predicate py = y -> y instanceof Y; > > Predicate psy = px; > > Predicate superyandy = psy.and(py); // <-- error > superyandy.test(new Y()); > } > } > > $ javac -Xdiags:verbose A.java > A.java:15: error: method and in interface Predicate cannot be applied to given types; > Predicate superyandy = psy.and(py); // <-- error > ^ > required: Predicate > found: Predicate > reason: argument mismatch; Predicate cannot be converted to Predicate > where T is a type-variable: > T extends Object declared in interface Predicate > where CAP#1 is a fresh type-variable: > CAP#1 extends Object super: Y from capture of ? super Y > 1 error > > > It's confusing... The concrete explanation: the 'and' method of the type Predicate<[something]>, where [something] is some type that is a supertype of Y (written CAP#1 in the error message), requires a Predicate. Is a Predicate a Predicate? No. For example, consider the case in which [something] is Object. The abstract explanation: we accept that 'px.and(py)' is a type error, right? So it certainly doesn't make any sense that _up-casting_ px to one of its supertypes (Predicate in this case) would provide some functionality that px itself doesn't have. ?Dan From daniel.smith at oracle.com Tue Dec 17 10:30:10 2013 From: daniel.smith at oracle.com (Dan Smith) Date: Tue, 17 Dec 2013 11:30:10 -0700 Subject: Trouble with wildcards In-Reply-To: <08B92373-1C99-4CB5-873B-E47E8B4CF010@oracle.com> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <52AF72CE.9020101@univ-mlv.fr> <08B92373-1C99-4CB5-873B-E47E8B4CF010@oracle.com> Message-ID: <8DF3F258-D0C5-468E-8E69-24F34E52569A@oracle.com> On Dec 17, 2013, at 4:56 AM, Paul Sandoz wrote: > On Dec 17, 2013, at 12:10 AM, Zhong Yu wrote: > >> Not exactly sure what you guys are talking about... but I guess it's a >> complaint about the signature of Predicate.and()? >> >> It might be changed to be more receptive, like >> >> Predicate and(Predicate other) >> >> then the previous examples could be compiled, as well as this one >> >> Predicate p1 = null; >> Predicate p2 = null; >> Predicate p3 = p1.and(p2); >> > > Thanks, we used a similar trick with Comparator.thenComparing but removed it [1] and i can no longer recall why, perhaps Henry can though. Yes, this would solve the problem, and it is essentially the same thing as the proposed Comparator.thenComparing change. As I recall, two arguments for reverting 'thenComparing': - It makes the method generic in its return type, which changed the dependencies for overload resolution, and thus led to ambiguities. I think this is a moot point now, because overload resolution isn't going to look at an implicit lambda body in any case. (And besides, Predicate.and isn't overloaded.) - The exact same pattern should be used with naturally covariant types (see, e.g., Optional.orElse), but we can't express "S super T" when we declare S. It is kind of arbitrary to only do this for the (less common) naturally contravariant types. There may have been one or two other reasons that I can't recall right now. ?Dan From vicente.romero at oracle.com Tue Dec 17 10:29:52 2013 From: vicente.romero at oracle.com (Vicente-Arturo Romero-Zaldivar) Date: Tue, 17 Dec 2013 18:29:52 +0000 Subject: Overload resolution regression In-Reply-To: References: <528B4BD3.2070906@univ-mlv.fr> <528B7804.5000404@univ-mlv.fr> <52B06885.6020105@oracle.com> Message-ID: <52B09820.8040104@oracle.com> Hi Jonathan, In both cases we have nested invocation that returns an inference variable. I added the test case explicitly because if it's the case that both test cases don't have the same root cause then they both will be addressed anyway. Thanks, Vicente On 17/12/13 17:19, Jonathan Ross wrote: > Hi Vincente, > > Thanks for adding the test case. The original code example in > JDK-8028774 was > mine as well, by the way. It would appear to be a slightly different > issue, at least the compiler error is different. With the new test > case, we get: > > > $ javac Test.java > Test.java:10: error: reference to use is ambiguous > use(build()); > ^ > both method use(Collection) in Test and method use(Double) in > Test match > 1 error > > > What leads you to think it is the same issue? > > ? Jonathan > > On Dec 17, 2013, at 9:06 AM, Vicente-Arturo Romero-Zaldivar > > wrote: > >> Hi Jonathan, >> >> Thanks for the provided test case. I think that this is a bug in >> javac. The bug has been filed before, >> https://bugs.openjdk.java.net/browse/JDK-8028774, for similar cases. >> I have added your test case to the bug entry. >> >> Thanks, >> Vicente >> >> On 13/12/13 20:38, Jonathan C. Ross wrote: >>> Hi again, >>> >>> I thought I understood this issue after Remi?s explanation, but I >>> have run into a couple of cases where I still don?t understand the >>> outcome, One example is essentially para-phrased as follows: >>> >>> import java.util.Collection; >>> >>> abstract class Test { >>> abstract > T build(); >>> >>> abstract void use(Collection n); >>> abstract void use(Double s); >>> >>> void f() { >>> use(build()); >>> } >>> } >>> >>> Works fine in 7, and my JDK-8-savvy IDE?s (IntelliJ, Netbeans) think >>> it?s fine. However, ea-b119 thinks the overloading of ?use' is >>> ambiguous. In what scenario could this behaviour be an enhancement? >>> >>> ? Jonathan Ross >>> >>> >>> On 19 Nov 2013, at 10:43, Jonathan Ross >>> >> > wrote: >>> >>>> Or a pickMe(String) for that matter? >>>> >>>> Thanks for the explanation, Remi. Indeed, we were just using the >>>> coincidence of the Object fallback; it seems to predominantly >>>> affect our >>>> test fixtures - I hope, at least. The nasty thing about it is that it >>>> leads to a runtime exception rather than a compilation error, so we >>>> may not >>>> find out for certain for a while. >>>> >>>> >>>> On Tue, Nov 19, 2013 at 9:02 AM, Paul Benedict >>>> > wrote: >>>> >>>>> Ah, okay, that makes sense now. Filling me in on the background >>>>> was a big >>>>> helper. >>>>> >>>>> For the sake of clarity, what would happen to Jonathan's example >>>>> if there >>>>> was also a third pickMe(BigDecimal)? >>>>> >>>>> >>>>> On Tue, Nov 19, 2013 at 8:39 AM, Remi Forax >>>> > wrote: >>>>> >>>>>> On 11/19/2013 02:53 PM, Paul Benedict wrote: >>>>>> >>>>>>> I don't see how you can call the compiler "smarter" in this example. >>>>>>> >>>>>> 'smarter' because this is not the only use case :) >>>>>> Here is an example that fails to compile with 7 but compiles with 8 >>>>>> (comparingByValue is also a method that only uses type variables to >>>>>> specify the return type) >>>>>> Map map = ... >>>>>> map.entrySet().stream().sorted(Map.Entry.comparingByValue()); >>>>>> >>>>>> For pickMe(unsafe()) the inference fails in 7 and uses Object as a >>>>>> fallback, >>>>>> it appears that it's what the user want but that's just a >>>>>> coincidence. >>>>>> >>>>>> It is choosing pickMe(BigInteger) without >: BigInteger type being >>>>>>> present. >>>>>>> >>>>>> >>>>>> Don't forget that pickMe(null) also choose pickMe(BigInteger), >>>>>> it's the way the algorithm that choose the most specific method works >>>>>> since the beginning. >>>>>> here, the constraint is that T is a subtype of Object, so both >>>>>> pickMe(Object) and pickMe(BigInteger) are applicable, >>>>>> then the most specific algorithm chooses that pickMe(BigInteger) is >>>>> better >>>>>> than pickMe(Object). >>>>>> >>>>>> cheers, >>>>>> R?mi >>>>>> >>>>>> >>>>>>> On Tue, Nov 19, 2013 at 5:30 AM, Remi Forax >>>>>> >>>>>> forax at univ-mlv.fr >> wrote: >>>>>>> >>>>>>> On 11/19/2013 01:43 AM, Jonathan Ross wrote: >>>>>>>> Hi, >>>>>>> Hi Johnathan, >>>>>>> >>>>>>>> I recently started porting a 150k-line project to jdk 8 to try >>>>>>> my hand at >>>>>>>> the recent changes in the collection libraries. (Hadn't done >>>>>>> this since >>>>>>>> last year, my apologies!) >>>>>>>> >>>>>>>> I have run in to a large number of compilation errors: >>>>>>> regressions in type >>>>>>>> inference and overload resolution. A lot of these are in unit >>>>>>> tests using >>>>>>>> mockito and fest and other similar monadic apis that rely heavily >>>>> on >>>>>>>> overload resolution. >>>>>>> It's not a regression, it's an enhancement :) >>>>>>> >>>>>>>> The code snippet below is a distilled version of my typical >>>>>>> compilation >>>>>>>> error: our test code relying on the compiler choosing the Object >>>>>>> overload >>>>>>>> by default. >>>>>>>> >>>>>>>> >>>>>>>> import java.math.BigInteger; >>>>>>>> >>>>>>>> public class OverloadingRegression { >>>>>>>> >>>>>>>> static T unsafeCast(Object anObject) { >>>>>>>> return (T) anObject; >>>>>>>> } >>>>>>>> >>>>>>>> public void showOverloadResolutionIssue() { >>>>>>>> pickMe(unsafeCast(new String())); >>>>>>>> } >>>>>>>> >>>>>>>> private void pickMe(BigInteger o) { /* ClassCastException in >>>>>>>> 1.8.0-ea-b115 */ } >>>>>>>> >>>>>>>> private void pickMe(Object o) { /* fine, picked in 1.6 & >>>>>>> 1.7 */ } >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> Obviously the unsafeCast is not going to win any beauty prizes, >>>>> but >>>>>>>> sometimes you just have to do this sort of thing. My main point >>>>>>> is: it >>>>>>>> used to work in java 7, it doesn't any more. >>>>>>>> >>>>>>>> Is this a known issue (or is it even expected behaviour)? >>>>>>> Yes, it's the expected behavior, when you try do inference >>>>>>> inside a >>>>>>> method call, >>>>>>> here unsafeCast is inside pickMe, in that case with jdk6 & 7, the >>>>>>> inference >>>>>>> is not done and T is replaceb by its bound (Object), with >>>>>>> jdk8, the >>>>>>> compiler is smarter, >>>>>>> and find the most specific method first, here pickMe(BigInteger) >>>>>>> is more >>>>>>> specific than pickMe(Object) and then infers T (T = BigInteger). >>>>>>> >>>>>>>> I'm using 1.8.0-ea-b115, but I verified that it fails with all >>>>>>> 1.8 jdks I >>>>>>>> have my box. When I pass in -source 1.7 it does work. And when >>>>>>> I do an >>>>>>>> explicit cast to Object (of course). >>>>>>> so this is the correct behavior for 8, the new stream API heavily >>>>>>> relies >>>>>>> on that, >>>>>>> and yes, this new semantics is not compatible with 1.7 in the >>>>>>> case >>>>> the >>>>>>> inference was failing, >>>>>>> this is a known compatibility issue. >>>>>>> >>>>>>>> -- Jonathan Ross >>>>>>>> >>>>>>> cheers, >>>>>>> R?mi >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Cheers, >>>>>>> Paul >>>>>>> >>>>>> >>>>> >>>>> -- >>>>> Cheers, >>>>> Paul >>>>> >>>>> >>>>> ________________________________ >>>>> >>>>> The information in this e-mail is intended only for the person or >>>>> entity >>>>> to which it is addressed. >>>>> >>>>> It may contain confidential and /or privileged material. If >>>>> someone other >>>>> than the intended recipient should receive this e-mail, he / she >>>>> shall not >>>>> be entitled to read, disseminate, disclose or duplicate it. >>>>> >>>>> If you receive this e-mail unintentionally, please inform us >>>>> immediately >>>>> by "reply" and then delete it from your system. Although this >>>>> information >>>>> has been compiled with great care, neither IMC Financial Markets & >>>>> Asset >>>>> Management nor any of its related entities shall accept any >>>>> responsibility >>>>> for any errors, omissions or other inaccuracies in this >>>>> information or for >>>>> the consequences thereof, nor shall it be bound in any way by the >>>>> contents >>>>> of this e-mail or its attachments. In the event of incomplete or >>>>> incorrect >>>>> transmission, please return the e-mail to the sender and >>>>> permanently delete >>>>> this message and any attachments. >>>>> >>>>> Messages and attachments are scanned for all known viruses. Always >>>>> scan >>>>> attachments before opening them. >>>>> >>> >>> ________________________________ >>> >>> The information in this e-mail is intended only for the person or >>> entity to which it is addressed. >>> >>> It may contain confidential and /or privileged material. If someone >>> other than the intended recipient should receive this e-mail, he / >>> she shall not be entitled to read, disseminate, disclose or >>> duplicate it. >>> >>> If you receive this e-mail unintentionally, please inform us >>> immediately by "reply" and then delete it from your system. Although >>> this information has been compiled with great care, neither IMC >>> Financial Markets & Asset Management nor any of its related entities >>> shall accept any responsibility for any errors, omissions or other >>> inaccuracies in this information or for the consequences thereof, >>> nor shall it be bound in any way by the contents of this e-mail or >>> its attachments. In the event of incomplete or incorrect >>> transmission, please return the e-mail to the sender and permanently >>> delete this message and any attachments. >>> >>> Messages and attachments are scanned for all known viruses. Always >>> scan attachments before opening them. >>> >> > > > ------------------------------------------------------------------------ > > The information in this e-mail is intended only for the person or > entity to which it is addressed. > > It may contain confidential and /or privileged material. If someone > other than the intended recipient should receive this e-mail, he / she > shall not be entitled to read, disseminate, disclose or duplicate it. > > If you receive this e-mail unintentionally, please inform us > immediately by "reply" and then delete it from your system. Although > this information has been compiled with great care, neither IMC > Financial Markets & Asset Management nor any of its related entities > shall accept any responsibility for any errors, omissions or other > inaccuracies in this information or for the consequences thereof, nor > shall it be bound in any way by the contents of this e-mail or its > attachments. In the event of incomplete or incorrect transmission, > please return the e-mail to the sender and permanently delete this > message and any attachments. > > Messages and attachments are scanned for all known viruses. Always > scan attachments before opening them. From henry.jen at oracle.com Tue Dec 17 10:48:17 2013 From: henry.jen at oracle.com (Henry Jen) Date: Tue, 17 Dec 2013 10:48:17 -0800 Subject: Trouble with wildcards In-Reply-To: <8DF3F258-D0C5-468E-8E69-24F34E52569A@oracle.com> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <52AF72CE.9020101@univ-mlv.fr> <08B92373-1C99-4CB5-873B-E47E8B4CF010@oracle.com> <8DF3F258-D0C5-468E-8E69-24F34E52569A@oracle.com> Message-ID: <52B09C71.7090303@oracle.com> On 12/17/2013 10:30 AM, Dan Smith wrote: > On Dec 17, 2013, at 4:56 AM, Paul Sandoz > wrote: > >> On Dec 17, 2013, at 12:10 AM, Zhong Yu >> wrote: >> >>> Not exactly sure what you guys are talking about... but I guess >>> it's a complaint about the signature of Predicate.and()? >>> >>> It might be changed to be more receptive, like >>> >>> Predicate and(Predicate other) >>> >>> then the previous examples could be compiled, as well as this >>> one >>> >>> Predicate p1 = null; Predicate p2 = >>> null; Predicate p3 = p1.and(p2); >>> >> >> Thanks, we used a similar trick with Comparator.thenComparing but >> removed it [1] and i can no longer recall why, perhaps Henry can >> though. > > Yes, this would solve the problem, and it is essentially the same > thing as the proposed Comparator.thenComparing change. > > As I recall, two arguments for reverting 'thenComparing': > > - It makes the method generic in its return type, which changed the > dependencies for overload resolution, and thus led to ambiguities. I > think this is a moot point now, because overload resolution isn't > going to look at an implicit lambda body in any case. (And besides, > Predicate.and isn't overloaded.) The return type becomes generic can also cause problem chaining API, I think this still valid. > > - The exact same pattern should be used with naturally covariant > types (see, e.g., Optional.orElse), but we can't express "S super T" > when we declare S. It is kind of arbitrary to only do this for the > (less common) naturally contravariant types. > > There may have been one or two other reasons that I can't recall > right now. > That's all I can remember. :) Cheers, Henry From zhong.j.yu at gmail.com Tue Dec 17 11:21:30 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Tue, 17 Dec 2013 13:21:30 -0600 Subject: Trouble with wildcards In-Reply-To: <8DF3F258-D0C5-468E-8E69-24F34E52569A@oracle.com> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <52AF72CE.9020101@univ-mlv.fr> <08B92373-1C99-4CB5-873B-E47E8B4CF010@oracle.com> <8DF3F258-D0C5-468E-8E69-24F34E52569A@oracle.com> Message-ID: On Tue, Dec 17, 2013 at 12:30 PM, Dan Smith wrote: > On Dec 17, 2013, at 4:56 AM, Paul Sandoz wrote: > >> On Dec 17, 2013, at 12:10 AM, Zhong Yu wrote: >> >>> Not exactly sure what you guys are talking about... but I guess it's a >>> complaint about the signature of Predicate.and()? >>> >>> It might be changed to be more receptive, like >>> >>> Predicate and(Predicate other) >>> >>> then the previous examples could be compiled, as well as this one >>> >>> Predicate p1 = null; >>> Predicate p2 = null; >>> Predicate p3 = p1.and(p2); >>> >> >> Thanks, we used a similar trick with Comparator.thenComparing but removed it [1] and i can no longer recall why, perhaps Henry can though. > > Yes, this would solve the problem, and it is essentially the same thing as the proposed Comparator.thenComparing change. > > As I recall, two arguments for reverting 'thenComparing': > > - It makes the method generic in its return type, which changed the dependencies for overload resolution, and thus led to ambiguities. I think this is a moot point now, because overload resolution isn't going to look at an implicit lambda body in any case. (And besides, Predicate.and isn't overloaded.) > > - The exact same pattern should be used with naturally covariant types (see, e.g., Optional.orElse), but we can't express "S super T" when we declare S. It is kind of arbitrary to only do this for the (less common) naturally contravariant types. Contravariance in function types is very common because most functions accept args. And "S super T" was considered rarely needed. It is a shame to remove a useful feature to maintain some sense of symmetry that nobody cares. Remi's example is very reasonable; if it cannot be supported by Java, it's incumbent on the Java team to supply a workaround. > > There may have been one or two other reasons that I can't recall right now. > > ?Dan > From forax at univ-mlv.fr Tue Dec 17 11:46:41 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 17 Dec 2013 20:46:41 +0100 Subject: Trouble with wildcards In-Reply-To: <184D6EEE-18F0-4F1E-A25D-B024436F5793@oracle.com> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <184D6EEE-18F0-4F1E-A25D-B024436F5793@oracle.com> Message-ID: <52B0AA21.8010904@univ-mlv.fr> On 12/17/2013 07:21 PM, Dan Smith wrote: > On Dec 16, 2013, at 7:42 AM, Paul Sandoz wrote: > >> Hi Remi, >> >> Reducing it down a little: >> >> import java.util.*; >> import java.util.function.*; >> >> class A { >> >> static class X {}; >> static class Y extends X {}; >> >> public static void main(String[] args) { >> Predicate px = x -> x instanceof X; >> Predicate py = y -> y instanceof Y; >> >> Predicate psy = px; >> >> Predicate superyandy = psy.and(py); // <-- error >> superyandy.test(new Y()); >> } >> } >> >> $ javac -Xdiags:verbose A.java >> A.java:15: error: method and in interface Predicate cannot be applied to given types; >> Predicate superyandy = psy.and(py); // <-- error >> ^ >> required: Predicate >> found: Predicate >> reason: argument mismatch; Predicate cannot be converted to Predicate >> where T is a type-variable: >> T extends Object declared in interface Predicate >> where CAP#1 is a fresh type-variable: >> CAP#1 extends Object super: Y from capture of ? super Y >> 1 error >> >> >> It's confusing... > The concrete explanation: the 'and' method of the type Predicate<[something]>, where [something] is some type that is a supertype of Y (written CAP#1 in the error message), requires a Predicate. Is a Predicate a Predicate? No. For example, consider the case in which [something] is Object. I disagree, Predicate is a Predicate because Y can capture ? super [something], otherwise it means that 'and' should be a static method and not an instance method. The following code compiles: static Predicate staticAnd(Predicate that, Predicate other) { ... } Predicate p1 = null; Predicate p2 = null; Predicate p3 = staticAnd(p1,p2); but not Predicate p3 = p1.and(p2); which is not very logical. > > The abstract explanation: we accept that 'px.and(py)' is a type error, right? So it certainly doesn't make any sense that _up-casting_ px to one of its supertypes (Predicate in this case) would provide some functionality that px itself doesn't have. > > ?Dan R?mi From zhong.j.yu at gmail.com Tue Dec 17 12:35:07 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Tue, 17 Dec 2013 14:35:07 -0600 Subject: Trouble with wildcards In-Reply-To: <52B0AA21.8010904@univ-mlv.fr> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <184D6EEE-18F0-4F1E-A25D-B024436F5793@oracle.com> <52B0AA21.8010904@univ-mlv.fr> Message-ID: The static method works because it has an extra type parameter, which gives javac the freedom to make things work. The instance and() method has no such freedom (unless we give it a type parameter ) Zhong Yu On Tue, Dec 17, 2013 at 1:46 PM, Remi Forax wrote: > On 12/17/2013 07:21 PM, Dan Smith wrote: >> On Dec 16, 2013, at 7:42 AM, Paul Sandoz wrote: >> >>> Hi Remi, >>> >>> Reducing it down a little: >>> >>> import java.util.*; >>> import java.util.function.*; >>> >>> class A { >>> >>> static class X {}; >>> static class Y extends X {}; >>> >>> public static void main(String[] args) { >>> Predicate px = x -> x instanceof X; >>> Predicate py = y -> y instanceof Y; >>> >>> Predicate psy = px; >>> >>> Predicate superyandy = psy.and(py); // <-- error >>> superyandy.test(new Y()); >>> } >>> } >>> >>> $ javac -Xdiags:verbose A.java >>> A.java:15: error: method and in interface Predicate cannot be applied to given types; >>> Predicate superyandy = psy.and(py); // <-- error >>> ^ >>> required: Predicate >>> found: Predicate >>> reason: argument mismatch; Predicate cannot be converted to Predicate >>> where T is a type-variable: >>> T extends Object declared in interface Predicate >>> where CAP#1 is a fresh type-variable: >>> CAP#1 extends Object super: Y from capture of ? super Y >>> 1 error >>> >>> >>> It's confusing... >> The concrete explanation: the 'and' method of the type Predicate<[something]>, where [something] is some type that is a supertype of Y (written CAP#1 in the error message), requires a Predicate. Is a Predicate a Predicate? No. For example, consider the case in which [something] is Object. > > I disagree, Predicate is a Predicate because Y > can capture > ? super [something], otherwise it means that 'and' should be a static > method and not an instance method. > > The following code compiles: > static Predicate staticAnd(Predicate that, Predicate super T> other) { > ... > } > > Predicate p1 = null; > Predicate p2 = null; > Predicate p3 = staticAnd(p1,p2); > > but not > Predicate p3 = p1.and(p2); > which is not very logical. > >> >> The abstract explanation: we accept that 'px.and(py)' is a type error, right? So it certainly doesn't make any sense that _up-casting_ px to one of its supertypes (Predicate in this case) would provide some functionality that px itself doesn't have. >> >> ?Dan > > R?mi > > From forax at univ-mlv.fr Tue Dec 17 14:50:32 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 17 Dec 2013 23:50:32 +0100 Subject: Trouble with wildcards In-Reply-To: References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <184D6EEE-18F0-4F1E-A25D-B024436F5793@oracle.com> <52B0AA21.8010904@univ-mlv.fr> Message-ID: <52B0D538.5050804@univ-mlv.fr> On 12/17/2013 09:35 PM, Zhong Yu wrote: > The static method works because it has an extra type parameter, which > gives javac the freedom to make things work. The instance and() method > has no such freedom (unless we give it a type parameter ) > > Zhong Yu The instance method and() is called on a Predicate, and Predicate is declared as class Predicate, here T is already your extra type variable. R?mi > > On Tue, Dec 17, 2013 at 1:46 PM, Remi Forax wrote: >> On 12/17/2013 07:21 PM, Dan Smith wrote: >>> On Dec 16, 2013, at 7:42 AM, Paul Sandoz wrote: >>> >>>> Hi Remi, >>>> >>>> Reducing it down a little: >>>> >>>> import java.util.*; >>>> import java.util.function.*; >>>> >>>> class A { >>>> >>>> static class X {}; >>>> static class Y extends X {}; >>>> >>>> public static void main(String[] args) { >>>> Predicate px = x -> x instanceof X; >>>> Predicate py = y -> y instanceof Y; >>>> >>>> Predicate psy = px; >>>> >>>> Predicate superyandy = psy.and(py); // <-- error >>>> superyandy.test(new Y()); >>>> } >>>> } >>>> >>>> $ javac -Xdiags:verbose A.java >>>> A.java:15: error: method and in interface Predicate cannot be applied to given types; >>>> Predicate superyandy = psy.and(py); // <-- error >>>> ^ >>>> required: Predicate >>>> found: Predicate >>>> reason: argument mismatch; Predicate cannot be converted to Predicate >>>> where T is a type-variable: >>>> T extends Object declared in interface Predicate >>>> where CAP#1 is a fresh type-variable: >>>> CAP#1 extends Object super: Y from capture of ? super Y >>>> 1 error >>>> >>>> >>>> It's confusing... >>> The concrete explanation: the 'and' method of the type Predicate<[something]>, where [something] is some type that is a supertype of Y (written CAP#1 in the error message), requires a Predicate. Is a Predicate a Predicate? No. For example, consider the case in which [something] is Object. >> I disagree, Predicate is a Predicate because Y >> can capture >> ? super [something], otherwise it means that 'and' should be a static >> method and not an instance method. >> >> The following code compiles: >> static Predicate staticAnd(Predicate that, Predicate> super T> other) { >> ... >> } >> >> Predicate p1 = null; >> Predicate p2 = null; >> Predicate p3 = staticAnd(p1,p2); >> >> but not >> Predicate p3 = p1.and(p2); >> which is not very logical. >> >>> The abstract explanation: we accept that 'px.and(py)' is a type error, right? So it certainly doesn't make any sense that _up-casting_ px to one of its supertypes (Predicate in this case) would provide some functionality that px itself doesn't have. >>> >>> ?Dan >> R?mi >> >> From zhong.j.yu at gmail.com Tue Dec 17 15:48:22 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Tue, 17 Dec 2013 17:48:22 -0600 Subject: Trouble with wildcards In-Reply-To: <52B0D538.5050804@univ-mlv.fr> References: <52ACA6E4.3080109@univ-mlv.fr> <600AB4DA-FD59-4EE4-973E-1A65C1BA86FE@oracle.com> <184D6EEE-18F0-4F1E-A25D-B024436F5793@oracle.com> <52B0AA21.8010904@univ-mlv.fr> <52B0D538.5050804@univ-mlv.fr> Message-ID: In the instance method case p1.and(p2) there is no type variable to be inferred, all types are fixed. In the static case, staticAnd(p1,p2) there is a "floating" variable T to be inferred, and javac can "adjust" T to make the the code legal. The freedom given by the floating T is so much that even the following code compiles Predicate p1 = null; Predicate p2 = null; Predicate p3 = staticAnd(p1,p2); Zhong Yu On Tue, Dec 17, 2013 at 4:50 PM, Remi Forax wrote: > On 12/17/2013 09:35 PM, Zhong Yu wrote: >> >> The static method works because it has an extra type parameter, which >> gives javac the freedom to make things work. The instance and() method >> has no such freedom (unless we give it a type parameter ) >> >> Zhong Yu > > > The instance method and() is called on a Predicate, and Predicate > is declared as class Predicate, here T is already your extra type > variable. > > R?mi > > >> >> On Tue, Dec 17, 2013 at 1:46 PM, Remi Forax wrote: >>> >>> On 12/17/2013 07:21 PM, Dan Smith wrote: >>>> >>>> On Dec 16, 2013, at 7:42 AM, Paul Sandoz wrote: >>>> >>>>> Hi Remi, >>>>> >>>>> Reducing it down a little: >>>>> >>>>> import java.util.*; >>>>> import java.util.function.*; >>>>> >>>>> class A { >>>>> >>>>> static class X {}; >>>>> static class Y extends X {}; >>>>> >>>>> public static void main(String[] args) { >>>>> Predicate px = x -> x instanceof X; >>>>> Predicate py = y -> y instanceof Y; >>>>> >>>>> Predicate psy = px; >>>>> >>>>> Predicate superyandy = psy.and(py); // <-- error >>>>> superyandy.test(new Y()); >>>>> } >>>>> } >>>>> >>>>> $ javac -Xdiags:verbose A.java >>>>> A.java:15: error: method and in interface Predicate cannot be >>>>> applied to given types; >>>>> Predicate superyandy = psy.and(py); // <-- error >>>>> ^ >>>>> required: Predicate >>>>> found: Predicate >>>>> reason: argument mismatch; Predicate cannot be converted to >>>>> Predicate >>>>> where T is a type-variable: >>>>> T extends Object declared in interface Predicate >>>>> where CAP#1 is a fresh type-variable: >>>>> CAP#1 extends Object super: Y from capture of ? super Y >>>>> 1 error >>>>> >>>>> >>>>> It's confusing... >>>> >>>> The concrete explanation: the 'and' method of the type >>>> Predicate<[something]>, where [something] is some type that is a supertype >>>> of Y (written CAP#1 in the error message), requires a Predicate>>> [something]>. Is a Predicate a Predicate? No. For >>>> example, consider the case in which [something] is Object. >>> >>> I disagree, Predicate is a Predicate because Y >>> can capture >>> ? super [something], otherwise it means that 'and' should be a static >>> method and not an instance method. >>> >>> The following code compiles: >>> static Predicate staticAnd(Predicate that, Predicate>> super T> other) { >>> ... >>> } >>> >>> Predicate p1 = null; >>> Predicate p2 = null; >>> Predicate p3 = staticAnd(p1,p2); >>> >>> but not >>> Predicate p3 = p1.and(p2); >>> which is not very logical. >>> >>>> The abstract explanation: we accept that 'px.and(py)' is a type error, >>>> right? So it certainly doesn't make any sense that _up-casting_ px to one >>>> of its supertypes (Predicate in this case) would provide some >>>> functionality that px itself doesn't have. >>>> >>>> ?Dan >>> >>> R?mi >>> >>> > From zhong.j.yu at gmail.com Tue Dec 17 16:06:45 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Tue, 17 Dec 2013 18:06:45 -0600 Subject: "more specific method" w.r.t function return type Message-ID: The following code does not compile in jdk8b120 public class Tmp { void foo(Function function){} void foo(Consumer consumer){} void test() { foo( s->System::gc ); // javac: foo is ambiguous } } however I think that foo#1 should be more specific than foo#2, because Consumer returns void. Is this a javac bug or my understanding is incorrect? (If foo#1 is indeed the most specific method, the code still won't compile because gc() returns void) Zhong Yu From zhong.j.yu at gmail.com Tue Dec 17 16:16:15 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Tue, 17 Dec 2013 18:16:15 -0600 Subject: "more specific method" w.r.t function return type In-Reply-To: References: Message-ID: On Tue, Dec 17, 2013 at 6:06 PM, Zhong Yu wrote: > The following code does not compile in jdk8b120 > > public class Tmp > { > void foo(Function function){} > > void foo(Consumer consumer){} > > void test() > { > foo( s->System::gc ); // javac: foo is ambiguous sorry, what I meant was foo( s->System.gc() ); // javac: foo is ambiguous > } > } > > however I think that foo#1 should be more specific than foo#2, because > Consumer returns void. > > Is this a javac bug or my understanding is incorrect? > > (If foo#1 is indeed the most specific method, the code still won't > compile because gc() returns void) > > Zhong Yu From mohan.radhakrishnan at polarisFT.com Tue Dec 17 23:11:20 2013 From: mohan.radhakrishnan at polarisFT.com (mohan.radhakrishnan at polarisFT.com) Date: Wed, 18 Dec 2013 12:41:20 +0530 Subject: New overloading/overriding rules Message-ID: Hi, Do I have to look at any new JLS draft to understand the new rules ? Are there tests in the repository that I should look at ? Thanks, Mohan This e-Mail may contain proprietary and confidential information and is sent for the intended recipient(s) only. If by an addressing or transmission error this mail has been misdirected to you, you are requested to delete this mail immediately. You are also hereby notified that any use, any form of reproduction, dissemination, copying, disclosure, modification, distribution and/or publication of this e-mail message, contents or its attachment other than by its intended recipient/s is strictly prohibited. Visit us at http://www.polarisFT.com From tristan.yan at oracle.com Thu Dec 19 04:16:37 2013 From: tristan.yan at oracle.com (Tristan Yan) Date: Thu, 19 Dec 2013 20:16:37 +0800 Subject: Demo for Parallel Core Collection API In-Reply-To: <36B4EDF7-15DE-482C-AFB7-511A03BCDC92@oracle.com> References: <2CFB5F41-3C49-42A4-8C80-84F622C230E8@oracle.com> <36B4EDF7-15DE-482C-AFB7-511A03BCDC92@oracle.com> Message-ID: <52B2E3A5.3070807@oracle.com> Hi Paul And Everyone Sorry for getting back late. I took Paul's suggestion and have written other two demos which presents usage of parallel computation. One is using Monte-Carlo to calculate value of PI. Other is find a big prime by given length. Please review it. http://cr.openjdk.java.net/~tyan/sample/webrev.00/ There is another demo which present mandelbrot set was designed Alexander Kouznetsov has been already in reviewing. It's not my code review request. Thank you very much Tristan On 10/15/2013 11:20 PM, Paul Sandoz wrote: > > On Oct 15, 2013, at 4:35 PM, Tristan Yan > wrote: > >> Hi Paul >> you have comments "suggest that all streams are sequential. There is >> an inconsistency in the use and in some cases it is embedded in other >> stream usages." >> >> We do not really understand what exactly is meant, could you >> elaborate a little bit. Is it because we want to show ppl that we >> should use stream more than parallelStream? > > Going parallel is easy to do but not always the right thing to do. > Going parallel almost always requires more work with the expectation > that work will complete sooner than the work required to get the same > result sequentially. There are a number of factors that affect whether > parallel is faster than sequential. Two of those factors are N, the > size of the data, and Q the cost of processing an element in the > pipeline. N * Q is a simple cost model, the large that product the > better the chances of parallel speed up. N is easy to know, Q not so > easy but can often be intuitively guessed. (Note that there are other > factors such as the properties of the stream source and operations > that Brian and I talked about in our J1 presentation.) > > Demo code that just makes everything (or most streams) parallel is > sending out the wrong message. > > So i think the demo code should present two general things: > > 1) various stream functionality, as you have done; > > 2) parallel vs. sequential for various cases where it is known that > parallel is faster on a multi-core system. > > For 2) i strongly recommend measuring using jmh [1]. The data sets you > have may or may not be amenable to parallel processing, it's worth > investigating though. > > I have ideas for other parallel demos. One is creating probably primes > (now that SecureRandom is replaced with ThreadLocalRandom), creating a > probably prime that is a BigInteger is an relatively expensive > operation so Q should be high. Another more advanced demo is a > Monte-Carlo calculation of PI using SplittableRandom and a special > Spliterator, in this case N should be largish. But there are other > simpler demonstrations like sum of squares etc to get across that N > should be large. Another demo could be calculation of a mandelbrot > set, which is embarrassingly parallel over an area in the complex plane. > > So while you should try and fit some parallel vs. sequential execution > into your existing demos i do think it worth having a separate set of > demos that get across the the simple cost model of N * Q. So feel free > to use some of those ideas previously mentioned, i find those ideas > fun so perhaps others will too :-) > > Paul. > > [1] http://openjdk.java.net/projects/code-tools/jmh/ > > On Oct 15, 2013, at 4:37 PM, Tristan Yan > wrote: > >> Also there is one more question I missed >> >> You suggested ""ParallelCore" is not a very descriptive name. Suggest >> "streams"." >> 1) yes we agree this demo is not for parallel computation per se >> 2) but we do not have a clear demo for parallel computation >> 3) if we are to rename this, we need to develop another one, do you >> have a scenario for that? > From vicente.romero at oracle.com Thu Dec 19 04:47:45 2013 From: vicente.romero at oracle.com (Vicente-Arturo Romero-Zaldivar) Date: Thu, 19 Dec 2013 12:47:45 +0000 Subject: "more specific method" w.r.t function return type In-Reply-To: References: Message-ID: <52B2EAF1.9000605@oracle.com> Hi Zhong Yu, There is a bug report to track this issue, https://bugs.openjdk.java.net/browse/JDK-8029718. I have added this test case to it. Thanks, Vicente On 18/12/13 00:16, Zhong Yu wrote: > On Tue, Dec 17, 2013 at 6:06 PM, Zhong Yu wrote: >> The following code does not compile in jdk8b120 >> >> public class Tmp >> { >> void foo(Function function){} >> >> void foo(Consumer consumer){} >> >> void test() >> { >> foo( s->System::gc ); // javac: foo is ambiguous > sorry, what I meant was > > foo( s->System.gc() ); // javac: foo is ambiguous > >> } >> } >> >> however I think that foo#1 should be more specific than foo#2, because >> Consumer returns void. >> >> Is this a javac bug or my understanding is incorrect? >> >> (If foo#1 is indeed the most specific method, the code still won't >> compile because gc() returns void) >> >> Zhong Yu From vicente.romero at oracle.com Thu Dec 19 04:51:25 2013 From: vicente.romero at oracle.com (Vicente-Arturo Romero-Zaldivar) Date: Thu, 19 Dec 2013 12:51:25 +0000 Subject: New overloading/overriding rules In-Reply-To: References: Message-ID: <52B2EBCD.8090308@oracle.com> Hi Mohan, Last version of the spec can be found here: http://cr.openjdk.java.net/~dlsmith/jsr335-0.8.0/ Thanks, Vicente On 18/12/13 07:11, mohan.radhakrishnan at polarisFT.com wrote: > Hi, > Do I have to look at any new JLS draft to understand the new > rules ? Are there tests in the repository that I should look at ? > > Thanks, > Mohan > > > This e-Mail may contain proprietary and confidential information and is sent for the intended recipient(s) only. If by an addressing or transmission error this mail has been misdirected to you, you are requested to delete this mail immediately. You are also hereby notified that any use, any form of reproduction, dissemination, copying, disclosure, modification, distribution and/or publication of this e-mail message, contents or its attachment other than by its intended recipient/s is strictly prohibited. > > Visit us at http://www.polarisFT.com > From blackdrag at gmx.org Thu Dec 19 05:57:55 2013 From: blackdrag at gmx.org (Jochen Theodorou) Date: Thu, 19 Dec 2013 14:57:55 +0100 Subject: State of lambda forms stealing stack frames? Message-ID: <52B2FB63.7070002@gmx.org> Hi all, I originally did sent this to another list, so sorry if someone sees this again... but since I got no reaction at all... I wanted to ask what the currrent state of invokedynamic using additional stack frames through lambda forms is. Will there be a jdk1.8.0 without the consumption of stack frames or not? Will there be any at all? Will there be a fix for jdk7? I am seriously afraid of larger systems making use of invokedynamic a lot. To illustrate the gravity of the problem look at this: @groovy.transform.Memoized BigInteger fib(BigInteger x) { x<2?x:fib(x-1)+fib(x-2) } this code will produce some background code resposible for caching results and as such increasing the maximum x. The current implementation could be much better but I show this to compare our old way in Groovy using custom callsite caching with method generation at runtime to invokedynamic. So in the old version I can go up to fib(292) and won't stack overflow. With jdk7u25 and indy this is similiar, even though slightly less. But with later versions of jdk7 and jdk8 the maximum of the indy version is fib(45)... 5-6 times less. Since the results are cached it is really only like going down one side of a tree of calculations here, meaning if I need the double amount of stack frames, it will half x. Are there any real plans to improve the situation? bye Jochen -- Jochen "blackdrag" Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org From timo.kinnunen at gmail.com Thu Dec 19 14:02:55 2013 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Thu, 19 Dec 2013 22:02:55 +0000 Subject: =?utf-8?Q?Why_no_Streamable_extends_Iterable_=3F?= Message-ID: <52b36d8c.84010e0a.586a.574c@mx.google.com> A rhetoric question; I?ve already read the reasoning. Instead of trying to come up with such a Streamable to prove everyone wrong I?ve written some code which reads JarEntries from a JarFile and in doing so I ended up with Streamed. Streamed is a utility class which tries to handle resources that need to be closed but can throw exceptions without trivially ignoring them, without trivially wrapping them in new unchecked exceptions to be ignored later, but tackling the problem head-on. It turns out Streamed, full name ?Streamed implements AutoCloseable, Iterable isn?t as trivial as I?d have liked. I?m not sure it?s even correct.. Does this look reasonable?? ---- some exception-aware functional interfaces, a Supplier analogue ---- @FunctionalInterface public interface Make { R create() throws E;} ---- a Function analogue ---- @FunctionalInterface public interface Change { R evolve(T t) throws E; } ---- and a Consumer analogue ---- @FunctionalInterface public interface Use { void consume(T t) throws E; } ---- a wrapper exception that can escape :-( ---- public final class OnCloseException extends RuntimeException { final Exception original; final Class originalClass; public OnCloseException(E e, Class classOfE) { super(e); this.original = e; this.originalClass = classOfE; } public void rethrow(Class classOfE) throws E { if(originalClass == classOfE) { throw classOfE.cast(original); } throw this; } @Override public synchronized Throwable fillInStackTrace() { return this; } } ---- the utility class itself ---- import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Iterator; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Stream; public final class Streamed implements AutoCloseable, Iterable { private final A resource; public final Stream stream; private final Use unwrapper; private final Runnable closeHandler; private Streamed(Make reserver, Change, E> opener, Use wrapper, Use unwrapper) throws E { this.resource = reserver.create(); this.unwrapper = unwrapper; this.closeHandler = () -> wrapper.consume(resource); this.stream = opener.evolve(resource).onClose(closeHandler); } @Override public void close() throws E { unwrapper.consume(closeHandler); } @Override public Iterator iterator() { return stream.iterator(); } public static Streamed fromJar(Path file) throws IOException { Make reserver = () -> new JarFile(file.toFile()); Change, IOException> opener = (JarFile jar) -> jar.stream(); Use releaser = (JarFile jar1) -> jar1.close(); Use wrapper = wrapper(releaser); Use unwrapper = unwrapper(); return new Streamed<>(reserver, opener, wrapper, unwrapper); } public static Streamed, IOException> fromLinesInFile(Path file) throws IOException { Make, IOException> reserver = () -> Files.lines(file); Change, Stream, IOException> opener = (Stream stream) -> stream; Use, IOException> releaser = (Stream stream) -> stream.close(); Use, OnCloseException> wrapper = wrapper(releaser); Use unwrapper = unwrapper(); return new Streamed<>(reserver, opener, wrapper, unwrapper); } private static Use wrapper(Use releaser) { return (T jar) -> { try { releaser.consume(jar); } catch(IOException e) { throw new OnCloseException(e, IOException.class); } }; } private static Use unwrapper() { return (Runnable runnable) -> { try { runnable.run(); } catch(OnCloseException e) { e.rethrow(IOException.class); } }; } } ---- if you?ve read this far, some closing thoughts ---- I could ask for some help from the library to make all that better, but rather than that.. Here?s why I think there is no Streamable extends Iterable: it?s because Streams are designed wrong. They start by allocating a source of items of T, called Stream. That?s step 1. Then, the operations to be taken on the items T are defined, the result of this step is also called a Stream because it?s irredeemably intertwined with the source of the items. This is step 2. In step 3 the operations are committed and results, if any, observed. If instead step 1 and step 2 switched places then providing a Streamable interface should be trivial. Sent from Windows Mail ? From howard.lovatt at gmail.com Thu Dec 19 21:15:19 2013 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Fri, 20 Dec 2013 16:15:19 +1100 Subject: Multiple traversals Message-ID: Hi All, In trying out Streams I keep coming up against an issue where I want two outputs from a single Stream. I will use the example of finding both min and max values from a double stream because min and max exist for a stream. The min and max example implies finite streams, but sometimes you might want multiple things from an infinite stream. Various options come to mind: 1. Put everything in an array or List and then use two streams: double[] values = someStream...process...toArray(); double max = DoubleStream.of(values).max().orElse(Double.NEGATIVE_INFINITY); double min = DoubleStream.of(values).min().orElse(Double.POSITIVE_INFINITY); Not really very stream like and only works for finite streams. 2. Peek at the first traversal and create a 2nd stream: DoubleStream.Builder copy = DoubleStream.builder(); double max = someStream...process...peek(d -> copy.add(d)) .max().orElse(Double.NEGATIVE_INFINITY); double min = copy.build().min().orElse(Double.POSITIVE_INFINITY); It has got a side effect which is frowned upon and only works for sequential finite streams. 3. Write a custom collector (for the min/max example a collector already exists - but it is useful to see what you need to write for when a collector in't provided): private static class MinMax { double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; } private static Collector minMax = new Collector() { @Override public Supplier supplier() { return () -> new MinMax(); } @Override public BiConsumer accumulator() { return (accumulator, value) -> { if (value < accumulator.min) { accumulator.min = value; } else if (value > accumulator.max) { accumulator.max = value; } }; } @Override public BinaryOperator combiner() { return (first, second) -> { if (first.min < second.min) { second.min = first.min; } if (first.max > second.max) { second.max = first.max; } return second; }; } @Override public Function finisher() { return (result) -> result; } @Override public Set characteristics() { return EnumSet.allOf(Collector.Characteristics.class); } }; double[] values = someStream...process...boxed().collect(minMax); Which is considerably more work and it boxes primitives, but it is the solution I err towards. Comments/suggestions? Is there a better approach? -- Howard. From brian.goetz at oracle.com Fri Dec 20 08:37:38 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 20 Dec 2013 11:37:38 -0500 Subject: Multiple traversals In-Reply-To: References: Message-ID: <52B47252.7060008@oracle.com> This is a common question (another form of it was asked just yesterday, albeit far less politely). The thing to realize is: streams don't store data; they are abstractions for pipelines of computation on sequences of data, whose source might be "repeatable" (like an immutable collection), or might be read off of /dev/urandom. The obvious comparison is "tee" on Unix. But tee entails buffering and flow control; we'd rather avoid imposing these issues on Streams users if we can. Further, any intuition derived from "tee" is likely assume a sequential processing model, since Unix pipes don't operate in parallel. The Stream API has been designed to minimize the semantic gap between sequential and parallel traversals, and each sequential-centric operation we add makes it harder for all users. If you have a repeatable source (collection or deterministic generator), you're done. You can capture that as follows: Supplier supplier = () -> IntStream.range(0, 1000); and pull new streams as needed: supplier.get().filter(...).map(...)... If you don't have a repeatable source, or the computational steps you apply to a repeatable source are expensive enough that you don't want to repeat them, you need to buffer. And ideally you want to buffer in such a way that whatever intermediate representation you pick is structured in such a way that it is no less splittable than the original source, otherwise you can still lose compared to just re-traversing the original source in parallel. There's lots of ways to buffer, but this is outside of what Stream does -- by design. It would have introduced a lot of complexity on the common case to support the uncommon case. On 12/20/2013 12:15 AM, Howard Lovatt wrote: > Hi All, > > In trying out Streams I keep coming up against an issue where I want two > outputs from a single Stream. I will use the example of finding both min > and max values from a double stream because min and max exist for a stream. > The min and max example implies finite streams, but sometimes you might > want multiple things from an infinite stream. > > Various options come to mind: > > 1. Put everything in an array or List and then use two streams: > > double[] values = someStream...process...toArray(); > double max = > DoubleStream.of(values).max().orElse(Double.NEGATIVE_INFINITY); > double min = > DoubleStream.of(values).min().orElse(Double.POSITIVE_INFINITY); > > Not really very stream like and only works for finite streams. > > 2. Peek at the first traversal and create a 2nd stream: > > DoubleStream.Builder copy = DoubleStream.builder(); > double max = someStream...process...peek(d -> copy.add(d)) > .max().orElse(Double.NEGATIVE_INFINITY); > double min = copy.build().min().orElse(Double.POSITIVE_INFINITY); > > It has got a side effect which is frowned upon and only works for > sequential finite streams. > > 3. Write a custom collector (for the min/max example a collector already > exists - but it is useful to see what you need to write for when a > collector in't provided): > > private static class MinMax { > double min = Double.POSITIVE_INFINITY; > double max = Double.NEGATIVE_INFINITY; > } > > private static Collector minMax = new > Collector() { > > @Override > public Supplier supplier() { > return () -> new MinMax(); > } > > @Override > public BiConsumer accumulator() { > return (accumulator, value) -> { > if (value < accumulator.min) { > accumulator.min = value; > } > else if (value > accumulator.max) { > accumulator.max = value; > } > }; > } > > @Override > public BinaryOperator combiner() { > return (first, second) -> { > if (first.min < second.min) { > second.min = first.min; > } > if (first.max > second.max) { > second.max = first.max; > } > return second; > }; > } > > @Override > public Function finisher() { > return (result) -> result; > } > > @Override > public Set characteristics() { > return EnumSet.allOf(Collector.Characteristics.class); > } > > }; > > double[] values = someStream...process...boxed().collect(minMax); > > Which is considerably more work and it boxes primitives, but it is the > solution I err towards. > > Comments/suggestions? Is there a better approach? > > -- Howard. > From paul.sandoz at oracle.com Fri Dec 20 09:25:00 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 20 Dec 2013 18:25:00 +0100 Subject: Demo for Parallel Core Collection API In-Reply-To: <52B2E3A5.3070807@oracle.com> References: <2CFB5F41-3C49-42A4-8C80-84F622C230E8@oracle.com> <36B4EDF7-15DE-482C-AFB7-511A03BCDC92@oracle.com> <52B2E3A5.3070807@oracle.com> Message-ID: <301A54AB-CD30-4763-8370-540C3B6D1914@oracle.com> Hi Tristan, Thanks, I need to look at this in more detail, but here are some quick comments. - recommend you try and avoid using limit with parallel ops, for example the Pi example cam be reformulated as: long M = LongStream.range(0, N).parallel().filter(sr -> { double x = ThreadLocalRandom.current().nextDouble(-1, 1); double y = ThreadLocalRandom.current().nextDouble(-1, 1); return x * x + y * y < R * R; // Don't use need to use sqrt }).count(); double pi = (M / N) * 4.0; the Primes example could be reformulated as: LongStream.range(0, limit).parallel().map(/odd values/).filter(RandomPrimeNumber::isPrime).findAny(); you don't need to declare unordered() since findAny implicitly makes the stream unordered by definition. The key message here is range has better decomposition characteristics than generate or iterate. More later, probably after the break, Paul. On Dec 19, 2013, at 1:16 PM, Tristan Yan wrote: > Hi Paul And Everyone > Sorry for getting back late. > I took Paul's suggestion and have written other two demos which presents usage of parallel computation. One is using Monte-Carlo to calculate value of PI. Other is find a big prime by given length. Please review it. > http://cr.openjdk.java.net/~tyan/sample/webrev.00/ > There is another demo which present mandelbrot set was designed Alexander Kouznetsov has been already in reviewing. It's not my code review request. > Thank you very much > Tristan From howard.lovatt at gmail.com Fri Dec 20 12:25:18 2013 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Sat, 21 Dec 2013 07:25:18 +1100 Subject: Multiple traversals In-Reply-To: <52B47252.7060008@oracle.com> References: <52B47252.7060008@oracle.com> Message-ID: Thanks for the reply. A BiParallelStream class styled after ExecutorService could be written, e.g.: BiParallelStream minMax = someStream...process...toBiParallelStream(); minMax.submit1().min().orElse(Double.POSITIVE_INFINITY); // Process in background minMax.submit2().max().orElse(Double.NEGATIVE_INFINITY); // Process in background double min = minMax.get1(); // Wait until process 1 has finished double max = minMax.get2(); // Wait until process 2 has finished The buffering in BiParallelStream would be interesting! If allowing the original stream, someStream...process..., to be parallel and the two tributaries, min and max, to also be parallel proved to be too difficult buffering wise there would still be value in supporting BiParallelStream because the tributaries would be executed in parallel. This concept of parallelism across streams, rather than along streams, would be an interesting addition to the stream API. That would be considerable work, maybe Java 9 :) -- Howard. Sent from my iPad > On 21 Dec 2013, at 3:37 am, Brian Goetz wrote: > > This is a common question (another form of it was asked just yesterday, albeit far less politely). The thing to realize is: streams don't store data; they are abstractions for pipelines of computation on sequences of data, whose source might be "repeatable" (like an immutable collection), or might be read off of /dev/urandom. > > The obvious comparison is "tee" on Unix. But tee entails buffering and flow control; we'd rather avoid imposing these issues on Streams users if we can. Further, any intuition derived from "tee" is likely assume a sequential processing model, since Unix pipes don't operate in parallel. The Stream API has been designed to minimize the semantic gap between sequential and parallel traversals, and each sequential-centric operation we add makes it harder for all users. > > If you have a repeatable source (collection or deterministic generator), you're done. You can capture that as follows: > > Supplier supplier = () -> IntStream.range(0, 1000); > > and pull new streams as needed: > > supplier.get().filter(...).map(...)... > > If you don't have a repeatable source, or the computational steps you apply to a repeatable source are expensive enough that you don't want to repeat them, you need to buffer. And ideally you want to buffer in such a way that whatever intermediate representation you pick is structured in such a way that it is no less splittable than the original source, otherwise you can still lose compared to just re-traversing the original source in parallel. > > There's lots of ways to buffer, but this is outside of what Stream does -- by design. It would have introduced a lot of complexity on the common case to support the uncommon case. > >> On 12/20/2013 12:15 AM, Howard Lovatt wrote: >> Hi All, >> >> In trying out Streams I keep coming up against an issue where I want two >> outputs from a single Stream. I will use the example of finding both min >> and max values from a double stream because min and max exist for a stream. >> The min and max example implies finite streams, but sometimes you might >> want multiple things from an infinite stream. >> >> Various options come to mind: >> >> 1. Put everything in an array or List and then use two streams: >> >> double[] values = someStream...process...toArray(); >> double max = >> DoubleStream.of(values).max().orElse(Double.NEGATIVE_INFINITY); >> double min = >> DoubleStream.of(values).min().orElse(Double.POSITIVE_INFINITY); >> >> Not really very stream like and only works for finite streams. >> >> 2. Peek at the first traversal and create a 2nd stream: >> >> DoubleStream.Builder copy = DoubleStream.builder(); >> double max = someStream...process...peek(d -> copy.add(d)) >> .max().orElse(Double.NEGATIVE_INFINITY); >> double min = copy.build().min().orElse(Double.POSITIVE_INFINITY); >> >> It has got a side effect which is frowned upon and only works for >> sequential finite streams. >> >> 3. Write a custom collector (for the min/max example a collector already >> exists - but it is useful to see what you need to write for when a >> collector in't provided): >> >> private static class MinMax { >> double min = Double.POSITIVE_INFINITY; >> double max = Double.NEGATIVE_INFINITY; >> } >> >> private static Collector minMax = new >> Collector() { >> >> @Override >> public Supplier supplier() { >> return () -> new MinMax(); >> } >> >> @Override >> public BiConsumer accumulator() { >> return (accumulator, value) -> { >> if (value < accumulator.min) { >> accumulator.min = value; >> } >> else if (value > accumulator.max) { >> accumulator.max = value; >> } >> }; >> } >> >> @Override >> public BinaryOperator combiner() { >> return (first, second) -> { >> if (first.min < second.min) { >> second.min = first.min; >> } >> if (first.max > second.max) { >> second.max = first.max; >> } >> return second; >> }; >> } >> >> @Override >> public Function finisher() { >> return (result) -> result; >> } >> >> @Override >> public Set characteristics() { >> return EnumSet.allOf(Collector.Characteristics.class); >> } >> >> }; >> >> double[] values = someStream...process...boxed().collect(minMax); >> >> Which is considerably more work and it boxes primitives, but it is the >> solution I err towards. >> >> Comments/suggestions? Is there a better approach? >> >> -- Howard. >> From brian.goetz at oracle.com Fri Dec 20 12:36:35 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 20 Dec 2013 15:36:35 -0500 Subject: Multiple traversals In-Reply-To: References: <52B47252.7060008@oracle.com> Message-ID: <52B4AA53.3050300@oracle.com> If the goal is simply to compute min/max at the same time (or any two reductions), then Collector already gives you an easy way to do that: IntSummaryStatistics ss = list.blah(...).barg(...) .collect(summarizingInt()); // or IntStream.summaryStatistics(); This computes sum, min, max, count in one pass. Of course, you can adapt this pattern to compute anything you want. The code is trivial: public static Collector summarizingInt(ToIntFunction mapper) { return new CollectorImpl( IntSummaryStatistics::new, (r, t) -> r.accept(mapper.applyAsInt(t)), (l, r) -> { l.combine(r); return l; }, CH_ID); } where public class IntSummaryStatistics implements IntConsumer { private long count; private long sum; private int min = Integer.MAX_VALUE; private int max = Integer.MIN_VALUE; /** * Construct an empty instance with zero count, zero sum, * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero * average. */ public IntSummaryStatistics() { } /** * Records a new value into the summary information * * @param value the input value */ @Override public void accept(int value) { ++count; sum += value; min = Math.min(min, value); max = Math.max(max, value); } /** * Combines the state of another {@code IntSummaryStatistics} into this one. * * @param other another {@code IntSummaryStatistics} * @throws NullPointerException if {@code other} is null */ public void combine(IntSummaryStatistics other) { count += other.count; sum += other.sum; min = Math.min(min, other.min); max = Math.max(max, other.max); } } From zhong.j.yu at gmail.com Fri Dec 20 14:31:12 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Fri, 20 Dec 2013 16:31:12 -0600 Subject: Reference a blank final field from lambda body Message-ID: The following code does not compile (jdk8b120), where a blank final field is referenced from a lambda body by its simple name public class Tmp { final int i; public Tmp(int i) { this.i = i; } void r() { int k = i; // [1] } final Runnable r = ()-> { int k = i; // [2] javac error: `i` not initialized }; } which is unfortunate, because this pattern of usage is quite innocent; people are probably going to do it a lot. There's no apparently reason why [1] is ok but [2] is not. Anyways, the workaround seems to be to prefix the simple name with "this." final Runnable r = ()-> { int k = this.i; }; It compiles in javac, *however*, I cannot take javac's word for it at this point [1]. Someone please confirm that this workaround is correct and is intended by the spec. Or if it is not, what other workarounds are available. Zhong Yu [1] Why javac seems unreliable on this matter - it also compiles this code public class Tmp { final int i; public Tmp(int i) { this.i = this.i; // it compiles! bug or feature? } } From howard.lovatt at gmail.com Fri Dec 20 17:07:05 2013 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Sat, 21 Dec 2013 12:07:05 +1100 Subject: Multiple traversals In-Reply-To: <52B4AA53.3050300@oracle.com> References: <52B47252.7060008@oracle.com> <52B4AA53.3050300@oracle.com> Message-ID: Thanks for the reply. I was aware that summary stats existed, min and max were just an example. Your implementation of the collector is better than mine, option 3 in original, so I will adopt your style from now on thanks. As I said in the original email I tend towards writing collectors, however they do force boxing (no Collector.ofDouble) and they are quite a lot of code to write. Thanks again for your reply, -- Howard. Sent from my iPad > On 21 Dec 2013, at 7:36 am, Brian Goetz wrote: > > If the goal is simply to compute min/max at the same time (or any two reductions), then Collector already gives you an easy way to do that: > > IntSummaryStatistics ss = list.blah(...).barg(...) > .collect(summarizingInt()); > // or IntStream.summaryStatistics(); > > This computes sum, min, max, count in one pass. Of course, you can adapt this pattern to compute anything you want. The code is trivial: > > public static > Collector summarizingInt(ToIntFunction mapper) { > return new CollectorImpl( > IntSummaryStatistics::new, > (r, t) -> r.accept(mapper.applyAsInt(t)), > (l, r) -> { l.combine(r); return l; }, CH_ID); > } > > where > > public class IntSummaryStatistics implements IntConsumer { > private long count; > private long sum; > private int min = Integer.MAX_VALUE; > private int max = Integer.MIN_VALUE; > > /** > * Construct an empty instance with zero count, zero sum, > * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero > * average. > */ > public IntSummaryStatistics() { } > > /** > * Records a new value into the summary information > * > * @param value the input value > */ > @Override > public void accept(int value) { > ++count; > sum += value; > min = Math.min(min, value); > max = Math.max(max, value); > } > > /** > * Combines the state of another {@code IntSummaryStatistics} into this one. > * > * @param other another {@code IntSummaryStatistics} > * @throws NullPointerException if {@code other} is null > */ > public void combine(IntSummaryStatistics other) { > count += other.count; > sum += other.sum; > min = Math.min(min, other.min); > max = Math.max(max, other.max); > } > } From brian.goetz at oracle.com Fri Dec 20 18:06:06 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 20 Dec 2013 21:06:06 -0500 Subject: Multiple traversals In-Reply-To: References: <52B47252.7060008@oracle.com> <52B4AA53.3050300@oracle.com> Message-ID: <52B4F78E.1050708@oracle.com> > As I said in the original email I tend towards writing collectors, > however they do force boxing (no Collector.ofDouble) and they are > quite a lot of code to write. If you start out with primitives, that's true. But if you are projecting objects to primitives, the only boxing is for the final answer; everything else happens in the primitive domain. See, for example, summarizingInt(T -> int); no matter how many elements or how many splits, there's only the one box operation for the final result. From mcnepp02 at googlemail.com Sun Dec 22 03:41:03 2013 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Sun, 22 Dec 2013 12:41:03 +0100 Subject: javac 8 with target level 7 In-Reply-To: <02e801cefb46$77e37180$67aa5480$@jetbrains.com> References: <02e801cefb46$77e37180$67aa5480$@jetbrains.com> Message-ID: <52B6CFCF.1070103@googlemail.com> Hi, I think the option "-target 7" mandates that the generated *classfiles* be compatible with a Java-7 VM. The option "-source 7" would mandate that the compiler accept all sources that were valid Java-7 sources. However, there is no option that would force a newer compiler to *reject* the same set of sources that was rejected in an earlier version. (The reason is, of course, that making previously invalid sources compilable certainly does not break any promises of compatibility.) Does that make sense? > Hi, > > The code compiles with java 8 (b. 119) target 7, but fails to compile with > javac 7 target 7: > > import java.util.Comparator; > > class GenericMethod { > > Comparator getComparator() { > return null; > } > > void useComparator(Comparator comparator) { > } > > void test() { > useComparator(this.getComparator()); > } > } > > Was that intended? > > Thanks, > Anna > > From marcos_antonio_ps at hotmail.com Tue Dec 24 06:48:31 2013 From: marcos_antonio_ps at hotmail.com (Marcos Antonio) Date: Tue, 24 Dec 2013 17:48:31 +0300 Subject: Is this code convertible to a lambda style? Message-ID: I'm really having trouble trying to convert this piece of code to lambda style, which makes me think if it is even possible. Property getParent() { for (PropertyDescriptor parent : getMetadataReader().getPropertyDescriptors()) { if (parent.getType() == PropertyType.ENTITY) { MetadataReader metadataReader = DataFactory.getInstance().getMetadataReader(parent.getReaderMethod().getReturnType()); for (CollectionDescriptor collection : metadataReader.getCollectionDescriptors()) { if (collection.isChildAssociation(parent)) { return parent.convertToProperty() } } } } return null; } I think this code seems very simple but in trying to convert it I'm not able to keep the reference to the parent to later methods in the stream pipeline. Any help? Thank you. Marcos From marcos_antonio_ps at hotmail.com Tue Dec 24 07:21:08 2013 From: marcos_antonio_ps at hotmail.com (Marcos Antonio) Date: Tue, 24 Dec 2013 18:21:08 +0300 Subject: Is this code convertible to a lambda style? In-Reply-To: References: Message-ID: I'd been trying a little more and maybe this is the solution I was looking for (I haven't tested it yet). return getMetadataReader().getPropertyDescriptors().stream(). filter(d -> d.getType() == PropertyType.ENTITY). filter(d -> DataFactory.getInstance().getMetadataReader(d.getReaderMethod().getReturnType()). getCollectionDescriptors().stream(). anyMatch(c -> c.isChildAssociation(d))). findFirst(). map(d -> d.convertToProperty()). orElse(null); Does it look right? Thank you. Marcos ---------------------------------------- > From: marcos_antonio_ps at hotmail.com > To: lambda-dev at openjdk.java.net > Subject: Is this code convertible to a lambda style? > Date: Tue, 24 Dec 2013 17:48:31 +0300 > > I'm really having trouble trying to convert this piece of code to lambda style, which makes me think if it is even possible. > > Property getParent() > { > for (PropertyDescriptor parent : getMetadataReader().getPropertyDescriptors()) > { > if (parent.getType() == PropertyType.ENTITY) > { > MetadataReader metadataReader = > DataFactory.getInstance().getMetadataReader(parent.getReaderMethod().getReturnType()); > for (CollectionDescriptor collection : metadataReader.getCollectionDescriptors()) > { > if (collection.isChildAssociation(parent)) > { > return parent.convertToProperty() > } > } > } > } > return null; > } > > I think this code seems very simple but in trying to convert it I'm not able to keep the reference to the parent to later methods in the stream pipeline. > > Any help? > > Thank you. > > Marcos > From jan.beernink at gmail.com Tue Dec 24 14:56:49 2013 From: jan.beernink at gmail.com (Jan Beernink) Date: Tue, 24 Dec 2013 23:56:49 +0100 Subject: DoubleStream.count() overflow bug Message-ID: <247F6F66-BCBF-4FEE-9EBA-3A168184FFD6@gmail.com> Hi, I believe I may have discovered a small bug in the DoubleStream.count() operation. On JDK 8 b120, the following code will return -2147483648: DoubleStream.generate(() -> 0.0) .limit(2147483648L) .count() I had a look at the code of java.util.stream.DoublePipeline.count() and noticed that, although the return type is long, each element in the stream is (indirectly) mapped to an int of value 1 and then these ints are summed using IntStream.sum(). IntPipeline, LongPipeline and ReferencePipeline all count the number of elements in a similar way, but use longs instead of ints and correctly return 2147483648. Regards, Jan Beernink From howard.lovatt at gmail.com Fri Dec 27 16:56:59 2013 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Sat, 28 Dec 2013 11:56:59 +1100 Subject: Is this code convertible to a lambda style? In-Reply-To: References: Message-ID: Hi Marcos, I would make some small changes: private static boolean hasChildAssociation(PropertyDescriptor d) { return DataFactory.getInstance().getMetadataReader(d.getReaderMethod(). getReturnType()).getCollectionDescriptors().stream() .anyMatch(c -> c.isChildAssociation(d))); } private static Property convertToPropertyOrNull(Optional d) { if (d.isPresent()) { return d.get().convertToProperty() } return null; } return getMetadataReader().getPropertyDescriptors().stream() .unordered() // Assuming that order is not important .parallel() // Assuming that there are a lot of Properties .filter(d -> d.getType() == PropertyType.ENTITY) .filter(ThisClass::hasChildAssociation) .findAny() // Potentially faster .map(ThisClass::convertToPropertyOrNull); Cheers, -- Howard. On 25 December 2013 02:21, Marcos Antonio wrote: > I'd been trying a little more and maybe this is the solution I was looking > for (I haven't tested it yet). > > return getMetadataReader().getPropertyDescriptors().stream(). > filter(d -> d.getType() == PropertyType.ENTITY). > filter(d -> > DataFactory.getInstance().getMetadataReader(d.getReaderMethod().getReturnType()). > getCollectionDescriptors().stream(). > anyMatch(c -> c.isChildAssociation(d))). > findFirst(). > map(d -> d.convertToProperty()). > orElse(null); > > Does it look right? > > Thank you. > > Marcos > > ---------------------------------------- > > From: marcos_antonio_ps at hotmail.com > > To: lambda-dev at openjdk.java.net > > Subject: Is this code convertible to a lambda style? > > Date: Tue, 24 Dec 2013 17:48:31 +0300 > > > > I'm really having trouble trying to convert this piece of code to lambda > style, which makes me think if it is even possible. > > > > Property getParent() > > { > > for (PropertyDescriptor parent : > getMetadataReader().getPropertyDescriptors()) > > { > > if (parent.getType() == PropertyType.ENTITY) > > { > > MetadataReader metadataReader = > > > DataFactory.getInstance().getMetadataReader(parent.getReaderMethod().getReturnType()); > > for (CollectionDescriptor collection : > metadataReader.getCollectionDescriptors()) > > { > > if (collection.isChildAssociation(parent)) > > { > > return parent.convertToProperty() > > } > > } > > } > > } > > return null; > > } > > > > I think this code seems very simple but in trying to convert it I'm not > able to keep the reference to the parent to later methods in the stream > pipeline. > > > > Any help? > > > > Thank you. > > > > Marcos > > > > -- -- Howard. From marcos_antonio_ps at hotmail.com Sat Dec 28 06:37:09 2013 From: marcos_antonio_ps at hotmail.com (Marcos Antonio) Date: Sat, 28 Dec 2013 17:37:09 +0300 Subject: Is this code convertible to a lambda style? In-Reply-To: References: , , Message-ID: Hello, Howard. Thanks for the suggestions to improve the code. I really liked the increased abstraction by the introduction of the static hasChildAssociation() method. That really made the code more clear and readable. The tip about the findAny() method was also useful, I will change it, although I have my doubts if the introduction of a convertToPropertyOrNull() method is needed. Thank you once again. Marcos ________________________________ > Date: Sat, 28 Dec 2013 11:56:59 +1100 > Subject: Re: Is this code convertible to a lambda style? > From: howard.lovatt at gmail.com > To: marcos_antonio_ps at hotmail.com > CC: lambda-dev at openjdk.java.net > > Hi Marcos, > > I would make some small changes: > > private static boolean hasChildAssociation(PropertyDescriptor d) { > return > DataFactory.getInstance().getMetadataReader(d.getReaderMethod().getReturnType()).getCollectionDescriptors().stream() > .anyMatch(c -> c.isChildAssociation(d))); > } > > private static Property > convertToPropertyOrNull(Optional d) { > if (d.isPresent()) { > return d.get().convertToProperty() > } > return null; > } > > return getMetadataReader().getPropertyDescriptors().stream() > .unordered() // Assuming that order is not important > .parallel() // Assuming that there are a lot of Properties > .filter(d -> d.getType() == PropertyType.ENTITY) > .filter(ThisClass::hasChildAssociation) > .findAny() // Potentially faster > .map(ThisClass::convertToPropertyOrNull); > > Cheers, > > -- Howard. From samir at noodlesandwich.com Sat Dec 28 07:32:21 2013 From: samir at noodlesandwich.com (Samir Talwar) Date: Sat, 28 Dec 2013 15:32:21 +0000 Subject: Is this code convertible to a lambda style? In-Reply-To: References: Message-ID: That `convertToPropertyOrNull` method won't be useful, and in fact isn't possible to use like that. You would use it like this: return convertToPropertyOrNull(getMetadataReader().blahblahblah().findAny()); I actually think this is harder to read because it combines the nested function style with the method pipeline style. You're better off sticking to the original for that part, IMO. Howard is totally right to show you how to extract `hasChildAssociation`. In general, complexity with lambda-ified code should follow the same rules as complexity in regular code: when in doubt, extract it out. I'd argue that the real problem here, though, is too much Spring; some proper OO code following the tell-don't-ask principle will help you clean this up far more than lambdas can, and a mix of both really does work wonders. One more thing: you could change `d -> d.convertToProperty()` to `PropertyDescriptor::convertToProperty`. IntelliJ will suggest this refactoring for you if you load up the code there. ? Samir. On Sat, Dec 28, 2013 at 2:37 PM, Marcos Antonio < marcos_antonio_ps at hotmail.com> wrote: > Hello, Howard. Thanks for the suggestions to improve the code. > > I really liked the increased abstraction by the introduction of the static > hasChildAssociation() method. That really made the code more clear and > readable. The tip about the findAny() method was also useful, I will change > it, although I have my doubts if the introduction of a > convertToPropertyOrNull() method is needed. > > Thank you once again. > > Marcos > > ________________________________ > > Date: Sat, 28 Dec 2013 11:56:59 +1100 > > Subject: Re: Is this code convertible to a lambda style? > > From: howard.lovatt at gmail.com > > To: marcos_antonio_ps at hotmail.com > > CC: lambda-dev at openjdk.java.net > > > > Hi Marcos, > > > > I would make some small changes: > > > > private static boolean hasChildAssociation(PropertyDescriptor d) { > > return > > > DataFactory.getInstance().getMetadataReader(d.getReaderMethod().getReturnType()).getCollectionDescriptors().stream() > > .anyMatch(c -> c.isChildAssociation(d))); > > } > > > > private static Property > > convertToPropertyOrNull(Optional d) { > > if (d.isPresent()) { > > return d.get().convertToProperty() > > } > > return null; > > } > > > > return getMetadataReader().getPropertyDescriptors().stream() > > .unordered() // Assuming that order is not important > > .parallel() // Assuming that there are a lot of Properties > > .filter(d -> d.getType() == PropertyType.ENTITY) > > .filter(ThisClass::hasChildAssociation) > > .findAny() // Potentially faster > > .map(ThisClass::convertToPropertyOrNull); > > > > Cheers, > > > > -- Howard. > > From marcos_antonio_ps at hotmail.com Sat Dec 28 08:00:12 2013 From: marcos_antonio_ps at hotmail.com (Marcos Antonio) Date: Sat, 28 Dec 2013 19:00:12 +0300 Subject: Is this code convertible to a lambda style? In-Reply-To: References: , , , , Message-ID: Hello, Samir. ________________________________ > Date: Sat, 28 Dec 2013 15:32:21 +0000 > Subject: Re: Is this code convertible to a lambda style? > From: samir at noodlesandwich.com > To: marcos_antonio_ps at hotmail.com > CC: lambda-dev at openjdk.java.net > > That `convertToPropertyOrNull` method won't be useful, and in fact > isn't possible to use like that. You would use it like this: > > return > convertToPropertyOrNull(getMetadataReader().blahblahblah().findAny()); > > I actually think this is harder to read because it combines the nested > function style with the method pipeline style. You're better off > sticking to the original for that part, IMO. I agree with that. > > Howard is totally right to show you how to extract > `hasChildAssociation`. In general, complexity with lambda-ified code > should follow the same rules as complexity in regular code: when in > doubt, extract it out. I'd argue that the real problem here, though, is > too much Spring; some proper OO code following the tell-don't-ask > principle will help you clean this up far more than lambdas can, and a > mix of both really does work wonders. Also agree. > One more thing: you could change `d -> d.convertToProperty()` to > `PropertyDescriptor::convertToProperty`. IntelliJ will suggest this > refactoring for you if you load up the code there. > > ? Samir. Maybe at this point you can call me a little paranoid, but I like a code that looks a bit more symmetric (maybe just for aesthetic reasons). This is how my code is now: return getMetadataReader().getPropertyDescriptors().stream(). filter(d -> d.getType() == PropertyType.ENTITY). filter(d -> hasChildAssociation(d)). findFirst(). map(d -> d.convertToProperty()). orElse(null); If a change to this: return getMetadataReader().getPropertyDescriptors().stream(). filter(d -> d.getType() == PropertyType.ENTITY). filter(this::hasChildAssociation). findFirst(). map(PropertyDescriptor::convertToProperty). orElse(null); Some lambda functions will have explicit parameters and others not. I don't like the final result visually. I think it's better to stick to one style when it is possible. Also, regarding PropertyDescriptor::convertToProperty I don't know if it is a good idea in general to atach explicit type names (PropertyDescriptor in this case) to method calls when you have alternative. Thank you for the suggestions. Marcos > > > On Sat, Dec 28, 2013 at 2:37 PM, Marcos Antonio > > > wrote: > Hello, Howard. Thanks for the suggestions to improve the code. > > I really liked the increased abstraction by the introduction of the > static hasChildAssociation() method. That really made the code more > clear and readable. The tip about the findAny() method was also useful, > I will change it, although I have my doubts if the introduction of a > convertToPropertyOrNull() method is needed. > > Thank you once again. > > Marcos > > ________________________________ >> Date: Sat, 28 Dec 2013 11:56:59 +1100 >> Subject: Re: Is this code convertible to a lambda style? >> From: howard.lovatt at gmail.com >> To: marcos_antonio_ps at hotmail.com >> CC: lambda-dev at openjdk.java.net >> >> Hi Marcos, >> >> I would make some small changes: >> >> private static boolean hasChildAssociation(PropertyDescriptor d) { >> return >> > DataFactory.getInstance().getMetadataReader(d.getReaderMethod().getReturnType()).getCollectionDescriptors().stream() >> .anyMatch(c -> c.isChildAssociation(d))); >> } >> >> private static Property >> convertToPropertyOrNull(Optional d) { >> if (d.isPresent()) { >> return d.get().convertToProperty() >> } >> return null; >> } >> >> return getMetadataReader().getPropertyDescriptors().stream() >> .unordered() // Assuming that order is not important >> .parallel() // Assuming that there are a lot of Properties >> .filter(d -> d.getType() == PropertyType.ENTITY) >> .filter(ThisClass::hasChildAssociation) >> .findAny() // Potentially faster >> .map(ThisClass::convertToPropertyOrNull); >> >> Cheers, >> >> -- Howard. > > From brian.goetz at oracle.com Sat Dec 28 08:26:36 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 28 Dec 2013 11:26:36 -0500 Subject: Is this code convertible to a lambda style? In-Reply-To: References: , , , , Message-ID: <52BEFBBC.1060307@oracle.com> > Some lambda functions will have explicit parameters and others not. I > don't like the final result visually. I think it's better to stick to > one style when it is possible. I would correct this to "when it is beneficial". Consistency is not the ultimate goal, or an end unto itself. Readability is far more important. (Yes, gratuitous inconsistency inhibits readability, but so does gratuitous consistency.) Unfortunately improving readability is not simply a matter of maximizing consistency. Sometimes adding explicit parameter types makes it more readable; sometimes adding explicit types makes it less readable. Same is true with replacing lambdas with method refs. (Overall my experience is that static/unbound method refs are almost always more readable than their equivalent lambdas, but bound methods refs sometimes are and sometimes are not, and call for judgment.) From mike.duigou at oracle.com Sat Dec 28 16:10:55 2013 From: mike.duigou at oracle.com (mike.duigou at oracle.com) Date: Sun, 29 Dec 2013 00:10:55 +0000 Subject: hg: lambda/lambda/jdk: update combo-tests aurora target to reduce heap size per Sonali Goel Message-ID: <20131229001217.84D2062F79@hg.openjdk.java.net> Changeset: 2b0c2fc213d6 Author: mduigou Date: 2013-12-27 09:51 -0800 URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/2b0c2fc213d6 update combo-tests aurora target to reduce heap size per Sonali Goel ! combo-tests/build.xml From mcnepp02 at googlemail.com Sun Dec 29 03:04:29 2013 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Sun, 29 Dec 2013 12:04:29 +0100 Subject: Is this code convertible to a lambda style? In-Reply-To: References: , , , , Message-ID: <52C001BD.8060601@googlemail.com> Am 28.12.2013 17:00, schrieb Marcos Antonio: > > Maybe at this point you can call me a little paranoid, but I like a code that looks a bit more symmetric (maybe just for aesthetic reasons). This is how my code is now: > > return getMetadataReader().getPropertyDescriptors().stream(). > filter(d -> d.getType() == PropertyType.ENTITY). > filter(d -> hasChildAssociation(d)). > findFirst(). > map(d -> d.convertToProperty()). > orElse(null); > > Maybe it would benefit (at least in terms of readability, but also performance-wise) from combining the two filters like this: return getMetadataReader().getPropertyDescriptors().stream(). filter(d -> d.getType() == PropertyType.ENTITY && hasChildAssociation(d)). findFirst(). map(d -> d.convertToProperty()). orElse(null); From pavel.shackih at gmail.com Sun Dec 29 03:34:18 2013 From: pavel.shackih at gmail.com (=?KOI8-R?B?8MHXxcwg+8HDy8nI?=) Date: Sun, 29 Dec 2013 14:34:18 +0300 Subject: Is this code convertible to a lambda style? In-Reply-To: <52C001BD.8060601@googlemail.com> References: <52C001BD.8060601@googlemail.com> Message-ID: In terms of perfomance first variant can better because under hood stream implementation know about 2 predicates and can optimise this (for example parallelize) on the fly. Anyway I believe it is hard to say about perfomance benefits in this case. Also I think in terms of readability two filters looks more elegant and clean but it is a matter of taste :) 2013/12/29 Gernot Neppert > Am 28.12.2013 17:00, schrieb Marcos Antonio: > > > > Maybe at this point you can call me a little paranoid, but I like a code > that looks a bit more symmetric (maybe just for aesthetic reasons). This is > how my code is now: > > > > return getMetadataReader().getPropertyDescriptors().stream(). > > filter(d -> d.getType() == PropertyType.ENTITY). > > filter(d -> hasChildAssociation(d)). > > findFirst(). > > map(d -> d.convertToProperty()). > > orElse(null); > > > > > > Maybe it would benefit (at least in terms of readability, but also > performance-wise) from combining the two filters like this: > > return getMetadataReader().getPropertyDescriptors().stream(). > filter(d -> d.getType() == PropertyType.ENTITY && > hasChildAssociation(d)). > findFirst(). > map(d -> d.convertToProperty()). > orElse(null); > > > > -- Pavel From marcos_antonio_ps at hotmail.com Sun Dec 29 07:13:17 2013 From: marcos_antonio_ps at hotmail.com (Marcos Antonio) Date: Sun, 29 Dec 2013 18:13:17 +0300 Subject: Is this code convertible to a lambda style? In-Reply-To: References: , , , , , , <52C001BD.8060601@googlemail.com>, Message-ID: I agree with you. In terms of readibility two filters are better and, as you pointed out, it doesn't hurt performance. Also, as I work with 80 columns in my editor, two filters fit better; with one filter I would have to continue the lambda in the next line. Marcos ________________________________ > Date: Sun, 29 Dec 2013 14:34:18 +0300 > Subject: Re: Is this code convertible to a lambda style? > From: pavel.shackih at gmail.com > To: mcnepp02 at googlemail.com > CC: marcos_antonio_ps at hotmail.com; lambda-dev at openjdk.java.net > > In terms of perfomance first variant can better because under hood > stream implementation know about 2 predicates and can optimise this > (for example parallelize) on the fly. Anyway I believe it is hard to > say about perfomance benefits in this case. Also I think in terms of > readability two filters looks more elegant and clean but it is a matter > of taste :) > > > 2013/12/29 Gernot Neppert > > > Am 28.12.2013 17:00, schrieb Marcos Antonio: >> >> Maybe at this point you can call me a little paranoid, but I like a > code that looks a bit more symmetric (maybe just for aesthetic > reasons). This is how my code is now: >> >> return getMetadataReader().getPropertyDescriptors().stream(). >> filter(d -> d.getType() == PropertyType.ENTITY). >> filter(d -> hasChildAssociation(d)). >> findFirst(). >> map(d -> d.convertToProperty()). >> orElse(null); >> >> > > Maybe it would benefit (at least in terms of readability, but also > performance-wise) from combining the two filters like this: > > return getMetadataReader().getPropertyDescriptors().stream(). > filter(d -> d.getType() == PropertyType.ENTITY && > hasChildAssociation(d)). > findFirst(). > map(d -> d.convertToProperty()). > orElse(null); > > > > > > > -- > Pavel