From mike.duigou at oracle.com Thu Oct 3 15:02:16 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Thu, 3 Oct 2013 15:02:16 -0700 Subject: Renaming Stream.subStream(int) to Stream.skip(int) Message-ID: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> Hello all; A bit of feedback from the recent JavaOne hands-on-lab is that people have trouble finding the correct API to skip entries. The Stream.limit(count) operation and Stream.subStream(from,to) are easily found but new users fail to find the Stream.subStream(from) operation. One suggestion has been to rename the Stream.subStream(from) to Stream.skip(count). The docs for Stream.subStream() also be updated to say something similar to "source.stream().subStream(from,to) produces the same set of elements in the same encounter order as source.stream().skip(from).limit(to-from)". I will go ahead with a renaming patch on Monday unless there objections. Any counter proposals should be *very* narrow in scope--we're past the point were we can do redesign. Mike From forax at univ-mlv.fr Sat Oct 5 04:49:48 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 05 Oct 2013 13:49:48 +0200 Subject: Lambda proxy class doesn't carry generics information Message-ID: <524FFCDC.9090006@univ-mlv.fr> David Gageot [1] talk to me about this issue after my presentation at ParisJUG and I totally forgot to report it. He said that he is using a framework that uses the generic information inserted by javac (and available by reflection) so he can not retrofit its code that uses inner classes to use lambdas because the generated lambda proxy doesn't carry this information. Here is a small test to see the issue: public static void main(String[] args) { Comparator c = new Comparator() { @Override public int compare(String s1, String s2) { return s1.compareTo(s2); } }; Comparator c2 = (s1, s2) -> s1.compareTo(s2); System.out.println(Arrays.toString(c.getClass().getGenericInterfaces())); // [java.util.Comparator] System.out.println(Arrays.toString(c2.getClass().getGenericInterfaces())); // [interface java.util.Comparator] } I said to him that it was not a bug, but it's less clear to me now :( cheers, R?mi From brian.goetz at oracle.com Sat Oct 5 08:25:34 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 5 Oct 2013 16:25:34 +0100 Subject: Lambda proxy class doesn't carry generics information In-Reply-To: <524FFCDC.9090006@univ-mlv.fr> References: <524FFCDC.9090006@univ-mlv.fr> Message-ID: In the first example, there exists a statically defined class. In the second, there is not. Currently we are generating one class per lambda capture site, but we view that as a temporary implementation. So while we *could* "fix" this with the current translation strategy, it would just break when we tried to go to, say, the one-class-per-SAM strategy anyway. (I am sure the strategy he is using fails anyway when you are more than one hop away from the instantiation site. For example, if you create a combinator for "compose comparators"; the inner class in compose(c1, c2) will not know that its a Comparator since compose will be a generic method anyway.) On Oct 5, 2013, at 12:49 PM, Remi Forax wrote: > David Gageot [1] talk to me about this issue after my presentation at ParisJUG and > I totally forgot to report it. > He said that he is using a framework that uses the generic information inserted by javac > (and available by reflection) so he can not retrofit its code that uses inner classes to > use lambdas because the generated lambda proxy doesn't carry this information. > > Here is a small test to see the issue: > public static void main(String[] args) { > Comparator c = new Comparator() { > @Override > public int compare(String s1, String s2) { > return s1.compareTo(s2); > } > }; > Comparator c2 = (s1, s2) -> s1.compareTo(s2); > > System.out.println(Arrays.toString(c.getClass().getGenericInterfaces())); // [java.util.Comparator] > System.out.println(Arrays.toString(c2.getClass().getGenericInterfaces())); // [interface java.util.Comparator] > } > > I said to him that it was not a bug, but it's less clear to me now :( > > cheers, > R?mi > From david.holmes at oracle.com Sat Oct 5 22:48:16 2013 From: david.holmes at oracle.com (David Holmes) Date: Sun, 06 Oct 2013 15:48:16 +1000 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> Message-ID: <5250F9A0.3040407@oracle.com> On 4/10/2013 8:02 AM, Mike Duigou wrote: > Hello all; > > A bit of feedback from the recent JavaOne hands-on-lab is that people have trouble finding the correct API to skip entries. The Stream.limit(count) operation and Stream.subStream(from,to) are easily found but new users fail to find the Stream.subStream(from) operation. One suggestion has been to rename the Stream.subStream(from) to Stream.skip(count). > > The docs for Stream.subStream() also be updated to say something similar to "source.stream().subStream(from,to) produces the same set of elements in the same encounter order as source.stream().skip(from).limit(to-from)". My suspicion is that people are taking their I/O stream knowledge and trying to map that to general Streams, hence looking for a "skip" operation. I can't convince myself that this is worthwhile changing given that it really produces a substream. Plus the I/O usage can be somewhat different as you often decide what to skip based on what has already been read, but with streams that won't be the case. David > I will go ahead with a renaming patch on Monday unless there objections. Any counter proposals should be *very* narrow in scope--we're past the point were we can do redesign. > > Mike > From joe.bowbeer at gmail.com Sun Oct 6 00:05:57 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sun, 6 Oct 2013 00:05:57 -0700 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: <5250F9A0.3040407@oracle.com> References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> Message-ID: More arguments not to rename: 1. The InputStream.skip(n) that Java programmers are familiar with is an eager consumer, where subStream(n) is a lazy view, more like subList. 2. Shouldn't both subStream-like methods have similar names? On Sat, Oct 5, 2013 at 10:48 PM, David Holmes wrote: > On 4/10/2013 8:02 AM, Mike Duigou wrote: > >> Hello all; >> >> A bit of feedback from the recent JavaOne hands-on-lab is that people >> have trouble finding the correct API to skip entries. The >> Stream.limit(count) operation and Stream.subStream(from,to) are easily >> found but new users fail to find the Stream.subStream(from) operation. One >> suggestion has been to rename the Stream.subStream(from) to >> Stream.skip(count). >> >> The docs for Stream.subStream() also be updated to say something similar >> to "source.stream().subStream(**from,to) produces the same set of >> elements in the same encounter order as source.stream().skip(from).** >> limit(to-from)". >> > > My suspicion is that people are taking their I/O stream knowledge and > trying to map that to general Streams, hence looking for a "skip" > operation. I can't convince myself that this is worthwhile changing given > that it really produces a substream. Plus the I/O usage can be somewhat > different as you often decide what to skip based on what has already been > read, but with streams that won't be the case. > > David > > > I will go ahead with a renaming patch on Monday unless there objections. >> Any counter proposals should be *very* narrow in scope--we're past the >> point were we can do redesign. >> >> Mike >> >> From brian.goetz at oracle.com Sun Oct 6 00:48:33 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 6 Oct 2013 08:48:33 +0100 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> Message-ID: I think users naturally view the opposite of limit as skip. This is a constant point of user confusion. Users are not thinking substream. Sent from my iPhone On Oct 6, 2013, at 8:05 AM, Joe Bowbeer wrote: > More arguments not to rename: > > 1. The InputStream.skip(n) that Java programmers are familiar with is an eager consumer, where subStream(n) is a lazy view, more like subList. > > 2. Shouldn't both subStream-like methods have similar names? > > > > On Sat, Oct 5, 2013 at 10:48 PM, David Holmes wrote: >> On 4/10/2013 8:02 AM, Mike Duigou wrote: >>> Hello all; >>> >>> A bit of feedback from the recent JavaOne hands-on-lab is that people have trouble finding the correct API to skip entries. The Stream.limit(count) operation and Stream.subStream(from,to) are easily found but new users fail to find the Stream.subStream(from) operation. One suggestion has been to rename the Stream.subStream(from) to Stream.skip(count). >>> >>> The docs for Stream.subStream() also be updated to say something similar to "source.stream().subStream(from,to) produces the same set of elements in the same encounter order as source.stream().skip(from).limit(to-from)". >> >> My suspicion is that people are taking their I/O stream knowledge and trying to map that to general Streams, hence looking for a "skip" operation. I can't convince myself that this is worthwhile changing given that it really produces a substream. Plus the I/O usage can be somewhat different as you often decide what to skip based on what has already been read, but with streams that won't be the case. >> >> David >> >> >>> I will go ahead with a renaming patch on Monday unless there objections. Any counter proposals should be *very* narrow in scope--we're past the point were we can do redesign. >>> >>> Mike > From brian.goetz at oracle.com Sun Oct 6 02:39:35 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 6 Oct 2013 10:39:35 +0100 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> Message-ID: <6955B2E1-6BAE-4452-AA99-0D528D4F5014@oracle.com> Btw it used to be skip, and no one complained then they couldn't find the method. Only after renaming to substream did the confusion start. Sent from my iPhone On Oct 6, 2013, at 8:05 AM, Joe Bowbeer wrote: > More arguments not to rename: > > 1. The InputStream.skip(n) that Java programmers are familiar with is an eager consumer, where subStream(n) is a lazy view, more like subList. > > 2. Shouldn't both subStream-like methods have similar names? > > > > On Sat, Oct 5, 2013 at 10:48 PM, David Holmes wrote: >> On 4/10/2013 8:02 AM, Mike Duigou wrote: >>> Hello all; >>> >>> A bit of feedback from the recent JavaOne hands-on-lab is that people have trouble finding the correct API to skip entries. The Stream.limit(count) operation and Stream.subStream(from,to) are easily found but new users fail to find the Stream.subStream(from) operation. One suggestion has been to rename the Stream.subStream(from) to Stream.skip(count). >>> >>> The docs for Stream.subStream() also be updated to say something similar to "source.stream().subStream(from,to) produces the same set of elements in the same encounter order as source.stream().skip(from).limit(to-from)". >> >> My suspicion is that people are taking their I/O stream knowledge and trying to map that to general Streams, hence looking for a "skip" operation. I can't convince myself that this is worthwhile changing given that it really produces a substream. Plus the I/O usage can be somewhat different as you often decide what to skip based on what has already been read, but with streams that won't be the case. >> >> David >> >> >>> I will go ahead with a renaming patch on Monday unless there objections. Any counter proposals should be *very* narrow in scope--we're past the point were we can do redesign. >>> >>> Mike > From david.holmes at oracle.com Sun Oct 6 18:24:01 2013 From: david.holmes at oracle.com (David Holmes) Date: Mon, 07 Oct 2013 11:24:01 +1000 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: <6955B2E1-6BAE-4452-AA99-0D528D4F5014@oracle.com> References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> <6955B2E1-6BAE-4452-AA99-0D528D4F5014@oracle.com> Message-ID: <52520D31.9090307@oracle.com> On 6/10/2013 7:39 PM, Brian Goetz wrote: > Btw it used to be skip, and no one complained then they couldn't find > the method. Only after renaming to substream did the confusion start. I wonder how much of the HOL feedback came from people who had previously seen it this way? What were all the arguments for renaming to substream? Have they somehow been invalidated or are we just deciding that this HOL feedback puts more weight on the old position? David > Sent from my iPhone > > On Oct 6, 2013, at 8:05 AM, Joe Bowbeer > wrote: > >> More arguments not to rename: >> >> 1. The InputStream.skip(n) that Java programmers are familiar with is >> an eager consumer, where subStream(n) is a lazy view, more like subList. >> >> 2. Shouldn't both subStream-like methods have similar names? >> >> >> >> On Sat, Oct 5, 2013 at 10:48 PM, David Holmes > > wrote: >> >> On 4/10/2013 8:02 AM, Mike Duigou wrote: >> >> Hello all; >> >> A bit of feedback from the recent JavaOne hands-on-lab is that >> people have trouble finding the correct API to skip entries. >> The Stream.limit(count) operation and >> Stream.subStream(from,to) are easily found but new users fail >> to find the Stream.subStream(from) operation. One suggestion >> has been to rename the Stream.subStream(from) to >> Stream.skip(count). >> >> The docs for Stream.subStream() also be updated to say >> something similar to "source.stream().subStream(__from,to) >> produces the same set of elements in the same encounter order >> as source.stream().skip(from).__limit(to-from)". >> >> >> My suspicion is that people are taking their I/O stream knowledge >> and trying to map that to general Streams, hence looking for a >> "skip" operation. I can't convince myself that this is worthwhile >> changing given that it really produces a substream. Plus the I/O >> usage can be somewhat different as you often decide what to skip >> based on what has already been read, but with streams that won't >> be the case. >> >> David >> >> >> I will go ahead with a renaming patch on Monday unless there >> objections. Any counter proposals should be *very* narrow in >> scope--we're past the point were we can do redesign. >> >> Mike >> >> From paul.sandoz at oracle.com Mon Oct 7 01:10:41 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 7 Oct 2013 10:10:41 +0200 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: <6955B2E1-6BAE-4452-AA99-0D528D4F5014@oracle.com> References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> <6955B2E1-6BAE-4452-AA99-0D528D4F5014@oracle.com> Message-ID: I am also revalidating my own position because i forgot that the single argument variant of substream existed and thought it was skip too :-) cue alarm bells. It's very common in other APIs to have a duality for such lazy operations; often called take and drop, in addition to predicate receiving takeWhile and dropWhile. Intuitively i think developers will look for such a duality (as observed in the HoLs). I don't perceive skip as being any less lazy than limit. Nor do i perceive limit/skip being predominately associated with I/O-backed streams. Furthermore, if/when we add predicate receiving methods it's gonna be awkward. I would argue that substream(int, int) is actually the outlier (even though fundamentally limit/substream all point to the same implementation). FWIW if we want to ever consider these methods as more general concepts slice(int, int) might be a better name, thus not binding explicitly to stream. Paul. On Oct 6, 2013, at 11:39 AM, Brian Goetz wrote: > Btw it used to be skip, and no one complained then they couldn't find the method. Only after renaming to substream did the confusion start. > > Sent from my iPhone > > On Oct 6, 2013, at 8:05 AM, Joe Bowbeer wrote: > >> More arguments not to rename: >> >> 1. The InputStream.skip(n) that Java programmers are familiar with is an eager consumer, where subStream(n) is a lazy view, more like subList. >> >> 2. Shouldn't both subStream-like methods have similar names? >> >> >> >> On Sat, Oct 5, 2013 at 10:48 PM, David Holmes wrote: >>> On 4/10/2013 8:02 AM, Mike Duigou wrote: >>>> Hello all; >>>> >>>> A bit of feedback from the recent JavaOne hands-on-lab is that people have trouble finding the correct API to skip entries. The Stream.limit(count) operation and Stream.subStream(from,to) are easily found but new users fail to find the Stream.subStream(from) operation. One suggestion has been to rename the Stream.subStream(from) to Stream.skip(count). >>>> >>>> The docs for Stream.subStream() also be updated to say something similar to "source.stream().subStream(from,to) produces the same set of elements in the same encounter order as source.stream().skip(from).limit(to-from)". >>> >>> My suspicion is that people are taking their I/O stream knowledge and trying to map that to general Streams, hence looking for a "skip" operation. I can't convince myself that this is worthwhile changing given that it really produces a substream. Plus the I/O usage can be somewhat different as you often decide what to skip based on what has already been read, but with streams that won't be the case. >>> >>> David >>> >>> >>>> I will go ahead with a renaming patch on Monday unless there objections. Any counter proposals should be *very* narrow in scope--we're past the point were we can do redesign. >>>> >>>> Mike >> From brian.goetz at oracle.com Mon Oct 7 02:13:40 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 07 Oct 2013 05:13:40 -0400 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: <52520D31.9090307@oracle.com> References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> <6955B2E1-6BAE-4452-AA99-0D528D4F5014@oracle.com> <52520D31.9090307@oracle.com> Message-ID: <52527B44.8000801@oracle.com> >> Btw it used to be skip, and no one complained then they couldn't find >> the method. Only after renaming to substream did the confusion start. > > I wonder how much of the HOL feedback came from people who had > previously seen it this way? > I think zero. I think skip is whats used in all the other libraries of this sort (e.g., RxJava). > What were all the arguments for renaming to substream? Have they somehow > been invalidated or are we just deciding that this HOL feedback puts > more weight on the old position? It was a random shift whose entire motivation was "Hmm, more like String, let's try that." I think it was just a bad experiment. From brian.goetz at oracle.com Mon Oct 7 09:38:09 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 07 Oct 2013 12:38:09 -0400 Subject: forEachOrdered semantics Message-ID: <5252E371.5020403@oracle.com> Recall that Stream.forEach(action) may perform the action for different elements in whatever order, in whatever thread, with whatever concurrency it chooses, and forEachOrdered(action) promises to perform the action in encounter order. Working through the specs, I think users are expecting a tail-to-head sequencing of actions, and that processing element n happens-before processing element n+1? The real question is: what should happen when you do a .forEachOrdered() on an unordered stream. My first thought was that this was plain old forEach. But, I think this is not what the user will expect; I believe they will be reasonably expecting that the action is performed in some order, one element at a time. So I'm inclined to spec that this operates in *some* order, which is the encounter order if one exists, and that there is a HB edge between successive actions? From tim at peierls.net Mon Oct 7 09:51:53 2013 From: tim at peierls.net (Tim Peierls) Date: Mon, 7 Oct 2013 12:51:53 -0400 Subject: forEachOrdered semantics In-Reply-To: <5252E371.5020403@oracle.com> References: <5252E371.5020403@oracle.com> Message-ID: If so, doesn't the name "forEachOrdered" become a bit off-target? Doc readers are sure to confuse the ordered-ness of the stream with the "-Ordered" modifier in the method name. Something like "forEachSequentially" would be more on-target. --tim On Mon, Oct 7, 2013 at 12:38 PM, Brian Goetz wrote: > Recall that Stream.forEach(action) may perform the action for different > elements in whatever order, in whatever thread, with whatever concurrency > it chooses, and forEachOrdered(action) promises to perform the action in > encounter order. > > Working through the specs, I think users are expecting a tail-to-head > sequencing of actions, and that processing element n happens-before > processing element n+1? > > The real question is: what should happen when you do a .forEachOrdered() > on an unordered stream. My first thought was that this was plain old > forEach. But, I think this is not what the user will expect; I believe > they will be reasonably expecting that the action is performed in some > order, one element at a time. > > So I'm inclined to spec that this operates in *some* order, which is the > encounter order if one exists, and that there is a HB edge between > successive actions? > > From brian.goetz at oracle.com Mon Oct 7 10:04:34 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 07 Oct 2013 13:04:34 -0400 Subject: forEachOrdered semantics In-Reply-To: References: <5252E371.5020403@oracle.com> Message-ID: <5252E9A2.9010308@oracle.com> I think a bit off-target, but I'm not sure it is too far? The history here is that we used to support arbitrary transitions between seq-ness and par-ness: list.parallel() .filter(...) .map(...) .sequential() .forEach(...); We then realized that (a) this ability added lots of complexity and (b) the only use case we could think of was "generate stuff in parallel and forEach it sequentially." So we created forEachOrdered for that purpose. (I think it might once have been called "forEachInOrder".) So you are right that the intent of forEachOrdered did include some sequentiality to it. So, question is, is the current naming and proposed semantics reasonable? On 10/7/2013 12:51 PM, Tim Peierls wrote: > If so, doesn't the name "forEachOrdered" become a bit off-target? Doc > readers are sure to confuse the ordered-ness of the stream with the > "-Ordered" modifier in the method name. Something like > "forEachSequentially" would be more on-target. > > --tim > > > On Mon, Oct 7, 2013 at 12:38 PM, Brian Goetz > wrote: > > Recall that Stream.forEach(action) may perform the action for > different elements in whatever order, in whatever thread, with > whatever concurrency it chooses, and forEachOrdered(action) promises > to perform the action in encounter order. > > Working through the specs, I think users are expecting a > tail-to-head sequencing of actions, and that processing element n > happens-before processing element n+1? > > The real question is: what should happen when you do a > .forEachOrdered() on an unordered stream. My first thought was that > this was plain old forEach. But, I think this is not what the user > will expect; I believe they will be reasonably expecting that the > action is performed in some order, one element at a time. > > So I'm inclined to spec that this operates in *some* order, which is > the encounter order if one exists, and that there is a HB edge > between successive actions? > > From tim at peierls.net Mon Oct 7 10:16:24 2013 From: tim at peierls.net (Tim Peierls) Date: Mon, 7 Oct 2013 13:16:24 -0400 Subject: forEachOrdered semantics In-Reply-To: <5252E9A2.9010308@oracle.com> References: <5252E371.5020403@oracle.com> <5252E9A2.9010308@oracle.com> Message-ID: On Mon, Oct 7, 2013 at 1:04 PM, Brian Goetz wrote: > So you are right that the intent of forEachOrdered did include some > sequentiality to it. So, question is, is the current naming and proposed > semantics reasonable? I think it's just confusing enough -- unreasonable enough -- to re-open the naming question rather than trying to spec around it. --tim From mike.duigou at oracle.com Mon Oct 7 13:20:26 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Mon, 7 Oct 2013 13:20:26 -0700 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> Message-ID: <1034C56D-FAC9-4FA2-B6E7-D6F711CF6D1F@oracle.com> On Oct 6 2013, at 00:05 , Joe Bowbeer wrote: > More arguments not to rename: > > 1. The InputStream.skip(n) that Java programmers are familiar with is an eager consumer, where subStream(n) is a lazy view, more like subList. Any consequences of this we should be highlighting in the documentation? > 2. Shouldn't both subStream-like methods have similar names? What to do with limit() then? The difficulty is that people see limit() and look for skip(). Unfortunately we can't make another overload for subStream() to provide limit() due to arity Mike > > > > On Sat, Oct 5, 2013 at 10:48 PM, David Holmes wrote: > On 4/10/2013 8:02 AM, Mike Duigou wrote: > Hello all; > > A bit of feedback from the recent JavaOne hands-on-lab is that people have trouble finding the correct API to skip entries. The Stream.limit(count) operation and Stream.subStream(from,to) are easily found but new users fail to find the Stream.subStream(from) operation. One suggestion has been to rename the Stream.subStream(from) to Stream.skip(count). > > The docs for Stream.subStream() also be updated to say something similar to "source.stream().subStream(from,to) produces the same set of elements in the same encounter order as source.stream().skip(from).limit(to-from)". > > My suspicion is that people are taking their I/O stream knowledge and trying to map that to general Streams, hence looking for a "skip" operation. I can't convince myself that this is worthwhile changing given that it really produces a substream. Plus the I/O usage can be somewhat different as you often decide what to skip based on what has already been read, but with streams that won't be the case. > > David > > > I will go ahead with a renaming patch on Monday unless there objections. Any counter proposals should be *very* narrow in scope--we're past the point were we can do redesign. > > Mike > > From brian.goetz at oracle.com Mon Oct 7 13:31:39 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 07 Oct 2013 16:31:39 -0400 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: <1034C56D-FAC9-4FA2-B6E7-D6F711CF6D1F@oracle.com> References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> <1034C56D-FAC9-4FA2-B6E7-D6F711CF6D1F@oracle.com> Message-ID: <52531A2B.1010601@oracle.com> Yeah, I agree with Paul that substream is the oddball and that the attempt to rename skip() to substream() was a failure. If we have limit+skip, should the remaining substream(n,k) be renamed back to slice()? WHich is what it was originally called. On 10/7/2013 4:20 PM, Mike Duigou wrote: > > On Oct 6 2013, at 00:05 , Joe Bowbeer wrote: > >> More arguments not to rename: >> >> 1. The InputStream.skip(n) that Java programmers are familiar with is >> an eager consumer, where subStream(n) is a lazy view, more like subList. > > Any consequences of this we should be highlighting in the documentation? > >> 2. Shouldn't both subStream-like methods have similar names? > > What to do with limit() then? The difficulty is that people see limit() > and look for skip(). Unfortunately we can't make another overload for > subStream() to provide limit() due to arity > > Mike > > >> >> >> >> On Sat, Oct 5, 2013 at 10:48 PM, David Holmes > > wrote: >> >> On 4/10/2013 8:02 AM, Mike Duigou wrote: >> >> Hello all; >> >> A bit of feedback from the recent JavaOne hands-on-lab is that >> people have trouble finding the correct API to skip entries. >> The Stream.limit(count) operation and >> Stream.subStream(from,to) are easily found but new users fail >> to find the Stream.subStream(from) operation. One suggestion >> has been to rename the Stream.subStream(from) to >> Stream.skip(count). >> >> The docs for Stream.subStream() also be updated to say >> something similar to "source.stream().subStream(__from,to) >> produces the same set of elements in the same encounter order >> as source.stream().skip(from).__limit(to-from)". >> >> >> My suspicion is that people are taking their I/O stream knowledge >> and trying to map that to general Streams, hence looking for a >> "skip" operation. I can't convince myself that this is worthwhile >> changing given that it really produces a substream. Plus the I/O >> usage can be somewhat different as you often decide what to skip >> based on what has already been read, but with streams that won't >> be the case. >> >> David >> >> >> I will go ahead with a renaming patch on Monday unless there >> objections. Any counter proposals should be *very* narrow in >> scope--we're past the point were we can do redesign. >> >> Mike >> >> > From spullara at gmail.com Mon Oct 7 13:47:20 2013 From: spullara at gmail.com (Sam Pullara) Date: Mon, 7 Oct 2013 13:47:20 -0700 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: <52531A2B.1010601@oracle.com> References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> <1034C56D-FAC9-4FA2-B6E7-D6F711CF6D1F@oracle.com> <52531A2B.1010601@oracle.com> Message-ID: <48A6035E-51B5-405B-9E01-17EBED2B452C@gmail.com> Agree 100%. Sam On Oct 7, 2013, at 1:31 PM, Brian Goetz wrote: > Yeah, I agree with Paul that substream is the oddball and that the attempt to rename skip() to substream() was a failure. > > If we have limit+skip, should the remaining substream(n,k) be renamed back to slice()? WHich is what it was originally called. > > On 10/7/2013 4:20 PM, Mike Duigou wrote: >> >> On Oct 6 2013, at 00:05 , Joe Bowbeer wrote: >> >>> More arguments not to rename: >>> >>> 1. The InputStream.skip(n) that Java programmers are familiar with is >>> an eager consumer, where subStream(n) is a lazy view, more like subList. >> >> Any consequences of this we should be highlighting in the documentation? >> >>> 2. Shouldn't both subStream-like methods have similar names? >> >> What to do with limit() then? The difficulty is that people see limit() >> and look for skip(). Unfortunately we can't make another overload for >> subStream() to provide limit() due to arity >> >> Mike >> >> >>> >>> >>> >>> On Sat, Oct 5, 2013 at 10:48 PM, David Holmes >> > wrote: >>> >>> On 4/10/2013 8:02 AM, Mike Duigou wrote: >>> >>> Hello all; >>> >>> A bit of feedback from the recent JavaOne hands-on-lab is that >>> people have trouble finding the correct API to skip entries. >>> The Stream.limit(count) operation and >>> Stream.subStream(from,to) are easily found but new users fail >>> to find the Stream.subStream(from) operation. One suggestion >>> has been to rename the Stream.subStream(from) to >>> Stream.skip(count). >>> >>> The docs for Stream.subStream() also be updated to say >>> something similar to "source.stream().subStream(__from,to) >>> produces the same set of elements in the same encounter order >>> as source.stream().skip(from).__limit(to-from)". >>> >>> >>> My suspicion is that people are taking their I/O stream knowledge >>> and trying to map that to general Streams, hence looking for a >>> "skip" operation. I can't convince myself that this is worthwhile >>> changing given that it really produces a substream. Plus the I/O >>> usage can be somewhat different as you often decide what to skip >>> based on what has already been read, but with streams that won't >>> be the case. >>> >>> David >>> >>> >>> I will go ahead with a renaming patch on Monday unless there >>> objections. Any counter proposals should be *very* narrow in >>> scope--we're past the point were we can do redesign. >>> >>> Mike >>> >>> >> From joe.bowbeer at gmail.com Mon Oct 7 14:54:24 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Mon, 7 Oct 2013 14:54:24 -0700 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: <48A6035E-51B5-405B-9E01-17EBED2B452C@gmail.com> References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> <1034C56D-FAC9-4FA2-B6E7-D6F711CF6D1F@oracle.com> <52531A2B.1010601@oracle.com> <48A6035E-51B5-405B-9E01-17EBED2B452C@gmail.com> Message-ID: slice is OK with me. It partners well with skip and limit. On Mon, Oct 7, 2013 at 1:47 PM, Sam Pullara wrote: > Agree 100%. > > Sam > > On Oct 7, 2013, at 1:31 PM, Brian Goetz wrote: > > > Yeah, I agree with Paul that substream is the oddball and that the > attempt to rename skip() to substream() was a failure. > > > > If we have limit+skip, should the remaining substream(n,k) be renamed > back to slice()? WHich is what it was originally called. > > > > On 10/7/2013 4:20 PM, Mike Duigou wrote: > >> > >> On Oct 6 2013, at 00:05 , Joe Bowbeer wrote: > >> > >>> More arguments not to rename: > >>> > >>> 1. The InputStream.skip(n) that Java programmers are familiar with is > >>> an eager consumer, where subStream(n) is a lazy view, more like > subList. > >> > >> Any consequences of this we should be highlighting in the documentation? > >> > >>> 2. Shouldn't both subStream-like methods have similar names? > >> > >> What to do with limit() then? The difficulty is that people see limit() > >> and look for skip(). Unfortunately we can't make another overload for > >> subStream() to provide limit() due to arity > >> > >> Mike > >> > >> > >>> > >>> > >>> > >>> On Sat, Oct 5, 2013 at 10:48 PM, David Holmes >>> > wrote: > >>> > >>> On 4/10/2013 8:02 AM, Mike Duigou wrote: > >>> > >>> Hello all; > >>> > >>> A bit of feedback from the recent JavaOne hands-on-lab is that > >>> people have trouble finding the correct API to skip entries. > >>> The Stream.limit(count) operation and > >>> Stream.subStream(from,to) are easily found but new users fail > >>> to find the Stream.subStream(from) operation. One suggestion > >>> has been to rename the Stream.subStream(from) to > >>> Stream.skip(count). > >>> > >>> The docs for Stream.subStream() also be updated to say > >>> something similar to "source.stream().subStream(__from,to) > >>> produces the same set of elements in the same encounter order > >>> as source.stream().skip(from).__limit(to-from)". > >>> > >>> > >>> My suspicion is that people are taking their I/O stream knowledge > >>> and trying to map that to general Streams, hence looking for a > >>> "skip" operation. I can't convince myself that this is worthwhile > >>> changing given that it really produces a substream. Plus the I/O > >>> usage can be somewhat different as you often decide what to skip > >>> based on what has already been read, but with streams that won't > >>> be the case. > >>> > >>> David > >>> > >>> > >>> I will go ahead with a renaming patch on Monday unless there > >>> objections. Any counter proposals should be *very* narrow in > >>> scope--we're past the point were we can do redesign. > >>> > >>> Mike > >>> > >>> > >> > > From mike.duigou at oracle.com Mon Oct 7 15:04:47 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Mon, 7 Oct 2013 15:04:47 -0700 Subject: Renaming Stream.subStream(int) to Stream.skip(int) In-Reply-To: References: <62B704B9-2C81-4010-8A58-1477A904A854@oracle.com> <5250F9A0.3040407@oracle.com> <1034C56D-FAC9-4FA2-B6E7-D6F711CF6D1F@oracle.com> <52531A2B.1010601@oracle.com> <48A6035E-51B5-405B-9E01-17EBED2B452C@gmail.com> Message-ID: <51FD54A7-2780-4725-85D4-19337479D689@oracle.com> I am going to go ahead with slice/skip/limit. Thanks to all for the feedback. Mike On Oct 7 2013, at 14:54 , Joe Bowbeer wrote: > slice is OK with me. It partners well with skip and limit. > > > On Mon, Oct 7, 2013 at 1:47 PM, Sam Pullara wrote: > Agree 100%. > > Sam > > On Oct 7, 2013, at 1:31 PM, Brian Goetz wrote: > > > Yeah, I agree with Paul that substream is the oddball and that the attempt to rename skip() to substream() was a failure. > > > > If we have limit+skip, should the remaining substream(n,k) be renamed back to slice()? WHich is what it was originally called. > > > > On 10/7/2013 4:20 PM, Mike Duigou wrote: > >> > >> On Oct 6 2013, at 00:05 , Joe Bowbeer wrote: > >> > >>> More arguments not to rename: > >>> > >>> 1. The InputStream.skip(n) that Java programmers are familiar with is > >>> an eager consumer, where subStream(n) is a lazy view, more like subList. > >> > >> Any consequences of this we should be highlighting in the documentation? > >> > >>> 2. Shouldn't both subStream-like methods have similar names? > >> > >> What to do with limit() then? The difficulty is that people see limit() > >> and look for skip(). Unfortunately we can't make another overload for > >> subStream() to provide limit() due to arity > >> > >> Mike > >> > >> > >>> > >>> > >>> > >>> On Sat, Oct 5, 2013 at 10:48 PM, David Holmes >>> > wrote: > >>> > >>> On 4/10/2013 8:02 AM, Mike Duigou wrote: > >>> > >>> Hello all; > >>> > >>> A bit of feedback from the recent JavaOne hands-on-lab is that > >>> people have trouble finding the correct API to skip entries. > >>> The Stream.limit(count) operation and > >>> Stream.subStream(from,to) are easily found but new users fail > >>> to find the Stream.subStream(from) operation. One suggestion > >>> has been to rename the Stream.subStream(from) to > >>> Stream.skip(count). > >>> > >>> The docs for Stream.subStream() also be updated to say > >>> something similar to "source.stream().subStream(__from,to) > >>> produces the same set of elements in the same encounter order > >>> as source.stream().skip(from).__limit(to-from)". > >>> > >>> > >>> My suspicion is that people are taking their I/O stream knowledge > >>> and trying to map that to general Streams, hence looking for a > >>> "skip" operation. I can't convince myself that this is worthwhile > >>> changing given that it really produces a substream. Plus the I/O > >>> usage can be somewhat different as you often decide what to skip > >>> based on what has already been read, but with streams that won't > >>> be the case. > >>> > >>> David > >>> > >>> > >>> I will go ahead with a renaming patch on Monday unless there > >>> objections. Any counter proposals should be *very* narrow in > >>> scope--we're past the point were we can do redesign. > >>> > >>> Mike > >>> > >>> > >> > > From mike.duigou at oracle.com Wed Oct 9 20:46:15 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Wed, 9 Oct 2013 20:46:15 -0700 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> Message-ID: <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> On Oct 8 2013, at 01:27 , Paul Sandoz wrote: > Hi Mike, > > I am probably going over old ground here... > > Given that there is ConcurrentMap is there any point in having the defaults on Map detect concurrent modification and barf, or retry, or neither of the previous two e.g. putIfAbsent, computeIfPresent and replace respectively i.e. there seems to be inconsistent behaviour here. > > Would it not be better to separate concerns of serial and concurrent access in the defaults of Map and ConcurrentMap? I have created a prototype renovated Map and ConcurrentMap to provide (mostly) separate implementations. http://cr.openjdk.java.net/~mduigou/JDK-8024688.2/0/webrev/ This passes all of the existing regression tests and I believe is performance neutral. The implementations are now more relatively correct for both flavours. ie. Map defaults don't retry and throw CME when they detect that something changed unexpectedly. The ConcurrentMap defaults were mostly just moving over the prior Map defaults but I also removed a few cases of null value handling that were no longer needed. I've wanted to explore this for a while (since June) but haven't previously had a chance. I'm somewhat convinced that this is the right direction to be going but I am sure further refinement is possible (particularly in regards to the spec). > The defaults on Map could state they are not suitable for maps that can be concurrently modified, if that is required extend from ConcurrentMap. If function values passed to methods modify the Map then undefined behaviour will result. (I am also wondering if there are currently edge cases e.g. if a function value modifies the source then the re-try loop will never terminate.) > > I realize that is separate from the null behaviour, but perhaps this separate will help clarify null behaviour? I realized that some of the statements about "implementations must document how they handle nulls with this method" were no longer relevant. The null handling behaviour was entirely covered by the class documentation and the method specification. This is mostly a consequence of having added "or is mapped to null value" in couple of cases later on in the process. Thanks for pushing on this point (and David Holmes for earlier suggestion that this might be important) Mike > Paul. > > On Oct 4, 2013, at 5:35 AM, Mike Duigou wrote: > >> Hello all; >> >> This is a changeset which improves the consistency of several Map.merge implementations for handling of null values. >> >> The existing unit tests hadn't considered several cases where the result of the remapper was not the same as the value. I've restructured the merge tests to be more thorough and systematic this revealed a couple of problems. >> >> http://cr.openjdk.java.net/~mduigou/JDK-8024688/0/webrev/ >> >> Like several of the previous patches, this one introduces an alternative default for ConcurrentMap to work around issues involving null values where the handling in the general Map default would be incorrect. >> >> Mike > From paul.sandoz at oracle.com Thu Oct 10 06:37:40 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 10 Oct 2013 15:37:40 +0200 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> Message-ID: <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> Hi Mike, This looks like a good direction. Need to look more closely. I wonder if we even require such detailed support to throw CME? For the cases where no function values are passed it has very limited value, we know it is effectively useless for non-current collections being modified concurrently. For the cases where a function value is passed and it modifies the map then it could have some value. But i wonder, for any non-looping function value accepting method on Map (anything other than forEach/replaceAll), whether it is just simpler to state: "if a function value modifies the entry under computation then this method may return incorrect results`". Paul. On Oct 10, 2013, at 5:46 AM, Mike Duigou wrote: > > On Oct 8 2013, at 01:27 , Paul Sandoz wrote: > >> Hi Mike, >> >> I am probably going over old ground here... >> >> Given that there is ConcurrentMap is there any point in having the defaults on Map detect concurrent modification and barf, or retry, or neither of the previous two e.g. putIfAbsent, computeIfPresent and replace respectively i.e. there seems to be inconsistent behaviour here. >> >> Would it not be better to separate concerns of serial and concurrent access in the defaults of Map and ConcurrentMap? > > I have created a prototype renovated Map and ConcurrentMap to provide (mostly) separate implementations. > > http://cr.openjdk.java.net/~mduigou/JDK-8024688.2/0/webrev/ > > This passes all of the existing regression tests and I believe is performance neutral. The implementations are now more relatively correct for both flavours. ie. Map defaults don't retry and throw CME when they detect that something changed unexpectedly. The ConcurrentMap defaults were mostly just moving over the prior Map defaults but I also removed a few cases of null value handling that were no longer needed. > > I've wanted to explore this for a while (since June) but haven't previously had a chance. I'm somewhat convinced that this is the right direction to be going but I am sure further refinement is possible (particularly in regards to the spec). > >> The defaults on Map could state they are not suitable for maps that can be concurrently modified, if that is required extend from ConcurrentMap. If function values passed to methods modify the Map then undefined behaviour will result. (I am also wondering if there are currently edge cases e.g. if a function value modifies the source then the re-try loop will never terminate.) >> >> I realize that is separate from the null behaviour, but perhaps this separate will help clarify null behaviour? > > I realized that some of the statements about "implementations must document how they handle nulls with this method" were no longer relevant. The null handling behaviour was entirely covered by the class documentation and the method specification. This is mostly a consequence of having added "or is mapped to null value" in couple of cases later on in the process. > > Thanks for pushing on this point (and David Holmes for earlier suggestion that this might be important) > > Mike > >> Paul. >> >> On Oct 4, 2013, at 5:35 AM, Mike Duigou wrote: >> >>> Hello all; >>> >>> This is a changeset which improves the consistency of several Map.merge implementations for handling of null values. >>> >>> The existing unit tests hadn't considered several cases where the result of the remapper was not the same as the value. I've restructured the merge tests to be more thorough and systematic this revealed a couple of problems. >>> >>> http://cr.openjdk.java.net/~mduigou/JDK-8024688/0/webrev/ >>> >>> Like several of the previous patches, this one introduces an alternative default for ConcurrentMap to work around issues involving null values where the handling in the general Map default would be incorrect. >>> >>> Mike >> > From mike.duigou at oracle.com Thu Oct 10 16:54:02 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Thu, 10 Oct 2013 16:54:02 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question Message-ID: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> Hello all; In the review of the renaming patch for Stream.substream() -> slice() Brian asked me to consider also changing the semantics of the parameters from the current Stream.slice(fromInclusive,toExclusive). The rationale is that we then have only one sense of usage in the parameters for skip/limit/slice. This also makes slice() more obviously equivalent to skip(toSkip).limit(limit). I am inclined to agree with him that using the same semantics for the parameters across the three methods has value. I will go forward with changing to Stream.slice(toSkip,limit) before Monday assuming there is no outcry. Mike From brian.goetz at oracle.com Thu Oct 10 17:04:52 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 Oct 2013 20:04:52 -0400 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> Message-ID: <525740A4.2010406@oracle.com> FWIW, this is what the semantics were originally, and they got modified to be consistent with substring() when we renamed slice to substring() originally. So this is a reversion to where we were before. On 10/10/2013 7:54 PM, Mike Duigou wrote: > Hello all; > > In the review of the renaming patch for Stream.substream() -> slice() > Brian asked me to consider also changing the semantics of the > parameters from the current Stream.slice(fromInclusive,toExclusive). > The rationale is that we then have only one sense of usage in the > parameters for skip/limit/slice. This also makes slice() more > obviously equivalent to skip(toSkip).limit(limit). I am inclined to > agree with him that using the same semantics for the parameters > across the three methods has value. > > I will go forward with changing to Stream.slice(toSkip,limit) before > Monday assuming there is no outcry. > > Mike > From joe.bowbeer at gmail.com Thu Oct 10 18:28:00 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Thu, 10 Oct 2013 18:28:00 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <525740A4.2010406@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> Message-ID: slice(start, end) would be more useful and more consistent with its use in other languages (Python, Perl). In Python, the elements are start .. end-1 whereas the end is inclusive in Perl. But I think the use of start:end is fairly consistent for most implementations of slice. I claim this would be more useful because otherwise there's no difference between slice and skip(start) + limit(end-start) --Joe On Thu, Oct 10, 2013 at 5:04 PM, Brian Goetz wrote: > FWIW, this is what the semantics were originally, and they got modified > to be consistent with substring() when we renamed slice to substring() > originally. So this is a reversion to where we were before. > > > On 10/10/2013 7:54 PM, Mike Duigou wrote: > >> Hello all; >> >> In the review of the renaming patch for Stream.substream() -> slice() >> Brian asked me to consider also changing the semantics of the >> parameters from the current Stream.slice(fromInclusive,**toExclusive). >> The rationale is that we then have only one sense of usage in the >> parameters for skip/limit/slice. This also makes slice() more >> obviously equivalent to skip(toSkip).limit(limit). I am inclined to >> agree with him that using the same semantics for the parameters >> across the three methods has value. >> >> I will go forward with changing to Stream.slice(toSkip,limit) before >> Monday assuming there is no outcry. >> >> Mike >> >> From paul.sandoz at oracle.com Fri Oct 11 01:12:09 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 11 Oct 2013 10:12:09 +0200 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> Message-ID: <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> Hi Joe, I tend to think of slice(s, l) as the fused (optimal) form of skip(s).limit(l). For parallel streams the the fused form will result in less wrapping and/or buffering (depending on the properties of the input stream). Documentation-wise we should probably include an api note on skip and limit referring to slice in this respect. Paul. On Oct 11, 2013, at 3:28 AM, Joe Bowbeer wrote: > slice(start, end) would be more useful and more consistent with its use in > other languages (Python, Perl). > > In Python, the elements are start .. end-1 whereas the end is inclusive in > Perl. But I think the use of start:end is fairly consistent for most > implementations of slice. > > I claim this would be more useful because otherwise there's no difference > between slice and skip(start) + limit(end-start) > > --Joe > > > On Thu, Oct 10, 2013 at 5:04 PM, Brian Goetz wrote: > >> FWIW, this is what the semantics were originally, and they got modified >> to be consistent with substring() when we renamed slice to substring() >> originally. So this is a reversion to where we were before. >> >> >> On 10/10/2013 7:54 PM, Mike Duigou wrote: >> >>> Hello all; >>> >>> In the review of the renaming patch for Stream.substream() -> slice() >>> Brian asked me to consider also changing the semantics of the >>> parameters from the current Stream.slice(fromInclusive,**toExclusive). >>> The rationale is that we then have only one sense of usage in the >>> parameters for skip/limit/slice. This also makes slice() more >>> obviously equivalent to skip(toSkip).limit(limit). I am inclined to >>> agree with him that using the same semantics for the parameters >>> across the three methods has value. >>> >>> I will go forward with changing to Stream.slice(toSkip,limit) before >>> Monday assuming there is no outcry. >>> >>> Mike >>> >>> From joe.bowbeer at gmail.com Fri Oct 11 02:52:10 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Fri, 11 Oct 2013 02:52:10 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> Message-ID: slice notation in groovy is also start..end, and slice notation in scala and clojure is start:end. Those are all the languages I know that have a slice. In what language is a slice parameterized by start:count? On Oct 11, 2013 1:12 AM, "Paul Sandoz" wrote: > Hi Joe, > > I tend to think of slice(s, l) as the fused (optimal) form of > skip(s).limit(l). For parallel streams the the fused form will result in > less wrapping and/or buffering (depending on the properties of the input > stream). Documentation-wise we should probably include an api note on skip > and limit referring to slice in this respect. > > Paul. > > On Oct 11, 2013, at 3:28 AM, Joe Bowbeer wrote: > > > slice(start, end) would be more useful and more consistent with its use > in > > other languages (Python, Perl). > > > > In Python, the elements are start .. end-1 whereas the end is inclusive > in > > Perl. But I think the use of start:end is fairly consistent for most > > implementations of slice. > > > > I claim this would be more useful because otherwise there's no difference > > between slice and skip(start) + limit(end-start) > > > > --Joe > > > > > > On Thu, Oct 10, 2013 at 5:04 PM, Brian Goetz > wrote: > > > >> FWIW, this is what the semantics were originally, and they got modified > >> to be consistent with substring() when we renamed slice to substring() > >> originally. So this is a reversion to where we were before. > >> > >> > >> On 10/10/2013 7:54 PM, Mike Duigou wrote: > >> > >>> Hello all; > >>> > >>> In the review of the renaming patch for Stream.substream() -> slice() > >>> Brian asked me to consider also changing the semantics of the > >>> parameters from the current Stream.slice(fromInclusive,**toExclusive). > >>> The rationale is that we then have only one sense of usage in the > >>> parameters for skip/limit/slice. This also makes slice() more > >>> obviously equivalent to skip(toSkip).limit(limit). I am inclined to > >>> agree with him that using the same semantics for the parameters > >>> across the three methods has value. > >>> > >>> I will go forward with changing to Stream.slice(toSkip,limit) before > >>> Monday assuming there is no outcry. > >>> > >>> Mike > >>> > >>> > > From scolebourne at joda.org Fri Oct 11 03:32:00 2013 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 11 Oct 2013 11:32:00 +0100 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> Message-ID: skip() and limit() make perfect sense. I'm surprised by the notion that skip(60).limit(10) would be less efficient than skipAndLimit(60,10) - that seems like an implementation detail that should not drive the API. Thus I dislike the current slice definition. More generally, my expectation from experience is that slice would be slice(start, endExclusive). I'd also expect slice to support negative indicies to refer releative to the end, otherwise I'd be wondering why it wasn't called subStream. Thus my preference is: - skip(elementsToSkip) - limit(elementLimit) - subStream(startInclusive, endExclusive) - make skip().limit() efficient internally I don't think anyone will be surprised by those three methods. Stephen On 11 October 2013 10:52, Joe Bowbeer wrote: > slice notation in groovy is also start..end, and slice notation in scala > and clojure is start:end. > > Those are all the languages I know that have a slice. In what language is a > slice parameterized by start:count? > On Oct 11, 2013 1:12 AM, "Paul Sandoz" wrote: > >> Hi Joe, >> >> I tend to think of slice(s, l) as the fused (optimal) form of >> skip(s).limit(l). For parallel streams the the fused form will result in >> less wrapping and/or buffering (depending on the properties of the input >> stream). Documentation-wise we should probably include an api note on skip >> and limit referring to slice in this respect. >> >> Paul. >> >> On Oct 11, 2013, at 3:28 AM, Joe Bowbeer wrote: >> >> > slice(start, end) would be more useful and more consistent with its use >> in >> > other languages (Python, Perl). >> > >> > In Python, the elements are start .. end-1 whereas the end is inclusive >> in >> > Perl. But I think the use of start:end is fairly consistent for most >> > implementations of slice. >> > >> > I claim this would be more useful because otherwise there's no difference >> > between slice and skip(start) + limit(end-start) >> > >> > --Joe >> > >> > >> > On Thu, Oct 10, 2013 at 5:04 PM, Brian Goetz >> wrote: >> > >> >> FWIW, this is what the semantics were originally, and they got modified >> >> to be consistent with substring() when we renamed slice to substring() >> >> originally. So this is a reversion to where we were before. >> >> >> >> >> >> On 10/10/2013 7:54 PM, Mike Duigou wrote: >> >> >> >>> Hello all; >> >>> >> >>> In the review of the renaming patch for Stream.substream() -> slice() >> >>> Brian asked me to consider also changing the semantics of the >> >>> parameters from the current Stream.slice(fromInclusive,**toExclusive). >> >>> The rationale is that we then have only one sense of usage in the >> >>> parameters for skip/limit/slice. This also makes slice() more >> >>> obviously equivalent to skip(toSkip).limit(limit). I am inclined to >> >>> agree with him that using the same semantics for the parameters >> >>> across the three methods has value. >> >>> >> >>> I will go forward with changing to Stream.slice(toSkip,limit) before >> >>> Monday assuming there is no outcry. >> >>> >> >>> Mike >> >>> >> >>> >> >> From paul.sandoz at oracle.com Fri Oct 11 04:41:02 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 11 Oct 2013 13:41:02 +0200 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> Message-ID: <075B3AAD-831E-4329-B94E-CB369E60318A@oracle.com> On Oct 11, 2013, at 12:32 PM, Stephen Colebourne wrote: > skip() and limit() make perfect sense. I'm surprised by the notion > that skip(60).limit(10) would be less efficient than > skipAndLimit(60,10) - that seems like an implementation detail that > should not drive the API. I did not mean suggest that was driving the reason for slice (or for that matter subStream), regardless of the form of its arguments. The main point i wanted to make is it is easy to comprehend slice as a *more concise* representation of skip immediately followed by limit (and additionally there are currently implementation reasons as to why it is beneficial to use that form, since we don't currently internally fuse operations). Paul. > Thus I dislike the current slice definition. > > More generally, my expectation from experience is that slice would be > slice(start, endExclusive). I'd also expect slice to support negative > indicies to refer releative to the end, otherwise I'd be wondering why > it wasn't called subStream. > > Thus my preference is: > - skip(elementsToSkip) > - limit(elementLimit) > - subStream(startInclusive, endExclusive) > - make skip().limit() efficient internally > > I don't think anyone will be surprised by those three methods. > > Stephen From paul.sandoz at oracle.com Fri Oct 11 05:13:11 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Fri, 11 Oct 2013 14:13:11 +0200 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> Message-ID: On Oct 11, 2013, at 11:52 AM, Joe Bowbeer wrote: > slice notation in groovy is also start..end, and slice notation in scala and clojure is start:end. > > Those are all the languages I know that have a slice. In what language is a slice parameterized by start:count? > Haskell: http://hackage.haskell.org/package/vector-0.10.9.1/docs/Data-Vector.html#v%3aslice Although that is on a vector and AFAICT not some generic traversable thing. But point taken; there are other languages that take the absolute approach. Paul. > On Oct 11, 2013 1:12 AM, "Paul Sandoz" wrote: > Hi Joe, > > I tend to think of slice(s, l) as the fused (optimal) form of skip(s).limit(l). For parallel streams the the fused form will result in less wrapping and/or buffering (depending on the properties of the input stream). Documentation-wise we should probably include an api note on skip and limit referring to slice in this respect. > > Paul. From brian.goetz at oracle.com Fri Oct 11 07:06:48 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2013 10:06:48 -0400 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> Message-ID: <525805F8.6080100@oracle.com> > skip() and limit() make perfect sense. I'm surprised by the notion > that skip(60).limit(10) would be less efficient than > skipAndLimit(60,10) That's because you're thinking sequentially! The sequential implementation is fast no matter what you do. But skip and limit are constrained to operate in *encounter order* -- you don't just skip any N, you skip the *first N*. This is death for parallel operations, unless there's something else you can do to sidestep the problem (which we do for streams with predictable size and splitting characteristics, or for unordered streams.) As a general rule, whenever you find yourself thinking "I don't understand why they just don't...", the answer is probably because you've got your sequential goggles on, which filters the hard part from your view. From scolebourne at joda.org Fri Oct 11 07:18:18 2013 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 11 Oct 2013 15:18:18 +0100 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <525805F8.6080100@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525805F8.6080100@oracle.com> Message-ID: On 11 October 2013 15:06, Brian Goetz wrote: >> skip() and limit() make perfect sense. I'm surprised by the notion >> that skip(60).limit(10) would be less efficient than >> skipAndLimit(60,10) > > That's because you're thinking sequentially! No, I wasn't thinking at all about the implementation. I was commenting on API design. If skipAndLimit(60, 10) is an important enough optmization, I'd really want the implementation to do that for me - one less concern for me as a user. Especially important as the API trades on the notion that you just build up a request from a sequence of small fluent commands. If you can't make the optimization internal, then it would be much better to call the method skipAndLimit() or skipLimit() as then it will appear next to skip() in IDEs and people might, just might, pause and think about using the combined operation. Stephen From brian.goetz at oracle.com Fri Oct 11 07:18:38 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2013 10:18:38 -0400 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> Message-ID: <525808BE.2050108@oracle.com> Rather than focus on "what do other Java APIs/languages do" (which is a useful data point, but rarely provides the whole story), we should ask "what's the goal." I think the start:end notation makes essentially no sense for non-indexed entities. For indexed entities like strings and lists, it is very natural, and the analogy with something similar but different is confusing us. If you were slicing a String, you would probably do something like: int startPos = s.indexOf("["); int endPos = s.indexOf("]"); if (startPos != -1 && endPos != -1) s = s.substring(startPos+1, endPos); But, without being able to search through the characters to find the pattern you're looking for, how would you know where to end the slice? The same is true with lists. In order for "stop at position N" to be useful, you have to have a way of searching through the elements to find at what position you might want to stop. But streams don't let you do that. So this use case, motivated by strings and other indexable entities, is a red herring. However, with streams it is still useful to say "I want the n'th page of results." Which translates to "Skip (n-1)*K, and limit to K". It is useful to say "I want no more than K results." Several have pointed out that it is surprising that .skip(n).limit(k) is inefficient enough to want a fusing. Of course, in the sequential case, its fine. But because skip/limit are constrained to operate in encounter order, in the worst case (non-SIZED+SUBSIZED, non-UNORDERED), we have to buffer. Doing two rounds of buffering would suck twice -- and this was the primary motivation for a fused operation. So I think there are two sensible choices here: - slice(toSkip, toLimit) - drop slice entirely The cost of the latter is that those who need it in parallel in the unpleasant cases are even more likely to have to retreat to sequential. On 10/11/2013 5:52 AM, Joe Bowbeer wrote: > slice notation in groovy is also start..end, and slice notation in scala > and clojure is start:end. > > Those are all the languages I know that have a slice. In what language > is a slice parameterized by start:count? > > On Oct 11, 2013 1:12 AM, "Paul Sandoz" > wrote: > > Hi Joe, > > I tend to think of slice(s, l) as the fused (optimal) form of > skip(s).limit(l). For parallel streams the the fused form will > result in less wrapping and/or buffering (depending on the > properties of the input stream). Documentation-wise we should > probably include an api note on skip and limit referring to slice in > this respect. > > Paul. > > On Oct 11, 2013, at 3:28 AM, Joe Bowbeer > wrote: > > > slice(start, end) would be more useful and more consistent with > its use in > > other languages (Python, Perl). > > > > In Python, the elements are start .. end-1 whereas the end is > inclusive in > > Perl. But I think the use of start:end is fairly consistent for most > > implementations of slice. > > > > I claim this would be more useful because otherwise there's no > difference > > between slice and skip(start) + limit(end-start) > > > > --Joe > > > > > > On Thu, Oct 10, 2013 at 5:04 PM, Brian Goetz > > wrote: > > > >> FWIW, this is what the semantics were originally, and they got > modified > >> to be consistent with substring() when we renamed slice to > substring() > >> originally. So this is a reversion to where we were before. > >> > >> > >> On 10/10/2013 7:54 PM, Mike Duigou wrote: > >> > >>> Hello all; > >>> > >>> In the review of the renaming patch for Stream.substream() -> > slice() > >>> Brian asked me to consider also changing the semantics of the > >>> parameters from the current > Stream.slice(fromInclusive,**toExclusive). > >>> The rationale is that we then have only one sense of usage in the > >>> parameters for skip/limit/slice. This also makes slice() more > >>> obviously equivalent to skip(toSkip).limit(limit). I am inclined to > >>> agree with him that using the same semantics for the parameters > >>> across the three methods has value. > >>> > >>> I will go forward with changing to Stream.slice(toSkip,limit) > before > >>> Monday assuming there is no outcry. > >>> > >>> Mike > >>> > >>> > From dl at cs.oswego.edu Fri Oct 11 07:31:18 2013 From: dl at cs.oswego.edu (Doug Lea) Date: Fri, 11 Oct 2013 10:31:18 -0400 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <525808BE.2050108@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> Message-ID: <52580BB6.2010503@cs.oswego.edu> On 10/11/2013 10:18 AM, Brian Goetz wrote: > Several have pointed out that it is surprising that .skip(n).limit(k) is > inefficient enough to want a fusing. Of course, in the sequential case, its > fine. But because skip/limit are constrained to operate in encounter order, in > the worst case (non-SIZED+SUBSIZED, non-UNORDERED), we have to buffer. Doing > two rounds of buffering would suck twice -- and this was the primary motivation > for a fused operation. > > So I think there are two sensible choices here: > > - slice(toSkip, toLimit) > - drop slice entirely > > The cost of the latter is that those who need it in parallel in the unpleasant > cases are even more likely to have to retreat to sequential. > In other words: If running sequentially, skip(n).limit(k) costs almost nothing more than slice. And the same nearly holds for cases where people do an intrinsically sequential operation in parallel (i.e., using either skip or limit on ordered data) -- you get about twice the terrible cost of either skip or limit. Seems like a fine idea to just drop it. -Doug From brian.goetz at oracle.com Fri Oct 11 07:54:01 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2013 10:54:01 -0400 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <52580BB6.2010503@cs.oswego.edu> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> Message-ID: <52581109.3090608@oracle.com> Further argument for dropping: while we don't do implicit op fusion now (an earlier version had this, but we dropped it as it was getting in the way of some more valuable things), now that the implementation has stabilized, it looks like the current implementation is pretty amenable to pairwise op fusion. So it seems likely there's a path to having the implementation just turn skip+limit into the more efficient version. On 10/11/2013 10:31 AM, Doug Lea wrote: > On 10/11/2013 10:18 AM, Brian Goetz wrote: > >> Several have pointed out that it is surprising that .skip(n).limit(k) is >> inefficient enough to want a fusing. Of course, in the sequential >> case, its >> fine. But because skip/limit are constrained to operate in encounter >> order, in >> the worst case (non-SIZED+SUBSIZED, non-UNORDERED), we have to >> buffer. Doing >> two rounds of buffering would suck twice -- and this was the primary >> motivation >> for a fused operation. >> >> So I think there are two sensible choices here: >> >> - slice(toSkip, toLimit) >> - drop slice entirely >> >> The cost of the latter is that those who need it in parallel in the >> unpleasant >> cases are even more likely to have to retreat to sequential. >> > > In other words: If running sequentially, skip(n).limit(k) costs almost > nothing more than slice. And the same nearly holds for cases where > people do an intrinsically sequential operation in parallel > (i.e., using either skip or limit on ordered data) -- > you get about twice the terrible cost of either skip or limit. > > Seems like a fine idea to just drop it. > > -Doug > > From spullara at gmail.com Fri Oct 11 08:23:16 2013 From: spullara at gmail.com (Sam Pullara) Date: Fri, 11 Oct 2013 08:23:16 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <52581109.3090608@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> Message-ID: <0D137AB2-CB8A-4F87-B79A-B45C1991FEFC@gmail.com> I'm ok with not having slice at all.? Sam ---Sent from Boxer Further argument for dropping: while we don't do implicit op fusion now (an earlier version had this, but we dropped it as it was getting in the way of some more valuable things), now that the implementation has stabilized, it looks like the current implementation is pretty amenable to pairwise op fusion. So it seems likely there's a path to having the implementation just turn skip+limit into the more efficient version. On 10/11/2013 10:31 AM, Doug Lea wrote: > On 10/11/2013 10:18 AM, Brian Goetz wrote: > >> Several have pointed out that it is surprising that .skip(n).limit(k) is >> inefficient enough to want a fusing. Of course, in the sequential >> case, its >> fine. But because skip/limit are constrained to operate in encounter >> order, in >> the worst case (non-SIZED+SUBSIZED, non-UNORDERED), we have to >> buffer. Doing >> two rounds of buffering would suck twice -- and this was the primary >> motivation >> for a fused operation. >> >> So I think there are two sensible choices here: >> >> - slice(toSkip, toLimit) >> - drop slice entirely >> >> The cost of the latter is that those who need it in parallel in the >> unpleasant >> cases are even more likely to have to retreat to sequential. >> > > In other words: If running sequentially, skip(n).limit(k) costs almost > nothing more than slice. And the same nearly holds for cases where > people do an intrinsically sequential operation in parallel > (i.e., using either skip or limit on ordered data) -- > you get about twice the terrible cost of either skip or limit. > > Seems like a fine idea to just drop it. > > -Doug > > From joe.bowbeer at gmail.com Fri Oct 11 08:48:20 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Fri, 11 Oct 2013 08:48:20 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <52581109.3090608@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> Message-ID: slice *is* start:end The comparison with all the other slices can't be avoided. If we want skipAndLimit, then let's add one of those. Our not. On Oct 11, 2013 7:54 AM, "Brian Goetz" wrote: > Further argument for dropping: while we don't do implicit op fusion now > (an earlier version had this, but we dropped it as it was getting in the > way of some more valuable things), now that the implementation has > stabilized, it looks like the current implementation is pretty amenable to > pairwise op fusion. So it seems likely there's a path to having the > implementation just turn skip+limit into the more efficient version. > > On 10/11/2013 10:31 AM, Doug Lea wrote: > >> On 10/11/2013 10:18 AM, Brian Goetz wrote: >> >> Several have pointed out that it is surprising that .skip(n).limit(k) is >>> inefficient enough to want a fusing. Of course, in the sequential >>> case, its >>> fine. But because skip/limit are constrained to operate in encounter >>> order, in >>> the worst case (non-SIZED+SUBSIZED, non-UNORDERED), we have to >>> buffer. Doing >>> two rounds of buffering would suck twice -- and this was the primary >>> motivation >>> for a fused operation. >>> >>> So I think there are two sensible choices here: >>> >>> - slice(toSkip, toLimit) >>> - drop slice entirely >>> >>> The cost of the latter is that those who need it in parallel in the >>> unpleasant >>> cases are even more likely to have to retreat to sequential. >>> >>> >> In other words: If running sequentially, skip(n).limit(k) costs almost >> nothing more than slice. And the same nearly holds for cases where >> people do an intrinsically sequential operation in parallel >> (i.e., using either skip or limit on ordered data) -- >> you get about twice the terrible cost of either skip or limit. >> >> Seems like a fine idea to just drop it. >> >> -Doug >> >> >> From joe.bowbeer at gmail.com Fri Oct 11 10:31:19 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Fri, 11 Oct 2013 10:31:19 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> Message-ID: Concerning the index requirement of these operations, I think skip is implicitly indexed (start is an index), whereas limit is not. So any operation fused with skip is also implicitly indexed, right? If you have a non-indexed stream, why would you ever skip(start).limit(count) instead of simply limit(count)? To be clear where I stand: I think Java would benefit from slice(start, end) On Fri, Oct 11, 2013 at 8:48 AM, Joe Bowbeer wrote: > slice *is* start:end > > The comparison with all the other slices can't be avoided. > > If we want skipAndLimit, then let's add one of those. > > Our not. > On Oct 11, 2013 7:54 AM, "Brian Goetz" wrote: > >> Further argument for dropping: while we don't do implicit op fusion now >> (an earlier version had this, but we dropped it as it was getting in the >> way of some more valuable things), now that the implementation has >> stabilized, it looks like the current implementation is pretty amenable to >> pairwise op fusion. So it seems likely there's a path to having the >> implementation just turn skip+limit into the more efficient version. >> >> On 10/11/2013 10:31 AM, Doug Lea wrote: >> >>> On 10/11/2013 10:18 AM, Brian Goetz wrote: >>> >>> Several have pointed out that it is surprising that .skip(n).limit(k) is >>>> inefficient enough to want a fusing. Of course, in the sequential >>>> case, its >>>> fine. But because skip/limit are constrained to operate in encounter >>>> order, in >>>> the worst case (non-SIZED+SUBSIZED, non-UNORDERED), we have to >>>> buffer. Doing >>>> two rounds of buffering would suck twice -- and this was the primary >>>> motivation >>>> for a fused operation. >>>> >>>> So I think there are two sensible choices here: >>>> >>>> - slice(toSkip, toLimit) >>>> - drop slice entirely >>>> >>>> The cost of the latter is that those who need it in parallel in the >>>> unpleasant >>>> cases are even more likely to have to retreat to sequential. >>>> >>>> >>> In other words: If running sequentially, skip(n).limit(k) costs almost >>> nothing more than slice. And the same nearly holds for cases where >>> people do an intrinsically sequential operation in parallel >>> (i.e., using either skip or limit on ordered data) -- >>> you get about twice the terrible cost of either skip or limit. >>> >>> Seems like a fine idea to just drop it. >>> >>> -Doug >>> >>> >>> From brian.goetz at oracle.com Fri Oct 11 10:34:02 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2013 13:34:02 -0400 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> Message-ID: <5258368A.7000900@oracle.com> > If you have a non-indexed stream, why would you ever > skip(start).limit(count) instead of simply limit(count)? Here's one use case: Paging. You've got a stream of results, and you want to display them by pages. Stream results = input.skip((pageNo-1)*pageSize).limit(pageSize); From brian.goetz at oracle.com Fri Oct 11 10:42:31 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 Oct 2013 13:42:31 -0400 Subject: Specs In-Reply-To: <52262C7D.8070900@oracle.com> References: <521E7269.6010502@oracle.com> <52262C7D.8070900@oracle.com> Message-ID: <52583887.7050604@oracle.com> Latest (possibly final) spec update. Previous docs: http://cr.openjdk.java.net/~briangoetz/doctmp/doc1 Current docs: http://cr.openjdk.java.net/~briangoetz/doctmp/doc2 "specdiff" between them at: http://cr.openjdk.java.net/~briangoetz/doctmp/diff2 On 9/3/2013 2:37 PM, Brian Goetz wrote: > Plowing through all of these today...I've got just about all the > directly actionable ones processed, stumbling a bit on the less > actionable ones (e.g., "This section needs work.") > > I've updated the docs at the temporary site. > > Old docs: http://cr.openjdk.java.net/~briangoetz/doctmp/doc0 > New docs: http://cr.openjdk.java.net/~briangoetz/doctmp/doc1 > > And posted a "specdiff" between them at: > http://cr.openjdk.java.net/~briangoetz/doctmp/diff1 > > > > > On 9/2/2013 2:42 PM, Tim Peierls wrote: >> I sent Brian comments on the package summary a couple of days ago. I am >> curious to see whether there's any overlap or disagreement between what >> Joe wrote and what I wrote, but I'm sort of hoping Brian will summarize >> all of the responses rather than having to wade through them myself. >> (Yes, I know that just adds to Brian's work pile, but some sort of >> summary will be needed in any case.) >> >> --tim >> >> >> On Mon, Sep 2, 2013 at 12:15 PM, Joe Bowbeer > > wrote: >> >> I just sent Brian comments on the package description and the >> BaseStream family of interfaces. >> >> Overall, I like the way this is coming together. The package >> description is substantial, but it's worth the programmer's time. >> The references to package-description in the Stream methods are >> effective. Hey, I *feel* like I understand. >> >> However, there's plenty of room for improvement. I'd be happy to >> send my detailed review - or a simplified summary - to this list if >> there is interest. >> >> --Joe >> >> >> On Wed, Aug 28, 2013 at 2:58 PM, Brian Goetz > > wrote: >> >> Have I mentioned that reviews of the specs and package doc at: >> >> http://cr.openjdk.java.net/~__briangoetz/doctmp/doc/ >> >> >> would be appreciated? >> >> >> From david.lloyd at redhat.com Fri Oct 11 12:10:14 2013 From: david.lloyd at redhat.com (David M. Lloyd) Date: Fri, 11 Oct 2013 14:10:14 -0500 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <5258368A.7000900@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> <5258368A.7000900@oracle.com> Message-ID: <52584D16.9040000@redhat.com> On 10/11/2013 12:34 PM, Brian Goetz wrote: >> If you have a non-indexed stream, why would you ever >> skip(start).limit(count) instead of simply limit(count)? > > Here's one use case: Paging. You've got a stream of results, and you > want to display them by pages. > > Stream results = input.skip((pageNo-1)*pageSize).limit(pageSize); A very similar problem (and solution) exists in the RDBMS world; though (IIRC) there is no standardized mechanism, just about every major SQL RDBMS supports a (conceptually) very similar construct for choosing a subset of results, for very similar use cases (AFAICT). Take that for what it's worth. -- - DML From mike.duigou at oracle.com Fri Oct 11 12:46:55 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Fri, 11 Oct 2013 12:46:55 -0700 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> Message-ID: On Oct 10 2013, at 06:37 , Paul Sandoz wrote: > Hi Mike, > > This looks like a good direction. Need to look more closely. > > I wonder if we even require such detailed support to throw CME? Some additional CME will be thrown indirectly by iteration. This applies to forEach/replaceAll. Virtually all the cases where CME is thrown in the "new" Map defaults are the points where previously the implementation would have looped/retried. > For the cases where no function values are passed it has very limited value, we know it is effectively useless for non-current collections being modified concurrently. Understood. The alternative would be to GIGO these situations, return and ignore them. > For the cases where a function value is passed and it modifies the map then it could have some value. But i wonder, for any non-looping function value accepting method on Map (anything other than forEach/replaceAll), whether it is just simpler to state: "if a function value modifies the entry under computation then this method may return incorrect results`". Modification of any other entry may have the same result. I suspect that modification by some other thread is as likely to be a problem as modification by the function. Any thoughts Doug? Is this advancing or retreating from the right direction? Mike > > Paul. > > On Oct 10, 2013, at 5:46 AM, Mike Duigou wrote: > >> >> On Oct 8 2013, at 01:27 , Paul Sandoz wrote: >> >>> Hi Mike, >>> >>> I am probably going over old ground here... >>> >>> Given that there is ConcurrentMap is there any point in having the defaults on Map detect concurrent modification and barf, or retry, or neither of the previous two e.g. putIfAbsent, computeIfPresent and replace respectively i.e. there seems to be inconsistent behaviour here. >>> >>> Would it not be better to separate concerns of serial and concurrent access in the defaults of Map and ConcurrentMap? >> >> I have created a prototype renovated Map and ConcurrentMap to provide (mostly) separate implementations. >> >> http://cr.openjdk.java.net/~mduigou/JDK-8024688.2/0/webrev/ >> >> This passes all of the existing regression tests and I believe is performance neutral. The implementations are now more relatively correct for both flavours. ie. Map defaults don't retry and throw CME when they detect that something changed unexpectedly. The ConcurrentMap defaults were mostly just moving over the prior Map defaults but I also removed a few cases of null value handling that were no longer needed. >> >> I've wanted to explore this for a while (since June) but haven't previously had a chance. I'm somewhat convinced that this is the right direction to be going but I am sure further refinement is possible (particularly in regards to the spec). >> >>> The defaults on Map could state they are not suitable for maps that can be concurrently modified, if that is required extend from ConcurrentMap. If function values passed to methods modify the Map then undefined behaviour will result. (I am also wondering if there are currently edge cases e.g. if a function value modifies the source then the re-try loop will never terminate.) >>> >>> I realize that is separate from the null behaviour, but perhaps this separate will help clarify null behaviour? >> >> I realized that some of the statements about "implementations must document how they handle nulls with this method" were no longer relevant. The null handling behaviour was entirely covered by the class documentation and the method specification. This is mostly a consequence of having added "or is mapped to null value" in couple of cases later on in the process. >> >> Thanks for pushing on this point (and David Holmes for earlier suggestion that this might be important) >> >> Mike >> >>> Paul. >>> >>> On Oct 4, 2013, at 5:35 AM, Mike Duigou wrote: >>> >>>> Hello all; >>>> >>>> This is a changeset which improves the consistency of several Map.merge implementations for handling of null values. >>>> >>>> The existing unit tests hadn't considered several cases where the result of the remapper was not the same as the value. I've restructured the merge tests to be more thorough and systematic this revealed a couple of problems. >>>> >>>> http://cr.openjdk.java.net/~mduigou/JDK-8024688/0/webrev/ >>>> >>>> Like several of the previous patches, this one introduces an alternative default for ConcurrentMap to work around issues involving null values where the handling in the general Map default would be incorrect. >>>> >>>> Mike >>> >> > From joe.bowbeer at gmail.com Fri Oct 11 13:12:32 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Fri, 11 Oct 2013 13:12:32 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <5258368A.7000900@oracle.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> <5258368A.7000900@oracle.com> Message-ID: Thanks for the example. In terms of readability, I think skip(offset).limit(size) works well in this case. I think slice(offset, offset+size) works fine here, as well. By the way, slice(start, end) has another potential advantage in that negative values for the 'end' argument can be interpreted as an offset from the end -- skipping the final x entries. --Joe On Fri, Oct 11, 2013 at 10:34 AM, Brian Goetz wrote: > If you have a non-indexed stream, why would you ever >> skip(start).limit(count) instead of simply limit(count)? >> > > Here's one use case: Paging. You've got a stream of results, and you want > to display them by pages. > > Stream results = input.skip((pageNo-1)***pageSize).limit(pageSize); > > From spullara at gmail.com Fri Oct 11 13:25:04 2013 From: spullara at gmail.com (Sam Pullara) Date: Fri, 11 Oct 2013 13:25:04 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> <5258368A.7000900@oracle.com> Message-ID: <9467A732-56DA-476D-93B8-EAB876F07D8D@gmail.com> Couldn't a negative limit be seen the same way if we wanted it to? ---Sent from Boxer On Fri, Oct 11, 2013 at 01:12 PM, Joe Bowbeer wrote:Thanks for the example. In terms of readability, I think skip(offset).limit(size) works well in this case. I think slice(offset, offset+size) works fine here, as well. By the way, slice(start, end) has another potential advantage in that negative values for the 'end' argument can be interpreted as an offset from the end -- skipping the final x entries. --Joe On Fri, Oct 11, 2013 at 10:34 AM, Brian Goetz wrote: If you have a non-indexed stream, why would you ever skip(start).limit(count) instead of simply limit(count)? Here's one use case: Paging. ?You've got a stream of results, and you want to display them by pages. ? Stream results = input.skip((pageNo-1)* pageSize).limit(pageSize); From joe.bowbeer at gmail.com Sat Oct 12 09:25:03 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sat, 12 Oct 2013 09:25:03 -0700 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <9467A732-56DA-476D-93B8-EAB876F07D8D@gmail.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> <5258368A.7000900@oracle.com> <9467A732-56DA-476D-93B8-EAB876F07D8D@gmail.com> Message-ID: > Couldn't a negative limit be seen the same way if we wanted it to? I guess so. Though I'm more comfortable with a negative offset than a negative quantity. I forgot to mention that javascript also has slice(start, end) On Fri, Oct 11, 2013 at 1:25 PM, Sam Pullara wrote: > Couldn't a negative limit be seen the same way if we wanted it to? > > --- > Sent from Boxer > On Fri, Oct 11, 2013 at 01:12 PM, Joe Bowbeer ** wrote: > > Thanks for the example. > > In terms of readability, I think skip(offset).limit(size) works well in > this case. > > I think slice(offset, offset+size) works fine here, as well. > > By the way, slice(start, end) has another potential advantage in that > negative values for the 'end' argument can be interpreted as an offset from > the end -- skipping the final x entries. > > --Joe > > > On Fri, Oct 11, 2013 at 10:34 AM, Brian Goetz wrote: > > If you have a non-indexed stream, why would you ever > skip(start).limit(count) instead of simply limit(count)? > > > Here's one use case: Paging. You've got a stream of results, and you want > to display them by pages. > > Stream results = input.skip((pageNo-1)***pageSize).limit(pageSize); > > > ** > From paul.sandoz at oracle.com Mon Oct 14 02:32:25 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 14 Oct 2013 11:32:25 +0200 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> Message-ID: <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> On Oct 11, 2013, at 9:46 PM, Mike Duigou wrote: > > On Oct 10 2013, at 06:37 , Paul Sandoz wrote: > >> Hi Mike, >> >> This looks like a good direction. Need to look more closely. >> >> I wonder if we even require such detailed support to throw CME? > > Some additional CME will be thrown indirectly by iteration. This applies to forEach/replaceAll. Yes, that is OK (catching IllegalStateException). It is the explicit cases in other non-traversing methods i am referring to. > Virtually all the cases where CME is thrown in the "new" Map defaults are the points where previously the implementation would have looped/retried. > >> For the cases where no function values are passed it has very limited value, we know it is effectively useless for non-current collections being modified concurrently. > > Understood. The alternative would be to GIGO these situations, return and ignore them. > Yeah, unnecessarily complicates the code. >> For the cases where a function value is passed and it modifies the map then it could have some value. But i wonder, for any non-looping function value accepting method on Map (anything other than forEach/replaceAll), whether it is just simpler to state: "if a function value modifies the entry under computation then this method may return incorrect results`". > > Modification of any other entry may have the same result. Yes, although IIUC modification, by the function value, of other entries will not interfere with that of operating on the entry under computation. A more general recommendation is the function values should be stateless. > I suspect that modification by some other thread is as likely to be a problem as modification by the function. > And under concurrent modification we cannot deterministically detect. CME in the non-concurrent collections is only useful for detecting serial modification due to inversion of control, and in these particular cases it is really very limited as to what it detects. Paul. > Any thoughts Doug? Is this advancing or retreating from the right direction? > > Mike From asviraspossible at gmail.com Mon Oct 14 03:15:15 2013 From: asviraspossible at gmail.com (Victor Nazarov) Date: Mon, 14 Oct 2013 14:15:15 +0400 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: <52584D16.9040000@redhat.com> References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> <5258368A.7000900@oracle.com> <52584D16.9040000@redhat.com> Message-ID: Pagination in the form that you've stated is highly discouraged in RDBMS world. First the expression input.skip((pageNo-1)*pageSize).limit(pageSize) will almost always be in the form input.sorted(Comparator.comparing(Element::getKey)) .skip((pageNo-1)*pageSize) .limit(pageSize) And second, the above form is discouraged too and the following form should be used instead: input.sorted(Comparator.comparing(Element::getKey)) .filter(e ->e .getKey() > lastElementOnPreviousPage.getKey()) .limit(pageSize) I think last expression can be made more efficient with operation reordering in in Stream's case: input.filter(e ->e .getKey() > lastElementOnPreviousPage.getKey()) .sortedAndLimited(Comparator.comparing(Element::getKey), pageSize) "Filter" will be parallelized. And there can be efficient enough fused sort and limit operation. -- Victor Nazarov On Fri, Oct 11, 2013 at 11:10 PM, David M. Lloyd wrote: > On 10/11/2013 12:34 PM, Brian Goetz wrote: > >> If you have a non-indexed stream, why would you ever >>> skip(start).limit(count) instead of simply limit(count)? >>> >> >> Here's one use case: Paging. You've got a stream of results, and you >> want to display them by pages. >> >> Stream results = input.skip((pageNo-1)*pageSize).limit(pageSize); >> > > A very similar problem (and solution) exists in the RDBMS world; though > (IIRC) there is no standardized mechanism, just about every major SQL RDBMS > supports a (conceptually) very similar construct for choosing a subset of > results, for very similar use cases (AFAICT). Take that for what it's > worth. > > > -- > - DML > From paul.sandoz at oracle.com Mon Oct 14 05:03:19 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Mon, 14 Oct 2013 14:03:19 +0200 Subject: To Stream.slice(fromInclusive, toExclusive) or Stream.slice(toSkip, limit) that is the question In-Reply-To: References: <7BD20C20-FC89-459F-8C4C-3474D87201A1@oracle.com> <525740A4.2010406@oracle.com> <0FDF252B-C03B-4668-9507-95B776B36209@oracle.com> <525808BE.2050108@oracle.com> <52580BB6.2010503@cs.oswego.edu> <52581109.3090608@oracle.com> <5258368A.7000900@oracle.com> Message-ID: <90E2A8CF-96DA-4D7D-B348-2093832CF18B@oracle.com> On Oct 11, 2013, at 10:12 PM, Joe Bowbeer wrote: > Thanks for the example. > > In terms of readability, I think skip(offset).limit(size) works well in > this case. > > I think slice(offset, offset+size) works fine here, as well. > > By the way, slice(start, end) has another potential advantage in that > negative values for the 'end' argument can be interpreted as an offset from > the end -- skipping the final x entries. > Although that only works best for sized/subsized pipelines. Stick a filter op in front and it is necessary to buffer everything for both sequential and parallel pipelines. My preference would be to drop this method. Paul. From mike.duigou at oracle.com Tue Oct 15 09:25:09 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Tue, 15 Oct 2013 09:25:09 -0700 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> Message-ID: On Oct 14 2013, at 02:32 , Paul Sandoz wrote: >> Virtually all the cases where CME is thrown in the "new" Map defaults are the points where previously the implementation would have looped/retried. >> > >>> For the cases where no function values are passed it has very limited value, we know it is effectively useless for non-current collections being modified concurrently. >> >> Understood. The alternative would be to GIGO these situations, return and ignore them. >> > > Yeah, unnecessarily complicates the code. It does detect legitimate errors and it makes me uncomfortable to just ignore them. >>> For the cases where a function value is passed and it modifies the map then it could have some value. But i wonder, for any non-looping function value accepting method on Map (anything other than forEach/replaceAll), whether it is just simpler to state: "if a function value modifies the entry under computation then this method may return incorrect results`". >> >> Modification of any other entry may have the same result. > > Yes, although IIUC modification, by the function value, of other entries will not interfere with that of operating on the entry under computation. A more general recommendation is the function values should be stateless. > > >> I suspect that modification by some other thread is as likely to be a problem as modification by the function. >> > > And under concurrent modification we cannot deterministically detect. CME in the non-concurrent collections is only useful for detecting serial modification due to inversion of control, and in these particular cases it is really very limited as to what it detects. True, but it generally doesn't impose any extra cost. The error detection happens as a side effect of necessary operations. I'd like to bring this set of changes to conclusion as soon as possible. Mike From paul.sandoz at oracle.com Tue Oct 15 09:38:17 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 15 Oct 2013 18:38:17 +0200 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> Message-ID: <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> On Oct 15, 2013, at 6:25 PM, Mike Duigou wrote: > > On Oct 14 2013, at 02:32 , Paul Sandoz wrote: > >>> Virtually all the cases where CME is thrown in the "new" Map defaults are the points where previously the implementation would have looped/retried. >>> >> >>>> For the cases where no function values are passed it has very limited value, we know it is effectively useless for non-current collections being modified concurrently. >>> >>> Understood. The alternative would be to GIGO these situations, return and ignore them. >>> >> >> Yeah, unnecessarily complicates the code. > > It does detect legitimate errors and it makes me uncomfortable to just ignore them. > It is not deterministic. Does HashMap's implementation of putIfAbsent throw a CME? >>>> For the cases where a function value is passed and it modifies the map then it could have some value. But i wonder, for any non-looping function value accepting method on Map (anything other than forEach/replaceAll), whether it is just simpler to state: "if a function value modifies the entry under computation then this method may return incorrect results`". >>> >>> Modification of any other entry may have the same result. >> >> Yes, although IIUC modification, by the function value, of other entries will not interfere with that of operating on the entry under computation. A more general recommendation is the function values should be stateless. >> >> >>> I suspect that modification by some other thread is as likely to be a problem as modification by the function. >>> >> >> And under concurrent modification we cannot deterministically detect. CME in the non-concurrent collections is only useful for detecting serial modification due to inversion of control, and in these particular cases it is really very limited as to what it detects. > > True, but it generally doesn't impose any extra cost. The error detection happens as a side effect of necessary operations. > There cost to code complexity. I would argue that additional complexity is not worth it given the limits of what can be detected. I guess you know my opinion: remove 'em. So i will be silent for a bit and see if anyone else speaks up :-) Paul. > I'd like to bring this set of changes to conclusion as soon as possible. > > Mike > From mike.duigou at oracle.com Tue Oct 15 13:18:17 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Tue, 15 Oct 2013 13:18:17 -0700 Subject: RFR : 8025910 : (s) Rename Stream.substream(long) -> skip(long) and remove substream(long, long) Message-ID: Hello all; As promised on the lambda-libs-spec-experts mailing list I have prepared a changeset which renames the single arg substream() to skip() and remove the two arg substream() method (aka "slice"). The rationale behind these changes is: - skip() is easier for new users to locate than substream(). - substream(long,long) has ambiguous semantics and duplicates skip().limit() http://cr.openjdk.java.net/~mduigou/JDK-8025910/1/webrev/ http://cr.openjdk.java.net/~mduigou/JDK-8025910/1/specidff/overview-summary.html Cheers, Mike From henry.jen at oracle.com Tue Oct 15 14:13:07 2013 From: henry.jen at oracle.com (Henry Jen) Date: Tue, 15 Oct 2013 14:13:07 -0700 Subject: RFR : 8025910 : (s) Rename Stream.substream(long) -> skip(long) and remove substream(long, long) In-Reply-To: References: Message-ID: <525DAFE3.8040603@oracle.com> On 10/15/2013 01:18 PM, Mike Duigou wrote: > Hello all; > > As promised on the lambda-libs-spec-experts mailing list I have prepared a changeset which renames the single arg substream() to skip() and remove the two arg substream() method (aka "slice"). > > The rationale behind these changes is: > > - skip() is easier for new users to locate than substream(). > - substream(long,long) has ambiguous semantics and duplicates skip().limit() > > http://cr.openjdk.java.net/~mduigou/JDK-8025910/1/webrev/ The javadoc for skip() has reference to generate(Supplier), the link is not correct for Primitive versions, they should be corresponding version like IntSupplier. Cheers, Henry From david.holmes at oracle.com Tue Oct 15 21:41:01 2013 From: david.holmes at oracle.com (David Holmes) Date: Wed, 16 Oct 2013 14:41:01 +1000 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> Message-ID: <525E18DD.2080604@oracle.com> Okay you have incited me to throw in my 2c :) I think the CME issue has been raised a number of times in the past (and if the below doesn't agree with what I've said in the past Hey! It's a brand new day! ;-) ) But first, Mike the missing spaces are creeping back in "if(xxx)" :) For Map I don't think looking for external concurrent modification and throwing CME is necessary or worthwhile. These are not thread-safe methods. That covers: - remove, replace and it implies that putIfAbsent should not check for or throw CME. For compute* and merge it is possible that the computation function modifies the Map - unlikely perhaps but possible - so CME here seems more reasonable. (As for forEach, replaceAll etc.) I fully agree with removing the retry loops in these non-concurrent implementations. That said it makes ConcurrentMap somewhat different to Map as it never throws CME even if it was an internal mutation. Aside: do you still need to re-list every unchecked exception when overriding (i.e. @throws foo {@inheritDoc}) to get them to show up in the subtype docs? I can't tell if this has been forgotten or whether the ConcurrentMap methods truly will never throw such exceptions. Cheers, David ----- On 16/10/2013 2:38 AM, Paul Sandoz wrote: > > On Oct 15, 2013, at 6:25 PM, Mike Duigou wrote: > >> >> On Oct 14 2013, at 02:32 , Paul Sandoz wrote: >> >>>> Virtually all the cases where CME is thrown in the "new" Map defaults are the points where previously the implementation would have looped/retried. >>>> >>> >>>>> For the cases where no function values are passed it has very limited value, we know it is effectively useless for non-current collections being modified concurrently. >>>> >>>> Understood. The alternative would be to GIGO these situations, return and ignore them. >>>> >>> >>> Yeah, unnecessarily complicates the code. >> >> It does detect legitimate errors and it makes me uncomfortable to just ignore them. >> > > It is not deterministic. > > Does HashMap's implementation of putIfAbsent throw a CME? > > >>>>> For the cases where a function value is passed and it modifies the map then it could have some value. But i wonder, for any non-looping function value accepting method on Map (anything other than forEach/replaceAll), whether it is just simpler to state: "if a function value modifies the entry under computation then this method may return incorrect results`". >>>> >>>> Modification of any other entry may have the same result. >>> >>> Yes, although IIUC modification, by the function value, of other entries will not interfere with that of operating on the entry under computation. A more general recommendation is the function values should be stateless. >>> >>> >>>> I suspect that modification by some other thread is as likely to be a problem as modification by the function. >>>> >>> >>> And under concurrent modification we cannot deterministically detect. CME in the non-concurrent collections is only useful for detecting serial modification due to inversion of control, and in these particular cases it is really very limited as to what it detects. >> >> True, but it generally doesn't impose any extra cost. The error detection happens as a side effect of necessary operations. >> > > There cost to code complexity. I would argue that additional complexity is not worth it given the limits of what can be detected. > > I guess you know my opinion: remove 'em. So i will be silent for a bit and see if anyone else speaks up :-) > > Paul. > >> I'd like to bring this set of changes to conclusion as soon as possible. >> >> Mike >> > From paul.sandoz at oracle.com Wed Oct 16 02:36:40 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 16 Oct 2013 11:36:40 +0200 Subject: RFR : 8025910 : (s) Rename Stream.substream(long) -> skip(long) and remove substream(long, long) In-Reply-To: References: Message-ID: <2BB63994-736D-4F87-97FF-2AD6A73F3B79@oracle.com> Looks good with Henry's correction (that i missed the first time around!). Paul. On Oct 15, 2013, at 10:18 PM, Mike Duigou wrote: > Hello all; > > As promised on the lambda-libs-spec-experts mailing list I have prepared a changeset which renames the single arg substream() to skip() and remove the two arg substream() method (aka "slice"). > > The rationale behind these changes is: > > - skip() is easier for new users to locate than substream(). > - substream(long,long) has ambiguous semantics and duplicates skip().limit() > > http://cr.openjdk.java.net/~mduigou/JDK-8025910/1/webrev/ > http://cr.openjdk.java.net/~mduigou/JDK-8025910/1/specidff/overview-summary.html > > Cheers, > > Mike From paul.sandoz at oracle.com Wed Oct 16 03:03:28 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 16 Oct 2013 12:03:28 +0200 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <525E18DD.2080604@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> Message-ID: On Oct 16, 2013, at 6:41 AM, David Holmes wrote: > Okay you have incited me to throw in my 2c :) I think the CME issue has been raised a number of times in the past (and if the below doesn't agree with what I've said in the past Hey! It's a brand new day! ;-) ) > > But first, Mike the missing spaces are creeping back in "if(xxx)" :) > > For Map I don't think looking for external concurrent modification and throwing CME is necessary or worthwhile. These are not thread-safe methods. That covers: > - remove, replace > > and it implies that putIfAbsent should not check for or throw CME. > > For compute* and merge it is possible that the computation function modifies the Map - unlikely perhaps but possible - so CME here seems more reasonable. (As for forEach, replaceAll etc.) > > I fully agree with removing the retry loops in these non-concurrent implementations. > > That said it makes ConcurrentMap somewhat different to Map as it never throws CME even if it was an internal mutation. > HashMap.compute*/merge methods do not throw CME either. I suppose those methods could and do so beyond that of only the entry under computation. I think this really points to the fact that, for non-traversal, only concrete implementations are capable of reliably detecting a CME and therefore it's best to leave it up to those implementations should they choose to do so. Paul. > Aside: do you still need to re-list every unchecked exception when overriding (i.e. @throws foo {@inheritDoc}) to get them to show up in the subtype docs? I can't tell if this has been forgotten or whether the ConcurrentMap methods truly will never throw such exceptions. > > Cheers, > David > ----- From david.holmes at oracle.com Wed Oct 16 03:28:42 2013 From: david.holmes at oracle.com (David Holmes) Date: Wed, 16 Oct 2013 20:28:42 +1000 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> Message-ID: <525E6A5A.6080301@oracle.com> On 16/10/2013 8:03 PM, Paul Sandoz wrote: > > On Oct 16, 2013, at 6:41 AM, David Holmes wrote: > >> Okay you have incited me to throw in my 2c :) I think the CME issue has been raised a number of times in the past (and if the below doesn't agree with what I've said in the past Hey! It's a brand new day! ;-) ) >> >> But first, Mike the missing spaces are creeping back in "if(xxx)" :) >> >> For Map I don't think looking for external concurrent modification and throwing CME is necessary or worthwhile. These are not thread-safe methods. That covers: >> - remove, replace >> >> and it implies that putIfAbsent should not check for or throw CME. >> >> For compute* and merge it is possible that the computation function modifies the Map - unlikely perhaps but possible - so CME here seems more reasonable. (As for forEach, replaceAll etc.) >> >> I fully agree with removing the retry loops in these non-concurrent implementations. >> >> That said it makes ConcurrentMap somewhat different to Map as it never throws CME even if it was an internal mutation. >> > > HashMap.compute*/merge methods do not throw CME either. I suppose those methods could and do so beyond that of only the entry under computation. I think this really points to the fact that, for non-traversal, only concrete implementations are capable of reliably detecting a CME and therefore it's best to leave it up to those implementations should they choose to do so. Perhaps HashMap's implementations should throw CME? But the possibility of CME has to be allowed for in the spec of the interfaced methods regardless. David > Paul. > > >> Aside: do you still need to re-list every unchecked exception when overriding (i.e. @throws foo {@inheritDoc}) to get them to show up in the subtype docs? I can't tell if this has been forgotten or whether the ConcurrentMap methods truly will never throw such exceptions. >> >> Cheers, >> David >> ----- > From paul.sandoz at oracle.com Wed Oct 16 04:26:11 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 16 Oct 2013 13:26:11 +0200 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <525E6A5A.6080301@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> Message-ID: <19D18902-695B-4039-94C0-C9375118975B@oracle.com> On Oct 16, 2013, at 12:28 PM, David Holmes wrote: > On 16/10/2013 8:03 PM, Paul Sandoz wrote: >> >> On Oct 16, 2013, at 6:41 AM, David Holmes wrote: >> >>> Okay you have incited me to throw in my 2c :) I think the CME issue has been raised a number of times in the past (and if the below doesn't agree with what I've said in the past Hey! It's a brand new day! ;-) ) >>> >>> But first, Mike the missing spaces are creeping back in "if(xxx)" :) >>> >>> For Map I don't think looking for external concurrent modification and throwing CME is necessary or worthwhile. These are not thread-safe methods. That covers: >>> - remove, replace >>> >>> and it implies that putIfAbsent should not check for or throw CME. >>> >>> For compute* and merge it is possible that the computation function modifies the Map - unlikely perhaps but possible - so CME here seems more reasonable. (As for forEach, replaceAll etc.) >>> >>> I fully agree with removing the retry loops in these non-concurrent implementations. >>> >>> That said it makes ConcurrentMap somewhat different to Map as it never throws CME even if it was an internal mutation. >>> >> >> HashMap.compute*/merge methods do not throw CME either. I suppose those methods could and do so beyond that of only the entry under computation. I think this really points to the fact that, for non-traversal, only concrete implementations are capable of reliably detecting a CME and therefore it's best to leave it up to those implementations should they choose to do so. > > Perhaps HashMap's implementations should throw CME? > Perhaps, seems to be going beyond the call of duty. My inclination is not to bother. It becomes most relevant with forEach since the consumer will have side-effects that might make it easier to unintentionally slip in a modification to the map itself. > But the possibility of CME has to be allowed for in the spec of the interfaced methods regardless. > Ideally by not say anything :-) otherwise perhaps a variant of the following: "If a function value passed to an operation of a non-concurrent map modifies the contents of that map then the result of that operation is undefined. An implementation may throw {@link ConcurrentModificationException} in such cases and if so that behaviour should be documented." Paul. From david.holmes at oracle.com Wed Oct 16 04:52:25 2013 From: david.holmes at oracle.com (David Holmes) Date: Wed, 16 Oct 2013 21:52:25 +1000 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <19D18902-695B-4039-94C0-C9375118975B@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> Message-ID: <525E7DF9.9020901@oracle.com> On 16/10/2013 9:26 PM, Paul Sandoz wrote: > > On Oct 16, 2013, at 12:28 PM, David Holmes wrote: > >> On 16/10/2013 8:03 PM, Paul Sandoz wrote: >>> >>> On Oct 16, 2013, at 6:41 AM, David Holmes wrote: >>> >>>> Okay you have incited me to throw in my 2c :) I think the CME issue has been raised a number of times in the past (and if the below doesn't agree with what I've said in the past Hey! It's a brand new day! ;-) ) >>>> >>>> But first, Mike the missing spaces are creeping back in "if(xxx)" :) >>>> >>>> For Map I don't think looking for external concurrent modification and throwing CME is necessary or worthwhile. These are not thread-safe methods. That covers: >>>> - remove, replace >>>> >>>> and it implies that putIfAbsent should not check for or throw CME. >>>> >>>> For compute* and merge it is possible that the computation function modifies the Map - unlikely perhaps but possible - so CME here seems more reasonable. (As for forEach, replaceAll etc.) >>>> >>>> I fully agree with removing the retry loops in these non-concurrent implementations. >>>> >>>> That said it makes ConcurrentMap somewhat different to Map as it never throws CME even if it was an internal mutation. >>>> >>> >>> HashMap.compute*/merge methods do not throw CME either. I suppose those methods could and do so beyond that of only the entry under computation. I think this really points to the fact that, for non-traversal, only concrete implementations are capable of reliably detecting a CME and therefore it's best to leave it up to those implementations should they choose to do so. >> >> Perhaps HashMap's implementations should throw CME? >> > > Perhaps, seems to be going beyond the call of duty. My inclination is not to bother. It becomes most relevant with forEach since the consumer will have side-effects that might make it easier to unintentionally slip in a modification to the map itself. I think there is a lot to be said for consistency. At present it seems we don't have a clear idea on how these methods should be spec'd or how the implementations should behave. >> But the possibility of CME has to be allowed for in the spec of the interfaced methods regardless. >> > > Ideally by not say anything :-) otherwise perhaps a variant of the following: Not saying anything doesn't permit CME to be thrown. > "If a function value passed to an operation of a non-concurrent map modifies the contents of that map then the result of that operation is undefined. An implementation may throw {@link ConcurrentModificationException} in such cases and if so that behaviour should be documented." I don't think it is the Java spirit to allow for undefined behaviour. Wouldn't: @throws CME if the modifies the map and this is detected by the implementation give the same flexibility while not being so obviously flimsy? I prefer to see exception info on methods as much as practical - with NPE being the obvious exception (no pun intended). David ----- > Paul. > From dl at cs.oswego.edu Wed Oct 16 04:58:47 2013 From: dl at cs.oswego.edu (Doug Lea) Date: Wed, 16 Oct 2013 07:58:47 -0400 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <19D18902-695B-4039-94C0-C9375118975B@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> Message-ID: <525E7F77.3050702@cs.oswego.edu> On 10/16/2013 07:26 AM, Paul Sandoz wrote: > > On Oct 16, 2013, at 12:28 PM, David Holmes wrote: > >> On 16/10/2013 8:03 PM, Paul Sandoz wrote: >>> >>> HashMap.compute*/merge methods do not throw CME either. I suppose those >>> methods could and do so beyond that of only the entry under computation. >>> I think this really points to the fact that, for non-traversal, only >>> concrete implementations are capable of reliably detecting a CME and >>> therefore it's best to leave it up to those implementations should they >>> choose to do so. >> >> Perhaps HashMap's implementations should throw CME? >> > > Perhaps, seems to be going beyond the call of duty. My inclination is not to > bother. It becomes most relevant with forEach since the consumer will have > side-effects that might make it easier to unintentionally slip in a > modification to the map itself. > > >> But the possibility of CME has to be allowed for in the spec of the >> interfaced methods regardless. >> > A variant of this issue came up a year or so ago for JDK8 ConcurrentHashMap.compute*/merge: What happens if the lambda side-effects by modifying some other map element? Because CHM (sometimes) uses fine-grained locks, it is possible for two such operations from different threads could cause a deadlock. We put in wording saying that the methods are allowed to throw exceptions in this case (rather than deadlock) but they currently don't catch all such errors. Which seems analogous to the non-concurrent case, so maybe similar wording could be used at Map level. CHM: * @throws IllegalStateException if the computation detectably * attempts a recursive update to this map that would * otherwise never complete Map? * @throws IllegalStateException if the computation detectably * attempts a secondary update to this map that would * otherwise never complete or perform an inconsistent update -Doug From paul.sandoz at oracle.com Wed Oct 16 05:34:00 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 16 Oct 2013 14:34:00 +0200 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <525E7DF9.9020901@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> <525E7DF9.9020901@oracle.com> Message-ID: <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> On Oct 16, 2013, at 1:52 PM, David Holmes wrote: >>> Perhaps HashMap's implementations should throw CME? >>> >> >> Perhaps, seems to be going beyond the call of duty. My inclination is not to bother. It becomes most relevant with forEach since the consumer will have side-effects that might make it easier to unintentionally slip in a modification to the map itself. > > I think there is a lot to be said for consistency. Yes, i was proposing to consistently not support it for non-traversal methods :-) > At present it seems we don't have a clear idea on how these methods should be spec'd or how the implementations should behave. > >>> But the possibility of CME has to be allowed for in the spec of the interfaced methods regardless. >>> >> >> Ideally by not say anything :-) otherwise perhaps a variant of the following: > > Not saying anything doesn't permit CME to be thrown. > Yeah, it was my poor attempt at a joke wishing CME would go away :-) >> "If a function value passed to an operation of a non-concurrent map modifies the contents of that map then the result of that operation is undefined. An implementation may throw {@link ConcurrentModificationException} in such cases and if so that behaviour should be documented." > > I don't think it is the Java spirit to allow for undefined behaviour. OK. > Wouldn't: > > @throws CME if the modifies the map and this is detected by the implementation > > give the same flexibility while not being so obviously flimsy? Reluctantly yes; i know it's more of a style thing but it is somewhat tiresome for each and every method receiving a function value to repeat the same thing. Paul. > I prefer to see exception info on methods as much as practical - with NPE being the obvious exception (no pun intended). > From mike.duigou at oracle.com Wed Oct 16 16:52:00 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Wed, 16 Oct 2013 16:52:00 -0700 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> <525E7DF9.9020901@oracle.com> <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> Message-ID: <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> On Oct 16 2013, at 05:34 , Paul Sandoz wrote: > On Oct 16, 2013, at 1:52 PM, David Holmes wrote: >>>> Perhaps HashMap's implementations should throw CME? >>>> >>> >>> Perhaps, seems to be going beyond the call of duty. My inclination is not to bother. It becomes most relevant with forEach since the consumer will have side-effects that might make it easier to unintentionally slip in a modification to the map itself. >> >> I think there is a lot to be said for consistency. > > Yes, i was proposing to consistently not support it for non-traversal methods :-) I have prepared an updated webrev removing all of the non-traversal CME throwing. http://cr.openjdk.java.net/~mduigou/JDK-8024688/2/webrev/ It does bother me to be throwing out "good information" by not throwing the CMEs but I'm willing to go with the flow. As a practical matter later reintroduction of even valid error detection would almost certainly be difficult. (https://bugs.openjdk.java.net/browse/JDK-5045147 for one example). The patch also fixes up missing @throws and @since from the ConcurrentMap implementations. Mike From david.holmes at oracle.com Wed Oct 16 21:20:17 2013 From: david.holmes at oracle.com (David Holmes) Date: Thu, 17 Oct 2013 14:20:17 +1000 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> <525E7DF9.9020901@oracle.com> <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> Message-ID: <525F6581.6060603@oracle.com> Hi Mike, Looking mainly at the docs not the operational semantics of null handling ... On 17/10/2013 9:52 AM, Mike Duigou wrote: > > On Oct 16 2013, at 05:34 , Paul Sandoz wrote: > >> On Oct 16, 2013, at 1:52 PM, David Holmes wrote: >>>>> Perhaps HashMap's implementations should throw CME? >>>>> >>>> >>>> Perhaps, seems to be going beyond the call of duty. My inclination is not to bother. It becomes most relevant with forEach since the consumer will have side-effects that might make it easier to unintentionally slip in a modification to the map itself. >>> >>> I think there is a lot to be said for consistency. >> >> Yes, i was proposing to consistently not support it for non-traversal methods :-) > > > I have prepared an updated webrev removing all of the non-traversal CME throwing. Hmmmm ... see below ... > http://cr.openjdk.java.net/~mduigou/JDK-8024688/2/webrev/ Map.java: The implNote for computeIfAbsent should be modified to match the implementation. Ditto for computeIfPresent. Ditto for compute, merge etc! Once these implementations have stabilized we need to check what the implNote says. It makes no sense to me for the impl note to describe anything other than the core logic of the actual implementation - particularly referring to putIfAbsent when put is used, or replace when put is used. HashMap.java: 1234 if(old.value != null) Space ConcurrentMap.java: 247 * @throws ClassCastException {@inheritDoc} 248 * @throws NullPointerException {@inheritDoc} 249 * @throws ClassCastException {@inheritDoc} CCE is repeated. 274 * contain null values and get() returning null unambiguously means the key get() should be in code font as per line #69. Ditto for line 300, 332 and 395. I now see that those Map implNotes were written with ConcurrentMap in mind so that it can just tag on the note about retries. But this seems wrong to me - each should have its own implNotes reflecting the true implementation. > It does bother me to be throwing out "good information" by not throwing the CMEs but I'm willing to go with the flow. As a practical matter later reintroduction of even valid error detection would almost certainly be difficult. (https://bugs.openjdk.java.net/browse/JDK-5045147 for one example). ... it still concerns me that a function object could mutate the map and so trigger a CCE. > The patch also fixes up missing @throws and @since from the ConcurrentMap implementations. I think you have a one-line conflict with Henry's latest @since update. Cheers, David > Mike > From paul.sandoz at oracle.com Thu Oct 17 07:36:56 2013 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 17 Oct 2013 16:36:56 +0200 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> <525E7DF9.9020901@oracle.com> <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> Message-ID: <69ACCA6E-EA00-4BC1-8A24-A623B41FF56B@oracle.com> On Oct 17, 2013, at 1:52 AM, Mike Duigou wrote: > > On Oct 16 2013, at 05:34 , Paul Sandoz wrote: > >> On Oct 16, 2013, at 1:52 PM, David Holmes wrote: >>>>> Perhaps HashMap's implementations should throw CME? >>>>> >>>> >>>> Perhaps, seems to be going beyond the call of duty. My inclination is not to bother. It becomes most relevant with forEach since the consumer will have side-effects that might make it easier to unintentionally slip in a modification to the map itself. >>> >>> I think there is a lot to be said for consistency. >> >> Yes, i was proposing to consistently not support it for non-traversal methods :-) > > > I have prepared an updated webrev removing all of the non-traversal CME throwing. > > http://cr.openjdk.java.net/~mduigou/JDK-8024688/2/webrev/ > Code looks good. Agree with David there is still some work to do cleaning up the doc. e.g.: On concurrent map this: * @implNote This implementation assumes that the ConcurrentMap cannot * contain null values and {@code get()} returning null unambiguously means * the key is absent. Implementations which support null values * must override this default implementation. and this variant of the same thing: * The default implementation assumes that the ConcurrentMap cannot * contain null values and get() returning null unambiguously means the key * is absent. Implementations which support null values * must override this default implementation. should be impl specs not notes. (It could also be pulled up into the class rather than repeating for each default method.) May get reformulated if you state "The default implementation is equivalent to...". For: /** * {@inheritDoc} * * @implNote The default implementation may retry these steps when multiple * threads attempt updates. * * The default implementation assumes that the ConcurrentMap cannot * contain null values and get() returning null unambiguously means the key * is absent. Implementations which support null values * must override this default implementation. * * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @since 1.8 */ @Override default V computeIfAbsent(K key, Function mappingFunction) { Objects.requireNonNull(mappingFunction); V v, newValue; return ((v = get(key)) == null && (newValue = mappingFunction.apply(key)) != null && (v = putIfAbsent(key, newValue)) == null) ? newValue : v; } there is no retry. > It does bother me to be throwing out "good information" by not throwing the CMEs but I'm willing to go with the flow. As a practical matter later reintroduction of even valid error detection would almost certainly be difficult. (https://bugs.openjdk.java.net/browse/JDK-5045147 for one example). > I still think we can solve that with a statement on Map (my preference is to be DRY). An impl supporting CME should override the defaults, which is not that different conceptually to what is said about synchronization/atomicity on Map or null values on ConcurrentMap. Paul. > The patch also fixes up missing @throws and @since from the ConcurrentMap implementations. > > Mike > From mike.duigou at oracle.com Fri Oct 18 12:34:25 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Fri, 18 Oct 2013 12:34:25 -0700 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <525F6581.6060603@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> <525E7DF9.9020901@oracle.com> <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> <525F6581.6060603@oracle.com> Message-ID: Updated webrev: http://cr.openjdk.java.net/~mduigou/JDK-8024688/3/webrev/ More notes below. On Oct 16 2013, at 21:20 , David Holmes wrote: > Hi Mike, > > Map.java: > > The implNote for computeIfAbsent should be modified to match the implementation. Ditto for computeIfPresent. Ditto for compute, merge etc! Once these implementations have stabilized we need to check what the implNote says. It makes no sense to me for the impl note to describe anything other than the core logic of the actual implementation - particularly referring to putIfAbsent when put is used, or replace when put is used. While removing the CME I opted to also remove some of use of the fancy new methods as they didn't add anything and (usually) had a performance cost. I will update the @implNote descriptions and review the other notes. > > HashMap.java: > > 1234 if(old.value != null) > > Space Got it. Thank you. > > > ConcurrentMap.java: > > 247 * @throws ClassCastException {@inheritDoc} > 248 * @throws NullPointerException {@inheritDoc} > 249 * @throws ClassCastException {@inheritDoc} > > CCE is repeated. Got it. > > 274 * contain null values and get() returning null unambiguously means the key > > get() should be in code font as per line #69. Ditto for line 300, 332 and 395. And a few more. Thanks. > > I now see that those Map implNotes were written with ConcurrentMap in mind so that it can just tag on the note about retries. But this seems wrong to me - each should have its own implNotes reflecting the true implementation. > >> It does bother me to be throwing out "good information" by not throwing the CMEs but I'm willing to go with the flow. As a practical matter later reintroduction of even valid error detection would almost certainly be difficult. (https://bugs.openjdk.java.net/browse/JDK-5045147 for one example). > > ... it still concerns me that a function object could mutate the map and so trigger a CCE. There seems to be no way to prevent it. > >> The patch also fixes up missing @throws and @since from the ConcurrentMap implementations. > > I think you have a one-line conflict with Henry's latest @since update. Got it. I had planned for that fix to go in with changeset.... > > Cheers, > David > >> Mike >> From mike.duigou at oracle.com Fri Oct 18 12:34:09 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Fri, 18 Oct 2013 12:34:09 -0700 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <69ACCA6E-EA00-4BC1-8A24-A623B41FF56B@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> <525E7DF9.9020901@oracle.com> <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> <69ACCA6E-EA00-4BC1-8A24-A623B41FF56B@oracle.com> Message-ID: <02582ED7-D337-4C8E-8D91-C73238C81424@oracle.com> On Oct 17 2013, at 07:36 , Paul Sandoz wrote: > > On Oct 17, 2013, at 1:52 AM, Mike Duigou wrote: > >> >> On Oct 16 2013, at 05:34 , Paul Sandoz wrote: >> >>> On Oct 16, 2013, at 1:52 PM, David Holmes wrote: >>>>>> Perhaps HashMap's implementations should throw CME? >>>>>> >>>>> >>>>> Perhaps, seems to be going beyond the call of duty. My inclination is not to bother. It becomes most relevant with forEach since the consumer will have side-effects that might make it easier to unintentionally slip in a modification to the map itself. >>>> >>>> I think there is a lot to be said for consistency. >>> >>> Yes, i was proposing to consistently not support it for non-traversal methods :-) >> >> >> I have prepared an updated webrev removing all of the non-traversal CME throwing. >> >> http://cr.openjdk.java.net/~mduigou/JDK-8024688/2/webrev/ >> > > Code looks good. > > Agree with David there is still some work to do cleaning up the doc. > > e.g.: > > On concurrent map this: > > * @implNote This implementation assumes that the ConcurrentMap cannot > * contain null values and {@code get()} returning null unambiguously means > * the key is absent. Implementations which support null values > * must override this default implementation. > > and this variant of the same thing: > > * The default implementation assumes that the ConcurrentMap cannot > * contain null values and get() returning null unambiguously means the key > * is absent. Implementations which support null values > * must override this default implementation. > > should be impl specs not notes. (It could also be pulled up into the class rather than repeating for each default method.) May get reformulated if you state "The default implementation is equivalent to...". Done. > > For: > > /** > * {@inheritDoc} > * > * @implNote The default implementation may retry these steps when multiple > * threads attempt updates. > * > * The default implementation assumes that the ConcurrentMap cannot > * contain null values and get() returning null unambiguously means the key > * is absent. Implementations which support null values > * must override this default implementation. > * > * @throws UnsupportedOperationException {@inheritDoc} > * @throws ClassCastException {@inheritDoc} > * @throws NullPointerException {@inheritDoc} > * @since 1.8 > */ > @Override > default V computeIfAbsent(K key, > Function mappingFunction) { > Objects.requireNonNull(mappingFunction); > V v, newValue; > return ((v = get(key)) == null && > (newValue = mappingFunction.apply(key)) != null && > (v = putIfAbsent(key, newValue)) == null) ? newValue : v; > } > > there is no retry. Fixed >> It does bother me to be throwing out "good information" by not throwing the CMEs but I'm willing to go with the flow. As a practical matter later reintroduction of even valid error detection would almost certainly be difficult. (https://bugs.openjdk.java.net/browse/JDK-5045147 for one example). >> > > I still think we can solve that with a statement on Map (my preference is to be DRY). An impl supporting CME should override the defaults, which is not that different conceptually to what is said about synchronization/atomicity on Map or null values on ConcurrentMap. I haven't tried to address this. My inclination is to instead document the behaviour or the implementing classes. I don't like the notes in Map referring to what ConcurrentMap impls must do. Mike From dl at cs.oswego.edu Sat Oct 19 11:16:17 2013 From: dl at cs.oswego.edu (Doug Lea) Date: Sat, 19 Oct 2013 14:16:17 -0400 Subject: A disclaimer or two for Optional Message-ID: <5262CC71.3020606@cs.oswego.edu> This arose while contemplating some JDK9 possibilities... Note that Optional is itself a value-like class, without a public constructor, just factory methods. The factory methods do not even guarantee to return unique objects. For all that the spec does and should say, every call to Optional.of could return the same Optional object. (This would require a magical implementation, but still not disallowed, and variants that sometimes return the same one are very much possible.) This means that there are no object-identity-related guarantees for Optionals. "myOptional1 == myOptional2" tells you nothing, and synchronized(myOptional) has unpredictable effects -- it might block forever. People might find this surprising, so we probably want to add a sentence or two to the javadoc. How about the following. (We could symmetrically say that the instance returned by Optional.empty() need not be the same each time, but that might be overkill?) /** * Returns an {@code Optional} with the specified present non-null value. adding... * The returned instance need not be unique. Thus the results of * comparing two instances using @code{==}, or using one as the * argument for a @code{synchronized} block are arbitrary and should * be avoided. * * @param the class of the value * @param value the value to be present, which must be non-null * @return an {@code Optional} with the value present * @throws NullPointerException if value is null */ public static Optional of(T value) { return new Optional<>(value); } From forax at univ-mlv.fr Sat Oct 19 11:44:19 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 19 Oct 2013 20:44:19 +0200 Subject: A disclaimer or two for Optional In-Reply-To: <5262CC71.3020606@cs.oswego.edu> References: <5262CC71.3020606@cs.oswego.edu> Message-ID: <5262D303.5000106@univ-mlv.fr> I agree. R?mi On 10/19/2013 08:16 PM, Doug Lea wrote: > > This arose while contemplating some JDK9 possibilities... > > Note that Optional is itself a value-like class, without > a public constructor, just factory methods. > The factory methods do not even guarantee to return unique > objects. For all that the spec does and should say, > every call to Optional.of could return the same Optional > object. (This would require a magical implementation, > but still not disallowed, and variants that sometimes > return the same one are very much possible.) > > This means that there are no object-identity-related > guarantees for Optionals. "myOptional1 == myOptional2" > tells you nothing, and synchronized(myOptional) has > unpredictable effects -- it might block forever. > > People might find this surprising, so we probably want to > add a sentence or two to the javadoc. How about the following. > (We could symmetrically say that the instance returned by > Optional.empty() need not be the same each time, but that > might be overkill?) > > /** > * Returns an {@code Optional} with the specified present non-null > value. > adding... > * The returned instance need not be unique. Thus the results of > * comparing two instances using @code{==}, or using one as the > * argument for a @code{synchronized} block are arbitrary and should > * be avoided. > * > * @param the class of the value > * @param value the value to be present, which must be non-null > * @return an {@code Optional} with the value present > * @throws NullPointerException if value is null > */ > public static Optional of(T value) { > return new Optional<>(value); > } > From tim at peierls.net Sat Oct 19 12:38:31 2013 From: tim at peierls.net (Tim Peierls) Date: Sat, 19 Oct 2013 15:38:31 -0400 Subject: A disclaimer or two for Optional In-Reply-To: <5262CC71.3020606@cs.oswego.edu> References: <5262CC71.3020606@cs.oswego.edu> Message-ID: I suppose there's no harm in adding this, but I think most people already get that a reference to an Optional isn't a meaningful value. On Sat, Oct 19, 2013 at 2:16 PM, Doug Lea
wrote: > > This arose while contemplating some JDK9 possibilities... > > Note that Optional is itself a value-like class, without > a public constructor, just factory methods. > The factory methods do not even guarantee to return unique > objects. For all that the spec does and should say, > every call to Optional.of could return the same Optional > object. (This would require a magical implementation, > but still not disallowed, and variants that sometimes > return the same one are very much possible.) > > This means that there are no object-identity-related > guarantees for Optionals. "myOptional1 == myOptional2" > tells you nothing, and synchronized(myOptional) has > unpredictable effects -- it might block forever. > > People might find this surprising, so we probably want to > add a sentence or two to the javadoc. How about the following. > (We could symmetrically say that the instance returned by > Optional.empty() need not be the same each time, but that > might be overkill?) > > /** > * Returns an {@code Optional} with the specified present non-null > value. > adding... > * The returned instance need not be unique. Thus the results of > * comparing two instances using @code{==}, or using one as the > * argument for a @code{synchronized} block are arbitrary and should > * be avoided. > * > * @param the class of the value > * @param value the value to be present, which must be non-null > * @return an {@code Optional} with the value present > * @throws NullPointerException if value is null > */ > public static Optional of(T value) { > return new Optional<>(value); > } > > From joe.bowbeer at gmail.com Sat Oct 19 12:54:26 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sat, 19 Oct 2013 12:54:26 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <5262CC71.3020606@cs.oswego.edu> References: <5262CC71.3020606@cs.oswego.edu> Message-ID: I don't understand why == means nothing, or why there is special wording for == in the javadoc disclaimer. Why does potential reuse mean that == says nothing? Doesn't it still mean they are the same instance? That's not surprising. It is similar reuse to the valueOf factory methods, right? And the valueOf factory methods don't include a == disclaimer. It comes with the territory. Or does opt1 == opt2 no longer imply that opt1.equals(opt2) ? Or are Optional instances ephemeral? Making it impossible for applications to retain them. If either of the above, I think a more explicit disclaimer is needed. --Joe On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea
wrote: > > This arose while contemplating some JDK9 possibilities... > > Note that Optional is itself a value-like class, without > a public constructor, just factory methods. > The factory methods do not even guarantee to return unique > objects. For all that the spec does and should say, > every call to Optional.of could return the same Optional > object. (This would require a magical implementation, > but still not disallowed, and variants that sometimes > return the same one are very much possible.) > > This means that there are no object-identity-related > guarantees for Optionals. "myOptional1 == myOptional2" > tells you nothing, and synchronized(myOptional) has > unpredictable effects -- it might block forever. > > People might find this surprising, so we probably want to > add a sentence or two to the javadoc. How about the following. > (We could symmetrically say that the instance returned by > Optional.empty() need not be the same each time, but that > might be overkill?) > > /** > * Returns an {@code Optional} with the specified present non-null > value. > adding... > * The returned instance need not be unique. Thus the results of > * comparing two instances using @code{==}, or using one as the > * argument for a @code{synchronized} block are arbitrary and should > * be avoided. > * > * @param the class of the value > * @param value the value to be present, which must be non-null > * @return an {@code Optional} with the value present > * @throws NullPointerException if value is null > */ > public static Optional of(T value) { > return new Optional<>(value); > } > > From joe.bowbeer at gmail.com Sat Oct 19 13:07:27 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sat, 19 Oct 2013 13:07:27 -0700 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> Message-ID: Doug, I think I understand what you're saying to mean that Optional instances may be reused, which is what factory methods often do. If I understand, then I think it's confusing to say that == returns an arbitrary result. The meaning of == hasn't changed. For example, == might still be employed in an implementation of Optional.equals(). I'm not convinced that synchronized needs special treatment in the javadoc either. This should be clear to anyone who understands what reuse means. I think the important point to document is that reuse may be arbitrary. In particular, the statement that empty() may return different instances -- this is surprising and needs to be documented. On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer wrote: > I don't understand why == means nothing, or why there is special wording > for == in the javadoc disclaimer. > > Why does potential reuse mean that == says nothing? Doesn't it still mean > they are the same instance? That's not surprising. It is similar reuse to > the valueOf factory methods, right? And the valueOf factory methods don't > include a == disclaimer. It comes with the territory. > > Or does opt1 == opt2 no longer imply that opt1.equals(opt2) ? > > Or are Optional instances ephemeral? Making it impossible for > applications to retain them. > > If either of the above, I think a more explicit disclaimer is needed. > > --Joe > > > On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea
wrote: > >> >> This arose while contemplating some JDK9 possibilities... >> >> Note that Optional is itself a value-like class, without >> a public constructor, just factory methods. >> The factory methods do not even guarantee to return unique >> objects. For all that the spec does and should say, >> every call to Optional.of could return the same Optional >> object. (This would require a magical implementation, >> but still not disallowed, and variants that sometimes >> return the same one are very much possible.) >> >> This means that there are no object-identity-related >> guarantees for Optionals. "myOptional1 == myOptional2" >> tells you nothing, and synchronized(myOptional) has >> unpredictable effects -- it might block forever. >> >> People might find this surprising, so we probably want to >> add a sentence or two to the javadoc. How about the following. >> (We could symmetrically say that the instance returned by >> Optional.empty() need not be the same each time, but that >> might be overkill?) >> >> /** >> * Returns an {@code Optional} with the specified present non-null >> value. >> adding... >> * The returned instance need not be unique. Thus the results of >> * comparing two instances using @code{==}, or using one as the >> * argument for a @code{synchronized} block are arbitrary and should >> * be avoided. >> * >> * @param the class of the value >> * @param value the value to be present, which must be non-null >> * @return an {@code Optional} with the value present >> * @throws NullPointerException if value is null >> */ >> public static Optional of(T value) { >> return new Optional<>(value); >> } >> >> > From forax at univ-mlv.fr Sat Oct 19 13:38:30 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 19 Oct 2013 22:38:30 +0200 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> Message-ID: <5262EDC6.2000501@univ-mlv.fr> On 10/19/2013 10:07 PM, Joe Bowbeer wrote: > Doug, > > I think I understand what you're saying to mean that Optional > instances may be reused, which is what factory methods often do. no, the idea is that the VM can always replace Optional by the wrapped value and re-wrap it if an Optional object is need. Basically, Optional acts as a value type. In that case, the notion of identity is very fuzzy. > > If I understand, then I think it's confusing to say that == returns an > arbitrary result. The meaning of == hasn't changed. For example, == > might still be employed in an implementation of Optional.equals(). > > I'm not convinced that synchronized needs special treatment in the > javadoc either. This should be clear to anyone who understands what > reuse means. synchronized rely on the identity of the object. > > I think the important point to document is that reuse may be > arbitrary. In particular, the statement that empty() may return > different instances -- this is surprising and needs to be documented. R?mi > > > > On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer > wrote: > > I don't understand why == means nothing, or why there is special > wording for == in the javadoc disclaimer. > > Why does potential reuse mean that == says nothing? Doesn't it > still mean they are the same instance? That's not surprising. It > is similar reuse to the valueOf factory methods, right? And the > valueOf factory methods don't include a == disclaimer. It comes > with the territory. > > Or does opt1 == opt2 no longer imply that opt1.equals(opt2) ? > > Or are Optional instances ephemeral? Making it impossible for > applications to retain them. > > If either of the above, I think a more explicit disclaimer is needed. > > --Joe > > > On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea
> wrote: > > > This arose while contemplating some JDK9 possibilities... > > Note that Optional is itself a value-like class, without > a public constructor, just factory methods. > The factory methods do not even guarantee to return unique > objects. For all that the spec does and should say, > every call to Optional.of could return the same Optional > object. (This would require a magical implementation, > but still not disallowed, and variants that sometimes > return the same one are very much possible.) > > This means that there are no object-identity-related > guarantees for Optionals. "myOptional1 == myOptional2" > tells you nothing, and synchronized(myOptional) has > unpredictable effects -- it might block forever. > > People might find this surprising, so we probably want to > add a sentence or two to the javadoc. How about the following. > (We could symmetrically say that the instance returned by > Optional.empty() need not be the same each time, but that > might be overkill?) > > /** > * Returns an {@code Optional} with the specified present > non-null value. > adding... > * The returned instance need not be unique. Thus the results of > * comparing two instances using @code{==}, or using one as the > * argument for a @code{synchronized} block are arbitrary and > should > * be avoided. > * > * @param the class of the value > * @param value the value to be present, which must be > non-null > * @return an {@code Optional} with the value present > * @throws NullPointerException if value is null > */ > public static Optional of(T value) { > return new Optional<>(value); > } > > > From joe.bowbeer at gmail.com Sat Oct 19 14:01:25 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sat, 19 Oct 2013 14:01:25 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <5262EDC6.2000501@univ-mlv.fr> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> Message-ID: As a Java programmer, "value-type class" doesn't mean anything to me. Is Integer a value-type class? If so, then Optional is not so odd. == still implies equals(); it does not return an arbitrary result. If Optional is not like anything else in Java (it's neither a primitive value nor an Object?) then a much more explicit disclaimer is needed. On Sat, Oct 19, 2013 at 1:38 PM, Remi Forax wrote: > On 10/19/2013 10:07 PM, Joe Bowbeer wrote: > >> Doug, >> >> I think I understand what you're saying to mean that Optional instances >> may be reused, which is what factory methods often do. >> > > no, the idea is that the VM can always replace Optional by the wrapped > value and re-wrap it if an Optional object is need. > Basically, Optional acts as a value type. In that case, the notion of > identity is very fuzzy. > > > >> If I understand, then I think it's confusing to say that == returns an >> arbitrary result. The meaning of == hasn't changed. For example, == might >> still be employed in an implementation of Optional.equals(). >> >> I'm not convinced that synchronized needs special treatment in the >> javadoc either. This should be clear to anyone who understands what reuse >> means. >> > > synchronized rely on the identity of the object. > > > >> I think the important point to document is that reuse may be arbitrary. >> In particular, the statement that empty() may return different instances >> -- this is surprising and needs to be documented. >> > > R?mi > > >> >> >> On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer > joe.bowbeer at gmail.com>**> wrote: >> >> I don't understand why == means nothing, or why there is special >> wording for == in the javadoc disclaimer. >> >> Why does potential reuse mean that == says nothing? Doesn't it >> still mean they are the same instance? That's not surprising. It >> is similar reuse to the valueOf factory methods, right? And the >> valueOf factory methods don't include a == disclaimer. It comes >> with the territory. >> >> Or does opt1 == opt2 no longer imply that opt1.equals(opt2) ? >> >> Or are Optional instances ephemeral? Making it impossible for >> applications to retain them. >> >> If either of the above, I think a more explicit disclaimer is needed. >> >> --Joe >> >> >> On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea
> > wrote: >> >> >> This arose while contemplating some JDK9 possibilities... >> >> Note that Optional is itself a value-like class, without >> a public constructor, just factory methods. >> The factory methods do not even guarantee to return unique >> objects. For all that the spec does and should say, >> every call to Optional.of could return the same Optional >> object. (This would require a magical implementation, >> but still not disallowed, and variants that sometimes >> return the same one are very much possible.) >> >> This means that there are no object-identity-related >> guarantees for Optionals. "myOptional1 == myOptional2" >> tells you nothing, and synchronized(myOptional) has >> unpredictable effects -- it might block forever. >> >> People might find this surprising, so we probably want to >> add a sentence or two to the javadoc. How about the following. >> (We could symmetrically say that the instance returned by >> Optional.empty() need not be the same each time, but that >> might be overkill?) >> >> /** >> * Returns an {@code Optional} with the specified present >> non-null value. >> adding... >> * The returned instance need not be unique. Thus the results of >> * comparing two instances using @code{==}, or using one as the >> * argument for a @code{synchronized} block are arbitrary and >> should >> * be avoided. >> * >> * @param the class of the value >> * @param value the value to be present, which must be >> non-null >> * @return an {@code Optional} with the value present >> * @throws NullPointerException if value is null >> */ >> public static Optional of(T value) { >> return new Optional<>(value); >> } >> >> >> >> > From forax at univ-mlv.fr Sat Oct 19 14:08:38 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 19 Oct 2013 23:08:38 +0200 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> Message-ID: <5262F4D6.4030309@univ-mlv.fr> On 10/19/2013 11:01 PM, Joe Bowbeer wrote: > As a Java programmer, "value-type class" doesn't mean anything to me. > > Is Integer a value-type class? If so, then Optional is not so odd. > == still implies equals(); it does not return an arbitrary result. > > If Optional is not like anything else in Java (it's neither a > primitive value nor an Object?) then a much more explicit disclaimer > is needed. There is a nice blog post from John Rose about value type. https://blogs.oracle.com/jrose/entry/value_types_in_the_vm R?mi > > > On Sat, Oct 19, 2013 at 1:38 PM, Remi Forax > wrote: > > On 10/19/2013 10:07 PM, Joe Bowbeer wrote: > > Doug, > > I think I understand what you're saying to mean that Optional > instances may be reused, which is what factory methods often do. > > > no, the idea is that the VM can always replace Optional by the > wrapped value and re-wrap it if an Optional object is need. > Basically, Optional acts as a value type. In that case, the notion > of identity is very fuzzy. > > > > If I understand, then I think it's confusing to say that == > returns an arbitrary result. The meaning of == hasn't > changed. For example, == might still be employed in an > implementation of Optional.equals(). > > I'm not convinced that synchronized needs special treatment in > the javadoc either. This should be clear to anyone who > understands what reuse means. > > > synchronized rely on the identity of the object. > > > > I think the important point to document is that reuse may be > arbitrary. In particular, the statement that empty() may > return different instances -- this is surprising and needs to > be documented. > > > R?mi > > > > > On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer > > >> > wrote: > > I don't understand why == means nothing, or why there is > special > wording for == in the javadoc disclaimer. > > Why does potential reuse mean that == says nothing? > Doesn't it > still mean they are the same instance? That's not > surprising. It > is similar reuse to the valueOf factory methods, right? > And the > valueOf factory methods don't include a == disclaimer. It > comes > with the territory. > > Or does opt1 == opt2 no longer imply that opt1.equals(opt2) ? > > Or are Optional instances ephemeral? Making it impossible for > applications to retain them. > > If either of the above, I think a more explicit disclaimer > is needed. > > --Joe > > > On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea >
> >> wrote: > > > This arose while contemplating some JDK9 possibilities... > > Note that Optional is itself a value-like class, without > a public constructor, just factory methods. > The factory methods do not even guarantee to return unique > objects. For all that the spec does and should say, > every call to Optional.of could return the same Optional > object. (This would require a magical implementation, > but still not disallowed, and variants that sometimes > return the same one are very much possible.) > > This means that there are no object-identity-related > guarantees for Optionals. "myOptional1 == myOptional2" > tells you nothing, and synchronized(myOptional) has > unpredictable effects -- it might block forever. > > People might find this surprising, so we probably want to > add a sentence or two to the javadoc. How about the > following. > (We could symmetrically say that the instance returned by > Optional.empty() need not be the same each time, but that > might be overkill?) > > /** > * Returns an {@code Optional} with the specified > present > non-null value. > adding... > * The returned instance need not be unique. Thus the > results of > * comparing two instances using @code{==}, or using > one as the > * argument for a @code{synchronized} block are > arbitrary and > should > * be avoided. > * > * @param the class of the value > * @param value the value to be present, which must be > non-null > * @return an {@code Optional} with the value present > * @throws NullPointerException if value is null > */ > public static Optional of(T value) { > return new Optional<>(value); > } > > > > > From brian.goetz at oracle.com Sat Oct 19 14:20:15 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 19 Oct 2013 17:20:15 -0400 Subject: A disclaimer or two for Optional In-Reply-To: <5262D303.5000106@univ-mlv.fr> References: <5262CC71.3020606@cs.oswego.edu> <5262D303.5000106@univ-mlv.fr> Message-ID: <5262F78F.6020700@oracle.com> I wish we could go farther. Such as: ... and will likely result in thrown exceptions in future versions of the JDK. On 10/19/2013 2:44 PM, Remi Forax wrote: > I agree. > > R?mi > > On 10/19/2013 08:16 PM, Doug Lea wrote: >> >> This arose while contemplating some JDK9 possibilities... >> >> Note that Optional is itself a value-like class, without >> a public constructor, just factory methods. >> The factory methods do not even guarantee to return unique >> objects. For all that the spec does and should say, >> every call to Optional.of could return the same Optional >> object. (This would require a magical implementation, >> but still not disallowed, and variants that sometimes >> return the same one are very much possible.) >> >> This means that there are no object-identity-related >> guarantees for Optionals. "myOptional1 == myOptional2" >> tells you nothing, and synchronized(myOptional) has >> unpredictable effects -- it might block forever. >> >> People might find this surprising, so we probably want to >> add a sentence or two to the javadoc. How about the following. >> (We could symmetrically say that the instance returned by >> Optional.empty() need not be the same each time, but that >> might be overkill?) >> >> /** >> * Returns an {@code Optional} with the specified present non-null >> value. >> adding... >> * The returned instance need not be unique. Thus the results of >> * comparing two instances using @code{==}, or using one as the >> * argument for a @code{synchronized} block are arbitrary and should >> * be avoided. >> * >> * @param the class of the value >> * @param value the value to be present, which must be non-null >> * @return an {@code Optional} with the value present >> * @throws NullPointerException if value is null >> */ >> public static Optional of(T value) { >> return new Optional<>(value); >> } >> > From joe.bowbeer at gmail.com Sat Oct 19 14:21:01 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sat, 19 Oct 2013 14:21:01 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <5262F4D6.4030309@univ-mlv.fr> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> Message-ID: Thanks, I'm aware of the blog post, but this post is not post of a Java programmer's education our experience, so some explicit treatment will be need if Optional is going to be breaking new ground. On Oct 19, 2013 2:11 PM, "Remi Forax" wrote: > On 10/19/2013 11:01 PM, Joe Bowbeer wrote: > >> As a Java programmer, "value-type class" doesn't mean anything to me. >> >> Is Integer a value-type class? If so, then Optional is not so odd. == >> still implies equals(); it does not return an arbitrary result. >> >> If Optional is not like anything else in Java (it's neither a primitive >> value nor an Object?) then a much more explicit disclaimer is needed. >> > > There is a nice blog post from John Rose about value type. > https://blogs.oracle.com/**jrose/entry/value_types_in_**the_vm > > R?mi > > >> >> On Sat, Oct 19, 2013 at 1:38 PM, Remi Forax > forax at univ-mlv.fr>> wrote: >> >> On 10/19/2013 10:07 PM, Joe Bowbeer wrote: >> >> Doug, >> >> I think I understand what you're saying to mean that Optional >> instances may be reused, which is what factory methods often do. >> >> >> no, the idea is that the VM can always replace Optional by the >> wrapped value and re-wrap it if an Optional object is need. >> Basically, Optional acts as a value type. In that case, the notion >> of identity is very fuzzy. >> >> >> >> If I understand, then I think it's confusing to say that == >> returns an arbitrary result. The meaning of == hasn't >> changed. For example, == might still be employed in an >> implementation of Optional.equals(). >> >> I'm not convinced that synchronized needs special treatment in >> the javadoc either. This should be clear to anyone who >> understands what reuse means. >> >> >> synchronized rely on the identity of the object. >> >> >> >> I think the important point to document is that reuse may be >> arbitrary. In particular, the statement that empty() may >> return different instances -- this is surprising and needs to >> be documented. >> >> >> R?mi >> >> >> >> >> On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer >> >> **>> >> wrote: >> >> I don't understand why == means nothing, or why there is >> special >> wording for == in the javadoc disclaimer. >> >> Why does potential reuse mean that == says nothing? >> Doesn't it >> still mean they are the same instance? That's not >> surprising. It >> is similar reuse to the valueOf factory methods, right? >> And the >> valueOf factory methods don't include a == disclaimer. It >> comes >> with the territory. >> >> Or does opt1 == opt2 no longer imply that opt1.equals(opt2) ? >> >> Or are Optional instances ephemeral? Making it impossible for >> applications to retain them. >> >> If either of the above, I think a more explicit disclaimer >> is needed. >> >> --Joe >> >> >> On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea >>
>> >> wrote: >> >> >> This arose while contemplating some JDK9 possibilities... >> >> Note that Optional is itself a value-like class, without >> a public constructor, just factory methods. >> The factory methods do not even guarantee to return unique >> objects. For all that the spec does and should say, >> every call to Optional.of could return the same Optional >> object. (This would require a magical implementation, >> but still not disallowed, and variants that sometimes >> return the same one are very much possible.) >> >> This means that there are no object-identity-related >> guarantees for Optionals. "myOptional1 == myOptional2" >> tells you nothing, and synchronized(myOptional) has >> unpredictable effects -- it might block forever. >> >> People might find this surprising, so we probably want to >> add a sentence or two to the javadoc. How about the >> following. >> (We could symmetrically say that the instance returned by >> Optional.empty() need not be the same each time, but that >> might be overkill?) >> >> /** >> * Returns an {@code Optional} with the specified >> present >> non-null value. >> adding... >> * The returned instance need not be unique. Thus the >> results of >> * comparing two instances using @code{==}, or using >> one as the >> * argument for a @code{synchronized} block are >> arbitrary and >> should >> * be avoided. >> * >> * @param the class of the value >> * @param value the value to be present, which must be >> non-null >> * @return an {@code Optional} with the value present >> * @throws NullPointerException if value is null >> */ >> public static Optional of(T value) { >> return new Optional<>(value); >> } >> >> >> >> >> >> > From brian.goetz at oracle.com Sat Oct 19 15:17:04 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 19 Oct 2013 18:17:04 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> Message-ID: <526304E0.6080305@oracle.com> OK, here's some of the background you may be missing. "A future version of Java" will almost certainly have support for "value types", "user-defined primitives", "identity-less aggregates", "structs", or whatever you would like to call them. Without making promises or projections or even going into any details, this is high on the priority list, and some nontrivial analysis has already been done on what it might look like and what the migration compatibility concerns would be. Doug's (completely correct) point about Optional is: morally, it *should* be a value type, and it would be a massive (and entirely predictable) shame if we could not, in a migration-compatible way, evolve it to be one in the future, when such a thing is possible to express in Java. The set of things that would break under such a migration is quite small: basically, "don't use it as a lock." Which, as Doug points out, is stupid anyway. It would be a shame if we lost the benefit of unboxing Optional just because we wanted to be compatible with some doofus using it as a lock object. This language just might be enough to deter such usage enough that we could justify the incidental breakage in the future for the sake of the greater good. On 10/19/2013 5:21 PM, Joe Bowbeer wrote: > Thanks, I'm aware of the blog post, but this post is not post of a Java > programmer's education our experience, so some explicit treatment will > be need if Optional is going to be breaking new ground. > > On Oct 19, 2013 2:11 PM, "Remi Forax" > wrote: > > On 10/19/2013 11:01 PM, Joe Bowbeer wrote: > > As a Java programmer, "value-type class" doesn't mean anything > to me. > > Is Integer a value-type class? If so, then Optional is not so > odd. == still implies equals(); it does not return an arbitrary > result. > > If Optional is not like anything else in Java (it's neither a > primitive value nor an Object?) then a much more explicit > disclaimer is needed. > > > There is a nice blog post from John Rose about value type. > https://blogs.oracle.com/__jrose/entry/value_types_in___the_vm > > > R?mi > > > > On Sat, Oct 19, 2013 at 1:38 PM, Remi Forax >> wrote: > > On 10/19/2013 10:07 PM, Joe Bowbeer wrote: > > Doug, > > I think I understand what you're saying to mean that > Optional > instances may be reused, which is what factory methods > often do. > > > no, the idea is that the VM can always replace Optional by the > wrapped value and re-wrap it if an Optional object is need. > Basically, Optional acts as a value type. In that case, the > notion > of identity is very fuzzy. > > > > If I understand, then I think it's confusing to say that == > returns an arbitrary result. The meaning of == hasn't > changed. For example, == might still be employed in an > implementation of Optional.equals(). > > I'm not convinced that synchronized needs special > treatment in > the javadoc either. This should be clear to anyone who > understands what reuse means. > > > synchronized rely on the identity of the object. > > > > I think the important point to document is that reuse > may be > arbitrary. In particular, the statement that empty() may > return different instances -- this is surprising and > needs to > be documented. > > > R?mi > > > > > On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer > > > > >__>> > wrote: > > I don't understand why == means nothing, or why > there is > special > wording for == in the javadoc disclaimer. > > Why does potential reuse mean that == says nothing? > Doesn't it > still mean they are the same instance? That's not > surprising. It > is similar reuse to the valueOf factory methods, right? > And the > valueOf factory methods don't include a == > disclaimer. It > comes > with the territory. > > Or does opt1 == opt2 no longer imply that > opt1.equals(opt2) ? > > Or are Optional instances ephemeral? Making it > impossible for > applications to retain them. > > If either of the above, I think a more explicit > disclaimer > is needed. > > --Joe > > > On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea >
> > > > >>> wrote: > > > This arose while contemplating some JDK9 > possibilities... > > Note that Optional is itself a value-like > class, without > a public constructor, just factory methods. > The factory methods do not even guarantee to > return unique > objects. For all that the spec does and should say, > every call to Optional.of could return the same > Optional > object. (This would require a magical > implementation, > but still not disallowed, and variants that > sometimes > return the same one are very much possible.) > > This means that there are no > object-identity-related > guarantees for Optionals. "myOptional1 == > myOptional2" > tells you nothing, and synchronized(myOptional) has > unpredictable effects -- it might block forever. > > People might find this surprising, so we > probably want to > add a sentence or two to the javadoc. How about the > following. > (We could symmetrically say that the instance > returned by > Optional.empty() need not be the same each > time, but that > might be overkill?) > > /** > * Returns an {@code Optional} with the > specified > present > non-null value. > adding... > * The returned instance need not be unique. > Thus the > results of > * comparing two instances using @code{==}, or using > one as the > * argument for a @code{synchronized} block are > arbitrary and > should > * be avoided. > * > * @param the class of the value > * @param value the value to be present, > which must be > non-null > * @return an {@code Optional} with the > value present > * @throws NullPointerException if value is > null > */ > public static Optional of(T value) { > return new Optional<>(value); > } > > > > > > From ali.ebrahimi1781 at gmail.com Sat Oct 19 16:23:17 2013 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sun, 20 Oct 2013 02:53:17 +0330 Subject: A disclaimer or two for Optional In-Reply-To: <526304E0.6080305@oracle.com> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> Message-ID: Or even annotate with @ValueType and javac warn for undesirable usages (lock object, ...). On Sun, Oct 20, 2013 at 1:47 AM, Brian Goetz wrote: > OK, here's some of the background you may be missing. > > "A future version of Java" will almost certainly have support for "value > types", "user-defined primitives", "identity-less aggregates", "structs", > or whatever you would like to call them. Without making promises or > projections or even going into any details, this is high on the priority > list, and some nontrivial analysis has already been done on what it might > look like and what the migration compatibility concerns would be. > > Doug's (completely correct) point about Optional is: morally, it *should* > be a value type, and it would be a massive (and entirely predictable) shame > if we could not, in a migration-compatible way, evolve it to be one in the > future, when such a thing is possible to express in Java. > > The set of things that would break under such a migration is quite small: > basically, "don't use it as a lock." Which, as Doug points out, is stupid > anyway. It would be a shame if we lost the benefit of unboxing Optional > just because we wanted to be compatible with some doofus using it as a lock > object. > > This language just might be enough to deter such usage enough that we > could justify the incidental breakage in the future for the sake of the > greater good. > > > > > On 10/19/2013 5:21 PM, Joe Bowbeer wrote: > >> Thanks, I'm aware of the blog post, but this post is not post of a Java >> programmer's education our experience, so some explicit treatment will >> be need if Optional is going to be breaking new ground. >> >> On Oct 19, 2013 2:11 PM, "Remi Forax" > > wrote: >> >> On 10/19/2013 11:01 PM, Joe Bowbeer wrote: >> >> As a Java programmer, "value-type class" doesn't mean anything >> to me. >> >> Is Integer a value-type class? If so, then Optional is not so >> odd. == still implies equals(); it does not return an arbitrary >> result. >> >> If Optional is not like anything else in Java (it's neither a >> primitive value nor an Object?) then a much more explicit >> disclaimer is needed. >> >> >> There is a nice blog post from John Rose about value type. >> https://blogs.oracle.com/__**jrose/entry/value_types_in___**the_vm >> >> >> > >> >> R?mi >> >> >> >> On Sat, Oct 19, 2013 at 1:38 PM, Remi Forax > > >> >> wrote: >> >> On 10/19/2013 10:07 PM, Joe Bowbeer wrote: >> >> Doug, >> >> I think I understand what you're saying to mean that >> Optional >> instances may be reused, which is what factory methods >> often do. >> >> >> no, the idea is that the VM can always replace Optional by >> the >> wrapped value and re-wrap it if an Optional object is need. >> Basically, Optional acts as a value type. In that case, the >> notion >> of identity is very fuzzy. >> >> >> >> If I understand, then I think it's confusing to say that >> == >> returns an arbitrary result. The meaning of == hasn't >> changed. For example, == might still be employed in an >> implementation of Optional.equals(). >> >> I'm not convinced that synchronized needs special >> treatment in >> the javadoc either. This should be clear to anyone who >> understands what reuse means. >> >> >> synchronized rely on the identity of the object. >> >> >> >> I think the important point to document is that reuse >> may be >> arbitrary. In particular, the statement that empty() may >> return different instances -- this is surprising and >> needs to >> be documented. >> >> >> R?mi >> >> >> >> >> On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer >> >> **> >> > > **>__>> >> >> wrote: >> >> I don't understand why == means nothing, or why >> there is >> special >> wording for == in the javadoc disclaimer. >> >> Why does potential reuse mean that == says nothing? >> Doesn't it >> still mean they are the same instance? That's not >> surprising. It >> is similar reuse to the valueOf factory methods, >> right? >> And the >> valueOf factory methods don't include a == >> disclaimer. It >> comes >> with the territory. >> >> Or does opt1 == opt2 no longer imply that >> opt1.equals(opt2) ? >> >> Or are Optional instances ephemeral? Making it >> impossible for >> applications to retain them. >> >> If either of the above, I think a more explicit >> disclaimer >> is needed. >> >> --Joe >> >> >> On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea >>
>> > >> >> >>> wrote: >> >> >> This arose while contemplating some JDK9 >> possibilities... >> >> Note that Optional is itself a value-like >> class, without >> a public constructor, just factory methods. >> The factory methods do not even guarantee to >> return unique >> objects. For all that the spec does and should >> say, >> every call to Optional.of could return the same >> Optional >> object. (This would require a magical >> implementation, >> but still not disallowed, and variants that >> sometimes >> return the same one are very much possible.) >> >> This means that there are no >> object-identity-related >> guarantees for Optionals. "myOptional1 == >> myOptional2" >> tells you nothing, and synchronized(myOptional) >> has >> unpredictable effects -- it might block forever. >> >> People might find this surprising, so we >> probably want to >> add a sentence or two to the javadoc. How about >> the >> following. >> (We could symmetrically say that the instance >> returned by >> Optional.empty() need not be the same each >> time, but that >> might be overkill?) >> >> /** >> * Returns an {@code Optional} with the >> specified >> present >> non-null value. >> adding... >> * The returned instance need not be unique. >> Thus the >> results of >> * comparing two instances using @code{==}, or >> using >> one as the >> * argument for a @code{synchronized} block are >> arbitrary and >> should >> * be avoided. >> * >> * @param the class of the value >> * @param value the value to be present, >> which must be >> non-null >> * @return an {@code Optional} with the >> value present >> * @throws NullPointerException if value is >> null >> */ >> public static Optional of(T value) { >> return new Optional<>(value); >> } >> >> >> >> >> >> >> From josh at bloch.us Sat Oct 19 18:32:59 2013 From: josh at bloch.us (Joshua Bloch) Date: Sat, 19 Oct 2013 18:32:59 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <526304E0.6080305@oracle.com> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> Message-ID: Brian, On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz wrote: > OK, here's some of the background you may be missing. > > "A future version of Java" will almost certainly have support for "value > types", "user-defined primitives", "identity-less aggregates", "structs", > or whatever you would like to call them. Without making promises or > projections or even going into anTy details, this is high on the priority > list, and some nontrivial analysis has already been done on what it might > look like and what the migration compatibility concerns would be. > That's great because, frankly, Java's type system is way too simple. I'm glad you guys are investigating ways to make it more complex, and to provide additional ways to do things that people are already doing. This will keep Java programmers on their toes, which, frankly, is just what they need. Josh From joe.bowbeer at gmail.com Sat Oct 19 19:23:56 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sat, 19 Oct 2013 19:23:56 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <526304E0.6080305@oracle.com> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> Message-ID: Thanks for the background. You can see the problem though. This discussion is like a chapter from Flatland. In this case a value-type visitor from the future is trying to explain its existence to the current denizens of Java land. If Optional is not like something else that exists now, then statements about what not to do will cause confusion. (Java programmers will interpret the statements in terms of what they know, like I did, and probably get it wrong.) You need to give this new thing a name (like @ValueType) to make it clear that this is something new and unfamiliar. On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz wrote: > OK, here's some of the background you may be missing. > > "A future version of Java" will almost certainly have support for "value > types", "user-defined primitives", "identity-less aggregates", "structs", > or whatever you would like to call them. Without making promises or > projections or even going into any details, this is high on the priority > list, and some nontrivial analysis has already been done on what it might > look like and what the migration compatibility concerns would be. > > Doug's (completely correct) point about Optional is: morally, it *should* > be a value type, and it would be a massive (and entirely predictable) shame > if we could not, in a migration-compatible way, evolve it to be one in the > future, when such a thing is possible to express in Java. > > The set of things that would break under such a migration is quite small: > basically, "don't use it as a lock." Which, as Doug points out, is stupid > anyway. It would be a shame if we lost the benefit of unboxing Optional > just because we wanted to be compatible with some doofus using it as a lock > object. > > This language just might be enough to deter such usage enough that we > could justify the incidental breakage in the future for the sake of the > greater good. > > > > > On 10/19/2013 5:21 PM, Joe Bowbeer wrote: > >> Thanks, I'm aware of the blog post, but this post is not post of a Java >> programmer's education our experience, so some explicit treatment will >> be need if Optional is going to be breaking new ground. >> >> On Oct 19, 2013 2:11 PM, "Remi Forax" > > wrote: >> >> On 10/19/2013 11:01 PM, Joe Bowbeer wrote: >> >> As a Java programmer, "value-type class" doesn't mean anything >> to me. >> >> Is Integer a value-type class? If so, then Optional is not so >> odd. == still implies equals(); it does not return an arbitrary >> result. >> >> If Optional is not like anything else in Java (it's neither a >> primitive value nor an Object?) then a much more explicit >> disclaimer is needed. >> >> >> There is a nice blog post from John Rose about value type. >> https://blogs.oracle.com/__**jrose/entry/value_types_in___**the_vm >> >> >> > >> >> R?mi >> >> >> >> On Sat, Oct 19, 2013 at 1:38 PM, Remi Forax > > >> >> wrote: >> >> On 10/19/2013 10:07 PM, Joe Bowbeer wrote: >> >> Doug, >> >> I think I understand what you're saying to mean that >> Optional >> instances may be reused, which is what factory methods >> often do. >> >> >> no, the idea is that the VM can always replace Optional by >> the >> wrapped value and re-wrap it if an Optional object is need. >> Basically, Optional acts as a value type. In that case, the >> notion >> of identity is very fuzzy. >> >> >> >> If I understand, then I think it's confusing to say that >> == >> returns an arbitrary result. The meaning of == hasn't >> changed. For example, == might still be employed in an >> implementation of Optional.equals(). >> >> I'm not convinced that synchronized needs special >> treatment in >> the javadoc either. This should be clear to anyone who >> understands what reuse means. >> >> >> synchronized rely on the identity of the object. >> >> >> >> I think the important point to document is that reuse >> may be >> arbitrary. In particular, the statement that empty() may >> return different instances -- this is surprising and >> needs to >> be documented. >> >> >> R?mi >> >> >> >> >> On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer >> >> **> >> > > **>__>> >> >> wrote: >> >> I don't understand why == means nothing, or why >> there is >> special >> wording for == in the javadoc disclaimer. >> >> Why does potential reuse mean that == says nothing? >> Doesn't it >> still mean they are the same instance? That's not >> surprising. It >> is similar reuse to the valueOf factory methods, >> right? >> And the >> valueOf factory methods don't include a == >> disclaimer. It >> comes >> with the territory. >> >> Or does opt1 == opt2 no longer imply that >> opt1.equals(opt2) ? >> >> Or are Optional instances ephemeral? Making it >> impossible for >> applications to retain them. >> >> If either of the above, I think a more explicit >> disclaimer >> is needed. >> >> --Joe >> >> >> On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea >>
>> > >> >> >>> wrote: >> >> >> This arose while contemplating some JDK9 >> possibilities... >> >> Note that Optional is itself a value-like >> class, without >> a public constructor, just factory methods. >> The factory methods do not even guarantee to >> return unique >> objects. For all that the spec does and should >> say, >> every call to Optional.of could return the same >> Optional >> object. (This would require a magical >> implementation, >> but still not disallowed, and variants that >> sometimes >> return the same one are very much possible.) >> >> This means that there are no >> object-identity-related >> guarantees for Optionals. "myOptional1 == >> myOptional2" >> tells you nothing, and synchronized(myOptional) >> has >> unpredictable effects -- it might block forever. >> >> People might find this surprising, so we >> probably want to >> add a sentence or two to the javadoc. How about >> the >> following. >> (We could symmetrically say that the instance >> returned by >> Optional.empty() need not be the same each >> time, but that >> might be overkill?) >> >> /** >> * Returns an {@code Optional} with the >> specified >> present >> non-null value. >> adding... >> * The returned instance need not be unique. >> Thus the >> results of >> * comparing two instances using @code{==}, or >> using >> one as the >> * argument for a @code{synchronized} block are >> arbitrary and >> should >> * be avoided. >> * >> * @param the class of the value >> * @param value the value to be present, >> which must be >> non-null >> * @return an {@code Optional} with the >> value present >> * @throws NullPointerException if value is >> null >> */ >> public static Optional of(T value) { >> return new Optional<>(value); >> } >> >> >> >> >> >> >> From brian.goetz at oracle.com Sat Oct 19 19:33:35 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 19 Oct 2013 22:33:35 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> Message-ID: <526340FF.10901@oracle.com> The Flatland analogy is apt! Doug's wording was carefully chosen to be consistent and sensible in the present reality, but the motivation did ride into town on a flux capacitor. Its a delicate dance between claiming to predict the future and ignoring a very real and entirely forseeable risk. But you can see the point. IF we're going to have values, then Optional should certainly be one; all the type safety with non of the runtime overhead of boxes, identity, object headers, or indirection. What a shame it would be if we couldn't make that change when we got there, just because someone used it as a lock. On 10/19/2013 10:23 PM, Joe Bowbeer wrote: > Thanks for the background. You can see the problem though. This > discussion is like a chapter from Flatland. In this case a value-type > visitor from the future is trying to explain its existence to the > current denizens of Java land. If Optional is not like something else > that exists now, then statements about what not to do will cause > confusion. (Java programmers will interpret the statements in terms of > what they know, like I did, and probably get it wrong.) You need to > give this new thing a name (like @ValueType) to make it clear that this > is something new and unfamiliar. > > > On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz > wrote: > > OK, here's some of the background you may be missing. > > "A future version of Java" will almost certainly have support for > "value types", "user-defined primitives", "identity-less > aggregates", "structs", or whatever you would like to call them. > Without making promises or projections or even going into any > details, this is high on the priority list, and some nontrivial > analysis has already been done on what it might look like and what > the migration compatibility concerns would be. > > Doug's (completely correct) point about Optional is: morally, it > *should* be a value type, and it would be a massive (and entirely > predictable) shame if we could not, in a migration-compatible way, > evolve it to be one in the future, when such a thing is possible to > express in Java. > > The set of things that would break under such a migration is quite > small: basically, "don't use it as a lock." Which, as Doug points > out, is stupid anyway. It would be a shame if we lost the benefit > of unboxing Optional just because we wanted to be compatible with > some doofus using it as a lock object. > > This language just might be enough to deter such usage enough that > we could justify the incidental breakage in the future for the sake > of the greater good. > > > > > On 10/19/2013 5:21 PM, Joe Bowbeer wrote: > > Thanks, I'm aware of the blog post, but this post is not post of > a Java > programmer's education our experience, so some explicit > treatment will > be need if Optional is going to be breaking new ground. > > On Oct 19, 2013 2:11 PM, "Remi Forax" > >> wrote: > > On 10/19/2013 11:01 PM, Joe Bowbeer wrote: > > As a Java programmer, "value-type class" doesn't mean > anything > to me. > > Is Integer a value-type class? If so, then Optional is > not so > odd. == still implies equals(); it does not return an > arbitrary > result. > > If Optional is not like anything else in Java (it's > neither a > primitive value nor an Object?) then a much more explicit > disclaimer is needed. > > > There is a nice blog post from John Rose about value type. > https://blogs.oracle.com/____jrose/entry/value_types_in_____the_vm > > > > > > > R?mi > > > > On Sat, Oct 19, 2013 at 1:38 PM, Remi Forax > > > > > > >>> > wrote: > > On 10/19/2013 10:07 PM, Joe Bowbeer wrote: > > Doug, > > I think I understand what you're saying to > mean that > Optional > instances may be reused, which is what factory > methods > often do. > > > no, the idea is that the VM can always replace > Optional by the > wrapped value and re-wrap it if an Optional object > is need. > Basically, Optional acts as a value type. In that > case, the > notion > of identity is very fuzzy. > > > > If I understand, then I think it's confusing > to say that == > returns an arbitrary result. The meaning of > == hasn't > changed. For example, == might still be > employed in an > implementation of Optional.equals(). > > I'm not convinced that synchronized needs special > treatment in > the javadoc either. This should be clear to > anyone who > understands what reuse means. > > > synchronized rely on the identity of the object. > > > > I think the important point to document is > that reuse > may be > arbitrary. In particular, the statement that > empty() may > return different instances -- this is > surprising and > needs to > be documented. > > > R?mi > > > > > On Sat, Oct 19, 2013 at 12:54 PM, Joe Bowbeer > > > >__> > > > > >__>__>> > > wrote: > > I don't understand why == means nothing, > or why > there is > special > wording for == in the javadoc disclaimer. > > Why does potential reuse mean that == says > nothing? > Doesn't it > still mean they are the same instance? > That's not > surprising. It > is similar reuse to the valueOf factory > methods, right? > And the > valueOf factory methods don't include a == > disclaimer. It > comes > with the territory. > > Or does opt1 == opt2 no longer imply that > opt1.equals(opt2) ? > > Or are Optional instances ephemeral? > Making it > impossible for > applications to retain them. > > If either of the above, I think a more > explicit > disclaimer > is needed. > > --Joe > > > On Sat, Oct 19, 2013 at 11:16 AM, Doug Lea >
> > > > >> > > > > >>>> wrote: > > > This arose while contemplating some JDK9 > possibilities... > > Note that Optional is itself a value-like > class, without > a public constructor, just factory > methods. > The factory methods do not even > guarantee to > return unique > objects. For all that the spec does > and should say, > every call to Optional.of could return > the same > Optional > object. (This would require a magical > implementation, > but still not disallowed, and variants > that > sometimes > return the same one are very much > possible.) > > This means that there are no > object-identity-related > guarantees for Optionals. "myOptional1 == > myOptional2" > tells you nothing, and > synchronized(myOptional) has > unpredictable effects -- it might > block forever. > > People might find this surprising, so we > probably want to > add a sentence or two to the javadoc. > How about the > following. > (We could symmetrically say that the > instance > returned by > Optional.empty() need not be the same > each > time, but that > might be overkill?) > > /** > * Returns an {@code Optional} > with the > specified > present > non-null value. > adding... > * The returned instance need not be > unique. > Thus the > results of > * comparing two instances using > @code{==}, or using > one as the > * argument for a @code{synchronized} > block are > arbitrary and > should > * be avoided. > * > * @param the class of the value > * @param value the value to be > present, > which must be > non-null > * @return an {@code Optional} > with the > value present > * @throws NullPointerException if > value is > null > */ > public static Optional of(T > value) { > return new Optional<>(value); > } > > > > > > > From forax at univ-mlv.fr Sun Oct 20 05:49:12 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 20 Oct 2013 14:49:12 +0200 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> Message-ID: <5263D148.3080404@univ-mlv.fr> On 10/20/2013 03:32 AM, Joshua Bloch wrote: > Brian, > > > On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz > wrote: > > OK, here's some of the background you may be missing. > > "A future version of Java" will almost certainly have support for > "value types", "user-defined primitives", "identity-less > aggregates", "structs", or whatever you would like to call them. > Without making promises or projections or even going into anTy > details, this is high on the priority list, and some nontrivial > analysis has already been done on what it might look like and what > the migration compatibility concerns would be. > > > That's great because, frankly, Java's type system is way too simple. > I'm glad you guys are investigating ways to make it more complex, and > to provide additional ways to do things that people are already doing. > This will keep Java programmers on their toes, which, frankly, is just > what they need. > > Josh Hi Josh, It's a consequence of the introduction of auto-boxing/unboxing. When you call Integer.valueOf() you explicitly say that you don't care about the identity of the returned object, only the wrapped value is important. As you know, you can not predict the result of Integer.valueOf(x) == Integer.valueOf(x), which means that == on Integer is meaningless. Currently, the code that try to remove boxing in the VM is full of special cases because the semantics of boxing is not the same for each wrappers (and is also partially specified in each Wrapper.valueOf). Recognizing that value types already exist in Java, and give them a proper documented semantics* is in my opinion a good idea. cheers, R?mi *by example, what is an array of value types is an interesting question. From dl at cs.oswego.edu Sun Oct 20 06:13:20 2013 From: dl at cs.oswego.edu (Doug Lea) Date: Sun, 20 Oct 2013 09:13:20 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> Message-ID: <5263D6F0.8030307@cs.oswego.edu> On 10/19/2013 03:38 PM, Tim Peierls wrote: > I suppose there's no harm in adding this, but I think most people already get > that a reference to an Optional isn't a meaningful value. > The reaction of others seems to argue for adding the wording. Most people know that comparing Integers via "==" is almost always wrong. (So wrong that autoboxing normally rescues you from this if one of the arguments is an int.) And most people would not even think to do synchronized(Integer.valueOf(aNumber), and would if asked think that it is such a terrible idea that it is a good candidate to being outlawed. But most people haven't noticed that the same issues apply even moreso to Optional. -Doug > > On Sat, Oct 19, 2013 at 2:16 PM, Doug Lea
> wrote: > > > This arose while contemplating some JDK9 possibilities... > > Note that Optional is itself a value-like class, without > a public constructor, just factory methods. > The factory methods do not even guarantee to return unique > objects. For all that the spec does and should say, > every call to Optional.of could return the same Optional > object. (This would require a magical implementation, > but still not disallowed, and variants that sometimes > return the same one are very much possible.) > > This means that there are no object-identity-related > guarantees for Optionals. "myOptional1 == myOptional2" > tells you nothing, and synchronized(myOptional) has > unpredictable effects -- it might block forever. > > People might find this surprising, so we probably want to > add a sentence or two to the javadoc. How about the following. > (We could symmetrically say that the instance returned by > Optional.empty() need not be the same each time, but that > might be overkill?) > > /** > * Returns an {@code Optional} with the specified present non-null value. > adding... > * The returned instance need not be unique. Thus the results of > * comparing two instances using @code{==}, or using one as the > * argument for a @code{synchronized} block are arbitrary and should > * be avoided. > * > * @param the class of the value > * @param value the value to be present, which must be non-null > * @return an {@code Optional} with the value present > * @throws NullPointerException if value is null > */ > public static Optional of(T value) { > return new Optional<>(value); > } > > From tim at peierls.net Sun Oct 20 07:54:30 2013 From: tim at peierls.net (Tim Peierls) Date: Sun, 20 Oct 2013 10:54:30 -0400 Subject: A disclaimer or two for Optional In-Reply-To: <5263D6F0.8030307@cs.oswego.edu> References: <5262CC71.3020606@cs.oswego.edu> <5263D6F0.8030307@cs.oswego.edu> Message-ID: On Sun, Oct 20, 2013 at 9:13 AM, Doug Lea
wrote: > On 10/19/2013 03:38 PM, Tim Peierls wrote: > >> I suppose there's no harm in adding this, but I think most people already >> get >> that a reference to an Optional isn't a meaningful value. >> > > The reaction of others seems to argue for adding the wording. > Most people know that comparing Integers via "==" is > almost always wrong. (So wrong that autoboxing normally > rescues you from this if one of the arguments is an int.) > And most people would not even think to do > synchronized(Integer.valueOf(**aNumber), and would if asked > think that it is such a terrible idea that it is a good > candidate to being outlawed. > But most people haven't noticed that the same issues apply > even moreso to Optional. I think the opposite is true: People are more likely to make mistakes because of autoboxing than they are to write code that synchronizes on Optional instances or compares Optional references. The virtue of Optional, in my experience with the Guava variety, is that the compiler never lets you forget that you aren't dealing with a Foo, you're dealing with a (probably lightweight, possibly magical) potential container of a Foo. It's no more tempting to say "synchronized (optionalFoo)" than it is to say "synchronized (singletonFoo)". Maybe even less tempting, because a singleton at least has a (misleading) whiff of permanence, whereas an optional thing might not be there at all. It's fine to warn people in general about the potential pitfalls that exist today or that might arise in the future due to new language features. It just seems strange to focus on Optional, a class whose name practically shouts to the user, "Don't synchronize on me!" --tim From brian.goetz at oracle.com Sun Oct 20 08:41:39 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 20 Oct 2013 11:41:39 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5263D6F0.8030307@cs.oswego.edu> Message-ID: <5263F9B3.1070107@oracle.com> > It's fine to warn people in general about the potential pitfalls that > exist today or that might arise in the future due to new language > features. It just seems strange to focus on Optional, a class whose name > practically shouts to the user, "Don't synchronize on me!" Its not *just* Optional. For example, the JSR-310 folks are listening to this discussion with interest, since all of their new date-time classes are morally values, and they would understandably prefer to not have them all boxed. But we should only focus on stuff that's new in 8; the previous classes that are morally values are likely too far polluted with existing usages. Its only the new value-ish classes in 8 that we have a fighting chance of turning into values in a future version. From joe.bowbeer at gmail.com Sun Oct 20 09:08:29 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sun, 20 Oct 2013 09:08:29 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <5263D148.3080404@univ-mlv.fr> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> Message-ID: Remi: Integer.valueOf is defined to return singletons for a range of values near zero, and new instances in other cases. Java programmers understand what this means, and their code sometimes depends on it. On Oct 20, 2013 5:52 AM, "Remi Forax" wrote: > On 10/20/2013 03:32 AM, Joshua Bloch wrote: > >> Brian, >> >> >> On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz > brian.goetz at oracle.com**>> wrote: >> >> OK, here's some of the background you may be missing. >> >> "A future version of Java" will almost certainly have support for >> "value types", "user-defined primitives", "identity-less >> aggregates", "structs", or whatever you would like to call them. >> Without making promises or projections or even going into anTy >> details, this is high on the priority list, and some nontrivial >> analysis has already been done on what it might look like and what >> the migration compatibility concerns would be. >> >> >> That's great because, frankly, Java's type system is way too simple. I'm >> glad you guys are investigating ways to make it more complex, and to >> provide additional ways to do things that people are already doing. This >> will keep Java programmers on their toes, which, frankly, is just what they >> need. >> >> Josh >> > > Hi Josh, > > It's a consequence of the introduction of auto-boxing/unboxing. > When you call Integer.valueOf() you explicitly say that you don't care > about the identity of the returned object, only the wrapped value is > important. > As you know, you can not predict the result of Integer.valueOf(x) == > Integer.valueOf(x), which means that == on Integer is meaningless. > > Currently, the code that try to remove boxing in the VM is full of special > cases because the semantics of boxing is not the same for each wrappers > (and is also partially specified in each Wrapper.valueOf). Recognizing that > value types already exist in Java, and give them a proper documented > semantics* is in my opinion a good idea. > > cheers, > R?mi > *by example, what is an array of value types is an interesting question. > > From brian.goetz at oracle.com Sun Oct 20 09:09:57 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 20 Oct 2013 12:09:57 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> Message-ID: <52640055.8000304@oracle.com> Right, which is why Integer is likely too far polluted to be rescued. But, wouldn't it have been better if we could enforce that no one depended on it in the first place? Wouldn't it be a shame for Optional to join it in the "hopelessly polluted by identity" department? On 10/20/2013 12:08 PM, Joe Bowbeer wrote: > Remi: Integer.valueOf is defined to return singletons for a range of > values near zero, and new instances in other cases. Java programmers > understand what this means, and their code sometimes depends on it. > > On Oct 20, 2013 5:52 AM, "Remi Forax" > wrote: > > On 10/20/2013 03:32 AM, Joshua Bloch wrote: > > Brian, > > > On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz > > __>> wrote: > > OK, here's some of the background you may be missing. > > "A future version of Java" will almost certainly have > support for > "value types", "user-defined primitives", "identity-less > aggregates", "structs", or whatever you would like to call > them. > Without making promises or projections or even going into anTy > details, this is high on the priority list, and some nontrivial > analysis has already been done on what it might look like > and what > the migration compatibility concerns would be. > > > That's great because, frankly, Java's type system is way too > simple. I'm glad you guys are investigating ways to make it > more complex, and to provide additional ways to do things that > people are already doing. This will keep Java programmers on > their toes, which, frankly, is just what they need. > > Josh > > > Hi Josh, > > It's a consequence of the introduction of auto-boxing/unboxing. > When you call Integer.valueOf() you explicitly say that you don't > care about the identity of the returned object, only the wrapped > value is important. > As you know, you can not predict the result of Integer.valueOf(x) == > Integer.valueOf(x), which means that == on Integer is meaningless. > > Currently, the code that try to remove boxing in the VM is full of > special cases because the semantics of boxing is not the same for > each wrappers (and is also partially specified in each > Wrapper.valueOf). Recognizing that value types already exist in > Java, and give them a proper documented semantics* is in my opinion > a good idea. > > cheers, > R?mi > *by example, what is an array of value types is an interesting question. > From josh at bloch.us Sun Oct 20 09:41:26 2013 From: josh at bloch.us (Joshua Bloch) Date: Sun, 20 Oct 2013 09:41:26 -0700 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5263D6F0.8030307@cs.oswego.edu> Message-ID: I agree with Tim. Regarding Remi's apologia: Having == mean object identity was a mistake, albeit one made two decades ago. Of course it should have been a synonym for .equals when applied to object references. But what's done is done. Support for autoboxing was another mistake: pretty much the only thing it's used for is collections of primitives. It would have been better to support them via some form of generics that applied to primitives, via heterogeneous translation. It's amazing how many puzzlers were caused by autoboxing:( Unlike the == flub, this one would haave required real effort to right, but it would have been worth it. It might still be worth doing, but probably not. It would involve some change to the type system, which is a bad thing. Given that we did support autoboxing in Java 5, it was a huge mistake to preserve the meaning of == when applied to boxed primitives. It produces the horrible situation where the == operator does something completely different from <= and >= when applied to boxed primitives. This was common sense sacrificed at the altar of backwards compatibility. And it would still be easy to fix this one. Any program whose behavior changes as a result of the obvious fix probably contained a bug that would be fixed by the change. Regards from the Airport Flyer Bus (PIttsburgh, PA), Josh On Sun, Oct 20, 2013 at 7:54 AM, Tim Peierls wrote: > On Sun, Oct 20, 2013 at 9:13 AM, Doug Lea
wrote: > >> On 10/19/2013 03:38 PM, Tim Peierls wrote: >> >>> I suppose there's no harm in adding this, but I think most people >>> already get >>> that a reference to an Optional isn't a meaningful value. >>> >> >> The reaction of others seems to argue for adding the wording. >> Most people know that comparing Integers via "==" is >> almost always wrong. (So wrong that autoboxing normally >> rescues you from this if one of the arguments is an int.) >> And most people would not even think to do >> synchronized(Integer.valueOf(**aNumber), and would if asked >> think that it is such a terrible idea that it is a good >> candidate to being outlawed. >> But most people haven't noticed that the same issues apply >> even moreso to Optional. > > > I think the opposite is true: People are more likely to make mistakes > because of autoboxing than they are to write code that synchronizes on > Optional instances or compares Optional references. > > The virtue of Optional, in my experience with the Guava variety, is that > the compiler never lets you forget that you aren't dealing with a Foo, > you're dealing with a (probably lightweight, possibly magical) potential > container of a Foo. It's no more tempting to say "synchronized > (optionalFoo)" than it is to say "synchronized (singletonFoo)". Maybe even > less tempting, because a singleton at least has a (misleading) whiff of > permanence, whereas an optional thing might not be there at all. > > It's fine to warn people in general about the potential pitfalls that > exist today or that might arise in the future due to new language features. > It just seems strange to focus on Optional, a class whose name practically > shouts to the user, "Don't synchronize on me!" > > --tim > From forax at univ-mlv.fr Sun Oct 20 09:44:22 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 20 Oct 2013 18:44:22 +0200 Subject: A disclaimer or two for Optional In-Reply-To: <52640055.8000304@oracle.com> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> Message-ID: <52640866.6010707@univ-mlv.fr> On 10/20/2013 06:09 PM, Brian Goetz wrote: > Right, which is why Integer is likely too far polluted to be rescued. > But, wouldn't it have been better if we could enforce that no one > depended on it in the first place? Wouldn't it be a shame for > Optional to join it in the "hopelessly polluted by identity" department? JLS 5.1.7 is what is what is usually called a premature optimization. IMO the only sane choice is to just remove the wording about caching and performance and pretend that it has never existed. R?mi > > On 10/20/2013 12:08 PM, Joe Bowbeer wrote: >> Remi: Integer.valueOf is defined to return singletons for a range of >> values near zero, and new instances in other cases. Java programmers >> understand what this means, and their code sometimes depends on it. >> >> On Oct 20, 2013 5:52 AM, "Remi Forax" > > wrote: >> >> On 10/20/2013 03:32 AM, Joshua Bloch wrote: >> >> Brian, >> >> >> On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz >> >> > __>> wrote: >> >> OK, here's some of the background you may be missing. >> >> "A future version of Java" will almost certainly have >> support for >> "value types", "user-defined primitives", "identity-less >> aggregates", "structs", or whatever you would like to call >> them. >> Without making promises or projections or even going >> into anTy >> details, this is high on the priority list, and some >> nontrivial >> analysis has already been done on what it might look like >> and what >> the migration compatibility concerns would be. >> >> >> That's great because, frankly, Java's type system is way too >> simple. I'm glad you guys are investigating ways to make it >> more complex, and to provide additional ways to do things that >> people are already doing. This will keep Java programmers on >> their toes, which, frankly, is just what they need. >> >> Josh >> >> >> Hi Josh, >> >> It's a consequence of the introduction of auto-boxing/unboxing. >> When you call Integer.valueOf() you explicitly say that you don't >> care about the identity of the returned object, only the wrapped >> value is important. >> As you know, you can not predict the result of Integer.valueOf(x) == >> Integer.valueOf(x), which means that == on Integer is meaningless. >> >> Currently, the code that try to remove boxing in the VM is full of >> special cases because the semantics of boxing is not the same for >> each wrappers (and is also partially specified in each >> Wrapper.valueOf). Recognizing that value types already exist in >> Java, and give them a proper documented semantics* is in my opinion >> a good idea. >> >> cheers, >> R?mi >> *by example, what is an array of value types is an interesting >> question. >> From josh at bloch.us Sun Oct 20 09:59:42 2013 From: josh at bloch.us (Joshua Bloch) Date: Sun, 20 Oct 2013 09:59:42 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <52640866.6010707@univ-mlv.fr> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> Message-ID: Not premature optimization, but overspecification. That's true for all the identity guarantees (String and boxed primitive). At most, they should have been weak implementation suggestions. I'm astonished how much time is wasted on trivial questions about the identity of these object references. Josh On Sun, Oct 20, 2013 at 9:44 AM, Remi Forax wrote: > On 10/20/2013 06:09 PM, Brian Goetz wrote: > >> Right, which is why Integer is likely too far polluted to be rescued. >> But, wouldn't it have been better if we could enforce that no one depended >> on it in the first place? Wouldn't it be a shame for Optional to join it >> in the "hopelessly polluted by identity" department? >> > > JLS 5.1.7 is what is what is usually called a premature optimization. > IMO the only sane choice is to just remove the wording about caching and > performance and pretend that it has never existed. > > R?mi > > > >> On 10/20/2013 12:08 PM, Joe Bowbeer wrote: >> >>> Remi: Integer.valueOf is defined to return singletons for a range of >>> values near zero, and new instances in other cases. Java programmers >>> understand what this means, and their code sometimes depends on it. >>> >>> On Oct 20, 2013 5:52 AM, "Remi Forax" >> > wrote: >>> >>> On 10/20/2013 03:32 AM, Joshua Bloch wrote: >>> >>> Brian, >>> >>> >>> On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz >>> >>> >> __>> wrote: >>> >>> OK, here's some of the background you may be missing. >>> >>> "A future version of Java" will almost certainly have >>> support for >>> "value types", "user-defined primitives", "identity-less >>> aggregates", "structs", or whatever you would like to call >>> them. >>> Without making promises or projections or even going into >>> anTy >>> details, this is high on the priority list, and some >>> nontrivial >>> analysis has already been done on what it might look like >>> and what >>> the migration compatibility concerns would be. >>> >>> >>> That's great because, frankly, Java's type system is way too >>> simple. I'm glad you guys are investigating ways to make it >>> more complex, and to provide additional ways to do things that >>> people are already doing. This will keep Java programmers on >>> their toes, which, frankly, is just what they need. >>> >>> Josh >>> >>> >>> Hi Josh, >>> >>> It's a consequence of the introduction of auto-boxing/unboxing. >>> When you call Integer.valueOf() you explicitly say that you don't >>> care about the identity of the returned object, only the wrapped >>> value is important. >>> As you know, you can not predict the result of Integer.valueOf(x) == >>> Integer.valueOf(x), which means that == on Integer is meaningless. >>> >>> Currently, the code that try to remove boxing in the VM is full of >>> special cases because the semantics of boxing is not the same for >>> each wrappers (and is also partially specified in each >>> Wrapper.valueOf). Recognizing that value types already exist in >>> Java, and give them a proper documented semantics* is in my opinion >>> a good idea. >>> >>> cheers, >>> R?mi >>> *by example, what is an array of value types is an interesting >>> question. >>> >>> > From brian.goetz at oracle.com Sun Oct 20 09:59:14 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 20 Oct 2013 12:59:14 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5263D6F0.8030307@cs.oswego.edu> Message-ID: <52640BE2.1060805@oracle.com> > The virtue of Optional, in my experience with the Guava variety, is that > the compiler never lets you forget that you aren't dealing with a Foo, > you're dealing with a (probably lightweight, possibly magical) potential > container of a Foo. Agreed. But currently, its not lightweight or magical; its a full-blown object box (a 4x cost in memory for a 32-bit pointer, plus a loss of locality, plus more work for the GC). And, the fact that it has identity is what keeps the VM from being able to work magic. Which is really sad! Since no one really needs or benefits from that identity. Wouldn't it be *even better* if we enabled future JDKs to represent Optional as an embeddable pointer-sized scalar under the covers, rather than a full-blown object box, while retaining all the type-safety? The only thing standing in the way is misuse of == and synchronized between now and (some future time). The Flatland conversation that reminds us not to do stupid things with Optional (and similar types like DateTime) seems a small price to pay for this representation flexibility. The question to be discussed here should be: exactly how hortatory the Flatland visitor should be permitted to be. From joe.bowbeer at gmail.com Sun Oct 20 10:01:34 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Sun, 20 Oct 2013 10:01:34 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <52640866.6010707@univ-mlv.fr> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> Message-ID: The Integer.valueOf definition is useful to Java programmers developing for contained devices, and library writers trying to eek out performance. (These Java programmers are not idiots. They are us.) It creates a safe zone for equals, much like the specification that string constants are ==. Changing Integer values is a Java 10 order of change. I'm fine with carving a spot for Optional evolution, but it is going to be challenging to document in a way that is not misunderstood. On Oct 20, 2013 9:47 AM, "Remi Forax" wrote: > On 10/20/2013 06:09 PM, Brian Goetz wrote: > >> Right, which is why Integer is likely too far polluted to be rescued. >> But, wouldn't it have been better if we could enforce that no one depended >> on it in the first place? Wouldn't it be a shame for Optional to join it >> in the "hopelessly polluted by identity" department? >> > > JLS 5.1.7 is what is what is usually called a premature optimization. > IMO the only sane choice is to just remove the wording about caching and > performance and pretend that it has never existed. > > R?mi > > >> On 10/20/2013 12:08 PM, Joe Bowbeer wrote: >> >>> Remi: Integer.valueOf is defined to return singletons for a range of >>> values near zero, and new instances in other cases. Java programmers >>> understand what this means, and their code sometimes depends on it. >>> >>> On Oct 20, 2013 5:52 AM, "Remi Forax" >> > wrote: >>> >>> On 10/20/2013 03:32 AM, Joshua Bloch wrote: >>> >>> Brian, >>> >>> >>> On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz >>> >>> >> __>> wrote: >>> >>> OK, here's some of the background you may be missing. >>> >>> "A future version of Java" will almost certainly have >>> support for >>> "value types", "user-defined primitives", "identity-less >>> aggregates", "structs", or whatever you would like to call >>> them. >>> Without making promises or projections or even going into >>> anTy >>> details, this is high on the priority list, and some >>> nontrivial >>> analysis has already been done on what it might look like >>> and what >>> the migration compatibility concerns would be. >>> >>> >>> That's great because, frankly, Java's type system is way too >>> simple. I'm glad you guys are investigating ways to make it >>> more complex, and to provide additional ways to do things that >>> people are already doing. This will keep Java programmers on >>> their toes, which, frankly, is just what they need. >>> >>> Josh >>> >>> >>> Hi Josh, >>> >>> It's a consequence of the introduction of auto-boxing/unboxing. >>> When you call Integer.valueOf() you explicitly say that you don't >>> care about the identity of the returned object, only the wrapped >>> value is important. >>> As you know, you can not predict the result of Integer.valueOf(x) == >>> Integer.valueOf(x), which means that == on Integer is meaningless. >>> >>> Currently, the code that try to remove boxing in the VM is full of >>> special cases because the semantics of boxing is not the same for >>> each wrappers (and is also partially specified in each >>> Wrapper.valueOf). Recognizing that value types already exist in >>> Java, and give them a proper documented semantics* is in my opinion >>> a good idea. >>> >>> cheers, >>> R?mi >>> *by example, what is an array of value types is an interesting >>> question. >>> >>> > From brian.goetz at oracle.com Sun Oct 20 10:08:19 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 20 Oct 2013 13:08:19 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> Message-ID: <52640E03.1010109@oracle.com> > I'm astonished how > much time is wasted on trivial questions about the identity of these > object references. (Sadly, same will be true with lambdas too.) One might be astonished, but one can also learn something from this experience, which in hindsight is actually kind of obvious. For "classes" that don't need identity (and the existence of this unneeded identity also happens to cripple the VM), we can avoid both the wasted time of programmers and wasted performance of programs by *giving users a means to express that an abstract data type cannot have an identity.* You can't waste time asking about the identity if there is none. And this unshackles the VM in a serious way. (We can see this with streams; reducing on an IntStream produces a parallel speedup with streams of a few thousand elements; reducing on a Stream never speeds up at all, because its bound by memory bandwidth due to cache thrashing due to boxing.) From forax at univ-mlv.fr Sun Oct 20 10:40:50 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 20 Oct 2013 19:40:50 +0200 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> Message-ID: <526415A2.4000701@univ-mlv.fr> On 10/20/2013 07:01 PM, Joe Bowbeer wrote: > > The Integer.valueOf definition is useful to Java programmers > developing for contained devices, and library writers trying to eek > out performance. (These Java programmers are not idiots. They are us.) > Sorry but we are all idiots when we start to think about performance because we focus only on the current data, the current program, the current VM, the current OS, the current hardware and all of these things change faster than our own vision of the world. Anyway, that's not the issue here. The real issue is that this part of the Java spec is overspecified as Josh said. > It creates a safe zone for equals, much like the specification that > string constants are ==. > again String constantification is not free, VMs use a global shared dictionary. > Changing Integer values is a Java 10 order of change. > yes, maybe, start to warn now, and change in 10, or just give up with Integers has Brian said. > I'm fine with carving a spot for Optional evolution, but it is going > to be challenging to document in a way that is not misunderstood. > yes, it's challenging. R?mi > On Oct 20, 2013 9:47 AM, "Remi Forax" > wrote: > > On 10/20/2013 06:09 PM, Brian Goetz wrote: > > Right, which is why Integer is likely too far polluted to be > rescued. But, wouldn't it have been better if we could enforce > that no one depended on it in the first place? Wouldn't it be > a shame for Optional to join it in the "hopelessly polluted by > identity" department? > > > JLS 5.1.7 is what is what is usually called a premature optimization. > IMO the only sane choice is to just remove the wording about > caching and performance and pretend that it has never existed. > > R?mi > > > On 10/20/2013 12:08 PM, Joe Bowbeer wrote: > > Remi: Integer.valueOf is defined to return singletons for > a range of > values near zero, and new instances in other cases. Java > programmers > understand what this means, and their code sometimes > depends on it. > > On Oct 20, 2013 5:52 AM, "Remi Forax" > >> wrote: > > On 10/20/2013 03:32 AM, Joshua Bloch wrote: > > Brian, > > > On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz > > > > > >__>> wrote: > > OK, here's some of the background you may be > missing. > > "A future version of Java" will almost > certainly have > support for > "value types", "user-defined primitives", > "identity-less > aggregates", "structs", or whatever you would > like to call > them. > Without making promises or projections or > even going into anTy > details, this is high on the priority list, > and some nontrivial > analysis has already been done on what it > might look like > and what > the migration compatibility concerns would be. > > > That's great because, frankly, Java's type system > is way too > simple. I'm glad you guys are investigating ways > to make it > more complex, and to provide additional ways to do > things that > people are already doing. This will keep Java > programmers on > their toes, which, frankly, is just what they need. > > Josh > > > Hi Josh, > > It's a consequence of the introduction of > auto-boxing/unboxing. > When you call Integer.valueOf() you explicitly say > that you don't > care about the identity of the returned object, only > the wrapped > value is important. > As you know, you can not predict the result of > Integer.valueOf(x) == > Integer.valueOf(x), which means that == on Integer is > meaningless. > > Currently, the code that try to remove boxing in the > VM is full of > special cases because the semantics of boxing is not > the same for > each wrappers (and is also partially specified in each > Wrapper.valueOf). Recognizing that value types already > exist in > Java, and give them a proper documented semantics* is > in my opinion > a good idea. > > cheers, > R?mi > *by example, what is an array of value types is an > interesting question. > > From zhong.j.yu at gmail.com Sun Oct 20 11:39:03 2013 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Sun, 20 Oct 2013 13:39:03 -0500 Subject: A disclaimer or two for Optional In-Reply-To: <5262CC71.3020606@cs.oswego.edu> References: <5262CC71.3020606@cs.oswego.edu> Message-ID: Is javac8 going to issue an error/warning if == or synchronized is applied to an Optional object? On Sat, Oct 19, 2013 at 1:16 PM, Doug Lea
wrote: > > This arose while contemplating some JDK9 possibilities... > > Note that Optional is itself a value-like class, without > a public constructor, just factory methods. > The factory methods do not even guarantee to return unique > objects. For all that the spec does and should say, > every call to Optional.of could return the same Optional > object. (This would require a magical implementation, > but still not disallowed, and variants that sometimes > return the same one are very much possible.) > > This means that there are no object-identity-related > guarantees for Optionals. "myOptional1 == myOptional2" > tells you nothing, and synchronized(myOptional) has > unpredictable effects -- it might block forever. > > People might find this surprising, so we probably want to > add a sentence or two to the javadoc. How about the following. > (We could symmetrically say that the instance returned by > Optional.empty() need not be the same each time, but that > might be overkill?) > > /** > * Returns an {@code Optional} with the specified present non-null > value. > adding... > * The returned instance need not be unique. Thus the results of > * comparing two instances using @code{==}, or using one as the > * argument for a @code{synchronized} block are arbitrary and should > * be avoided. > * > * @param the class of the value > * @param value the value to be present, which must be non-null > * @return an {@code Optional} with the value present > * @throws NullPointerException if value is null > */ > public static Optional of(T value) { > return new Optional<>(value); > } > From david.holmes at oracle.com Tue Oct 22 18:45:43 2013 From: david.holmes at oracle.com (David Holmes) Date: Wed, 23 Oct 2013 11:45:43 +1000 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> <525E7DF9.9020901@oracle.com> <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> <525F6581.6060603@oracle.com> Message-ID: <52672A47.2030803@oracle.com> Hi Mike, On 19/10/2013 5:34 AM, Mike Duigou wrote: > Updated webrev: > > http://cr.openjdk.java.net/~mduigou/JDK-8024688/3/webrev/ I see there is a version 4 now :) ConcurrentMap: In replaceAll: 261 *

This implementation assumes that the ConcurrentMap cannot contain null ... is this intended to be implSpec or implNote? Currently it appears to be implSpec. Ditto for the same text in compute*, merge Generally is the use of "this implementation" versus "the default implementation" significant? I thought perhaps the former was for implNotes and the latter implSpec ? ---- HashMap: None of the overriding implementations have any @throws for unchecked exceptions. Some of them may no longer apply but I'm not sure they all do - eg ClasscastException. Otherwise I have no further comments. :) Thanks, David > More notes below. > > On Oct 16 2013, at 21:20 , David Holmes wrote: > >> Hi Mike, >> >> Map.java: >> >> The implNote for computeIfAbsent should be modified to match the implementation. Ditto for computeIfPresent. Ditto for compute, merge etc! Once these implementations have stabilized we need to check what the implNote says. It makes no sense to me for the impl note to describe anything other than the core logic of the actual implementation - particularly referring to putIfAbsent when put is used, or replace when put is used. > > While removing the CME I opted to also remove some of use of the fancy new methods as they didn't add anything and (usually) had a performance cost. > > I will update the @implNote descriptions and review the other notes. > >> >> HashMap.java: >> >> 1234 if(old.value != null) >> >> Space > > Got it. Thank you. > >> >> >> ConcurrentMap.java: >> >> 247 * @throws ClassCastException {@inheritDoc} >> 248 * @throws NullPointerException {@inheritDoc} >> 249 * @throws ClassCastException {@inheritDoc} >> >> CCE is repeated. > > Got it. > >> >> 274 * contain null values and get() returning null unambiguously means the key >> >> get() should be in code font as per line #69. Ditto for line 300, 332 and 395. > > And a few more. Thanks. > >> >> I now see that those Map implNotes were written with ConcurrentMap in mind so that it can just tag on the note about retries. But this seems wrong to me - each should have its own implNotes reflecting the true implementation. >> >>> It does bother me to be throwing out "good information" by not throwing the CMEs but I'm willing to go with the flow. As a practical matter later reintroduction of even valid error detection would almost certainly be difficult. (https://bugs.openjdk.java.net/browse/JDK-5045147 for one example). >> >> ... it still concerns me that a function object could mutate the map and so trigger a CCE. > > There seems to be no way to prevent it. > >> >>> The patch also fixes up missing @throws and @since from the ConcurrentMap implementations. >> >> I think you have a one-line conflict with Henry's latest @since update. > > Got it. I had planned for that fix to go in with changeset.... > >> >> Cheers, >> David >> >>> Mike >>> > From mike.duigou at oracle.com Tue Oct 22 20:09:27 2013 From: mike.duigou at oracle.com (Mike Duigou) Date: Tue, 22 Oct 2013 20:09:27 -0700 Subject: RFR: 8024688: j.u.Map.merge doesn't work as specified if contains key:null pair In-Reply-To: <52672A47.2030803@oracle.com> References: <679CE08E-E954-414F-8717-255CBCCF64D5@oracle.com> <15BB8B5C-40C2-434C-927B-ABA6163740C9@oracle.com> <70D2641C-CBC2-4FC7-AB08-F3982C13BDE3@oracle.com> <4240E03C-C0A8-468F-8A11-300D51C72FFA@oracle.com> <274E77B8-E27A-4DF0-81E3-3E9A23CA44F2@oracle.com> <525E18DD.2080604@oracle.com> <525E6A5A.6080301@oracle.com> <19D18902-695B-4039-94C0-C9375118975B@oracle.com> <525E7DF9.9020901@oracle.com> <433CAECD-9BC6-4CD8-BD61-B140FDE01097@oracle.com> <9CD02703-50A3-41A8-A688-E4F1BE64EABD@oracle.com> <525F6581.6060603@oracle.com> <52672A47.2030803@oracle.com> Message-ID: <724CD85C-9B76-42F6-9CBE-BEE52E2A9E4C@oracle.com> Thank you for the feedback. Responses inline. On Oct 22 2013, at 18:45 , David Holmes wrote: > Hi Mike, > > On 19/10/2013 5:34 AM, Mike Duigou wrote: >> Updated webrev: >> >> http://cr.openjdk.java.net/~mduigou/JDK-8024688/3/webrev/ > > I see there is a version 4 now :) Yep, I generated it for the multiplatform test run. > ConcurrentMap: > > In replaceAll: > > 261 *

This implementation assumes that the ConcurrentMap cannot contain null ... > > is this intended to be implSpec or implNote? Currently it appears to be implSpec. Ditto for the same text in compute*, merge I believe this was made an implSpec because of the "Implementations which support null values *must* override this default implementation." sentence but you are right that it does read more like an @implNote. > > Generally is the use of "this implementation" versus "the default implementation" significant? I thought perhaps the former was for implNotes and the latter implSpec ? Both sound more like @implNote to me. The halcyon days after ZBB Stuart and I can finally finish the promised > ---- > > HashMap: > > None of the overriding implementations have any @throws for unchecked exceptions. Some of them may no longer apply but I'm not sure they all do - eg ClasscastException. You are, of course, correct. Reviewing the HTML javadoc this extends to Hashtable, ConcurrentHashMap, IdentityHashMap, and all the Collections.XXXMap and probably other places. I would like to tackle this as a separate issue since it's very widespread. I have filed https://bugs.openjdk.java.net/browse/JDK-8027125 to address this. I fear that with the proper tooling to locate missing @throws in overridden impls we could generate many bugs of this type.... > Otherwise I have no further comments. :) > > Thanks, > David > >> More notes below. >> >> On Oct 16 2013, at 21:20 , David Holmes wrote: >> >>> Hi Mike, >>> >>> Map.java: >>> >>> The implNote for computeIfAbsent should be modified to match the implementation. Ditto for computeIfPresent. Ditto for compute, merge etc! Once these implementations have stabilized we need to check what the implNote says. It makes no sense to me for the impl note to describe anything other than the core logic of the actual implementation - particularly referring to putIfAbsent when put is used, or replace when put is used. >> >> While removing the CME I opted to also remove some of use of the fancy new methods as they didn't add anything and (usually) had a performance cost. >> >> I will update the @implNote descriptions and review the other notes. >> >>> >>> HashMap.java: >>> >>> 1234 if(old.value != null) >>> >>> Space >> >> Got it. Thank you. >> >>> >>> >>> ConcurrentMap.java: >>> >>> 247 * @throws ClassCastException {@inheritDoc} >>> 248 * @throws NullPointerException {@inheritDoc} >>> 249 * @throws ClassCastException {@inheritDoc} >>> >>> CCE is repeated. >> >> Got it. >> >>> >>> 274 * contain null values and get() returning null unambiguously means the key >>> >>> get() should be in code font as per line #69. Ditto for line 300, 332 and 395. >> >> And a few more. Thanks. >> >>> >>> I now see that those Map implNotes were written with ConcurrentMap in mind so that it can just tag on the note about retries. But this seems wrong to me - each should have its own implNotes reflecting the true implementation. >>> >>>> It does bother me to be throwing out "good information" by not throwing the CMEs but I'm willing to go with the flow. As a practical matter later reintroduction of even valid error detection would almost certainly be difficult. (https://bugs.openjdk.java.net/browse/JDK-5045147 for one example). >>> >>> ... it still concerns me that a function object could mutate the map and so trigger a CCE. >> >> There seems to be no way to prevent it. >> >>> >>>> The patch also fixes up missing @throws and @since from the ConcurrentMap implementations. >>> >>> I think you have a one-line conflict with Henry's latest @since update. >> >> Got it. I had planned for that fix to go in with changeset.... >> >>> >>> Cheers, >>> David >>> >>>> Mike >>>> >> From joe.bowbeer at gmail.com Tue Oct 22 20:23:03 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Tue, 22 Oct 2013 20:23:03 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <526415A2.4000701@univ-mlv.fr> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> Message-ID: Does the paragraph below from Rose's blog list everything that shouldn't be done to an Optional? A value-safe expression may not be the subject of a value-unsafe operation. > In particular, it cannot be synchronized on, nor can it be compared with > the ?==? operator, not even with a null or with another value-safe type. Comparing an Optional with null would be pretty funny. For other potential value types, such as Boolean and Integer, comparing with null is, unfortunately, a somewhat common idiom: null means "not assigned". --Joe On Sun, Oct 20, 2013 at 10:40 AM, Remi Forax wrote: > On 10/20/2013 07:01 PM, Joe Bowbeer wrote: > >> >> The Integer.valueOf definition is useful to Java programmers developing >> for contained devices, and library writers trying to eek out performance. >> (These Java programmers are not idiots. They are us.) >> >> > Sorry but we are all idiots when we start to think about performance > because we focus only on the current data, the current program, the current > VM, the current OS, the current hardware and all of these things change > faster than our own vision of the world. > Anyway, that's not the issue here. The real issue is that this part of the > Java spec is overspecified as Josh said. > > > It creates a safe zone for equals, much like the specification that >> string constants are ==. >> >> > again String constantification is not free, VMs use a global shared > dictionary. > > > Changing Integer values is a Java 10 order of change. >> >> > yes, maybe, start to warn now, and change in 10, or just give up with > Integers has Brian said. > > > I'm fine with carving a spot for Optional evolution, but it is going to >> be challenging to document in a way that is not misunderstood. >> >> > yes, it's challenging. > R?mi > > On Oct 20, 2013 9:47 AM, "Remi Forax" > forax at univ-mlv.fr>> wrote: >> >> On 10/20/2013 06:09 PM, Brian Goetz wrote: >> >> Right, which is why Integer is likely too far polluted to be >> rescued. But, wouldn't it have been better if we could enforce >> that no one depended on it in the first place? Wouldn't it be >> a shame for Optional to join it in the "hopelessly polluted by >> identity" department? >> >> >> JLS 5.1.7 is what is what is usually called a premature optimization. >> IMO the only sane choice is to just remove the wording about >> caching and performance and pretend that it has never existed. >> >> R?mi >> >> >> On 10/20/2013 12:08 PM, Joe Bowbeer wrote: >> >> Remi: Integer.valueOf is defined to return singletons for >> a range of >> values near zero, and new instances in other cases. Java >> programmers >> understand what this means, and their code sometimes >> depends on it. >> >> On Oct 20, 2013 5:52 AM, "Remi Forax" > >> >> wrote: >> >> On 10/20/2013 03:32 AM, Joshua Bloch wrote: >> >> Brian, >> >> >> On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz >> > >> > > >> > >> > >__>> wrote: >> >> OK, here's some of the background you may be >> missing. >> >> "A future version of Java" will almost >> certainly have >> support for >> "value types", "user-defined primitives", >> "identity-less >> aggregates", "structs", or whatever you would >> like to call >> them. >> Without making promises or projections or >> even going into anTy >> details, this is high on the priority list, >> and some nontrivial >> analysis has already been done on what it >> might look like >> and what >> the migration compatibility concerns would be. >> >> >> That's great because, frankly, Java's type system >> is way too >> simple. I'm glad you guys are investigating ways >> to make it >> more complex, and to provide additional ways to do >> things that >> people are already doing. This will keep Java >> programmers on >> their toes, which, frankly, is just what they need. >> >> Josh >> >> >> Hi Josh, >> >> It's a consequence of the introduction of >> auto-boxing/unboxing. >> When you call Integer.valueOf() you explicitly say >> that you don't >> care about the identity of the returned object, only >> the wrapped >> value is important. >> As you know, you can not predict the result of >> Integer.valueOf(x) == >> Integer.valueOf(x), which means that == on Integer is >> meaningless. >> >> Currently, the code that try to remove boxing in the >> VM is full of >> special cases because the semantics of boxing is not >> the same for >> each wrappers (and is also partially specified in each >> Wrapper.valueOf). Recognizing that value types already >> exist in >> Java, and give them a proper documented semantics* is >> in my opinion >> a good idea. >> >> cheers, >> R?mi >> *by example, what is an array of value types is an >> interesting question. >> >> >> > From howard.lovatt at gmail.com Tue Oct 22 23:31:58 2013 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Wed, 23 Oct 2013 17:31:58 +1100 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> Message-ID: Unfortunately I think that once Optional is introduced as a reference type it will be used like all the other reference types, e.g. null will mean not assigned. This is not unreasonable for programmers to do this because it is exactly what Java does when initialising fields. When (and I hope sooner rather than latter) Java gets value types it will be necessary to come up with some mechanism to cope with this, e.g. optional (note lower case) gets auto boxed to Optional (note upper case) and the stream API is changed to return optional (which won't be a problem because Stream never returns a null Optional). It would be nice if the programmer when defining a value type could specify a companion reference type that could be auto boxed to and could perhaps automatically gain the same methods. On Wednesday, October 23, 2013, Joe Bowbeer wrote: > Does the paragraph below from Rose's blog list everything that shouldn't be > done to an Optional? > > A value-safe expression may not be the subject of a value-unsafe operation. > > In particular, it cannot be synchronized on, nor can it be compared with > > the ?==? operator, not even with a null or with another value-safe type. > > > Comparing an Optional with null would be pretty funny. For other potential > value types, such as Boolean and Integer, comparing with null is, > unfortunately, a somewhat common idiom: null means "not assigned". > > --Joe > > > On Sun, Oct 20, 2013 at 10:40 AM, Remi Forax > > wrote: > > > On 10/20/2013 07:01 PM, Joe Bowbeer wrote: > > > >> > >> The Integer.valueOf definition is useful to Java programmers developing > >> for contained devices, and library writers trying to eek out > performance. > >> (These Java programmers are not idiots. They are us.) > >> > >> > > Sorry but we are all idiots when we start to think about performance > > because we focus only on the current data, the current program, the > current > > VM, the current OS, the current hardware and all of these things change > > faster than our own vision of the world. > > Anyway, that's not the issue here. The real issue is that this part of > the > > Java spec is overspecified as Josh said. > > > > > > It creates a safe zone for equals, much like the specification that > >> string constants are ==. > >> > >> > > again String constantification is not free, VMs use a global shared > > dictionary. > > > > > > Changing Integer values is a Java 10 order of change. > >> > >> > > yes, maybe, start to warn now, and change in 10, or just give up with > > Integers has Brian said. > > > > > > I'm fine with carving a spot for Optional evolution, but it is going to > >> be challenging to document in a way that is not misunderstood. > >> > >> > > yes, it's challenging. > > R?mi > > > > On Oct 20, 2013 9:47 AM, "Remi Forax" >> forax at univ-mlv.fr >> wrote: > >> > >> On 10/20/2013 06:09 PM, Brian Goetz wrote: > >> > >> Right, which is why Integer is likely too far polluted to be > >> rescued. But, wouldn't it have been better if we could enforce > >> that no one depended on it in the first place? Wouldn't it be > >> a shame for Optional to join it in the "hopelessly polluted by > >> identity" department? > >> > >> > >> JLS 5.1.7 is what is what is usually called a premature > optimization. > >> IMO the only sane choice is to just remove the wording about > >> caching and performance and pretend that it has never existed. > >> > >> R?mi > >> > >> > >> On 10/20/2013 12:08 PM, Joe Bowbeer wrote: > >> > >> Remi: Integer.valueOf is defined to return singletons for > >> a range of > >> values near zero, and new instances in other cases. Java > >> programmers > >> understand what this means, and their code sometimes > >> depends on it. > >> > >> On Oct 20, 2013 5:52 AM, "Remi Forax" > >> > > >> forax at univ-mlv.fr >>> wrote: > >> > >> On 10/20/2013 03:32 AM, Joshua Bloch wrote: > >> > >> Brian, > >> > >> > >> On Sat, Oct 19, 2013 at 3:17 PM, Brian Goetz > >> > >> **> > >> > >> **>> > >> > >> **> > >> > >> >__>> wrote: > >> > >> OK, here's some of the background you may be > >> missing. > >> > >> "A future version of Java" will almost > >> certainly have > >> support for > >> "value types", "user-defined primitives", > >> "identity-less > >> aggregates", "structs", or whatever you would > >> like to call > >> them. > >> Without making promises or projections or > >> even going into anTy > >> details, this is high on the priority list, > >> and some nontrivial > >> analysis has already been done on what it > >> might look like > >> and what > >> the migration compatibility concerns would be. > >> > >> > >> That's great because, frankly, Java's type system > >> is way too > >> simple. I'm glad you guys are investigating ways > >> to make it > >> more complex, and to provide additional ways to do > >> things that > >> people are already doing. This will keep Java > >> programmers on > >> their toes, which, frankly, is just what they need. > >> > >> Josh > >> > >> > >> Hi Josh, > >> > >> It's a consequence of the introduction of > >> auto-boxing/unboxing. > >> When you call Integer.valueOf() you explicitly say > >> that you don't > >> care about the identity of the returned object, only > >> the wrapped > >> value is important. > >> As you know, you can not predict the result of > >> Integer.valueOf(x) == > >> Integer.valueOf(x), which means that == on Integer is > >> meaningless. > >> > >> Currently, the code that try to remove boxing in the > >> VM is full of > >> special cases because the semantics of boxing is not > >> the same for > >> each wrappers (and is also partially specified in each > >> -- -- Howard. From brian.goetz at oracle.com Wed Oct 23 06:48:05 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 23 Oct 2013 09:48:05 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> Message-ID: <5267D395.1030507@oracle.com> > Does the paragraph below from Rose's blog list everything that shouldn't > be done to an Optional? > > A value-safe expression may not be the subject of a value-unsafe > operation. In particular, it cannot be synchronized on, nor can it > be compared with the ?==? operator, not even with a null or with > another value-safe type. Also: System.identityHashCode. And assignment of null. On the other hand, we are considering whether == and identityHashCode can be retrofitted to values by an automated componentwise/bitwise computation. Which means that == is unwise but probably supportable. The real killer is synchronizing (and its friends, wait/notify.) > Comparing an Optional with null would be pretty funny. For other > potential value types, such as Boolean and Integer, comparing with null > is, unfortunately, a somewhat common idiom: null means "not assigned". Right. My take is that the existing primitive wrapper types are hopelessly polluted and must always mean "boxed primitives". But, for new-in-8 classes (Optional, and the 310 date-time classes), there may be hope. From tim at peierls.net Wed Oct 23 07:29:05 2013 From: tim at peierls.net (Tim Peierls) Date: Wed, 23 Oct 2013 10:29:05 -0400 Subject: A disclaimer or two for Optional In-Reply-To: <5267D395.1030507@oracle.com> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> Message-ID: On Wed, Oct 23, 2013 at 9:48 AM, Brian Goetz wrote: > Comparing an Optional with null would be pretty funny. For other >> > potential value types, such as Boolean and Integer, comparing with null >> is, unfortunately, a somewhat common idiom: null means "not assigned". >> > > Right. My take is that the existing primitive wrapper types are > hopelessly polluted and must always mean "boxed primitives". But, for > new-in-8 classes (Optional, and the 310 date-time classes), there may be > hope. > By "there may be hope", you mean there may be hope of reducing misuse -- as-if-full-reference-type use -- of these new-in-8 valueish types while they are not yet full value types by adding class-specific disclaimers? If so, Optional is probably the least appropriate candidate for such special pleading. Since avoidance of null is a big motivation for Optional in the first place, you're far less likely to find folks doing comparison to null (or other Rose no-nos) with Optional than with any other valueish-type you can think of. Users of Optional have already got the religion; no need to preach to the choir. I think a better way to prepare folks for such a language change would be to create a separate section in an overview or package doc that describes valueish types and what you shouldn't do with them, perhaps mentioning the possibility of a language change that would make such misuse entirely broken, and add links from the class comment for all such types to this section. --tim From brian.goetz at oracle.com Wed Oct 23 07:33:27 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 23 Oct 2013 10:33:27 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> Message-ID: <5267DE37.4030201@oracle.com> > By "there may be hope", you mean there may be hope of reducing misuse -- > as-if-full-reference-type use -- of these new-in-8 valueish types while > they are not yet full value types by adding class-specific disclaimers? Exactly. > If so, Optional is probably the least appropriate candidate for such > special pleading. Since avoidance of null is a big motivation for > Optional in the first place, you're far less likely to find folks doing > comparison to null (or other Rose no-nos) with Optional than with any > other valueish-type you can think of. Users of Optional have already got > the religion; no need to preach to the choir. They are more likely to behave, but the special pleading has two motivations, only one of which is addressed above: - discourage users from doing wrong things - provide cover so that when we break code that does wrong things, they were adequately warned > I think a better way to prepare folks for such a language change would > be to create a separate section in an overview or package doc that > describes valueish types and what you shouldn't do with them, perhaps > mentioning the possibility of a language change that would make such > misuse entirely broken, and add links from the class comment for all > such types to this section. In a perfect world, the visitor from Flatland would show up and lay the entire future out for us. We're a few days from Public Review; we're in "better than nothing" territory here. From tim at peierls.net Wed Oct 23 07:47:29 2013 From: tim at peierls.net (Tim Peierls) Date: Wed, 23 Oct 2013 10:47:29 -0400 Subject: A disclaimer or two for Optional In-Reply-To: <5267DE37.4030201@oracle.com> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> <5267DE37.4030201@oracle.com> Message-ID: On Wed, Oct 23, 2013 at 10:33 AM, Brian Goetz wrote: > > They are more likely to behave, but the special pleading has two > motivations, only one of which is addressed above: > - discourage users from doing wrong things > - provide cover so that when we break code that does wrong things, they > were adequately warned ... In a perfect world, the visitor from Flatland would show up and lay the > entire future out for us. We're a few days from Public Review; we're in > "better than nothing" territory here. > Isn't this a little like putting a warning about the dangers of addictive drugs only on the methadone because you don't have time to post general warnings about the harder drugs? Optional users are already in treatment. There's not much cover if you have to say, "You should have read the warning we clearly posted in the rehab clinic," to users still on the street. If it would take more time to *not* add this disclaimer, then never mind. Otherwise, there are better uses of the few days remaining. --tim From brian.goetz at oracle.com Wed Oct 23 07:51:15 2013 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 23 Oct 2013 10:51:15 -0400 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> <5267DE37.4030201@oracle.com> Message-ID: <5267E263.8050805@oracle.com> (Sigh, why does everything related to Optional have to take 300 messages?) Here's the reality: if we don't put this disclaimer on, there is ABSOLUTELY NO CHANCE we will be able to make Optional a value type in the future. Which would be terrible. If we do, there is SOME chance. Not 100%, but more than zero. On 10/23/2013 10:47 AM, Tim Peierls wrote: > On Wed, Oct 23, 2013 at 10:33 AM, Brian Goetz > wrote: > > They are more likely to behave, but the special pleading has two > motivations, only one of which is addressed above: > - discourage users from doing wrong things > - provide cover so that when we break code that does wrong things, > they were adequately warned > > ... > > In a perfect world, the visitor from Flatland would show up and lay > the entire future out for us. We're a few days from Public Review; > we're in "better than nothing" territory here. > > > Isn't this a little like putting a warning about the dangers of > addictive drugs only on the methadone because you don't have time to > post general warnings about the harder drugs? Optional users are already > in treatment. There's not much cover if you have to say, "You should > have read the warning we clearly posted in the rehab clinic," to users > still on the street. > > If it would take more time to *not* add this disclaimer, then never > mind. Otherwise, there are better uses of the few days remaining. > > --tim > From tim at peierls.net Wed Oct 23 08:10:30 2013 From: tim at peierls.net (Tim Peierls) Date: Wed, 23 Oct 2013 11:10:30 -0400 Subject: A disclaimer or two for Optional In-Reply-To: <5267E263.8050805@oracle.com> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> <5267DE37.4030201@oracle.com> <5267E263.8050805@oracle.com> Message-ID: On Wed, Oct 23, 2013 at 10:51 AM, Brian Goetz wrote: > (Sigh, why does everything related to Optional have to take 300 messages?) > Only 33 or so for this conversation, and Doug started it. :-) > Here's the reality: if we don't put this disclaimer on, there is > ABSOLUTELY NO CHANCE we will be able to make Optional a value type in the > future. Which would be terrible. If we do, there is SOME chance. Not > 100%, but more than zero. OK, I don't understand why, and that rationale is different from "better than nothing", but you're right that the discussion has gone on too long given the size of the proposal. No more objections on that front. --tim From forax at univ-mlv.fr Wed Oct 23 10:08:26 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 23 Oct 2013 19:08:26 +0200 Subject: A disclaimer or two for Optional In-Reply-To: References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> <5267DE37.4030201@oracle.com> Message-ID: <5268028A.2090007@univ-mlv.fr> On 10/23/2013 04:47 PM, Tim Peierls wrote: > On Wed, Oct 23, 2013 at 10:33 AM, Brian Goetz > wrote: > > They are more likely to behave, but the special pleading has two > motivations, only one of which is addressed above: > - discourage users from doing wrong things > - provide cover so that when we break code that does wrong > things, they were adequately warned > > ... > > In a perfect world, the visitor from Flatland would show up and > lay the entire future out for us. We're a few days from Public > Review; we're in "better than nothing" territory here. > > > Isn't this a little like putting a warning about the dangers of > addictive drugs only on the methadone because you don't have time to > post general warnings about the harder drugs? Optional users are > already in treatment. There's not much cover if you have to say, "You > should have read the warning we clearly posted in the rehab clinic," > to users still on the street. > > If it would take more time to *not* add this disclaimer, then never > mind. Otherwise, there are better uses of the few days remaining. > > --tim > Given the previous discussions, there is also a good chance that Optional became the new heroine. R?mi From dl at cs.oswego.edu Wed Oct 23 11:49:00 2013 From: dl at cs.oswego.edu (Doug Lea) Date: Wed, 23 Oct 2013 14:49:00 -0400 Subject: A disclaimer or two for Optional In-Reply-To: <5268028A.2090007@univ-mlv.fr> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> <5267DE37.4030201@oracle.com> <5268028A.2090007@univ-mlv.fr> Message-ID: <52681A1C.7010506@cs.oswego.edu> On 10/23/2013 01:08 PM, Remi Forax wrote: > Given the previous discussions, there is also a good chance that Optional became > the new heroine. > I can't decide if you meant heroine (femme h?ro?que) or heroin (opiac?s)! Either way is best post yet on this thread. -Doug From joe.bowbeer at gmail.com Wed Oct 23 14:59:51 2013 From: joe.bowbeer at gmail.com (Joe Bowbeer) Date: Wed, 23 Oct 2013 14:59:51 -0700 Subject: A disclaimer or two for Optional In-Reply-To: <52681A1C.7010506@cs.oswego.edu> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> <5267DE37.4030201@oracle.com> <5268028A.2090007@univ-mlv.fr> <52681A1C.7010506@cs.oswego.edu> Message-ID: I think the note should instruct users to refrain from applying value-unsafe operations to Optionals so that their programs can benefit from more performant implementations in the future. More carrot, less stick. If Optionals become value types, I'm betting that the implementation will identify when its safe to optimize, and will fallback to a slow but correct path in other cases. On Wed, Oct 23, 2013 at 11:49 AM, Doug Lea

wrote: > On 10/23/2013 01:08 PM, Remi Forax wrote: > >> Given the previous discussions, there is also a good chance that Optional >> became >> the new heroine. >> >> > I can't decide if you meant heroine (femme h?ro?que) or heroin (opiac?s)! > Either way is best post yet on this thread. > > -Doug > > > > > > > > From forax at univ-mlv.fr Thu Oct 24 11:15:39 2013 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 24 Oct 2013 20:15:39 +0200 Subject: A disclaimer or two for Optional In-Reply-To: <52681A1C.7010506@cs.oswego.edu> References: <5262CC71.3020606@cs.oswego.edu> <5262EDC6.2000501@univ-mlv.fr> <5262F4D6.4030309@univ-mlv.fr> <526304E0.6080305@oracle.com> <5263D148.3080404@univ-mlv.fr> <52640055.8000304@oracle.com> <52640866.6010707@univ-mlv.fr> <526415A2.4000701@univ-mlv.fr> <5267D395.1030507@oracle.com> <5267DE37.4030201@oracle.com> <5268028A.2090007@univ-mlv.fr> <52681A1C.7010506@cs.oswego.edu> Message-ID: <526963CB.9020802@univ-mlv.fr> On 10/23/2013 08:49 PM, Doug Lea wrote: > On 10/23/2013 01:08 PM, Remi Forax wrote: >> Given the previous discussions, there is also a good chance that >> Optional became >> the new heroine. >> > > I can't decide if you meant heroine (femme h?ro?que) or heroin (opiac?s)! > Either way is best post yet on this thread. Both, I think and dream in French, usually :) > > -Doug > R?mi