From Daniel_Heidinga at ca.ibm.com Thu Sep 13 13:39:28 2012 From: Daniel_Heidinga at ca.ibm.com (Daniel Heidinga) Date: Thu, 13 Sep 2012 16:39:28 -0400 Subject: Lambda metafactory + default methods + bridges Message-ID: We've been investigating a test case with Brian that causes the lambda metafactory to generate bridges in the SAM implementation class for signatures that would otherwise be handled by the VM processing of default methods. This example shows a situation where the metafactory's bridging will conflict with the bridges required for default methods: interface I { String be(T s); String be(V n); } interface DI extends I { String be(String s) default {return s; }; String be(Integer n); } DI is a SAM interface; it has one abstract method be(Integer), which has bridge method be(Number). At the same time, be(String) is a default method that has bridge method be(Object) generated by the VM. Without generic analysis, the metafactory cannot distinguish the fates of its two methods (it does not see that be(T s) will be bridged by the VM), so bridges both. In this case generating a ClassCastException. After considering (and rejecting) a number of options, we've been concentrating on the idea of allowing the metafactory to request that the VM generate all the appropriate bridges for a given class. The VM already needs to be able to do this analysis to correctly wire in default methods and this would lean on the same infrastructure. We currently believe this is a feasible approach in both J9 & Hotspot. This leaves a number of open questions to resolve: 1) How does a classfile signal to the VM that it requires the VM to generate all bridge methods? Either a bit in the class modifiers or an attribute could be used. We've guessed at three possible bridging modes that could be requested: i) bridge nothing, ii) bridge everything, iii) bridge defaults only. Both i) & ii) are obviously useful modes while iii) may be less useful. More thought required. 2) How closely should VM bridge methods match the behaviour of bridge methods generated by the static compiler? Should these methods be visible in a stack trace? There are cases where the VM can skip generating a bridge by reusing the original method and we'll need to spec the behaviour very carefully to ensure all implementations are compatible. The spec needs to be clear so we don't run into security / visibility issues, for example when doing caller class checks. I'm sure other questions will arise as we dig into this. --Dan -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120913/fa915ba7/attachment.html From sam at sampullara.com Thu Sep 13 22:23:08 2012 From: sam at sampullara.com (Sam Pullara) Date: Thu, 13 Sep 2012 22:23:08 -0700 Subject: Streams Message-ID: Here are some issues that I find with the current Streams implementation: 1) Collection is not a Stream. This means that whenever you use collections and want to use some of the great new features you have to first convert it to a stream: list.stream().map(l -> parseInt(l)).into(new ArrayList<>()) I find this unnecessary. Collection could implement Stream and the default methods could do the conversion for me, probably by calling .stream() as above. 2) Optional should implement more of the Stream API like flatMap and some others. Option flatMap(Mapper>) I also hate that with Optional.none() often needs to be witnessed and not a big fan of using a constructor for Optional: return matcher.matches() ? new Optional<>(matcher) : Optional.empty(); should really be something more like (using static imports): return matcher.matches() ? option(matcher) : none(); 3) I really, really believe that we should have something around Future like I have prototyped here: https://github.com/spullara/java-future-jdk8/blob/master/src/main/java/spullara/util/concurrent/Promise.java Blocking to get the result of a Future is a bad code smell in my mind after using Promises for a long time at Twitter. This will be a great opportunity to get all the APIs in line with a much better way of handling asynchronous work that isn't CPU bound. Sam From forax at univ-mlv.fr Fri Sep 14 00:13:54 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 14 Sep 2012 09:13:54 +0200 Subject: Streams In-Reply-To: References: Message-ID: <5052D932.3090808@univ-mlv.fr> On 09/14/2012 07:23 AM, Sam Pullara wrote: > Here are some issues that I find with the current Streams implementation: > > 1) Collection is not a Stream. This means that whenever you use > collections and want to use some of the great new features you have to > first convert it to a stream: > > list.stream().map(l -> parseInt(l)).into(new ArrayList<>()) > > I find this unnecessary. Collection could implement Stream and the > default methods could do the conversion for me, probably by calling > .stream() as above. I fuly agree, it will be convenient to have such delegation mechanism. > > 2) Optional should implement more of the Stream API like flatMap and > some others. > > Option flatMap(Mapper>) > > I also hate that with Optional.none() often needs to be witnessed and > not a big fan of using a constructor for Optional: > > return matcher.matches() ? new Optional<>(matcher) : Optional.empty(); > > should really be something more like (using static imports): > > return matcher.matches() ? option(matcher) : none(); Is there a document somewhere that explain the pro and cons of using Optional ? Currently I see it as a way to add a level of indirection with no real benefit, the VM currently optimizes code that check a variable is null if the variable is never null, so this kind of nullcheck are free. With Optional you add a level of indirection in any case (null or not null) and you have an allocation if you're not lucky and the escape analysis doesn't work. > > 3) I really, really believe that we should have something around > Future like I have prototyped here: > > https://github.com/spullara/java-future-jdk8/blob/master/src/main/java/spullara/util/concurrent/Promise.java > > Blocking to get the result of a Future is a bad code smell in my mind > after using Promises for a long time at Twitter. This will be a great > opportunity to get all the APIs in line with a much better way of > handling asynchronous work that isn't CPU bound. Sam, I fully agree, and think you should move this question to concurrency-interest mailing list at least to have Doug comments on this idea. > > Sam R?mi From sam at sampullara.com Fri Sep 14 00:23:06 2012 From: sam at sampullara.com (Sam Pullara) Date: Fri, 14 Sep 2012 00:23:06 -0700 Subject: Streams In-Reply-To: <5052D932.3090808@univ-mlv.fr> References: <5052D932.3090808@univ-mlv.fr> Message-ID: On Fri, Sep 14, 2012 at 12:13 AM, Remi Forax wrote: >> 2) Optional should implement more of the Stream API like flatMap and >> some others. > > Is there a document somewhere that explain the pro and cons of using > Optional ? > Currently I see it as a way to add a level of indirection with no real > benefit, > the VM currently optimizes code that check a variable is null if the > variable is never null, > so this kind of nullcheck are free. With Optional you add a level of > indirection in any case > (null or not null) and you have an allocation if you're not lucky and the > escape analysis doesn't work. There is a performance cost, but it looks nicer than null checks and works when null is a real answer. They are very commonly used on the Scala side of things and clean up a lot of code. It would be nice if it was natively supported by the VM though. Here is a blog post on using them in Scala: http://www.codecommit.com/blog/scala/the-option-pattern I just find it much more natural versus an exception or null check. >> >> 3) I really, really believe that we should have something around >> Future like I have prototyped here: >> >> https://github.com/spullara/java-future-jdk8/blob/master/src/main/java/spullara/util/concurrent/Promise.java >> >> Blocking to get the result of a Future is a bad code smell in my mind >> after using Promises for a long time at Twitter. This will be a great >> opportunity to get all the APIs in line with a much better way of >> handling asynchronous work that isn't CPU bound. > > Sam, > I fully agree, and think you should move this question to > concurrency-interest mailing list > at least to have Doug comments on this idea. I think when he saw it last he said something like it doesn't look very Java like. I'll post it anyway. It dovetails nicely with the collections API as well, using many of the same verbs. Sam > > > R?mi > From dl at cs.oswego.edu Fri Sep 14 04:54:24 2012 From: dl at cs.oswego.edu (Doug Lea) Date: Fri, 14 Sep 2012 07:54:24 -0400 Subject: Streams In-Reply-To: <5052D932.3090808@univ-mlv.fr> References: <5052D932.3090808@univ-mlv.fr> Message-ID: <50531AF0.2090804@cs.oswego.edu> (CCing lambda-libs-spec-experts, which seems better for follow-ups). On 09/14/12 03:13, Remi Forax wrote: > On 09/14/2012 07:23 AM, Sam Pullara wrote: >> Here are some issues that I find with the current Streams implementation: >> >> 1) Collection is not a Stream. This means that whenever you use >> collections and want to use some of the great new features you have to >> first convert it to a stream: >> >> list.stream().map(l -> parseInt(l)).into(new ArrayList<>()) >> >> I find this unnecessary. Collection could implement Stream and the >> default methods could do the conversion for me, probably by calling >> .stream() as above. > > I fuly agree, it will be convenient to have such delegation mechanism. There's some tension between convenience and sanity here :-) I'll let Brian walk through the decision space... > > Is there a document somewhere that explain the pro and cons of using Optional ? > Currently I see it as a way to add a level of indirection with no real benefit, I don't think there is a document, but there has been a lot of discussion about it here and there over the years. I think they mainly amount to two technical problems, plus at least one style/usage issue: 1. Some collections allow null elements, which means that you cannot unambiguously use null in its otherwise only reasonable sense of "there's nothing there". 2. If/when some of these APIs are extended to primitives, there is no value to return in the case of nothing there. The alternative to Optional is to return boxed types, which some people would prefer not to do. 3. Some people like the idea of using Optional to allow more fluent APIs. As in x = s.findFirst().or(valueIfEmpty) vs if ((x = s.findFirst()) == null) x = valueIfEmpty; Some people are happy to create an object for the sake of being able to do this. Although sometimes less happy when they realize that Optionalism then starts propagating through their designs, leading to Set>'s and so on. It's hard to win here. One of the many reasons that we are supplying parallel bulk ops for ConcurrentHashMap that fall outside the main stream framework is that issue #1 does not arise (CHM disallows null keys and values), which streamlines many design issues. >> 3) I really, really believe that we should have something around >> Future like I have prototyped here: Right. FutureValue/Promise/whatever is on our todo list for JDK8 (see JEP 155). One of the many little snags that have held it back so far is getting past related issues like Numeric (see my post on this). -Doug From Daniel_Heidinga at ca.ibm.com Thu Sep 20 09:01:24 2012 From: Daniel_Heidinga at ca.ibm.com (Daniel Heidinga) Date: Thu, 20 Sep 2012 12:01:24 -0400 Subject: Fw: [jsr-335-eg] Default method survey results Message-ID: (Apologies for the delay in responding to this issue - I'm experiencing email issues with new list) If we count Kevin's late vote, the survey ends in a tie. My inclination would be to then fall back to the result of the vote at JVM Languages Summit EG meeting - the 'default' keyword should be placed between the signature and the body. I don't want to drag this topic out too much further, but I think there are two pretty compelling reasons to avoid 'default' as a method modifier: 1) Users believe package access is 'default access' regardless of what the spec says and will be surprised that default means something else. Because we're introducing a lot of new concepts in this JSR, we should be careful to avoid perturbing user's mental models when we can. This is clearly a case where we can avoid the mismatch between what the user expects and what the new concept means. 2) Precedent matters - the annotation example is a clear precedent for placing 'default' between the signature and body. We've strived to respect precedent so far (when appropriate, of course) and the annotation example is a clear match to what we're trying to do. Let's run one more EG poll on this issue - a straight choice between: A) void foo() default { ... } B) default void foo() { ... } and let that decide the issue. --Dan -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120920/f332cb9a/attachment.html From brian.goetz at oracle.com Thu Sep 20 10:45:43 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 20 Sep 2012 13:45:43 -0400 Subject: Fw: [jsr-335-eg] Default method survey results In-Reply-To: References: Message-ID: <505B5647.5060307@oracle.com> While we're clear that "the syntax for default methods should be different", there is still clearly some diversity of opinion on the finer details. And this isn't surprising; syntax issue are highly subjective and therefore often fail to converge. They are the hardest issues to decide because people often feel strongly and our feelings are usually as much emotional as logical on such issues. The last poll had equal components "strongly for" and (less strongly) "against". The community has come down with a clear "strongly for", in a large enough survey (> 4000 votes) from a broad enough demographic to be taken seriously, and that should count with some weight in our deliberation. I don't want to get into a "hanging chad" debate about the polling methodology (i.e., should "strongly X" count equally against "weakly not X", "late votes don't count", "ties are broken by arm-wrestling", etc.) This isn't how we've worked so far and we won't start now. I think we have to be careful about leaning too hard on the "precedent" arguments; it's just too easy to get lost in your own perspective. Realistically, there is consistency and inconsistency with precedent to be found in both options, and this is almost always the case with syntax issues. Modifier-position-supporters will cite abstract as a precedent, and annotation-position-supporters will cite annotations as a precedent, and neither are wrong. The reality is which consistencies or inconsistencies we personally find more compelling are often more visceral than logical, and we should be up-front about that. Java is full enough of inconsistencies that its almost always possible to claim consistency with *something*. One confounding detail is that the positional preference and the choice of keyword do not seem to be as independent as we'd like them to be. Based on what you've said, I don't think you have a deep objection to the positioning per se, as much as the combination of modifier position + specific "default" keyword which will dispose some users to interpret "default" as "default accessibility." If there's a different keyword that would work here, I'd be OK with that. We chose "default" initially because it was already a keyword and a "pretty good" intuitive fit, but if there's something better, let's have it. One data point that may be significant here is: I've been writing Java 8 library code nearly every day for the last four months, and I still haven't gotten used to the "dangling" default syntax. We've frequently discussed how people's initial reactions and their long term reactions to syntax are often quite different. Usually the first impression is excessively negative ("bleah, different is scary!") but the long-term impression less negative once people "get use to it" (this was certainly the case for many with the lambda syntax); here's one that went the other way. This is a red flag for me. The current positioning is an irritant. The modifier positioning seems less of an irritant, while still sufficiently maintaining the goal of being different. (Also, the current positioning suffers when you consider the addition of final/static methods to interfaces.) I think the "default as modifier" is the best we've come up with *so far*. I think we should keep looking, but we shouldn't let that stop us from taking that step in the meantime. On 9/20/2012 12:01 PM, Daniel Heidinga wrote: > (Apologies for the delay in responding to this issue - I'm experiencing > email issues with new list) > > If we count Kevin's late vote, the survey ends in a tie. My inclination > would be to then fall back to the result of the vote at JVM Languages > Summit EG meeting - the 'default' keyword should be placed between the > signature and the body. > > I don't want to drag this topic out too much further, but I think there > are two pretty compelling reasons to avoid 'default' as a method modifier: > > 1) Users believe package access is 'default access' regardless of what > the spec says and will be surprised that default means something else. > Because we're introducing a lot of new concepts in this JSR, we should > be careful to avoid perturbing user's mental models when we can. This is > clearly a case where we can avoid the mismatch between what the user > expects and what the new concept means. > > 2) Precedent matters - the annotation example is a clear precedent for > placing 'default' between the signature and body. We've strived to > respect precedent so far (when appropriate, of course) and the > annotation example is a clear match to what we're trying to do. > > Let's run one more EG poll on this issue - a straight choice between: > A) void foo() default { ... } > B) default void foo() { ... } > and let that decide the issue. > > --Dan > From brian.goetz at oracle.com Thu Sep 20 15:03:06 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 20 Sep 2012 18:03:06 -0400 Subject: Exception transparency Message-ID: <505B929A.9080307@oracle.com> At the in-person meeting, I promised a writeup of why BGGA-style exception transparency seemed a poor balance of complexity/benefit for Java SE 8. Basically, this proposal would extend generics with variadic type arguments (where a generic type argument can represent a list of zero or more types.) This would let us define SAM types that abstract over the set of types thrown from their method: interface Block { void apply(T arg) throws X; } The "throws X" would indicate that X is a variadic type argument. Similarly, we could define generic methods that are generic in X: interface List { void forEach(Block block) throws X; } This seems kind of attractive at first. But, this gets uglier when you try to write even a simple combinator method, such as Predicate.and: class Predicates { static Predicate and(Predicate p1, Predicate p2) { return t -> p1.apply(t) && p2.apply(t); } } It's possible, but its pretty ugly, really easy to get wrong, and (like everything else with generics) if the library writer gets it wrong, the user is hosed. The generics foo overwhelms the simple body of the and() method. We've done a lot more investigation, but here is just a quick summary of disadvantages of BGGA-style exception transparency: - Makes the declarations of functional interfaces and lambda-consuming methods more complicated - Doubly so for combinator methods (e.g., Predicates.and) - Requires extra args at the use site on the non-throwing case (e.g., Predicate), which is ugly and ?leaky? (though this could probably be patched up in common cases, at the cost of extra complexity) - Challenges for retrofitting existing functional interfaces (e.g., Runnable, Comparator) because most existing SAM types are not generic over exceptions - Takes liberties with meaning of generic type params ? sometimes they refer to types, sometimes to sets of types - Inference undecidability ? if you have a generic method that accepts a SAM type throwing both X1, X2, cannot partition the set of exceptions thrown by the lambda body - Unsoundness of ?catch X? ? X will be erased, and you would be catching Exception instead - Would likely interact with future attempts to extend generics, such as varargs generics, which would be desirable for things like tuples - Not very transparent at all -- pretty intrusive, in fact. We're continuing to explore some ideas that might make exception transparency more tractable, but these would definitely be out of scope for Java SE 8. From brian.goetz at oracle.com Sun Sep 23 12:21:14 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 23 Sep 2012 15:21:14 -0400 Subject: Issue tracker Message-ID: <505F612A.3070507@oracle.com> As part of the transition to JCP 2.8, we need a publicly accessible issue tracker. We had, of course, hoped to have our new JIRA instance available for this purpose long ago, but there have been delays with that (though progress is still being made.) In order to not further delay the transition to JCP 2.8, we will use a temporary issue tracker on java.net under the OpenJDK specification terms of use (same as this mailing list.) Please send me (privately) your java.net IDs and I will add you as members of the project. From brian.goetz at oracle.com Wed Sep 26 13:07:14 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 26 Sep 2012 16:07:14 -0400 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed Message-ID: <50636072.5040407@oracle.com> The Lmabda JSR was originally submitted in November 2010, under the rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 [1], Oracle publicly committed to convert all in-flight JSRs led by Oracle to JCP 2.8. To convert an in-flight JSR to 2.8 requires the EG members to agree to the change. Would each of the JSR-335 EG members as listed on [2] please indicate your agreement or disagreement by responding to this message with a "Yes" or "No", on-list. [1] https://blogs.oracle.com/pcurran/entry/no_more_smoke_filled_rooms [2] http://www.jcp.org/en/jsr/detail?id=335 From david.lloyd at redhat.com Wed Sep 26 13:19:11 2012 From: david.lloyd at redhat.com (David M. Lloyd) Date: Wed, 26 Sep 2012 15:19:11 -0500 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed In-Reply-To: <50636072.5040407@oracle.com> References: <50636072.5040407@oracle.com> Message-ID: <5063633F.2090007@redhat.com> Red Hat: Yes On 09/26/2012 03:07 PM, Brian Goetz wrote: > The Lmabda JSR was originally submitted in November 2010, under the > rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 > [1], Oracle publicly committed to convert all in-flight JSRs led by > Oracle to JCP 2.8. > > To convert an in-flight JSR to 2.8 requires the EG members to agree to > the change. Would each of the JSR-335 EG members as listed on [2] > please indicate your agreement or disagreement by responding to this > message with a "Yes" or "No", on-list. > > > [1] https://blogs.oracle.com/pcurran/entry/no_more_smoke_filled_rooms > [2] http://www.jcp.org/en/jsr/detail?id=335 > -- - DML From Vladimir.Zakharov at gs.com Wed Sep 26 13:25:38 2012 From: Vladimir.Zakharov at gs.com (Zakharov, Vladimir) Date: Wed, 26 Sep 2012 16:25:38 -0400 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed In-Reply-To: <50636072.5040407@oracle.com> References: <50636072.5040407@oracle.com> Message-ID: Yes The Goldman Sachs Group, Inc. All rights reserved. See http://www.gs.com/disclaimer/global_email for important risk disclosures, conflicts of interest and other terms and conditions relating to this e-mail and your reliance on information contained in it.? This message may contain confidential or privileged information.? If you are not the intended recipient, please advise us immediately and delete this message.? See http://www.gs.com/disclaimer/email for further information on confidentiality and the risks of non-secure electronic communication.? If you cannot access these links, please notify us by reply message and we will send the contents to you.? -----Original Message----- From: lambda-spec-experts-bounces at openjdk.java.net [mailto:lambda-spec-experts-bounces at openjdk.java.net] On Behalf Of Brian Goetz Sent: Wednesday, September 26, 2012 4:07 PM To: lambda-spec-experts at openjdk.java.net Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed The Lmabda JSR was originally submitted in November 2010, under the rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 [1], Oracle publicly committed to convert all in-flight JSRs led by Oracle to JCP 2.8. To convert an in-flight JSR to 2.8 requires the EG members to agree to the change. Would each of the JSR-335 EG members as listed on [2] please indicate your agreement or disagreement by responding to this message with a "Yes" or "No", on-list. [1] https://blogs.oracle.com/pcurran/entry/no_more_smoke_filled_rooms [2] http://www.jcp.org/en/jsr/detail?id=335 From dl at cs.oswego.edu Wed Sep 26 13:26:53 2012 From: dl at cs.oswego.edu (Doug Lea) Date: Wed, 26 Sep 2012 16:26:53 -0400 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed In-Reply-To: <50636072.5040407@oracle.com> References: <50636072.5040407@oracle.com> Message-ID: <5063650D.9040105@cs.oswego.edu> Yes On 09/26/12 16:07, Brian Goetz wrote: > The Lmabda JSR was originally submitted in November 2010, under the > rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 > [1], Oracle publicly committed to convert all in-flight JSRs led by > Oracle to JCP 2.8. > > To convert an in-flight JSR to 2.8 requires the EG members to agree to the > change. Would each of the JSR-335 EG members as listed on [2] please indicate > your agreement or disagreement by responding to this message with a "Yes" or > "No", on-list. > > > [1] https://blogs.oracle.com/pcurran/entry/no_more_smoke_filled_rooms > [2] http://www.jcp.org/en/jsr/detail?id=335 > From kevinb at google.com Wed Sep 26 13:30:40 2012 From: kevinb at google.com (Kevin Bourrillion) Date: Wed, 26 Sep 2012 13:30:40 -0700 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed In-Reply-To: <50636072.5040407@oracle.com> References: <50636072.5040407@oracle.com> Message-ID: Google says yes. On Wed, Sep 26, 2012 at 1:07 PM, Brian Goetz wrote: > The Lmabda JSR was originally submitted in November 2010, under the > rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 > [1], Oracle publicly committed to convert all in-flight JSRs led by > Oracle to JCP 2.8. > > To convert an in-flight JSR to 2.8 requires the EG members to agree to the > change. Would each of the JSR-335 EG members as listed on [2] please > indicate your agreement or disagreement by responding to this message with > a "Yes" or "No", on-list. > > > [1] https://blogs.oracle.com/**pcurran/entry/no_more_smoke_**filled_rooms > [2] http://www.jcp.org/en/jsr/**detail?id=335 > > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120926/01294c9c/attachment.html From forax at univ-mlv.fr Wed Sep 26 13:56:34 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 26 Sep 2012 22:56:34 +0200 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed In-Reply-To: <50636072.5040407@oracle.com> References: <50636072.5040407@oracle.com> Message-ID: <50636C02.7090002@univ-mlv.fr> Yes, R?mi On 09/26/2012 10:07 PM, Brian Goetz wrote: > The Lambda JSR was originally submitted in November 2010, under the > rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 > [1], Oracle publicly committed to convert all in-flight JSRs led by > Oracle to JCP 2.8. > > To convert an in-flight JSR to 2.8 requires the EG members to agree to > the change. Would each of the JSR-335 EG members as listed on [2] > please indicate your agreement or disagreement by responding to this > message with a "Yes" or "No", on-list. > > > [1] https://blogs.oracle.com/pcurran/entry/no_more_smoke_filled_rooms > [2] http://www.jcp.org/en/jsr/detail?id=335 > From andrey.breslav at jetbrains.com Wed Sep 26 21:13:44 2012 From: andrey.breslav at jetbrains.com (Andrey Breslav) Date: Thu, 27 Sep 2012 08:13:44 +0400 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed In-Reply-To: <50636072.5040407@oracle.com> References: <50636072.5040407@oracle.com> Message-ID: JetBrains: yes On Sep 27, 2012, at 00:07 , Brian Goetz wrote: > The Lmabda JSR was originally submitted in November 2010, under the > rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 > [1], Oracle publicly committed to convert all in-flight JSRs led by > Oracle to JCP 2.8. > > To convert an in-flight JSR to 2.8 requires the EG members to agree to the change. Would each of the JSR-335 EG members as listed on [2] please indicate your agreement or disagreement by responding to this message with a "Yes" or "No", on-list. > > > [1] https://blogs.oracle.com/pcurran/entry/no_more_smoke_filled_rooms > [2] http://www.jcp.org/en/jsr/detail?id=335 > -- Andrey Breslav http://jetbrains.com Develop with pleasure! From brian.goetz at oracle.com Thu Sep 27 11:10:56 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 27 Sep 2012 14:10:56 -0400 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed In-Reply-To: <50636072.5040407@oracle.com> References: <50636072.5040407@oracle.com> Message-ID: <506496B0.5000109@oracle.com> So far we have Yes votes from: Oracle, IBM, Red Hat, JetBrains, Goldman Sachs, Doug Lea, Remi Forax Waiting for votes from: Bob Lee, Sam Pullara On 9/26/2012 4:07 PM, Brian Goetz wrote: > The Lmabda JSR was originally submitted in November 2010, under the > rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 > [1], Oracle publicly committed to convert all in-flight JSRs led by > Oracle to JCP 2.8. > > To convert an in-flight JSR to 2.8 requires the EG members to agree to > the change. Would each of the JSR-335 EG members as listed on [2] > please indicate your agreement or disagreement by responding to this > message with a "Yes" or "No", on-list. > > > [1] https://blogs.oracle.com/pcurran/entry/no_more_smoke_filled_rooms > [2] http://www.jcp.org/en/jsr/detail?id=335 > From brian.goetz at oracle.com Thu Sep 27 13:57:50 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 27 Sep 2012 16:57:50 -0400 Subject: Issue tracker Message-ID: <5064BDCE.2030508@oracle.com> I've started populating the issue tracker with currently open issues. I've created some "components", a subset of the cross product between { language, libs, vm } x { design, specification, implementation }. - Design -- how *should* things work - Specification -- how should they be specified - Implementation -- how should they be implemented I've populated the Language Design category with the issues that I've got noted as open as of the last EG meeting. http://java.net/jira/browse/JSR_335/component/14625 Please have a look to see if I've missed any significant open language issues. From spullara at gmail.com Thu Sep 27 16:26:53 2012 From: spullara at gmail.com (Sam Pullara) Date: Thu, 27 Sep 2012 16:26:53 -0700 Subject: Transitioning JSR-335 to JCP 2.8 -- EG approval needed In-Reply-To: <506496B0.5000109@oracle.com> References: <50636072.5040407@oracle.com> <506496B0.5000109@oracle.com> Message-ID: <7990618261362170451@unknownmsgid> Yes. Any errors are bugs in iOS 6 On Sep 27, 2012, at 11:27 AM, Brian Goetz wrote: > So far we have Yes votes from: > Oracle, IBM, Red Hat, JetBrains, Goldman Sachs, Doug Lea, Remi Forax > > Waiting for votes from: > Bob Lee, Sam Pullara > > On 9/26/2012 4:07 PM, Brian Goetz wrote: >> The Lmabda JSR was originally submitted in November 2010, under the >> rules of JCP 2.7. When JCP 2.8 (JSR 348) was approved in October 2011 >> [1], Oracle publicly committed to convert all in-flight JSRs led by >> Oracle to JCP 2.8. >> >> To convert an in-flight JSR to 2.8 requires the EG members to agree to >> the change. Would each of the JSR-335 EG members as listed on [2] >> please indicate your agreement or disagreement by responding to this >> message with a "Yes" or "No", on-list. >> >> >> [1] https://blogs.oracle.com/pcurran/entry/no_more_smoke_filled_rooms >> [2] http://www.jcp.org/en/jsr/detail?id=335 >> From brian.goetz at oracle.com Fri Sep 28 11:47:34 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 28 Sep 2012 14:47:34 -0400 Subject: Serialization opt-in syntax (again) Message-ID: <5065F0C6.4000509@oracle.com> I put all the candidate syntaxes so far in the JIRA issue for this, but a new one came to light this week that we kind of like. The problem is: let's say you have a SAM that is not serializable, but you want the instance to be, such as in: Runnable r = () -> { }; The problem is that we really want to specify multiple interfaces for the lambda, and as long as their intersection has only one abstract method, that should be OK. So, how about using the space between the closing paren and the arrow: Runnable r = () implements Serializable -> { ... } As a bonus, if we wanted to be explicit about all the implemented interfaces, this easily extends to: Object p = (String s) implements Predicate, Serializable -> { ... } This also extends nicely to inner class creation expressions. Right now there is a limit of one named supertype. But this could be extended: Predicate p = new Predicate() implements Serializable { ... } In this case, there is no single-method restriction; you could implement Iterator and Runnable if you wanted: new Iterator() implements Runnable { ... } Note that none of this is serialization-specific; it is simply a way of being explicit about multiple supertypes in contexts there this was not previously allowed. From sam at sampullara.com Fri Sep 28 12:12:30 2012 From: sam at sampullara.com (Sam Pullara) Date: Fri, 28 Sep 2012 12:12:30 -0700 Subject: Serialization opt-in syntax (again) In-Reply-To: <5065F0C6.4000509@oracle.com> References: <5065F0C6.4000509@oracle.com> Message-ID: Looks pretty good to me but I also don't use serialization. Sam On Fri, Sep 28, 2012 at 11:47 AM, Brian Goetz wrote: > I put all the candidate syntaxes so far in the JIRA issue for this, but a > new one came to light this week that we kind of like. > > The problem is: let's say you have a SAM that is not serializable, but you > want the instance to be, such as in: > > Runnable r = () -> { }; > > The problem is that we really want to specify multiple interfaces for the > lambda, and as long as their intersection has only one abstract method, that > should be OK. > > So, how about using the space between the closing paren and the arrow: > > Runnable r = () implements Serializable -> { ... } > > As a bonus, if we wanted to be explicit about all the implemented > interfaces, this easily extends to: > > Object p = (String s) implements Predicate, Serializable -> { ... > } > > > This also extends nicely to inner class creation expressions. Right now > there is a limit of one named supertype. But this could be extended: > > Predicate p = new Predicate() implements Serializable { > ... } > > In this case, there is no single-method restriction; you could implement > Iterator and Runnable if you wanted: > > new Iterator() implements Runnable { ... } > > Note that none of this is serialization-specific; it is simply a way of > being explicit about multiple supertypes in contexts there this was not > previously allowed. > From kevinb at google.com Fri Sep 28 12:34:18 2012 From: kevinb at google.com (Kevin Bourrillion) Date: Fri, 28 Sep 2012 12:34:18 -0700 Subject: Serialization opt-in syntax (again) In-Reply-To: References: <5065F0C6.4000509@oracle.com> Message-ID: Well, to me the positioning of "implements Whatever" after the argument list looks invasive and unnatural. It makes me think "how exactly is the *argument list* implementing this interface?" Even though none of the options we've found are *great*, I still think there are some better than this. On Fri, Sep 28, 2012 at 12:12 PM, Sam Pullara wrote: > Looks pretty good to me but I also don't use serialization. > > Sam > > On Fri, Sep 28, 2012 at 11:47 AM, Brian Goetz > wrote: > > I put all the candidate syntaxes so far in the JIRA issue for this, but a > > new one came to light this week that we kind of like. > > > > The problem is: let's say you have a SAM that is not serializable, but > you > > want the instance to be, such as in: > > > > Runnable r = () -> { }; > > > > The problem is that we really want to specify multiple interfaces for the > > lambda, and as long as their intersection has only one abstract method, > that > > should be OK. > > > > So, how about using the space between the closing paren and the arrow: > > > > Runnable r = () implements Serializable -> { ... } > > > > As a bonus, if we wanted to be explicit about all the implemented > > interfaces, this easily extends to: > > > > Object p = (String s) implements Predicate, Serializable -> { > ... > > } > > > > > > This also extends nicely to inner class creation expressions. Right now > > there is a limit of one named supertype. But this could be extended: > > > > Predicate p = new Predicate() implements Serializable { > > ... } > > > > In this case, there is no single-method restriction; you could implement > > Iterator and Runnable if you wanted: > > > > new Iterator() implements Runnable { ... } > > > > Note that none of this is serialization-specific; it is simply a way of > > being explicit about multiple supertypes in contexts there this was not > > previously allowed. > > > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120928/1672496f/attachment.html From crazybob at crazybob.org Fri Sep 28 13:14:07 2012 From: crazybob at crazybob.org (Bob Lee) Date: Fri, 28 Sep 2012 15:14:07 -0500 Subject: Serialization opt-in syntax (again) In-Reply-To: <5065F0C6.4000509@oracle.com> References: <5065F0C6.4000509@oracle.com> Message-ID: I like the semantics a lot! Maybe moving the "implements" decl to the right of the -> would address Kevin's concerns? Then it would read "lambda (->) implements ..." Bob On Fri, Sep 28, 2012 at 1:47 PM, Brian Goetz wrote: > I put all the candidate syntaxes so far in the JIRA issue for this, but a > new one came to light this week that we kind of like. > > The problem is: let's say you have a SAM that is not serializable, but you > want the instance to be, such as in: > > Runnable r = () -> { }; > > The problem is that we really want to specify multiple interfaces for the > lambda, and as long as their intersection has only one abstract method, > that should be OK. > > So, how about using the space between the closing paren and the arrow: > > Runnable r = () implements Serializable -> { ... } > > As a bonus, if we wanted to be explicit about all the implemented > interfaces, this easily extends to: > > Object p = (String s) implements Predicate, Serializable -> { > ... } > > > This also extends nicely to inner class creation expressions. Right now > there is a limit of one named supertype. But this could be extended: > > Predicate p = new Predicate() implements Serializable { > ... } > > In this case, there is no single-method restriction; you could implement > Iterator and Runnable if you wanted: > > new Iterator() implements Runnable { ... } > > Note that none of this is serialization-specific; it is simply a way of > being explicit about multiple supertypes in contexts there this was not > previously allowed. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120928/179e653e/attachment.html From kevinb at google.com Fri Sep 28 13:21:22 2012 From: kevinb at google.com (Kevin Bourrillion) Date: Fri, 28 Sep 2012 13:21:22 -0700 Subject: Serialization opt-in syntax (again) In-Reply-To: References: <5065F0C6.4000509@oracle.com> Message-ID: I don't think it changes much. These words still don't feel like they belong there. The fact of serializability has really intruded into the center of the expression... On Fri, Sep 28, 2012 at 1:14 PM, Bob Lee wrote: > I like the semantics a lot! Maybe moving the "implements" decl to the > right of the -> would address Kevin's concerns? Then it would read "lambda > (->) implements ..." > > Bob > > > On Fri, Sep 28, 2012 at 1:47 PM, Brian Goetz wrote: > >> I put all the candidate syntaxes so far in the JIRA issue for this, but a >> new one came to light this week that we kind of like. >> >> The problem is: let's say you have a SAM that is not serializable, but >> you want the instance to be, such as in: >> >> Runnable r = () -> { }; >> >> The problem is that we really want to specify multiple interfaces for the >> lambda, and as long as their intersection has only one abstract method, >> that should be OK. >> >> So, how about using the space between the closing paren and the arrow: >> >> Runnable r = () implements Serializable -> { ... } >> >> As a bonus, if we wanted to be explicit about all the implemented >> interfaces, this easily extends to: >> >> Object p = (String s) implements Predicate, Serializable -> { >> ... } >> >> >> This also extends nicely to inner class creation expressions. Right now >> there is a limit of one named supertype. But this could be extended: >> >> Predicate p = new Predicate() implements Serializable { >> ... } >> >> In this case, there is no single-method restriction; you could implement >> Iterator and Runnable if you wanted: >> >> new Iterator() implements Runnable { ... } >> >> Note that none of this is serialization-specific; it is simply a way of >> being explicit about multiple supertypes in contexts there this was not >> previously allowed. >> >> > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120928/f6678763/attachment.html From kevinb at google.com Fri Sep 28 13:40:52 2012 From: kevinb at google.com (Kevin Bourrillion) Date: Fri, 28 Sep 2012 13:40:52 -0700 Subject: Serialization opt-in syntax (again) In-Reply-To: References: <5065F0C6.4000509@oracle.com> Message-ID: On Fri, Sep 28, 2012 at 12:34 PM, Kevin Bourrillion wrote: Well, to me the positioning of "implements Whatever" after the argument > list looks invasive and unnatural. It makes me think "how exactly is the > *argument list* implementing this interface?" > > Even though none of the options we've found are *great*, I still think > there are some better than this. > And I've now updated the bug (http://java.net/jira/browse/JSR_335-1) to say which two options I specifically mean by this. -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120928/a544c82c/attachment-0001.html From forax at univ-mlv.fr Sat Sep 29 07:11:37 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 29 Sep 2012 16:11:37 +0200 Subject: Serialization opt-in syntax (again) In-Reply-To: <5065F0C6.4000509@oracle.com> References: <5065F0C6.4000509@oracle.com> Message-ID: <50670199.8070805@univ-mlv.fr> I've updated the corresponding bug: http://java.net/jira/browse/JSR_335-1 Anyway, I'm am still not convinced that making a lambda Serializable add a cost that worth the pain of creating a new syntax. Brian, do you have data about the supplementary cost of creating Serializable lambda ? R?mi On 09/28/2012 08:47 PM, Brian Goetz wrote: > I put all the candidate syntaxes so far in the JIRA issue for this, > but a new one came to light this week that we kind of like. > > The problem is: let's say you have a SAM that is not serializable, but > you want the instance to be, such as in: > > Runnable r = () -> { }; > > The problem is that we really want to specify multiple interfaces for > the lambda, and as long as their intersection has only one abstract > method, that should be OK. > > So, how about using the space between the closing paren and the arrow: > > Runnable r = () implements Serializable -> { ... } > > As a bonus, if we wanted to be explicit about all the implemented > interfaces, this easily extends to: > > Object p = (String s) implements Predicate, Serializable -> > { ... } > > > This also extends nicely to inner class creation expressions. Right > now there is a limit of one named supertype. But this could be extended: > > Predicate p = new Predicate() implements > Serializable { ... } > > In this case, there is no single-method restriction; you could > implement Iterator and Runnable if you wanted: > > new Iterator() implements Runnable { ... } > > Note that none of this is serialization-specific; it is simply a way > of being explicit about multiple supertypes in contexts there this was > not previously allowed. > From brian.goetz at oracle.com Fri Sep 28 20:48:04 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 28 Sep 2012 23:48:04 -0400 Subject: Serialization opt-in syntax (again) In-Reply-To: References: <5065F0C6.4000509@oracle.com> Message-ID: <07C3F547-6459-412F-A13D-E2616116832E@oracle.com> Bob is definitely right here that the semantics of this are closer to what we want than any of the others. While the proximate problem is "how do I make a serializable lambda", the way you make a class serializable in Java is (in part) to extend Serializable. So something that addresses the "how to I extend Serializable" question is much more in the spirit of how serialization works (for better or worse) than a special magic serialization syntax. On Sep 28, 2012, at 4:14 PM, Bob Lee wrote: > I like the semantics a lot! Maybe moving the "implements" decl to the right of the -> would address Kevin's concerns? Then it would read "lambda (->) implements ..." > > Bob > > On Fri, Sep 28, 2012 at 1:47 PM, Brian Goetz wrote: > I put all the candidate syntaxes so far in the JIRA issue for this, but a new one came to light this week that we kind of like. > > The problem is: let's say you have a SAM that is not serializable, but you want the instance to be, such as in: > > Runnable r = () -> { }; > > The problem is that we really want to specify multiple interfaces for the lambda, and as long as their intersection has only one abstract method, that should be OK. > > So, how about using the space between the closing paren and the arrow: > > Runnable r = () implements Serializable -> { ... } > > As a bonus, if we wanted to be explicit about all the implemented interfaces, this easily extends to: > > Object p = (String s) implements Predicate, Serializable -> { ... } > > > This also extends nicely to inner class creation expressions. Right now there is a limit of one named supertype. But this could be extended: > > Predicate p = new Predicate() implements Serializable { ... } > > In this case, there is no single-method restriction; you could implement Iterator and Runnable if you wanted: > > new Iterator() implements Runnable { ... } > > Note that none of this is serialization-specific; it is simply a way of being explicit about multiple supertypes in contexts there this was not previously allowed. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120928/73adf48b/attachment.html From brian.goetz at oracle.com Sat Sep 29 14:14:13 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 29 Sep 2012 17:14:13 -0400 Subject: Serialization opt-in syntax (again) In-Reply-To: <50670199.8070805@univ-mlv.fr> References: <5065F0C6.4000509@oracle.com> <50670199.8070805@univ-mlv.fr> Message-ID: <61F41F8E-1C9D-448F-BB5A-231A9CB5F769@oracle.com> > Anyway, I'm am still not convinced that making a lambda Serializable add a cost that worth the pain of creating a new syntax. Here's the reason this is important: libraries. We have lots of combinators that take a lambda and produce a new lambda, like Comparators.compose. We'd like to write it like (modulo generics): Comparator compose(Comparator one, Comparator two) { return (x, y) -> { int cmp = one.compare(x, y); return cmp != 0 ? cmp : two.compare(x, y); }; } But instead, we write it like this: private static class ComposedComparator implements Comparator, Serializable { private static final long serialVersionUID = -3088981872625314196L; private final Comparator first; private final Comparator second; private ComposedComparator(Comparator first, Comparator second) { this.first = Objects.requireNonNull(first); this.second = Objects.requireNonNull(second); } @Override public int compare(T c1, T c2) { int res = first.compare(c1, c2); return (res != 0) ? res : second.compare(c1, c2); } } public static Comparator compose(Comparator first, Comparator second) { return new ComposedComparator<>(first, second); } We do it this way entirely for serialization; if the user has two serializable comparators and wants to compose them, there should be a way of making the result serializable. Doubling the surface area of the library is not a good option. Nor is making it so that the result cannot be serialziable. And if the library has to choose between lambda and serialization support, that's not so good either. You should be able to write these combinators with lambda without giving up on serializability. That's why we need this. > Brian, do you have data about the supplementary cost of creating Serializable lambda ? Sadly I do not yet, and may not for a while. But I know that there will be a nonzero footprint and capture cost, and it imposes some additional hurdles on some VM optimizations we want to do. I think that's all the information we will ahve for a while, but I think we have to go on the assumption that the cost will be enough that "make all lambdas serializable" is not a very good choice. From brian.goetz at oracle.com Sat Sep 29 14:20:03 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 29 Sep 2012 17:20:03 -0400 Subject: Serialization opt-in syntax (again) In-Reply-To: <07C3F547-6459-412F-A13D-E2616116832E@oracle.com> References: <5065F0C6.4000509@oracle.com> <07C3F547-6459-412F-A13D-E2616116832E@oracle.com> Message-ID: <4DC8F899-2561-4453-A574-965DF8F63A13@oracle.com> Here is another option that we explored a while ago and initially turned our nose up at, but we are still willing to explore: using intersection types in a cast to target type, inspired by multiple type bounds in generics: Predicate ps = (Predicate & Serializable) x-> x.isEmpty(); The major downsides are: - Verbose (have to repeat the target type) - Another ad-hoc context where we allow intersection types, though offers some runway in the event we want to extend the use of intersection types in the future. It extends to inner class expressions in an OK manner: new Foo(blah) & Serializable { ... } Again, the cast syntax can apply to any intersection of types that meets the SAM-ness requirement, and the inner class syntax can be any arbitrary set of interfaces. On Sep 28, 2012, at 11:48 PM, Brian Goetz wrote: > Bob is definitely right here that the semantics of this are closer to what we want than any of the others. While the proximate problem is "how do I make a serializable lambda", the way you make a class serializable in Java is (in part) to extend Serializable. So something that addresses the "how to I extend Serializable" question is much more in the spirit of how serialization works (for better or worse) than a special magic serialization syntax. > > > On Sep 28, 2012, at 4:14 PM, Bob Lee wrote: > >> I like the semantics a lot! Maybe moving the "implements" decl to the right of the -> would address Kevin's concerns? Then it would read "lambda (->) implements ..." >> >> Bob >> >> On Fri, Sep 28, 2012 at 1:47 PM, Brian Goetz wrote: >> I put all the candidate syntaxes so far in the JIRA issue for this, but a new one came to light this week that we kind of like. >> >> The problem is: let's say you have a SAM that is not serializable, but you want the instance to be, such as in: >> >> Runnable r = () -> { }; >> >> The problem is that we really want to specify multiple interfaces for the lambda, and as long as their intersection has only one abstract method, that should be OK. >> >> So, how about using the space between the closing paren and the arrow: >> >> Runnable r = () implements Serializable -> { ... } >> >> As a bonus, if we wanted to be explicit about all the implemented interfaces, this easily extends to: >> >> Object p = (String s) implements Predicate, Serializable -> { ... } >> >> >> This also extends nicely to inner class creation expressions. Right now there is a limit of one named supertype. But this could be extended: >> >> Predicate p = new Predicate() implements Serializable { ... } >> >> In this case, there is no single-method restriction; you could implement Iterator and Runnable if you wanted: >> >> new Iterator() implements Runnable { ... } >> >> Note that none of this is serialization-specific; it is simply a way of being explicit about multiple supertypes in contexts there this was not previously allowed. >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120929/7209d096/attachment.html From forax at univ-mlv.fr Sun Sep 30 06:04:10 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 30 Sep 2012 15:04:10 +0200 Subject: Serialization opt-in syntax (again) In-Reply-To: <61F41F8E-1C9D-448F-BB5A-231A9CB5F769@oracle.com> References: <5065F0C6.4000509@oracle.com> <50670199.8070805@univ-mlv.fr> <61F41F8E-1C9D-448F-BB5A-231A9CB5F769@oracle.com> Message-ID: <5068434A.6070201@univ-mlv.fr> On 09/29/2012 11:14 PM, Brian Goetz wrote: >> >Brian, do you have data about the supplementary cost of creating Serializable lambda ? > Sadly I do not yet, and may not for a while. But I know that there will be a nonzero footprint and capture cost, and it imposes some additional hurdles on some VM optimizations we want to do. I think that's all the information we will ahve for a while, but I think we have to go on the assumption that the cost will be enough that "make all lambdas serializable" is not a very good choice. > > I've done some tests asking the VM to dump the assembly code so see the impact of having lambdas serializable or not. The serialization is implemented by storing the parameter of the lambda metafactory to be able to write them in the stream and replay them when deserializing. These parameters are the same for all lambdas created from the same call site (that why they are sent has bootstrap constants by the way) so you can create an object containing all the parameters once by callsite. First, if the lambda is constant i.e. don't capture any states, then the lambda is created once and reused, in that case the cost of a serializable lambda is only a memory cost, the object containing the serialization info is allocated once and the lambda has a supplementary field story a reference to that object. If the lambda capture some value from the scope, because the VM does escape analysis, there are two cases, or the escape analysis works or it doesn't work. The escape analysis as currently implemented in hotspot only works if the creation of the lambda and the call are in the same inlining blob. By example, in the following code, the escape analysis find that it's not necessary to allocate the lambda proxy object. private static void foo() { int[] array = new int[10_000_000]; for(int i=0; i { array[i] = i; }; r.run(); } } In that case, the serializable info object is allocated once and never used so there is no supplementary cost. And if the escape analysis fails, in the following example, the lambda object is stored in a static field thus escape and must be allocated. private static Runnable r1; private static void foo() { int[] array = new int[10_000_000]; for(int i=0; i { array[i] = i; }; } } In that case, the serialization object needs to be allocated once and for each iteration of the loop, the proxy object is created with a supplementary field which is assigned in one movl because the serializable info object is considered as constant. with serialization: 0x00007f649906dbc8: mov $0xc7cc47e8,%r10d ; {oop('serialization/Test2$ProxySer')} 0x00007f649906dbce: mov 0xb0(%r10),%r10 0x00007f649906dbd5: mov %r10,(%rax) 0x00007f649906dbd8: movl $0xc7cc47e8,0x8(%rax) ; {oop('serialization/Test2$ProxySer')} 0x00007f649906dbdf: mov %ebx,0xc(%rax) ;*putfield index 0x00007f649906dbe2: movl $0xeef41bc0,0x10(%rax) ;*putfield info 0x00007f649906dbe9: mov %rbp,%r10 0x00007f649906dbec: mov %r10d,0x14(%rax) ... without: 0x00007f78cce556cc: mov $0xc7cc15b8,%r10d ; {oop('serialization/Test2$Proxy')} 0x00007f78cce556d2: mov 0xb0(%r10),%r10 0x00007f78cce556d9: mov %r10,(%rax) 0x00007f78cce556dc: movl $0xc7cc15b8,0x8(%rax) ; {oop('serialization/Test2$Proxy')} 0x00007f78cce5565f: mov %r12d,0x14(%rax) 0x00007f78cce55663: mov %ebx,0xc(%rax) ;*putfield index 0x00007f78cce55666: mov %rbp,%r10 0x00007f78cce55669: mov %r10d,0x10(%rax) ... You can see the supplementary movl at 0x00007f649906dbe2. I think that the cost of serialization is negligible because if a lambda escape it means it will be used in a collection stream or in Doug's parallel stuff which usually allocates a small number of objects before doing the computation so the supplementary cost involved by creating a serializable lambda will be hidden by the cost of creating these objects. so I don't see why we have to burden users with a special syntax for something that they can get for free. The only concern is if someone want a lambda that is not serializable for security reason, but I think this case is not frequent enough to ask him to write an inner class instead. R?mi * by the way the last two instructions of the snippets show that the array variable is spilled on stack which is weird, the array is a hot variable of the loop, it should never be spilled. From brian.goetz at oracle.com Sun Sep 30 06:59:44 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 30 Sep 2012 09:59:44 -0400 Subject: Serialization opt-in syntax (again) In-Reply-To: <5068434A.6070201@univ-mlv.fr> References: <5065F0C6.4000509@oracle.com> <50670199.8070805@univ-mlv.fr> <61F41F8E-1C9D-448F-BB5A-231A9CB5F769@oracle.com> <5068434A.6070201@univ-mlv.fr> Message-ID: On Sep 30, 2012, at 9:04 AM, Remi Forax wrote: > On 09/29/2012 11:14 PM, Brian Goetz wrote: >>> >Brian, do you have data about the supplementary cost of creating Serializable lambda ? >> Sadly I do not yet, and may not for a while. But I know that there will be a nonzero footprint and capture cost, and it imposes some additional hurdles on some VM optimizations we want to do. I think that's all the information we will ahve for a while, but I think we have to go on the assumption that the cost will be enough that "make all lambdas serializable" is not a very good choice. > > I've done some tests asking the VM to dump the assembly code so see the impact of having lambdas serializable or not. Given that we don't have an implementation yet, not sure how you could have done this. > First, if the lambda is constant i.e. don't capture any states, then the lambda is created once and reused, Yes, that's the easy case. Also, note that our current translation scheme -- where we generate bytecode for each lambda -- is more serialization friendly than the alternate scheme, where we generate a single wrapper for each SAM and invoke the behavior as an MH. In the latter case, we have to keep around a lot more information that otherwise would have been thrown away by the MF, such as the captured arguments bound with insertArguments. It is NOT going to be free in most cases. We can do our best to make it small. From brian.goetz at oracle.com Sun Sep 30 07:43:04 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 30 Sep 2012 10:43:04 -0400 Subject: Serialization stability and naming (and syntax) Message-ID: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> A confounding factor with picking a serialization syntax is "does the syntax provide a place to put a name, or do we need to do something else for that?" The reality is that there is relatively little we can do to make serialized lambdas stable across recompilation. The desugared method name is one aspect of instability, but it is only one. This problem is worse than the "unstable class name" problem of inner classes, and I don't think we have the will to distort the design very much to make it all that much better. My conclusion is that being able to specify a stable name is only slightly less brittle than not being able to, which leads me to believe that we should not value a "name" slot very highly in picking a syntax. Example: order of capture. Suppose we have a lambda x -> (capA < capB) ? x : 0; If this is refactored into x -> (capB >= capA) ? 0 : x; as your IDE will happily do for you, you've broken serialized instances. If the compiler picks a stable algorithm at all for assigning captured values to indexed slots, it will probably be something like "the order in which the captured vars appear in the body." Example: capture arity change. This one is obvious; if you add or remove a captured variable, you change the arity of the desugared lambda body. Example: captured type change. If we have: Collection c = ... x -> c.contains(x); and change the type of the captured variable outside the lambda: List c = ... x -> c.contains(x); this will change the signature of the desguared lambda body. Example: compiler optimization Given: class X { public final int x = 3; ... y -> (y > x) ? y : 0; } Ordinarily we translate this by capturing 'this' so we can refer to this.x; a smarter compiler could realize that we can constant-fold x into the lambda and make it noncapturing. Again, breaking serialized instances. The bottom line is that there are so many ways that we can break eisting serialized instances -- even more than with inner classes. The target profile we set at the outset -- serialization works when you have bytecode-identical classes on both sides -- is really the only thing that is guaranteed to work. Eliminate one source of instability -- the name -- yields only a minor improvement. If we care about name stability, perhaps we should spend the effort on a better naming scheme than lambda$nnn, one that is less sensitive to small changes into the source code. From kevinb at google.com Sun Sep 30 09:04:31 2012 From: kevinb at google.com (Kevin Bourrillion) Date: Sun, 30 Sep 2012 09:04:31 -0700 Subject: Serialization stability and naming (and syntax) In-Reply-To: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> References: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> Message-ID: So, at issue is: do we need the ability to name lambdas at all? Your point is that the benefits to stability of serialized forms are very small, and I'm inclined to agree. But for what other reasons are names useful? We've talked about how that name could appear in toString output and in stack traces. Most users wouldn't bother to use names just for those reasons, but from feedback Guava has received I think many users would greatly appreciate that the *libraries* they use were able to name all their lambdas. On Sun, Sep 30, 2012 at 7:43 AM, Brian Goetz wrote: > A confounding factor with picking a serialization syntax is "does the > syntax provide a place to put a name, or do we need to do something else > for that?" > > The reality is that there is relatively little we can do to make > serialized lambdas stable across recompilation. The desugared method name > is one aspect of instability, but it is only one. This problem is worse > than the "unstable class name" problem of inner classes, and I don't think > we have the will to distort the design very much to make it all that much > better. My conclusion is that being able to specify a stable name is only > slightly less brittle than not being able to, which leads me to believe > that we should not value a "name" slot very highly in picking a syntax. > > Example: order of capture. Suppose we have a lambda > x -> (capA < capB) ? x : 0; > > If this is refactored into > > x -> (capB >= capA) ? 0 : x; > > as your IDE will happily do for you, you've broken serialized instances. > If the compiler picks a stable algorithm at all for assigning captured > values to indexed slots, it will probably be something like "the order in > which the captured vars appear in the body." > > > Example: capture arity change. This one is obvious; if you add or remove > a captured variable, you change the arity of the desugared lambda body. > > > Example: captured type change. If we have: > > Collection c = ... > x -> c.contains(x); > > and change the type of the captured variable outside the lambda: > > List c = ... > x -> c.contains(x); > > this will change the signature of the desguared lambda body. > > > Example: compiler optimization > > Given: > > class X { > public final int x = 3; > > ... > y -> (y > x) ? y : 0; > } > > Ordinarily we translate this by capturing 'this' so we can refer to > this.x; a smarter compiler could realize that we can constant-fold x into > the lambda and make it noncapturing. Again, breaking serialized instances. > > > The bottom line is that there are so many ways that we can break eisting > serialized instances -- even more than with inner classes. The target > profile we set at the outset -- serialization works when you have > bytecode-identical classes on both sides -- is really the only thing that > is guaranteed to work. > > Eliminate one source of instability -- the name -- yields only a minor > improvement. If we care about name stability, perhaps we should spend the > effort on a better naming scheme than lambda$nnn, one that is less > sensitive to small changes into the source code. > > > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/attachments/20120930/310d3797/attachment.html From brian.goetz at oracle.com Sun Sep 30 09:14:31 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 30 Sep 2012 09:14:31 -0700 Subject: Serialization stability and naming (and syntax) In-Reply-To: References: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> Message-ID: > Your point is that the benefits to stability of serialized forms are very small, and I'm inclined to agree. But for what other reasons are names useful? We've talked about how that name could appear in toString output and in stack traces. Named lambdas are potentially useful for: - stack traces, toString - nonlocal return - recursion - serialization Of these, its seeming that serialization is not important enough to add naming, and clearly nonlocal return is not, since we don't have that. Ditto for recursion. So that leaves stack traces / toString. A few folks have suggested the syntax name(args) -> body for named lambdas but I think this is impractical; the interaction with inferred parameter types renders the confusion between method invocations and lambdas too great: foo(x, y) -> x+y looks too much like a method invocation. We also considered a label-like scheme: (name: x, y, z) -> body But in any case, something like @Serial(name) lambda would really be bad, because then we would *only* be able to use the name for serialization.  > So, at issue is: do we need the ability to name lambdas at all? Need? No. Nice to have? Yes. Willing to pick an ugly syntax? Probably not. From sam at sampullara.com Sun Sep 30 10:42:27 2012 From: sam at sampullara.com (Sam Pullara) Date: Sun, 30 Sep 2012 10:42:27 -0700 Subject: Serialization stability and naming (and syntax) In-Reply-To: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> References: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> Message-ID: <343A3A21-6D0B-4D6E-9C14-19F7D5AA26F9@sampullara.com> On Sep 30, 2012, at 7:43 AM, Brian Goetz wrote: > > Example: order of capture. Suppose we have a lambda > x -> (capA < capB) ? x : 0; > > If this is refactored into > > x -> (capB >= capA) ? 0 : x; > > as your IDE will happily do for you, you've broken serialized instances. If the compiler picks a stable algorithm at all for assigning captured values to indexed slots, it will probably be something like "the order in which the captured vars appear in the body." Something similar would happen for renames even if we introduced a stable sort order. > The bottom line is that there are so many ways that we can break eisting serialized instances -- even more than with inner classes. The target profile we set at the outset -- serialization works when you have bytecode-identical classes on both sides -- is really the only thing that is guaranteed to work. > > Eliminate one source of instability -- the name -- yields only a minor improvement. If we care about name stability, perhaps we should spend the effort on a better naming scheme than lambda$nnn, one that is less sensitive to small changes into the source code. I don't think we will get better than "the same code on both sides of the wire works" which is all anyone has had to date with serialization anyway. I propose that you put in the method name and then number them. That might even be useful in a stack trace when debug is off. lamba$method$nnn You can change this for inner classes as well. Whatever syntax is proposed I would like some use case for it that isn't Serialization since I will never use Serialization and would vote not to do it at all if that was tenable. So, things where you can implement tagging interfaces or apply annotations are preferable to me. Sam From forax at univ-mlv.fr Sun Sep 30 11:16:51 2012 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 30 Sep 2012 20:16:51 +0200 Subject: Serialization opt-in syntax (again) In-Reply-To: References: <5065F0C6.4000509@oracle.com> <50670199.8070805@univ-mlv.fr> <61F41F8E-1C9D-448F-BB5A-231A9CB5F769@oracle.com> <5068434A.6070201@univ-mlv.fr> Message-ID: <50688C93.8080601@univ-mlv.fr> On 09/30/2012 03:59 PM, Brian Goetz wrote: > On Sep 30, 2012, at 9:04 AM, Remi Forax wrote: > >> On 09/29/2012 11:14 PM, Brian Goetz wrote: >>>>> Brian, do you have data about the supplementary cost of creating Serializable lambda ? >>> Sadly I do not yet, and may not for a while. But I know that there will be a nonzero footprint and capture cost, and it imposes some additional hurdles on some VM optimizations we want to do. I think that's all the information we will ahve for a while, but I think we have to go on the assumption that the cost will be enough that "make all lambdas serializable" is not a very good choice. >> I've done some tests asking the VM to dump the assembly code so see the impact of having lambdas serializable or not. > Given that we don't have an implementation yet, not sure how you could have done this. for the inner-class implementation as you said below you have already enough information to serialize bound values, for the method handle implementation, you have two ways to implement it, either you use insertArguments when you create the method handle and you crack the method handle to get the values back or the proxy object stores the bound values in an Object array along with the method handle, the values in the array are unboxed when the method handle is called and you teach the VM to know that the Object array is constant (stable). Thus for all ways to implement it, the fact that the lambda is serializable only add a reference to an object that store the information that are passed to the lambda metafactory. > >> First, if the lambda is constant i.e. don't capture any states, then the lambda is created once and reused, > Yes, that's the easy case. yes, and the other cases are also detailed in my previous email. > > Also, note that our current translation scheme -- where we generate bytecode for each lambda -- is more serialization friendly than the alternate scheme, where we generate a single wrapper for each SAM and invoke the behavior as an MH. In the latter case, we have to keep around a lot more information that otherwise would have been thrown away by the MF, such as the captured arguments bound with insertArguments. see above. > > It is NOT going to be free in most cases. We can do our best to make it small. Spending an extra mov when you see that just after the VM has spill another variable thus also spend an extra move, is something that I call free, at least free enough to not worth to bother users about that. R?mi From david.lloyd at redhat.com Sun Sep 30 14:09:31 2012 From: david.lloyd at redhat.com (David M. Lloyd) Date: Sun, 30 Sep 2012 16:09:31 -0500 Subject: Serialization stability and naming (and syntax) In-Reply-To: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> References: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> Message-ID: <5068B50B.6080601@redhat.com> On 09/30/2012 09:43 AM, Brian Goetz wrote: > A confounding factor with picking a serialization syntax is "does the syntax provide a place to put a name, or do we need to do something else for that?" > > The reality is that there is relatively little we can do to make serialized lambdas stable across recompilation. The desugared method name is one aspect of instability, but it is only one. This problem is worse than the "unstable class name" problem of inner classes, and I don't think we have the will to distort the design very much to make it all that much better. My conclusion is that being able to specify a stable name is only slightly less brittle than not being able to, which leads me to believe that we should not value a "name" slot very highly in picking a syntax. Why not consider limiting serializability to lambdas built from method references? I am in serious, serious doubt that any benefit derived from serializing capturing lambdas would outweigh the pain for users and implementors. We should not introduce any more of this type of instability than already exists in the serialization protocol due to inner classes. > > Example: order of capture. Suppose we have a lambda > x -> (capA < capB) ? x : 0; > > If this is refactored into > > x -> (capB >= capA) ? 0 : x; > > as your IDE will happily do for you, you've broken serialized instances. If the compiler picks a stable algorithm at all for assigning captured values to indexed slots, it will probably be something like "the order in which the captured vars appear in the body." > > > Example: capture arity change. This one is obvious; if you add or remove a captured variable, you change the arity of the desugared lambda body. > > > Example: captured type change. If we have: > > Collection c = ... > x -> c.contains(x); > > and change the type of the captured variable outside the lambda: > > List c = ... > x -> c.contains(x); > > this will change the signature of the desguared lambda body. > > > Example: compiler optimization > > Given: > > class X { > public final int x = 3; > > ... > y -> (y > x) ? y : 0; > } > > Ordinarily we translate this by capturing 'this' so we can refer to this.x; a smarter compiler could realize that we can constant-fold x into the lambda and make it noncapturing. Again, breaking serialized instances. > > > The bottom line is that there are so many ways that we can break eisting serialized instances -- even more than with inner classes. The target profile we set at the outset -- serialization works when you have bytecode-identical classes on both sides -- is really the only thing that is guaranteed to work. > > Eliminate one source of instability -- the name -- yields only a minor improvement. If we care about name stability, perhaps we should spend the effort on a better naming scheme than lambda$nnn, one that is less sensitive to small changes into the source code. > > -- - DML From david.lloyd at redhat.com Sun Sep 30 14:24:13 2012 From: david.lloyd at redhat.com (David M. Lloyd) Date: Sun, 30 Sep 2012 16:24:13 -0500 Subject: Serialization stability and naming (and syntax) In-Reply-To: References: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> Message-ID: <5068B87D.8020304@redhat.com> On 09/30/2012 11:14 AM, Brian Goetz wrote: >> Your point is that the benefits to stability of serialized forms are very small, and I'm inclined to agree. But for what other reasons are names useful? We've talked about how that name could appear in toString output and in stack traces. > > Named lambdas are potentially useful for: > - stack traces, toString > - nonlocal return > - recursion > - serialization > > Of these, its seeming that serialization is not important enough to add naming, and clearly nonlocal return is not, since we don't have that. Ditto for recursion. So that leaves stack traces / toString. > > A few folks have suggested the syntax > name(args) -> body > > for named lambdas but I think this is impractical; the interaction with inferred parameter types renders the confusion between method invocations and lambdas too great: > > foo(x, y) -> x+y > > looks too much like a method invocation. > > We also considered a label-like scheme: > > (name: x, y, z) -> body > > But in any case, something like @Serial(name) lambda would really be bad, because then we would *only* be able to use the name for serialization. >  >> So, at issue is: do we need the ability to name lambdas at all? > > Need? No. Nice to have? Yes. Willing to pick an ugly syntax? Probably not. If the problem is limited to *just* stack traces and toString, choosing a name based on the defining scope seems reasonable. For method references you have a name obviously (it would be surprising if it looked too far removed from a normal invocation); for other cases just pick the enclosing type or method name and add a tag to it to identify it as a lambda declared within that scope (maybe with a number for disambiguation). So if method Foo.bar() contains a lambda it could show up on the stack trace as ... at org.blah.Foo.bar[lambda#8](Foo.java:123) ... -- - DML From brian.goetz at oracle.com Sun Sep 30 14:46:59 2012 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 30 Sep 2012 14:46:59 -0700 Subject: Serialization stability and naming (and syntax) In-Reply-To: <5068B50B.6080601@redhat.com> References: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> <5068B50B.6080601@redhat.com> Message-ID: <1A0559B6-5F80-43B9-B155-BF97C5A17F16@oracle.com> The set of non capturing lambdas similarly has little stabity problems. It would be a shame to exclude those -- and they will be common. Sent from my iPhone On Sep 30, 2012, at 2:09 PM, "David M. Lloyd" wrote: > On 09/30/2012 09:43 AM, Brian Goetz wrote: >> A confounding factor with picking a serialization syntax is "does the syntax provide a place to put a name, or do we need to do something else for that?" >> >> The reality is that there is relatively little we can do to make serialized lambdas stable across recompilation. The desugared method name is one aspect of instability, but it is only one. This problem is worse than the "unstable class name" problem of inner classes, and I don't think we have the will to distort the design very much to make it all that much better. My conclusion is that being able to specify a stable name is only slightly less brittle than not being able to, which leads me to believe that we should not value a "name" slot very highly in picking a syntax. > > Why not consider limiting serializability to lambdas built from method references? I am in serious, serious doubt that any benefit derived from serializing capturing lambdas would outweigh the pain for users and implementors. We should not introduce any more of this type of instability than already exists in the serialization protocol due to inner classes. > >> >> Example: order of capture. Suppose we have a lambda >> x -> (capA < capB) ? x : 0; >> >> If this is refactored into >> >> x -> (capB >= capA) ? 0 : x; >> >> as your IDE will happily do for you, you've broken serialized instances. If the compiler picks a stable algorithm at all for assigning captured values to indexed slots, it will probably be something like "the order in which the captured vars appear in the body." >> >> >> Example: capture arity change. This one is obvious; if you add or remove a captured variable, you change the arity of the desugared lambda body. >> >> >> Example: captured type change. If we have: >> >> Collection c = ... >> x -> c.contains(x); >> >> and change the type of the captured variable outside the lambda: >> >> List c = ... >> x -> c.contains(x); >> >> this will change the signature of the desguared lambda body. >> >> >> Example: compiler optimization >> >> Given: >> >> class X { >> public final int x = 3; >> >> ... >> y -> (y > x) ? y : 0; >> } >> >> Ordinarily we translate this by capturing 'this' so we can refer to this.x; a smarter compiler could realize that we can constant-fold x into the lambda and make it noncapturing. Again, breaking serialized instances. >> >> >> The bottom line is that there are so many ways that we can break eisting serialized instances -- even more than with inner classes. The target profile we set at the outset -- serialization works when you have bytecode-identical classes on both sides -- is really the only thing that is guaranteed to work. >> >> Eliminate one source of instability -- the name -- yields only a minor improvement. If we care about name stability, perhaps we should spend the effort on a better naming scheme than lambda$nnn, one that is less sensitive to small changes into the source code. >> >> > > > -- > - DML From dl at cs.oswego.edu Sun Sep 30 15:07:16 2012 From: dl at cs.oswego.edu (Doug Lea) Date: Sun, 30 Sep 2012 18:07:16 -0400 Subject: Serialization stability and naming (and syntax) In-Reply-To: <5068B50B.6080601@redhat.com> References: <174C39C6-9033-4DEA-9B31-5FAD38274E00@oracle.com> <5068B50B.6080601@redhat.com> Message-ID: <5068C294.9000504@cs.oswego.edu> On 09/30/12 17:09, David M. Lloyd wrote: > Why not consider limiting serializability to lambdas built from method > references? Yes! I can't think of any reason not to do this. -Doug