From amaembo at gmail.com Mon Mar 2 04:57:47 2020 From: amaembo at gmail.com (Tagir Valeev) Date: Mon, 2 Mar 2020 11:57:47 +0700 Subject: [sealed] Draft Language Spec available In-Reply-To: <968C30B0-A4A3-4D36-B25B-595D4D0BAE24@oracle.com> References: <968C30B0-A4A3-4D36-B25B-595D4D0BAE24@oracle.com> Message-ID: Hello! Shouldn't we update a section 9.8 Functional Interfaces? E.g.: A functional interface is an interface that [is not declared as sealed and] has just one abstract method (aside from the methods of Object), and thus represents a single function contract. This will also imply that the @FunctionalInterface annotation cannot be applicable to sealed interfaces (9.6.4.9). With best regards, Tagir Valeev. On Fri, Feb 28, 2020 at 7:25 PM Gavin Bierman wrote: > > The next draft language spec for JEP 360 (Sealed Types) is available at: > > http://cr.openjdk.java.net/~gbierman/jep360/latest/ > > This version reflects the changes to the type system I mentioned [1], along with a number of other changes. We?d appreciate further comments on this in particular (along with anything else). > > Thanks, > Gavin > > [1] https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002018.html From amaembo at gmail.com Mon Mar 2 05:01:34 2020 From: amaembo at gmail.com (Tagir Valeev) Date: Mon, 2 Mar 2020 12:01:34 +0700 Subject: [sealed] Draft Language Spec available In-Reply-To: References: <968C30B0-A4A3-4D36-B25B-595D4D0BAE24@oracle.com> Message-ID: I see that you added a note to "15.27.3 Type of a Lambda Expression", but a similar note is missing in "15.13.2 Type of a Method Reference". I think both should be unnecessary if you just restrict the "functional interface" definition instead. With best regards, Tagir Valeev On Mon, Mar 2, 2020 at 11:57 AM Tagir Valeev wrote: > > Hello! > > Shouldn't we update a section 9.8 Functional Interfaces? E.g.: > > A functional interface is an interface that [is not declared as sealed > and] has just one abstract method (aside from the methods of Object), > and thus represents a single function contract. > > This will also imply that the @FunctionalInterface annotation cannot > be applicable to sealed interfaces (9.6.4.9). > > With best regards, > Tagir Valeev. > > > On Fri, Feb 28, 2020 at 7:25 PM Gavin Bierman wrote: > > > > The next draft language spec for JEP 360 (Sealed Types) is available at: > > > > http://cr.openjdk.java.net/~gbierman/jep360/latest/ > > > > This version reflects the changes to the type system I mentioned [1], along with a number of other changes. We?d appreciate further comments on this in particular (along with anything else). > > > > Thanks, > > Gavin > > > > [1] https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002018.html From gavin.bierman at oracle.com Tue Mar 3 08:14:19 2020 From: gavin.bierman at oracle.com (gavin.bierman at oracle.com) Date: Tue, 3 Mar 2020 08:14:19 +0000 Subject: [sealed] Draft Language Spec available In-Reply-To: References: Message-ID: <711AD1F3-82A7-4FFB-9A01-04DFF1E965CF@oracle.com> Thanks Tagir. I?ll take a look. Gavin Sent from my iPad > On 2 Mar 2020, at 05:01, Tagir Valeev wrote: > > ?I see that you added a note to "15.27.3 Type of a Lambda Expression", > but a similar note is missing in "15.13.2 Type of a Method Reference". > I think both should be unnecessary if you just restrict the > "functional interface" definition instead. > > With best regards, > Tagir Valeev > > >> On Mon, Mar 2, 2020 at 11:57 AM Tagir Valeev wrote: >> >> Hello! >> >> Shouldn't we update a section 9.8 Functional Interfaces? E.g.: >> >> A functional interface is an interface that [is not declared as sealed >> and] has just one abstract method (aside from the methods of Object), >> and thus represents a single function contract. >> >> This will also imply that the @FunctionalInterface annotation cannot >> be applicable to sealed interfaces (9.6.4.9). >> >> With best regards, >> Tagir Valeev. >> >> >>> On Fri, Feb 28, 2020 at 7:25 PM Gavin Bierman wrote: >>> >>> The next draft language spec for JEP 360 (Sealed Types) is available at: >>> >>> http://cr.openjdk.java.net/~gbierman/jep360/latest/ >>> >>> This version reflects the changes to the type system I mentioned [1], along with a number of other changes. We?d appreciate further comments on this in particular (along with anything else). >>> >>> Thanks, >>> Gavin >>> >>> [1] https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002018.html From forax at univ-mlv.fr Sun Mar 8 14:39:09 2020 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 8 Mar 2020 15:39:09 +0100 (CET) Subject: Pattern Matching for instanceof (Preview 2) In-Reply-To: <8d30d504-dd25-de1f-a54d-1a80fe1f6c5d@oracle.com> References: <8d30d504-dd25-de1f-a54d-1a80fe1f6c5d@oracle.com> Message-ID: <1361815960.1310835.1583678349499.JavaMail.zimbra@u-pem.fr> Hi all, I've taken a look where in my source code I can use instanceof Point(var x, var y) instead of instanceof Point p. I've discovered that i've a lot of occurrences where i only need some record components but not all of them, by example, i've an AST that defines the declaration of a variable like this record LocalVarExpr(String name, Expr init) implements Expr { } When i want to some analysis, i've a code like this: Env env = ... if (expr instanceof LocalVarExpr local) { visit(local.init, env); } Using the DeconstructionPattern, i can transform the code to Env env = ... if (expr instanceof LocalVarExpr(var name, var init)) { visit(init, env); } but it also introduce the local variable 'name' in the block Obviously, the way to solve that is to use '_' like this: Env env = ... if (expr instanceof LocalVarExpr(_, var init)) { visit(init, env); } I wonder if introducing only the DeconstructionPattern as Point(int x, int y) and Point(var x, var y) without introducing '_' is a good idea. Declaring a local variable you don't want make the code very artificial. cheers, R?mi ----- Mail original ----- > De: "jan lahoda" > ?: "amber-dev" > Envoy?: Jeudi 6 F?vrier 2020 21:18:52 > Objet: Pattern Matching for instanceof (Preview 2) > Hi, > > Thanks to Gavin, Brian and Alex, there is a new draft JEP for Pattern > Matching for instanceof (Preview 2): > https://bugs.openjdk.java.net/browse/JDK-8235186 > > Any feedback on the JEP is more than welcome! > > Thanks, > Jan From brian.goetz at oracle.com Tue Mar 10 12:30:35 2020 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 10 Mar 2020 08:30:35 -0400 Subject: Pattern Matching for instanceof (Preview 2) In-Reply-To: <1361815960.1310835.1583678349499.JavaMail.zimbra@u-pem.fr> References: <8d30d504-dd25-de1f-a54d-1a80fe1f6c5d@oracle.com> <1361815960.1310835.1583678349499.JavaMail.zimbra@u-pem.fr> Message-ID: <14cad812-1e4f-9b0c-712c-bb192395ecd3@oracle.com> While I understand your concern, I think its a bit of an exaggeration to suggest we consider not doing the feature at all if we cannot also staple on this other feature. I'll be brief since all of this has come up before: ?- Yes, we understand that some way to say "don't care about the name" is going to eventually be important. ?- I do not want to blindly assume that using underscore as it is in other languages is the obvious, or only, or right solution -- in fact, I don't think the "obvious" answer is the right solution for Java. ?- I really don't want to distract us with this right now; we have too much else on our plate.? Yes, I understand the problem; no, I don't agree with the proposed solution; yes, I have other ideas in mind; no, I don't want to talk about them now.? We can return to this issue when the bigger issues are covered. On 3/8/2020 10:39 AM, Remi Forax wrote: > Hi all, > I've taken a look where in my source code I can use instanceof Point(var x, var y) instead of instanceof Point p. > I've discovered that i've a lot of occurrences where i only need some record components but not all of them, > by example, i've an AST that defines the declaration of a variable like this > record LocalVarExpr(String name, Expr init) implements Expr { } > > When i want to some analysis, i've a code like this: > Env env = ... > if (expr instanceof LocalVarExpr local) { > visit(local.init, env); > } > > Using the DeconstructionPattern, i can transform the code to > Env env = ... > if (expr instanceof LocalVarExpr(var name, var init)) { > visit(init, env); > } > but it also introduce the local variable 'name' in the block > > Obviously, the way to solve that is to use '_' like this: > Env env = ... > if (expr instanceof LocalVarExpr(_, var init)) { > visit(init, env); > } > > I wonder if introducing only the DeconstructionPattern as Point(int x, int y) and Point(var x, var y) without introducing '_' is a good idea. > Declaring a local variable you don't want make the code very artificial. > > cheers, > R?mi > > ----- Mail original ----- >> De: "jan lahoda" >> ?: "amber-dev" >> Envoy?: Jeudi 6 F?vrier 2020 21:18:52 >> Objet: Pattern Matching for instanceof (Preview 2) >> Hi, >> >> Thanks to Gavin, Brian and Alex, there is a new draft JEP for Pattern >> Matching for instanceof (Preview 2): >> https://bugs.openjdk.java.net/browse/JDK-8235186 >> >> Any feedback on the JEP is more than welcome! >> >> Thanks, >> Jan From gavin.bierman at oracle.com Mon Mar 16 15:03:53 2020 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Mon, 16 Mar 2020 15:03:53 +0000 Subject: [patterns] Draft Spec for JEP 375 Pattern Matching for instanceof (Preview 2) Message-ID: Dear experts: A draft language spec for JEP 375 (Pattern Matching for instanceof) is available at: http://cr.openjdk.java.net/~gbierman/jep375/latest Main change from Preview 1 is, as discussed on this list, support for deconstruction patterns over record types. Comments welcome! Thanks, Gavin From brian.goetz at oracle.com Mon Mar 16 20:24:04 2020 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 16 Mar 2020 16:24:04 -0400 Subject: Fwd: [Records] Transparency and effects on collections In-Reply-To: References: Message-ID: <4febdb1b-73f0-e87d-6a3d-ff02ff808ac8@oracle.com> Received on the -comments list. -------- Forwarded Message -------- Subject: [Records] Transparency and effects on collections Date: Wed, 11 Mar 2020 07:45:32 -0700 (PDT) From: Daniel Latr?moli?re To: amber-spec-comments at openjdk.java.net I understand that records are transparent and have correct equals/hashcode, then are useful as keys in collections. When trying to find classes to evolve to records, I found classes having more or less the same use-cases in memory than a multi-column primary key would have in SQL. ------------------------------------------------------------------------ Records are a sugar above classes, like enum but for another use case, is it planned to have more evolved collections (like enum has with EnumSet/EnumMap)? Given records are explicitly transparent, API for pooling records would need to use this explicit transparency to allow partial queries and not only the Set/Map exact operations. If this is the case, it would probably need some specialised subtype of Set, like a new RecordSet (similar to a simple table without join, contrary to SQL). Current Java's Stream API would probably be perfect with some small enhancements, JPA-like (on a sub-type RecordStream) allowing to refer directly to the field to be filtered. In this case, the compiler would need to generate for each record one static field per instance field of the record to allow typed queries, like in the following example. |record R(|||String foo, ...)| {|| ||?? ...|| ||}|| | desugarized more completely in: |class R {|| ||? public static final RecordField FOO;|| ||? private String foo;|| ||?? ...|| ||}|| | It would allow some typed code for partial querying, like: |RecordSet keyPool;|| ||Predicate fooFilter;|| ||keyPool.stream().filter(R.FOO, fooFilter).forEach(...);|| | Thanks for your attention, Daniel. ------------------------------------------------------------------------ NB: in desugarization, I used standard static fields, like JPA, and not an enum containing all meta-fields (which would probably be more correct and efficient). This is due to the lack of JEP 301 (needed for typed constants in enum). If allowed, the desugarized record will become something like: |class R {|| ||? public static enum META implements RecordField {|| ||??? FOO(String.class);|| ||? }|| ||? private String foo;|| ||? ...|| ||}|| | In query, it would be used as R.META.FOO for filtering on field "foo" of the record: |keyPool.stream().filter(R.META.FOO, fooFilter).forEach(...)| ------------------------------------------------------------------------ PS: I am not interested in interning records but using them in pools defined by programmer. Pooling would improve memory and performance to deduplicate records, because equals would more frequently succeed at identity test without continuing to real equality test (field by field). Having specialized implementations of collections, using fields of records following the order given by user, would probably be useful for performance against simple Set/Map: structures like a hierarchical Map of Map of ..., field by field, can be more efficient if partial queries are frequently used or if the pool is big. From amaembo at gmail.com Tue Mar 17 04:33:09 2020 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 17 Mar 2020 11:33:09 +0700 Subject: [patterns] Draft Spec for JEP 375 Pattern Matching for instanceof (Preview 2) In-Reply-To: References: Message-ID: Hello! Just a reminder that parenthesized expression is still not covered by the spec draft. I expect to see it in chapter 6.3.1. Without this, even some samples listed in the spec draft itself are incorrect. E.g. the sample in 6.3.2: if (!(o instanceof String s)) {... With best regards, Tagir Valeev On Mon, Mar 16, 2020 at 10:04 PM Gavin Bierman wrote: > Dear experts: > > A draft language spec for JEP 375 (Pattern Matching for instanceof) is > available at: > > http://cr.openjdk.java.net/~gbierman/jep375/latest > > Main change from Preview 1 is, as discussed on this list, support for > deconstruction patterns over record types. > > Comments welcome! > > Thanks, > Gavin > From gavin.bierman at oracle.com Tue Mar 17 08:59:54 2020 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Tue, 17 Mar 2020 08:59:54 +0000 Subject: [patterns] Draft Spec for JEP 375 Pattern Matching for instanceof (Preview 2) In-Reply-To: References: Message-ID: Thanks. Must have slipped under the radar. Will fix soon. Gavin Sent from my iPhone > On 17 Mar 2020, at 04:33, Tagir Valeev wrote: > > ? > Hello! > > Just a reminder that parenthesized expression is still not covered by the spec draft. I expect to see it in chapter 6.3.1. Without this, even some samples listed in the spec draft itself are incorrect. E.g. the sample in 6.3.2: if (!(o instanceof String s)) {... > > With best regards, > Tagir Valeev > >> On Mon, Mar 16, 2020 at 10:04 PM Gavin Bierman wrote: >> Dear experts: >> >> A draft language spec for JEP 375 (Pattern Matching for instanceof) is available at: >> >> http://cr.openjdk.java.net/~gbierman/jep375/latest >> >> Main change from Preview 1 is, as discussed on this list, support for deconstruction patterns over record types. >> >> Comments welcome! >> >> Thanks, >> Gavin From forax at univ-mlv.fr Tue Mar 17 09:57:36 2020 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 17 Mar 2020 10:57:36 +0100 (CET) Subject: [Records] Transparency and effects on collections In-Reply-To: <4febdb1b-73f0-e87d-6a3d-ff02ff808ac8@oracle.com> References: <4febdb1b-73f0-e87d-6a3d-ff02ff808ac8@oracle.com> Message-ID: <355067327.904881.1584439056846.JavaMail.zimbra@u-pem.fr> Hi Daniel, Pooling of Java objects in memory usually do more harm than good, because you artificially change the liveness of the pooled objects which doesn't work well with modern GC algorithms. Obviously, if objects are stored in a database, it can still be a win but usually the pool is more or less coupled with the ORM and use off-heap memory. EnumSet/EnumMap are specialized because Enum.ordinal() is a perfect hashcode function, so you can implement fast and compact set and map. It's not clear to me why there is a need for a specialized version of set/map for record given has you said a record is a class. Do we miss something ? About filtering fields value on stream, adding a method isEqual that takes a mapping function and a value should be enough, Predicate filter = Predicate.isEqual(Company::name, "Apple"); I remember the lambda EG discuss that method (and its primitive variations), i don't remember why it's was not added. About introducing a typesafe representation of fields, we currently provide a non-typesafe representation, j.l.r.RecordComponent. There is no typesafe representation because what :: means on a field is still an open question. And if we go that way, a static final field is not the best representation in term of classfile because it is initialized too early. A ldc constantdynamic + a static method or something along that line is a better idea. regards, R?mi > De: "Brian Goetz" > ?: "amber-spec-experts" > Envoy?: Lundi 16 Mars 2020 21:24:04 > Objet: Fwd: [Records] Transparency and effects on collections > Received on the -comments list. > -------- Forwarded Message -------- > Subject: [Records] Transparency and effects on collections > Date: Wed, 11 Mar 2020 07:45:32 -0700 (PDT) > From: Daniel Latr?moli?re [ mailto:daniel.latremoliere at gmail.com | > ] > To: [ mailto:amber-spec-comments at openjdk.java.net | > amber-spec-comments at openjdk.java.net ] > I understand that records are transparent and have correct equals/hashcode, then > are useful as keys in collections. When trying to find classes to evolve to > records, I found classes having more or less the same use-cases in memory than > a multi-column primary key would have in SQL. > ------------------------------------------------------------------------ > Records are a sugar above classes, like enum but for another use case, is it > planned to have more evolved collections (like enum has with EnumSet/EnumMap)? > Given records are explicitly transparent, API for pooling records would need to > use this explicit transparency to allow partial queries and not only the > Set/Map exact operations. > If this is the case, it would probably need some specialised subtype of Set, > like a new RecordSet (similar to a simple table without join, contrary to SQL). > Current Java's Stream API would probably be perfect with some small > enhancements, JPA-like (on a sub-type RecordStream) allowing to refer > directly to the field to be filtered. > In this case, the compiler would need to generate for each record one static > field per instance field of the record to allow typed queries, like in the > following example. > |record R(|||String foo, ...)| {|| > || ...|| > ||}|| > desugarized more completely in: > |class R {|| > || public static final RecordField FOO;|| > || private String foo;|| > || ...|| > ||}|| > It would allow some typed code for partial querying, like: > |RecordSet keyPool;|| > ||Predicate fooFilter;|| > ||keyPool.stream().filter(R.FOO, fooFilter).forEach(...);|| > Thanks for your attention, > Daniel. > ------------------------------------------------------------------------ > NB: in desugarization, I used standard static fields, like JPA, and not an enum > containing all meta-fields (which would probably be more correct and > efficient). This is due to the lack of JEP 301 (needed for typed constants in > enum). If allowed, the desugarized record will become something like: > |class R {|| > || public static enum META implements RecordField {|| > || FOO(String.class);|| > || }|| > || private String foo;|| > || ...|| > ||}|| > In query, it would be used as R.META.FOO for filtering on field "foo" of the > record: > |keyPool.stream().filter(R.META.FOO, fooFilter).forEach(...)| > ------------------------------------------------------------------------ > PS: I am not interested in interning records but using them in pools defined by > programmer. Pooling would improve memory and performance to deduplicate > records, because equals would more frequently succeed at identity test without > continuing to real equality test (field by field). Having specialized > implementations of collections, using fields of records following the order > given by user, would probably be useful for performance against simple Set/Map: > structures like a hierarchical Map of Map of ..., field by field, can be more > efficient if partial queries are frequently used or if the pool is big. From amaembo at gmail.com Tue Mar 17 10:41:49 2020 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 17 Mar 2020 17:41:49 +0700 Subject: [Records] Transparency and effects on collections In-Reply-To: <355067327.904881.1584439056846.JavaMail.zimbra@u-pem.fr> References: <4febdb1b-73f0-e87d-6a3d-ff02ff808ac8@oracle.com> <355067327.904881.1584439056846.JavaMail.zimbra@u-pem.fr> Message-ID: Hello! I can imagine that we have somewhere in the library a FunctionHelper interface like this: interface FunctionHelper { default Predicate is(T value) { return r -> Objects.equals(map().apply(r), value); } default Predicate not(T value) { return r -> !Objects.equals(map().apply(r), value); } default Consumer consume(Consumer consumer) { return r -> consumer.accept(map().apply(r)); } // maybe more function adapters Function map(); static FunctionHelper forAccessor(Function accessor) { return () -> accessor; } } Then we generate static fields that correspond to every record component: record Point(int x, int y) { public static final FunctionHelper X = FunctionHelper.forAccessor(Point::x); public static final FunctionHelper Y = FunctionHelper.forAccessor(Point::y); } Then we can use them: var points = List.of(new Point(1, 2), new Point(3, 4), new Point(5, 6)); points.forEach(Point.X.consume(System.out::println)); points.stream().filter(Point.Y.is(4)).forEach(System.out::println); points.stream().filter(Point.Y.not(4)).forEach(System.out::println); Of course, nobody will do this but it looks nice to me. With best regards, Tagir Valeev On Tue, Mar 17, 2020 at 4:58 PM Remi Forax wrote: > Hi Daniel, > Pooling of Java objects in memory usually do more harm than good, because > you artificially change the liveness of the pooled objects which doesn't > work well with modern GC algorithms. > Obviously, if objects are stored in a database, it can still be a win but > usually the pool is more or less coupled with the ORM and use off-heap > memory. > > EnumSet/EnumMap are specialized because Enum.ordinal() is a perfect > hashcode function, so you can implement fast and compact set and map. It's > not clear to me why there is a need for a specialized version of set/map > for record given has you said a record is a class. Do we miss something ? > > About filtering fields value on stream, adding a method isEqual that takes > a mapping function and a value should be enough, > Predicate filter = Predicate.isEqual(Company::name, "Apple"); > I remember the lambda EG discuss that method (and its primitive > variations), i don't remember why it's was not added. > > About introducing a typesafe representation of fields, we currently > provide a non-typesafe representation, j.l.r.RecordComponent. > There is no typesafe representation because what :: means on a field is > still an open question. > And if we go that way, a static final field is not the best representation > in term of classfile because it is initialized too early. A ldc > constantdynamic + a static method or something along that line is a better > idea. > > regards, > R?mi > > ------------------------------ > > *De: *"Brian Goetz" > *?: *"amber-spec-experts" > *Envoy?: *Lundi 16 Mars 2020 21:24:04 > *Objet: *Fwd: [Records] Transparency and effects on collections > > Received on the -comments list. > > > -------- Forwarded Message -------- > Subject: [Records] Transparency and effects on collections > Date: Wed, 11 Mar 2020 07:45:32 -0700 (PDT) > From: Daniel Latr?moli?re > > To: amber-spec-comments at openjdk.java.net > > > I understand that records are transparent and have correct > equals/hashcode, then are useful as keys in collections. When trying to > find classes to evolve to records, I found classes having more or less the > same use-cases in memory than a multi-column primary key would have in SQL. > ------------------------------------------------------------------------ > Records are a sugar above classes, like enum but for another use case, is > it planned to have more evolved collections (like enum has with > EnumSet/EnumMap)? Given records are explicitly transparent, API for pooling > records would need to use this explicit transparency to allow partial > queries and not only the Set/Map exact operations. > > If this is the case, it would probably need some specialised subtype of > Set, like a new RecordSet (similar to a simple table without join, contrary > to SQL). Current Java's Stream API would probably be perfect with some > small enhancements, JPA-like (on a sub-type RecordStream) allowing to > refer directly to the field to be filtered. > > In this case, the compiler would need to generate for each record one > static field per instance field of the record to allow typed queries, like > in the following example. > > |record R(|||String foo, ...)| {|| > || ...|| > ||}|| > | > desugarized more completely in: > > |class R {|| > || public static final RecordField FOO;|| > || private String foo;|| > || ...|| > ||}|| > | > It would allow some typed code for partial querying, like: > > |RecordSet keyPool;|| > ||Predicate fooFilter;|| > ||keyPool.stream().filter(R.FOO, fooFilter).forEach(...);|| > | > > Thanks for your attention, > Daniel. > ------------------------------------------------------------------------ > NB: in desugarization, I used standard static fields, like JPA, and not an > enum containing all meta-fields (which would probably be more correct and > efficient). This is due to the lack of JEP 301 (needed for typed constants > in enum). If allowed, the desugarized record will become something like: > > |class R {|| > || public static enum META implements RecordField {|| > || FOO(String.class);|| > || }|| > || private String foo;|| > || ...|| > ||}|| > | > In query, it would be used as R.META.FOO for filtering on field "foo" of > the record: > > |keyPool.stream().filter(R.META.FOO, fooFilter).forEach(...)| > ------------------------------------------------------------------------ > PS: I am not interested in interning records but using them in pools > defined by programmer. Pooling would improve memory and performance to > deduplicate records, because equals would more frequently succeed at > identity test without continuing to real equality test (field by field). > Having specialized implementations of collections, using fields of records > following the order given by user, would probably be useful for performance > against simple Set/Map: structures like a hierarchical Map of Map of ..., > field by field, can be more efficient if partial queries are frequently > used or if the pool is big. > > From peter.levart at gmail.com Thu Mar 19 14:27:50 2020 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 19 Mar 2020 15:27:50 +0100 Subject: [records] Summary so far In-Reply-To: <1869961828.663033.1582891635044.JavaMail.zimbra@u-pem.fr> References: <1869961828.663033.1582891635044.JavaMail.zimbra@u-pem.fr> Message-ID: <74759272-3db9-a362-209f-37296c6eede6@gmail.com> On 2/28/20 1:07 PM, Remi Forax wrote: >> Q10. Special annotation for explicit declaration of accessors. >> >> Tagir [6] proposes a new `@RecordAccessor` annotation to mark explicit >> accessors, much as `@Override` is used to mark method overrides. >> >> A: Rather than introduce a new accessor, we will consider extending the >> meaning of the `@Override` annotation to include this case. > I agree, @Override is fine here even if it's not a real override (using @Override on an asbtract method of an interface is not a real override too so @Override doesn't mean @Override since Java 6 anyway). > So, wouldn't this be confusing? For example, if a record declaration also declared that it implements an interface, you wouldn't know from the 1st glance whether such method is an explicit declaration of accessor or just implementation of the interface method or maybe both? Would someone mind? Peter From brian.goetz at oracle.com Thu Mar 19 14:36:04 2020 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 19 Mar 2020 10:36:04 -0400 Subject: [records] Summary so far In-Reply-To: <74759272-3db9-a362-209f-37296c6eede6@gmail.com> References: <1869961828.663033.1582891635044.JavaMail.zimbra@u-pem.fr> <74759272-3db9-a362-209f-37296c6eede6@gmail.com> Message-ID: <04D0603A-D3A7-44B8-A74A-6005C1E4B42C@oracle.com> >>> Q10. Special annotation for explicit declaration of accessors. >>> >>> Tagir [6] proposes a new `@RecordAccessor` annotation to mark explicit >>> accessors, much as `@Override` is used to mark method overrides. >>> >>> A: Rather than introduce a new accessor, we will consider extending the >>> meaning of the `@Override` annotation to include this case. >> I agree, @Override is fine here even if it's not a real override (using @Override on an asbtract method of an interface is not a real override too so @Override doesn't mean @Override since Java 6 anyway). >> > So, wouldn't this be confusing? For example, if a record declaration also declared that it implements an interface, you wouldn't know from the 1st glance whether such method is an explicit declaration of accessor or just implementation of the interface method or maybe both? Would someone mind? I think its a question of which people would mind more. A good analogy is extends vs implements. We?re used to that in classes, but in generic type bounds, `` is used both for classes and interfaces. And think how irritating it would be to say ``. The distinction between ?what kind of extension? is not really important here, and were the compiler to demand this, we?d rightly say it is being pedantic. The alternatives to lumping ?explicit implementation of mandated member? into @Override is to make up a new thing, or not allow you to say it at all. ?Not at all? is a credible answer, but will make some people sad and they will continue to ask for it. A new thing seems like it is asking again users to make fine distinctions that don?t matter (and, if the mandated member is also an interface member, they should specify both? And, does it really matter?) An intuitive interpretation of ?@Override? is ?this is not a new method, it is a more refined declaration of a method I already have.? Which covers both override-from-super and explicitly-implement-mandated. I think more people would mind having to make the distinction than not being able to make the distinction. From amaembo at gmail.com Tue Mar 24 02:23:10 2020 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 24 Mar 2020 09:23:10 +0700 Subject: do expression Message-ID: Hello! Now we have a legal way to execute several statements within an expression, yielding the result with a yield statement. This could be done via `switch` expression. Sometimes it's desired to do this without any switch. One may abuse the switch expression feature writing `switch(0) { default -> { ... code block ending with 'yield' }}`. How about creating a special syntax for such kind of expression. It could look like `do { ... code block ending with 'yield' }`? E.g. consider: class X { static final String field; // now we are forced to split field declaration and initialization // also initializer could be long and it could be not evident that its main purpose // is to initialize the field static { try { field = initializeField(); } catch(CheckedException e) { throw new RuntimeException(e); } } } Since Java 14 we can write class X { // field declaration and initialization in the same place: easier to navigate through code // though we are abusing the switch expression static final String field = switch(0) { default -> { try { yield initializeField(); } catch(CheckedException e) { throw new RuntimeException(e); } }}; } It could be like class X { // concise syntax. Now we know that the main block purpose // is to initialize the field static final String field = do { try { yield initializeField(); } catch(CheckedException e) { throw new RuntimeException(e); } }; } It's similar to Perl 'do BLOCK' expression https://perldoc.perl.org/functions/do.html What do you think? With best regards, Tagir Valeev From guy.steele at oracle.com Tue Mar 24 03:00:40 2020 From: guy.steele at oracle.com (Guy Steele) Date: Mon, 23 Mar 2020 23:00:40 -0400 Subject: do expression In-Reply-To: References: Message-ID: <9190D7F2-5AB4-469D-B606-6C9C394284D3@oracle.com> There are many ways to invent a syntax for embedding a block within an expression (gcc allows a block to appear within immediately enclosing parentheses), but using the ?do? keyword could be problematic within Java because in principle there could be some confusion with the ?do { ? } while(x)? statement. Consider the statement: do { blah blah blah; if (p) yield myCollection; blah blah blah; yield otherCollection; }.add(x); It sure looks like a loop until you get to that last line and realize it?s really an expression statement. ?Guy > On Mar 23, 2020, at 10:23 PM, Tagir Valeev wrote: > > Hello! > > Now we have a legal way to execute several statements within an expression, yielding the result with a yield statement. This could be done via `switch` expression. > > Sometimes it's desired to do this without any switch. One may abuse the switch expression feature writing `switch(0) { default -> { ... code block ending with 'yield' }}`. > > How about creating a special syntax for such kind of expression. It could look like `do { ... code block ending with 'yield' }`? > > E.g. consider: > > class X { > static final String field; > > // now we are forced to split field declaration and initialization > // also initializer could be long and it could be not evident that its main purpose > // is to initialize the field > static { > try { > field = initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > } > } > > Since Java 14 we can write > > class X { > // field declaration and initialization in the same place: easier to navigate through code > // though we are abusing the switch expression > static final String field = switch(0) { default -> { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }}; > } > > It could be like > > class X { > // concise syntax. Now we know that the main block purpose > // is to initialize the field > static final String field = do { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }; > } > > It's similar to Perl 'do BLOCK' expression > https://perldoc.perl.org/functions/do.html > > What do you think? > > With best regards, > Tagir Valeev From amaembo at gmail.com Tue Mar 24 03:42:39 2020 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 24 Mar 2020 10:42:39 +0700 Subject: do expression In-Reply-To: <9190D7F2-5AB4-469D-B606-6C9C394284D3@oracle.com> References: <9190D7F2-5AB4-469D-B606-6C9C394284D3@oracle.com> Message-ID: Hello, Guy! I think, the same problem was already solved when we differentiate between switch expression and switch statement. In particular, this syntax is invalid: switch (0) { default -> { yield " foo "; } }.trim(); You must parenthesize the qualifier: (switch (0) { default -> { yield " foo "; } }).trim(); The same should be done with the proposed do-expression: (do { blah blah blah; if (p) yield myCollection; blah blah blah; yield otherCollection; }).add(x); This allows to syntactically separate do-expression and do-while statement. With best regards, Tagir Valeev On Tue, Mar 24, 2020 at 10:00 AM Guy Steele wrote: > > There are many ways to invent a syntax for embedding a block within an expression (gcc allows a block to appear within immediately enclosing parentheses), but using the ?do? keyword could be problematic within Java because in principle there could be some confusion with the ?do { ? } while(x)? statement. Consider the statement: > > do { blah blah blah; > if (p) yield myCollection; > blah blah blah; > yield otherCollection; > }.add(x); > > It sure looks like a loop until you get to that last line and realize it?s really an expression statement. > > ?Guy > > On Mar 23, 2020, at 10:23 PM, Tagir Valeev wrote: > > Hello! > > Now we have a legal way to execute several statements within an expression, yielding the result with a yield statement. This could be done via `switch` expression. > > Sometimes it's desired to do this without any switch. One may abuse the switch expression feature writing `switch(0) { default -> { ... code block ending with 'yield' }}`. > > How about creating a special syntax for such kind of expression. It could look like `do { ... code block ending with 'yield' }`? > > E.g. consider: > > class X { > static final String field; > > // now we are forced to split field declaration and initialization > // also initializer could be long and it could be not evident that its main purpose > // is to initialize the field > static { > try { > field = initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > } > } > > Since Java 14 we can write > > class X { > // field declaration and initialization in the same place: easier to navigate through code > // though we are abusing the switch expression > static final String field = switch(0) { default -> { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }}; > } > > It could be like > > class X { > // concise syntax. Now we know that the main block purpose > // is to initialize the field > static final String field = do { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }; > } > > It's similar to Perl 'do BLOCK' expression > https://perldoc.perl.org/functions/do.html > > What do you think? > > With best regards, > Tagir Valeev > > From john.r.rose at oracle.com Tue Mar 24 04:55:41 2020 From: john.r.rose at oracle.com (John Rose) Date: Mon, 23 Mar 2020 21:55:41 -0700 Subject: do expression In-Reply-To: References: Message-ID: <642D307F-2A06-4872-A1F7-C98952632B20@oracle.com> The keyword ?do? is so short and sweet, and so under-used, that it?s tempting to give it a new job. But I don?t think this job is important enough. It?s just making a little sugar for something you can express already with switch. As Guy says there are many ways to wrap a block in an expression, if we should want to do this. If we use a keyword, I would think it should be a larger keyword than ?do?, just to make it more visible. Or, if invisibility is OK, perhaps no keyword at all is OK, just ?({ x })?: But that clearly shows the problems with making the shift between statement and expression go almost invisible; and ?do? is like that also, just two characters. We went round and round on these issues with lambdas, because they are similar. It takes a long while to settle on just the right syntax to (a) read well, (b) not be too noisy, and (c) not be too invisible either. Let?s keep ?do? in reserve. There are much deeper things we can eventually ?do? with that keyword. In particular, if we open up Java to allow extended execution modes, such as parallel or differentiable or symbolic or side-effect-controlled, we will want a concise way to mark the blocks of code which are to be ?done? in an extended execution mode. For my money, that?s worth ?doing up? with a pretty keyword. Before anyone asks, no I don?t have a specific proposal for such a thing. A first draft, IMO, will use something like lambda cracking (or maybe a clumsier form of quoting) to work out the details of how to abstract over evaluation modes, and apply them independently of the code snippets themselves. There?s a lot of experimentation to work through first, with no sugar anywhere, before we would be confident of the correct degrees of freedom, the different ways to ?do? code. I ?do? have an unspecific proposal: Look at F# computation expression, and Haskell ?do? syntax. They cannot be spliced whole-sale into Java without many adjustments, but they are examples of what I mean by abstracting apart mode of computation from code-structure of computation. What?s required are two chunks of ordinary-looking code, one to supply local rules for evaluation, and one to execute, non-standardly, under the local rules. I have no idea (1) what the looks in in detail for Java, and (2) what the sugary syntax would be, but that?s the sort of juicy feature where little old ?do? might come into its own, something like (OK, syntax) ?using (x) do y?. ? John On Mar 23, 2020, at 7:23 PM, Tagir Valeev wrote: > > Hello! > > Now we have a legal way to execute several statements within an expression, yielding the result with a yield statement. This could be done via `switch` expression. > > Sometimes it's desired to do this without any switch. One may abuse the switch expression feature writing `switch(0) { default -> { ... code block ending with 'yield' }}`. > > How about creating a special syntax for such kind of expression. It could look like `do { ... code block ending with 'yield' }`? > > E.g. consider: > > class X { > static final String field; > > // now we are forced to split field declaration and initialization > // also initializer could be long and it could be not evident that its main purpose > // is to initialize the field > static { > try { > field = initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > } > } > > Since Java 14 we can write > > class X { > // field declaration and initialization in the same place: easier to navigate through code > // though we are abusing the switch expression > static final String field = switch(0) { default -> { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }}; > } > > It could be like > > class X { > // concise syntax. Now we know that the main block purpose > // is to initialize the field > static final String field = do { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }; > } > > It's similar to Perl 'do BLOCK' expression > https://perldoc.perl.org/functions/do.html > > What do you think? > > With best regards, > Tagir Valeev From forax at univ-mlv.fr Tue Mar 24 17:43:36 2020 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 24 Mar 2020 18:43:36 +0100 (CET) Subject: do expression In-Reply-To: References: Message-ID: <1952889629.1442076.1585071816275.JavaMail.zimbra@u-pem.fr> Hi Tagir, There already a syntax for that in Java, we are using it for lambda and switch, the arrow block syntax. static final String FIELD = -> { try { yield initializeField(); } catch(CheckedException e) { throw new RuntimeException(e); } }; R?mi > De: "Tagir Valeev" > ?: "amber-spec-experts" > Envoy?: Mardi 24 Mars 2020 03:23:10 > Objet: do expression > Hello! > Now we have a legal way to execute several statements within an expression, > yielding the result with a yield statement. This could be done via `switch` > expression. > Sometimes it's desired to do this without any switch. One may abuse the switch > expression feature writing `switch(0) { default -> { ... code block ending with > 'yield' }}`. > How about creating a special syntax for such kind of expression. It could look > like `do { ... code block ending with 'yield' }`? > E.g. consider: > class X { > static final String field; > // now we are forced to split field declaration and initialization > // also initializer could be long and it could be not evident that its main > purpose > // is to initialize the field > static { > try { > field = initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > } > } > Since Java 14 we can write > class X { > // field declaration and initialization in the same place: easier to navigate > through code > // though we are abusing the switch expression > static final String field = switch(0) { default -> { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }}; > } > It could be like > class X { > // concise syntax. Now we know that the main block purpose > // is to initialize the field > static final String field = do { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }; > } > It's similar to Perl 'do BLOCK' expression > [ https://perldoc.perl.org/functions/do.html | > https://perldoc.perl.org/functions/do.html ] > What do you think? > With best regards, > Tagir Valeev From forax at univ-mlv.fr Tue Mar 24 20:57:39 2020 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 24 Mar 2020 21:57:39 +0100 (CET) Subject: Record component type can be an inner class of a record Message-ID: <594699329.1500670.1585083459947.JavaMail.zimbra@u-pem.fr> Hi all, a record component can use as type a type declared inside the record itself, in term of scoping it's like if the record component is part of the internal scope of the record. record Foo(Bar bar) { class Bar { } } I think it's the right behaviour but i was not able to find any reference to that in the spec. regards, R?mi From brian.goetz at oracle.com Tue Mar 24 21:06:07 2020 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 24 Mar 2020 17:06:07 -0400 Subject: Record component type can be an inner class of a record In-Reply-To: <594699329.1500670.1585083459947.JavaMail.zimbra@u-pem.fr> References: <594699329.1500670.1585083459947.JavaMail.zimbra@u-pem.fr> Message-ID: <6ba9513a-7207-9b07-0461-86e8013c060d@oracle.com> It is kind of weird, though, when Bar is not static, since you can't create a Bar without having a Foo in hand, and you can't create a Foo without a Bar.? You could cheat and do this: ??? Foo f = new Foo(null); ??? Bar b = f.new Bar(...); ??? Foo ff = new Foo(b); but I doubt anyone will find this technique useful for anything other than a puzzler... On 3/24/2020 4:57 PM, Remi Forax wrote: > Hi all, > a record component can use as type a type declared inside the record itself, > in term of scoping it's like if the record component is part of the internal scope of the record. > > record Foo(Bar bar) { > class Bar { > > } > } > > I think it's the right behaviour but i was not able to find any reference to that in the spec. > > regards, > R?mi From forax at univ-mlv.fr Tue Mar 24 21:13:38 2020 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Tue, 24 Mar 2020 22:13:38 +0100 (CET) Subject: Record component type can be an inner class of a record In-Reply-To: <6ba9513a-7207-9b07-0461-86e8013c060d@oracle.com> References: <594699329.1500670.1585083459947.JavaMail.zimbra@u-pem.fr> <6ba9513a-7207-9b07-0461-86e8013c060d@oracle.com> Message-ID: <577660474.1503940.1585084418293.JavaMail.zimbra@u-pem.fr> > De: "Brian Goetz" > ?: "Remi Forax" , "amber-spec-experts" > > Envoy?: Mardi 24 Mars 2020 22:06:07 > Objet: Re: Record component type can be an inner class of a record > It is kind of weird, though, when Bar is not static, since you can't create a > Bar without having a Foo in hand, and you can't create a Foo without a Bar. You > could cheat and do this: > Foo f = new Foo(null); > Bar b = f.new Bar(...); > Foo ff = new Foo(b); > but I doubt anyone will find this technique useful for anything other than a > puzzler... I agree, it makes more sense if Bar is static record Foo(Kind kind) { enum Kind { ZOR, GLUB } } especially if it's a refactoring from class Foo { private final Kind kind; enum Kind { ZOR, GLUB } ... } R?mi > On 3/24/2020 4:57 PM, Remi Forax wrote: >> Hi all, >> a record component can use as type a type declared inside the record itself, >> in term of scoping it's like if the record component is part of the internal >> scope of the record. >> record Foo(Bar bar) { >> class Bar { >> } >> } >> I think it's the right behaviour but i was not able to find any reference to >> that in the spec. >> regards, >> R?mi From amaembo at gmail.com Wed Mar 25 03:19:24 2020 From: amaembo at gmail.com (Tagir Valeev) Date: Wed, 25 Mar 2020 10:19:24 +0700 Subject: do expression In-Reply-To: <1952889629.1442076.1585071816275.JavaMail.zimbra@u-pem.fr> References: <1952889629.1442076.1585071816275.JavaMail.zimbra@u-pem.fr> Message-ID: It looks weird to me. An arrow assumes some left-hand 'from' part, but it's absent here. Also, too easy to mix with actual lambda, to my taste. Still, better than nothing :-) Tagir. On Wed, Mar 25, 2020 at 7:18 AM Remi Forax wrote: > > Hi Tagir, > There already a syntax for that in Java, > we are using it for lambda and switch, the arrow block syntax. > > static final String FIELD = -> { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }; > > R?mi > > ________________________________ > > De: "Tagir Valeev" > ?: "amber-spec-experts" > Envoy?: Mardi 24 Mars 2020 03:23:10 > Objet: do expression > > Hello! > > Now we have a legal way to execute several statements within an expression, yielding the result with a yield statement. This could be done via `switch` expression. > > Sometimes it's desired to do this without any switch. One may abuse the switch expression feature writing `switch(0) { default -> { ... code block ending with 'yield' }}`. > > How about creating a special syntax for such kind of expression. It could look like `do { ... code block ending with 'yield' }`? > > E.g. consider: > > class X { > static final String field; > > // now we are forced to split field declaration and initialization > // also initializer could be long and it could be not evident that its main purpose > // is to initialize the field > static { > try { > field = initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > } > } > > Since Java 14 we can write > > class X { > // field declaration and initialization in the same place: easier to navigate through code > // though we are abusing the switch expression > static final String field = switch(0) { default -> { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }}; > } > > It could be like > > class X { > // concise syntax. Now we know that the main block purpose > // is to initialize the field > static final String field = do { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }; > } > > It's similar to Perl 'do BLOCK' expression > https://perldoc.perl.org/functions/do.html > > What do you think? > > With best regards, > Tagir Valeev > From bsideup at gmail.com Wed Mar 25 15:10:53 2020 From: bsideup at gmail.com (Sergei Egorov) Date: Wed, 25 Mar 2020 16:10:53 +0100 Subject: do expression In-Reply-To: <1952889629.1442076.1585071816275.JavaMail.zimbra@u-pem.fr> References: <1952889629.1442076.1585071816275.JavaMail.zimbra@u-pem.fr> Message-ID: Hi Remi, Is it a pseudo-code? Not something one can use in Java 14, right? Best Regards, Sergei On Tue, Mar 24, 2020 at 6:46 PM Remi Forax wrote: > Hi Tagir, > There already a syntax for that in Java, > we are using it for lambda and switch, the arrow block syntax. > > static final String FIELD = -> { > try { > yield initializeField(); > } > catch(CheckedException e) { > throw new RuntimeException(e); > } > }; > > R?mi > > > De: "Tagir Valeev" > > ?: "amber-spec-experts" > > Envoy?: Mardi 24 Mars 2020 03:23:10 > > Objet: do expression > > > Hello! > > > Now we have a legal way to execute several statements within an > expression, > > yielding the result with a yield statement. This could be done via > `switch` > > expression. > > > Sometimes it's desired to do this without any switch. One may abuse the > switch > > expression feature writing `switch(0) { default -> { ... code block > ending with > > 'yield' }}`. > > > How about creating a special syntax for such kind of expression. It > could look > > like `do { ... code block ending with 'yield' }`? > > > E.g. consider: > > > class X { > > static final String field; > > > // now we are forced to split field declaration and initialization > > // also initializer could be long and it could be not evident that its > main > > purpose > > // is to initialize the field > > static { > > try { > > field = initializeField(); > > } > > catch(CheckedException e) { > > throw new RuntimeException(e); > > } > > } > > } > > > Since Java 14 we can write > > > class X { > > // field declaration and initialization in the same place: easier to > navigate > > through code > > // though we are abusing the switch expression > > static final String field = switch(0) { default -> { > > try { > > yield initializeField(); > > } > > catch(CheckedException e) { > > throw new RuntimeException(e); > > } > > }}; > > } > > > It could be like > > > class X { > > // concise syntax. Now we know that the main block purpose > > // is to initialize the field > > static final String field = do { > > try { > > yield initializeField(); > > } > > catch(CheckedException e) { > > throw new RuntimeException(e); > > } > > }; > > } > > > It's similar to Perl 'do BLOCK' expression > > [ https://perldoc.perl.org/functions/do.html | > > https://perldoc.perl.org/functions/do.html ] > > > What do you think? > > > With best regards, > > Tagir Valeev > From john.r.rose at oracle.com Wed Mar 25 22:05:44 2020 From: john.r.rose at oracle.com (John Rose) Date: Wed, 25 Mar 2020 15:05:44 -0700 Subject: do expression In-Reply-To: References: <1952889629.1442076.1585071816275.JavaMail.zimbra@u-pem.fr> Message-ID: On Mar 24, 2020, at 8:19 PM, Tagir Valeev wrote: > > It looks weird to me. An arrow assumes some left-hand 'from' part, but > it's absent here. Also, too easy to mix with actual lambda, to my > taste. Still, better than nothing :-) To me the interesting observation here is that we already have a way for replacing an expression with a block, and this way works only in certain contexts. That is, after ?->? (that?s the context) you can have an expression, but if you want a block instead, you wrap it in (required) curly braces, and you also use a keyword ?return? or ?yield? (choice depending further on context) to nominate the value to use (instead of the expression) after executing the block. So a block can replace an expression, but there is a moderately gentle coloring: The curly braces are introduced (otherwise illegal at that point) and the contents of the braces have a keyword somewhere that nominates a value. I call it ?gentle? because there aren?t too many extra tokens, and ?coloring? because it?s there are special tokens that would not otherwise be present in an expression. (In other languages like Lisp, expressions and blocks are really the same kind of thing, the same color.) Furthermore, this ?gentle coloring? can only occur after an arrow token. The effect is a little less gentle, because you can visually scan for the pseudo-token ?-> {? which stands out a little more . My point is that there?s a more or less continuous range of design points between Lisp-like (so gentle and colorless as to be invisible) and C-like (rigid separation between statements and expressions). Java is less on the C-like end with the introduction of ?-> {?. That?s a good place to add more sugar, if we want to. (I don?t think we do, at present, but I argue there may be more compellingly powerful abstractions in the future which would lead us to further blur the line between statement and expression.) FWIW (this is less of a principled argument) I agree with you Tagir that the arrow token wants to connect two things, and so looks jarring without anything on the left and/or, as in Remi?s case, with an binary operator (?=?) before the arrow. Given the visual clarity already present in the sequence ?-> {?, I think a lowly keyword ?do? would not get lost if it were given the job of providing the LHS of the arrow, as in something like ?do -> { foo(); yield bar(); }?. But there are other reasons not to go there. As I mentioned, I don?t this job is big enough to devote a new syntax to it; there are bigger jobs that may warrant such a syntax, with statement-expressions as a special case. (Also, if ?do -> { foo(); yield bar(); }? were a thing, then one would also expect ?do -> baz()? to be an alias for ?baz()?, but that seems like a silly outcome. Arrow statements are a promising trick to play again and again, but whatever we get from such tricks should also give us useful arrow expressions.) ? John