From maurizio.cimadamore at oracle.com Thu Feb 2 15:46:15 2023 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 2 Feb 2023 15:46:15 +0000 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: References: Message-ID: On 31/01/2023 21:29, Tagir Valeev wrote: > #2 would unlock some more refactorings, notably "Convert ?: to > if-else", if ?: operator appears in this/super invocation. But in > general, it adds much less benefit. True. Note however, that even w/o #2, you can get something similar, by initializing a local variable which contains the desired value with an if/else before the (single) super call. I believe the JEP has one such example. So perhaps (speculating here :-) ), the IDE could still provide the refactoring, but the code you end up with would be slightly different. Maurizio From archie.cobbs at gmail.com Thu Feb 2 20:09:25 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Thu, 2 Feb 2023 14:09:25 -0600 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: References: Message-ID: On Tue, Jan 31, 2023 at 2:45 PM Archie Cobbs wrote: > Obviously this change requires a JEP, and so we have this JEP draft for > review: > > JDK-8300786 - No longer > require super() and this() to appear first in a constructor > Update on this JEP. Doing a little more research I discovered that since Java 8 the compiler has not been following the spec as it applies to allowing type parameters inside super() calls (bug filed as JDK-8301649 ). The spec says this is a "static context", so type parameters are in theory not allowed. But the compiler allows it, and in fact it seems the spec is being too restrictive. With the change in this JEP, this discrepancy will only get worse, because the "static context" that's part of a constructor can now include a lot more stuff. In this discussion on compiler-dev it was generally agreed that the spec should probably be fixed as part of this JEP. So I'm wondering about people's thoughts on this list - not only whether to fix the spec, but also how exactly to do so, any other suggestions, etc. I see two options: 1. Split "static context" in two: 1. The old "static context" gets renamed to "lexically static context". References to anything non-static are disallowed - same as now. 2. Define a new "referentially static context" which disallows any references to 'this' (explicit or implicit) but allows type parameters, etc. 2. Leave "static context" alone, but add an exception to how it applies prior to super() so that it permits type parameters, etc. Or maybe there is another option... ? Thoughts? Thanks, -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu Feb 2 20:16:50 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 2 Feb 2023 15:16:50 -0500 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: References: Message-ID: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> My sense is that the spec got a little over-zealous calling the preamable of a constructor a "static context".? This was accurate prior to generics, but no longer accurate when class type variables are involved because constructors are instance "members". The logical fix IMO is to sever the link to "static context" in 8.8.7.? Currently it says: > An explicit constructor invocation statement introduces a static > context (?8.1.3), > which limits the use of constructs that refer to the current object. > Notably, the > keywords this and super are prohibited in a static context (?15.8.3, > ?15.11.2), > as are unqualified references to instance variables, instance methods, > and type > parameters of lexically enclosing declarations (?6.5.5.1, ?6.5.6.1, > ?15.12.3). This can be amended to: An explicit constructor invocation statement introduces an _pre-initialization context_, which limits the use of constructs that refer to the current object.? Notably, the keywords `this` and `super` are prohibited in a pre-initialization context, as are unqualified references to instance variables and instance methods of lexically enclosing declarations. Then static context still means what it means, we are just being honest that the preamble of a constructor body is something different, and we spell out the restrictions of what that means directly in 8.8.7. On 2/2/2023 3:09 PM, Archie Cobbs wrote: > On Tue, Jan 31, 2023 at 2:45 PM Archie Cobbs > wrote: > > Obviously this change requires a JEP, and so we have this JEP > draft for review: > > JDK-8300786 - No > longer require super() and this() to appear first in a constructor > > > Update on this JEP. > > Doing a little more research I discovered that since Java 8 the > compiler has not been following the spec as it applies to allowing > type parameters inside super() calls (bug filed as JDK-8301649 > ). > > The spec says this is a "static context", so type parameters are in > theory not allowed. But the compiler allows it, and in fact it seems > the spec is being too restrictive. > > With the change in this JEP, this discrepancy will only get worse, > because the "static context" that's part of a constructor can now > include a lot more stuff. > > In this discussion on compiler-dev > > it was generally agreed that the spec should probably be fixed as part > of this JEP. > > So I'm wondering about people's thoughts on this list - not only > whether to fix the spec, but also how exactly to do so, any other > suggestions, etc. > > I see two options: > > 1. Split "static context" in two: > 1. The old "static context" gets renamed to "lexically static > context". References to anything non-static are disallowed - > same as now. > 2. Define a new "referentially static context" which disallows > any references to 'this' (explicit or implicit) but allows > type parameters, etc. > 2. Leave "static context" alone, but add an exception to how it > applies prior to super() so that it permits type parameters, etc. > > Or maybe there is another option... ? > > Thoughts? > > Thanks, > -Archie > > -- > Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Thu Feb 2 21:49:55 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Thu, 2 Feb 2023 15:49:55 -0600 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> References: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> Message-ID: On Thu, Feb 2, 2023 at 2:16 PM Brian Goetz wrote: > This can be amended to: > > An explicit constructor invocation statement introduces an > _pre-initialization context_, which limits the use of constructs that refer > to the current object. Notably, the keywords `this` and `super` are > prohibited in a pre-initialization context, as are unqualified references > to instance variables and instance methods of lexically enclosing > declarations. > That might not work. For example, this source is legal (as it should be) and yet the 'this' keyword appears within the super() call: $ cat Outer.java public class Outer { public int x; public Outer(int x) { this.x = x; } public class Inner extends Outer { public Inner() { super(Outer.this.x + 10); } } public static void main(String[] args) { System.out.println(new Outer(10).new Inner().x); } } $ java -cp classes Outer 20 What about something like this? An explicit constructor invocation statement introduces a *pre-initialization > context*, which includes the prologue of the constructor and the explicit > constructor invocation statement, and which prohibits the use of constructs > that refer explicitly or implicitly to the current object. These include > this or super referring to the current object, unqualified references to > instance variables or instance methods of the current object, method > references referring to instance methods of the current object, and > instantiations of inner classes of the current object's class for which the > current object is the enclosing instance (?8.1.3). > -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Tue Feb 7 17:52:15 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Tue, 7 Feb 2023 11:52:15 -0600 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: References: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> Message-ID: Ping to Brian... Any thoughts or comments on the proposed description below for "pre-initialization context"? I went ahead and added it into the JEP draft but am happy to adjust as needed. Thanks, -Archie On Thu, Feb 2, 2023 at 3:49 PM Archie Cobbs wrote: > On Thu, Feb 2, 2023 at 2:16 PM Brian Goetz wrote: > >> This can be amended to: >> >> An explicit constructor invocation statement introduces an >> _pre-initialization context_, which limits the use of constructs that refer >> to the current object. Notably, the keywords `this` and `super` are >> prohibited in a pre-initialization context, as are unqualified references >> to instance variables and instance methods of lexically enclosing >> declarations. >> > > That might not work. For example, this source is legal (as it should be) > and yet the 'this' keyword appears within the super() call: > > $ cat Outer.java > public class Outer { > > public int x; > > public Outer(int x) { > this.x = x; > } > > public class Inner extends Outer { > public Inner() { > super(Outer.this.x + 10); > } > } > > public static void main(String[] args) { > System.out.println(new Outer(10).new Inner().x); > } > } > $ java -cp classes Outer > 20 > > What about something like this? > > An explicit constructor invocation statement introduces a *pre-initialization >> context*, which includes the prologue of the constructor and the >> explicit constructor invocation statement, and which prohibits the use of >> constructs that refer explicitly or implicitly to the current object. These >> include this or super referring to the current object, unqualified >> references to instance variables or instance methods of the current object, >> method references referring to instance methods of the current object, and >> instantiations of inner classes of the current object's class for which the >> current object is the enclosing instance (?8.1.3). >> > -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Tue Feb 7 22:21:26 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 7 Feb 2023 17:21:26 -0500 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: References: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> Message-ID: <71e17c11-c446-6780-faea-8d08b19f2806@oracle.com> I think the approach is right, the specific list of stuff might need to be reviewed more carefully (specifically, I've not thought through the connection with inner classes, which we've now opened the door to.)? Let's call it a placeholder and we'll make sure to review it more carefully after you've worked through the implementation and caught any obvious gaps? On 2/7/2023 12:52 PM, Archie Cobbs wrote: > Ping to Brian... > > Any thoughts or comments on the proposed description below for > "pre-initialization context"? > > I went ahead and added it into the JEP draft but am happy to adjust as > needed. > > Thanks, > -Archie > > On Thu, Feb 2, 2023 at 3:49 PM Archie Cobbs > wrote: > > On Thu, Feb 2, 2023 at 2:16 PM Brian Goetz > wrote: > > This can be amended to: > > An explicit constructor invocation statement introduces an > _pre-initialization context_, which limits the use of > constructs that refer to the current object.? Notably, the > keywords `this` and `super` are prohibited in a > pre-initialization context, as are unqualified references to > instance variables and instance methods of lexically enclosing > declarations. > > > That might not work. For example, this source is legal (as it > should be) and yet the 'this' keyword appears within the super() call: > > $ cat Outer.java > public class Outer { > > ? ? public int x; > > ? ? public Outer(int x) { > ? ? ? ? this.x = x; > ? ? } > > ? ? public class Inner extends Outer { > ? ? ? ? public Inner() { > ? ? ? ? ? ? super(Outer.this.x + 10); > ? ? ? ? } > ? ? } > > ? ? public static void main(String[] args) { > ? ? ? ? System.out.println(new Outer(10).new Inner().x); > ? ? } > } > $ java -cp classes Outer > 20 > > What about something like this? > > An explicit constructor invocation statement introduces a > /pre-initialization context/, which includes the prologue of > the constructor and the explicit constructor invocation > statement, and which prohibits the use of constructs that > refer explicitly or implicitly to the current object. These > include this or super referring to the current object, > unqualified references to instance variables or instance > methods of the current object, method references referring to > instance methods of the current object, and instantiations of > inner classes of the current object's class for which the > current object is the enclosing instance (?8.1.3). > > -- > Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Tue Feb 7 22:48:15 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Tue, 7 Feb 2023 16:48:15 -0600 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: <71e17c11-c446-6780-faea-8d08b19f2806@oracle.com> References: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> <71e17c11-c446-6780-faea-8d08b19f2806@oracle.com> Message-ID: On Tue, Feb 7, 2023 at 4:21 PM Brian Goetz wrote: > I think the approach is right, the specific list of stuff might need to be > reviewed more carefully (specifically, I've not thought through the > connection with inner classes, which we've now opened the door to.) Let's > call it a placeholder and we'll make sure to review it more carefully after > you've worked through the implementation and caught any obvious gaps? > Thanks - that sounds like a plan. FWIW in the JEP I've raised the importance of fixing this bug in the spec (i.e., that constructor invocation is not really a "static context" but truly something different - what we're calling a "pre-initialization context") and made it one of the "goals" of the JEP, because the gulf between the spec on one hand and the compiler's current behavior (and what everyone has actually been doing for the past decade) on the other hand is pretty glaring. Regarding the prototype implementation , it's complete and seems to be working. One nice surprise is that, because the compiler already effectively implements this notion of "pre-initialization context" within superclass constructors, the changes required are relatively limited, in some cases, just ensuring the appropriate error message is generated. -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Tue Feb 7 22:49:30 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 7 Feb 2023 17:49:30 -0500 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: References: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> <71e17c11-c446-6780-faea-8d08b19f2806@oracle.com> Message-ID: <1238cf4d-b5d2-f44c-0440-2dc1992973ae@oracle.com> That's a nice side-effect of sticking to something the spec already talks about! On 2/7/2023 5:48 PM, Archie Cobbs wrote: > > > Regarding the prototype implementation > , > it's complete and seems to be working. One nice surprise is that, > because the compiler already effectively implements this notion of > "pre-initialization context" within superclass constructors, the > changes required are relatively limited, in some cases, just ensuring > the appropriate error message is generated. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Tue Feb 7 23:10:23 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Tue, 7 Feb 2023 17:10:23 -0600 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: <1238cf4d-b5d2-f44c-0440-2dc1992973ae@oracle.com> References: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> <71e17c11-c446-6780-faea-8d08b19f2806@oracle.com> <1238cf4d-b5d2-f44c-0440-2dc1992973ae@oracle.com> Message-ID: True :) On Tue, Feb 7, 2023 at 4:49 PM Brian Goetz wrote: > That's a nice side-effect of sticking to something the spec already talks > about! > > On 2/7/2023 5:48 PM, Archie Cobbs wrote: > > > > Regarding the prototype implementation > , > it's complete and seems to be working. One nice surprise is that, because > the compiler already effectively implements this notion of > "pre-initialization context" within superclass constructors, the changes > required are relatively limited, in some cases, just ensuring the > appropriate error message is generated. > > > -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Wed Feb 8 17:56:08 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Wed, 8 Feb 2023 11:56:08 -0600 Subject: JDK-8300786 - No longer require super() and this() to appear first in a constructor In-Reply-To: References: <23707139-fdff-07ce-0fbd-38a629f34f13@oracle.com> <71e17c11-c446-6780-faea-8d08b19f2806@oracle.com> Message-ID: On Tue, Feb 7, 2023 at 4:48 PM Archie Cobbs wrote: > FWIW in the JEP I've raised the importance of fixing this bug in the spec > (i.e., that constructor > invocation is not really a "static context" but truly something different - > what we're calling a "pre-initialization context") and made it one of the > "goals" of the JEP, because the gulf between the spec on one hand and the > compiler's current behavior (and what everyone has actually been doing for > the past decade) on the other hand is pretty glaring. > FYI, Along these lines, I've added this new section to the "Motivation" section: (Also, presumably people who are interested in following the JEP can 'watch' it, so I won't post any more such updates after this one.) Fixing a Specification Bug > > JLS ?8.1.3 defines *static context* and notes that "The purpose of a > static context is to demarcate code that must not refer explicitly or > implicitly to the current instance of the class whose declaration lexically > encloses the static context". Going by its stated purpose, a static context > would seem to naturally apply to code inside a super() or this() > invocation, and in fact the JLS does just that. Prior to the advent of > generics, inner classes, and captured free variables, this yielded the > correct semantics for superclass construtor invocation. > > However, as ?8.1.3 notes a static context prohibits: > > - this expressions (both unqualified and qualified) > - Unqualified references to instance variables of any lexically > enclosing class or interface declaration > - References to type parameters, local variables, formal parameters, > and exception parameters declared by methods or constructors of any > lexically enclosing class or interface declaration that is outside the > immediately enclosing class or interface > > Those rules make the following program illegal: > > import java.util.concurrent.atomic.AtomicReference; > > public class ClassA extends AtomicReference { > > private int intval; > > public ClassA(T obj) { > super(obj); > } > > public class ClassB extends ClassA { > public ClassB() { > super((T)null); // illegal - 'T' > } > } > > public class ClassC extends ClassA { > ClassC() { > super(ClassA.this); // illegal - 'this' > } > } > > public class ClassD extends ClassA { > ClassD() { > super(intval); // illegal - 'intval' > } > } > > public static Object method(int x) { > class ClassE extends ClassA { > ClassE() { > super((float)x); // illegal - 'x' > } > } > return new ClassE(); > } > } > > But not only has this program compiled successfully since at least Java 8, > the above idioms are in common use. The mental model that the compiler and > developers seem to both be using is indeed that code "must not refer > explicitly or implicitly to the current instance of the class whose > declaration lexically encloses" the code in question. However, this is no > longer what a "static context" prohibits; instead, it goes beyond that, for > example, restricting even references to generic type parameters. > > The underlying issue is that "static context" is applied to two scenarios > which are similar, but not equivalent: > > 1. When there is no 'this' instance defined, e.g., within a static > method > 2. When the 'this' instance is defined but must not be referened, > e.g., prior to superclass initialization > > The current definition of "static context" is appropriate for scenario #1, > but after the addition of generics, inner classes, and captured free > variables to the language, no longer for scenario #2. We need a new, > distinct concept; let's call it a "pre-initialization context". The rules > for a "pre-initialization context" should align with developers' current > mental models (and compiler behavior) for what's allowed prior to > superclass initialization. Once defined, the rules for a > "pre-initialization context" can then extend to statements prior to > superclass initialization, and for the same reason. > -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From gavin.bierman at oracle.com Thu Feb 9 15:28:41 2023 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Thu, 9 Feb 2023 15:28:41 +0000 Subject: Third draft spec for String Templates (JEP 430) now available Message-ID: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> Dear experts: A new, updated spec covering JEP 430 (String Templates) is now available at: https://cr.openjdk.java.net/~gbierman/jep430/latest This is a substantial rewrite: it now covers more fully how templates are tokenized, how to deal with ambiguities, and how text block templates are dealt with. Comments welcomed! Gavin -------------- next part -------------- An HTML attachment was scrubbed... URL: From alex.buckley at oracle.com Thu Feb 9 18:19:23 2023 From: alex.buckley at oracle.com (Alex Buckley) Date: Thu, 9 Feb 2023 10:19:23 -0800 Subject: Third draft spec for String Templates (JEP 430) now available In-Reply-To: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> References: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> Message-ID: On 2/9/2023 7:28 AM, Gavin Bierman wrote: > https://cr.openjdk.java.net/~gbierman/jep430/latest In 2.1, if we're going with the term "ambiguous", we should have some rationale for why the well known term "context-sensitive" isn't good enough. I don't want to lose the term "context-free" entirely. Perhaps a note in 2.2: "In early versions of the Java programming language, the lexical grammar was not ambiguous. Rather, it was _context-free_, meaning that ...". In 2.3, it is incongruous that there is no statement about whether the syntactic grammar is ambiguous. In 3.13, the content of a fragment is defined statefully/positionally, e.g., StringTemplateBegin: "... ends immediately before the sequence \{ that prefixes ***the first*** embedded expression" e.g., StringTemplateEnd: "... begins immediately after the character } that postfixes ***the final*** embedded expression" I don't think this statefulness is used to resolve ambiguities. If you defined "content" purely as the sequence of characters in the StringFragment of a StringTemplateBegin/Mid/End, do you lose anything? Regarding the note at the end of 3.13: The 4 and the 2 are separate input characters, they should have a space between them. Please say "input character" throughout, not "character". "The next twelve characters ~would be~ +are+ reduced to the tokens ..." I was tripped up by `the following two input characters (i.e. the sequence } } ")` -- the word "two" is followed by an example of three characters -- contrast this with the later clause which puts the word "two" next to an example with two characters: `two input characters (the sequence } ")` Let's be super-clear: The next input character, }, is ambiguous. It could be reduced to a Separator, or it could be reduced along with the following } and " input characters to a StringTemplateEnd. ... The remaining } and " input characters will then be reduced to a StringTemplateEnd. The phrase "... provide the context of matching the ArrayInitializer" is used. Given the earlier bullet -- "... was not in the context of being recognized as a terminal ..." -- I was looking out for the word "recognizing" rather than "matching". Alex From alex.buckley at oracle.com Fri Feb 10 00:06:32 2023 From: alex.buckley at oracle.com (Alex Buckley) Date: Thu, 9 Feb 2023 16:06:32 -0800 Subject: Third draft spec for String Templates (JEP 430) now available In-Reply-To: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> References: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> Message-ID: <46b350a6-c519-22de-90c5-620624045607@oracle.com> On 2/9/2023 7:28 AM, Gavin Bierman wrote: > https://cr.openjdk.java.net/~gbierman/jep430/latest Specifying the lexical and syntactic monster that we call a template expression is no mean feat, so congratulations on 15.8.6. The rejiggering of 15.8.6 that follows is mostly stylistic. There's a lot going on in the first paragraph; compare with the first paragraphs of 15.9 and 15.12 and 15.27, where less is more. The detail about a template (e.g., n+1, n>0) is perhaps excessive, and unusually we end up introducing "template" twice -- once as a "specification" (brilliant word BTW) and later as something that "resembles either a string literal ...". I would like to spotlight the novel fact that a template expression delegates to a template processor to do work. I would also like to dial down the grammatical device of "template argument" and the string literal/text block possibilities -- people can realize all that stuff from the grammar -- our job is to introduce "template". [Best to introduce a construct using the singular form, per the style of 15.9, 15.10, etc.] A _template expression_ provides a general means of combining literal text with the values of expressions. The text and expressions are specified by a _template_. The task of combining the text with the expressions' values is delegated to a _template processor_. [Note] Simple interpolation of text and values into a `String` is available from a predefined template processor, `STR` (7.3). Other template processors may combine text and values in arbitrary ways to produce a result of a more sophisticated type than `String`. [Grammar follows. A copy-paste error has crept in for the recap of StringTemplateEnd and TextBlockTemplateEnd.] A template is either a _string template_ or a _text block template_. [The JLS needs to get those terms on the record.] A string template (respectively, a text block template) resembles a string literal (a text block) but contains ... If nothing appears ... [See 4.8 for another use of this "respectively" idiom.] A string template with _n_ embedded expressions (n>0) consists of the alternate interleaving of _n+1_ fragments with the n embedded expressions. The first fragment is a StringTemplateBegin token; the next n-1 fragments are StringTemplateMid tokens; the last fragment is a StringTemplateEnd token. [Here, with a syntactic- grammar-derived StringTemplate in our hand, is where we finally get to describe fragments in positional terms: first, next, last.] A text block template with _n_ embedded expressions ... [Four example interleavings follow. Please avoid the term "simple string template". Can say: "Here is the breakdown of some string templates:".] [We have now fully described the form of a template. Time to motivate and derive an artifact. I'm going to avoid switching between "fragment" (which is a kind of token per 3.13) and "fragment token". Bear in mind that 3.13 defined "the content of a fragment".] The _fragment strings_ of a template represent the literal text that surrounds the embedded expressions. Fragment strings are determined as follows: - A string template with _n_ embedded expressions and _n+1_ fragments has _n+1_ fragment strings, where each fragment string is the content of the corresponding fragment. - A text block template with _n_ embedded expressions and _n+1_ fragments has _n+1_ fragment strings, determined as follows: 1. The _string content_ of the text block template is ... 2. The string content of the text block template is further ... 3. The fragment strings s_1 .. s_n+1 are based on the string content as follows: ... [Continues from the fragment strings example.] After the "At run time ..." evaluation procedure, please add a note: That is, the meaning of the template expression e . "_x_" is equivalent to the meaning of the method invocation expression e.process(y) where y refers to an instance of java.lang.template.StringTemplate that encapsulates both the literal text in x and the values of the embedded expressions in x. Alex From robbepincket at live.be Fri Feb 10 22:31:26 2023 From: robbepincket at live.be (Robbe Pincket) Date: Fri, 10 Feb 2023 22:31:26 +0000 Subject: Draft JEP on Primitive types in patterns, instanceof, and switch In-Reply-To: <226409753.5913335.1674743136668.JavaMail.zimbra@u-pem.fr> References: <345951843.5806933.1674738975706.JavaMail.zimbra@u-pem.fr> <226409753.5913335.1674743136668.JavaMail.zimbra@u-pem.fr> Message-ID: Hi all I've long considered whether I should voice my opinion on the matter or not, given that I felt like some of my arguments had already been made before. Spoiler, I'm not a fan of `instanceof byte`. Every time I write this email, I recheck something in the archives to check something and realize that someone already said *something* about one of the arguments I'm trying to make. So here is just a list of things that have come up that I still felt like mentioning something. --- I asked a whether the following would be legal in an earlier email. The draft now explains that it is, but I still wonder what this snippet would get desugared to. ```java Number num = ...; if (num instanceof byte b) { ... } ``` --- On 2023-01-27 at 12:01 UTC, Ron Pressler wrote (as reaction to an email by Remi Forax on 2023-01-27 at 11:06 UTC): > ?4.10.1 of the JLS has stated that a subtyping relationship among primitives exists (byte <: short <: int <: long, float <: double) since at least Java 1.6 (possibly earlier). > >> By example, you can not override a method that returns a double with a method that returns an int because overriding is about subtyping relationship, not conversion (for the history, Neal Gafter had implemented method overriding that allow primitive conversions in javac in one of the early versions of Java 1.5 but to it was decided to not go that path). > > The rules for return types in overridden methods (?8.4.8.3) doesn?t refer to subtyping but to "return-type-substitutability? (?8.4.5) which, in turn, also doesn?t talk about subtyping but only about subtyping *in the case that the return type is a reference type*. So even though there is a subtyping relationship between int and long (though not between int and double), they are not return-type-substitutable, which places additional constraints beyond mere subtyping. It seems you missed a single line in the spec. `long` is also a direct subtype of `float` so `int` is in fact a subtype of `double` >> I agree that revisiting concepts is something we have to do, but breaking the difference between subtyping and primitive conversions for a corner case, in isolation, is a decision hard to understand. > > First, a subtyping relationship for primitives does exist, though it doesn?t cover all of the possible conversions. Second, nothing is broken, shattered, or wrecked even in cases subtyping doesn?t exist, because the draft doesn?t propose to *change* the meaning of patterns, but rather to generalise them. I.e. its insight is that subtyping is a special case of assignment conversion, and so patterns are ?really? about the validity of such conversions rather than about the specific case of subtyping. I had a quick look over the spec and I couldn't find any place that actually used the subtyping relation between primitives. The case you seem to be claiming widening primitive conversion matches 100% with the rules about subtyping, it actually doesn't use subtyping at all and just lists all possible conversions. A interesting question that could be asked is: "What does subtype/supertype mean". Although it is used in the spec it isn't really explain apart from being a reflexive and transitive relationship between types. --- A few of the emails argue that we should see `instanceof` as a safe cast check, not like an "inheritance" check or a "reference subtype" check. If the operator was called `canbesafelyconvertedto` I might agree, but thats not the case. It feels very weird (to me) to not have an operator called `instanceof`, not check whether the lhs is an instance of the rhs. Some of you might be thinking: "I guess you want to argue that you can't have instances of an `byte` so `instanceof byte` doesn't make sense", which isn't true. Valhalla discussions have agreed that `byte` has instances. It has 256 different ones: the values from -128 to 127. Now this might seem I'm arguing in favour of `instanceof byte`. And on it's own that might look correct, but then you have justify the fact that the integer values/instances between -128 and 127 and the byte values/instances are the same. In my mind the way this would be justified is by using the fact that `byte` is a subtype of `int` which is why it's set of instances is a subset of the instances of `int`. But this raises the issue that the set of instances of `int` can't be a subset of the set of instances of `float` cause not all ints are valid floats. --- I feel like I spend too much time writing, rewriting and deleting this email so this is it (for now). TL; DR: I don't like `instanceof byte` and JLS chapter 4.10.1 Kind regards Robbe Pincket -------------- next part -------------- An HTML attachment was scrubbed... URL: From daniel.smith at oracle.com Sat Feb 11 00:38:51 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Sat, 11 Feb 2023 00:38:51 +0000 Subject: Third draft spec for String Templates (JEP 430) now available In-Reply-To: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> References: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> Message-ID: <1186125C-D813-4487-8900-1EB14FAD9F99@oracle.com> Enthusiastically endorse two big design choices reflected here: - The use of Fragments to represent the string content that gets interleaved with embedded expressions - The requirement that a StringTemplate or TextBlockTemplate only appear in a program after a '.' character Nice work, feels quite manageable and doesn't blow up the grammar! On Feb 9, 2023, at 7:28 AM, Gavin Bierman > wrote: Dear experts: A new, updated spec covering JEP 430 (String Templates) is now available at: https://cr.openjdk.java.net/~gbierman/jep430/latest This is a substantial rewrite: it now covers more fully how templates are tokenized, how to deal with ambiguities, and how text block templates are dealt with. Comments welcomed! Gavin -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Feb 13 20:31:06 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 13 Feb 2023 15:31:06 -0500 Subject: Third draft spec for String Templates (JEP 430) now available In-Reply-To: <1186125C-D813-4487-8900-1EB14FAD9F99@oracle.com> References: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> <1186125C-D813-4487-8900-1EB14FAD9F99@oracle.com> Message-ID: Yes, this was a pretty brilliant move of specsmanship here.? I had feared that we would have to pull out a bigger shotgun here. On 2/10/2023 7:38 PM, Dan Smith wrote: > Enthusiastically endorse two big design choices reflected here: > > - The use of Fragments to represent the string content that gets > interleaved with embedded expressions > > - The requirement that a StringTemplate or TextBlockTemplate only > appear in a program after a '.' character > > Nice work, feels quite manageable and doesn't blow up the grammar! > > >> On Feb 9, 2023, at 7:28 AM, Gavin Bierman >> wrote: >> >> Dear experts: >> >> A new, updated spec covering JEP 430 (String Templates) is now >> available at: >> >> https://cr.openjdk.java.net/~gbierman/jep430/latest >> >> This is a substantial rewrite: it now covers more fully how templates >> are tokenized, how to deal with ambiguities, and how text block >> templates are dealt with. >> >> Comments welcomed! >> Gavin > -------------- next part -------------- An HTML attachment was scrubbed... URL: From angelos.bimpoudis at oracle.com Tue Feb 14 22:22:06 2023 From: angelos.bimpoudis at oracle.com (Angelos Bimpoudis) Date: Tue, 14 Feb 2023 22:22:06 +0000 Subject: Draft JEP on Primitive types in patterns, instanceof, and switch In-Reply-To: <03241935-d564-c7e0-9577-52efc3935a92@oracle.com> References: <345951843.5806933.1674738975706.JavaMail.zimbra@u-pem.fr> <226409753.5913335.1674743136668.JavaMail.zimbra@u-pem.fr> <7e218f85-0181-bb00-ed5a-b9d3029c2c4c@oracle.com> <03241935-d564-c7e0-9577-52efc3935a92@oracle.com> Message-ID: Hello all, We've redone the presentation to try to make the motivation & connections more clear. The main points are the following: we lift restrictions around primitive type patterns in nested positions, in top-level positions, around constant case labels and instanceof. The semantics for instanceof? are naturally derived from pattern matching. Now instanceof? can safeguard all permitted casts according to Chapter 5. https://openjdk.org/jeps/8288476 Let us know of your thoughts. Angelos ________________________________ From: Brian Goetz Sent: 26 January 2023 17:04 To: Guy Steele Cc: forax at univ-mlv.fr ; Angelos Bimpoudis ; amber-spec-experts Subject: Re: Draft JEP on Primitive types in patterns, instanceof, and switch Yes, pardon my quick typing. More specifically, a case constant is not a _constant pattern_ (at least, not yet), it is just a constant case label. Constants are typed, and they carray both a type match and a value match. When you say case 0 this is a constant for an int, and doesn't match a floating point zero (if the match target is `float`, it won't even compile.) Similarly, `case 0.0` is a constant for a float, and is not applicable to a match target of int. (We do have the usual tolerance for matching int constants to shorter int types, as before.) We may generalize these to constant patterns in the future, but right now, these are constant case labels and their semantics are derived from that of existing case labels. On 1/26/2023 10:25 AM, Guy Steele wrote: On Jan 26, 2023, at 9:36 AM, Brian Goetz > wrote: ... For comparing a variable to a constant, representational equality is the obvious interpretation; `case nnn` means "is it the number nnn". This allows you to say `case NaN` and `case -0` and get the right answer (all of these relations agree on what to do about 1.0). Careful: I think you had better say ?case -0.0?; otherwise the constant expression ?-0? will be reduced to ?0? and only then converted to floating-point representation, producing +0.0. Yes, floating-point is VERY fiddly. ?Guy -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron.pressler at oracle.com Wed Feb 15 16:14:21 2023 From: ron.pressler at oracle.com (Ron Pressler) Date: Wed, 15 Feb 2023 16:14:21 +0000 Subject: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) Message-ID: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> Hi. I've published a JEP draft, Implicit Classes and Enhanced Main Methods (Preview) (https://openjdk.org/jeps/8302326) based on Brian?s article, Paving the On-Ramp (https://openjdk.org/projects/amber/design-notes/on-ramp). System.out.println and possible improvements to the import experience in general will be the subject of a separate JEP. Comments are welcome. ? Ron -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Wed Feb 15 16:37:38 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Wed, 15 Feb 2023 10:37:38 -0600 Subject: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> Message-ID: On Wed, Feb 15, 2023 at 10:17 AM Ron Pressler wrote: > I've published a JEP draft, Implicit Classes and Enhanced Main Methods > (Preview) (https://openjdk.org/jeps/8302326) > based on Brian?s article, Paving the On-Ramp ( > https://openjdk.org/projects/amber/design-notes/on-ramp). > I like this. Comments: Outside the scope of this JEP, but: a smarter launch protocol may be useful for reasons beyond on-ramping. For example, instead of only looking for default constructors, you could look for a constructor taking an object of type LauchEnvironment, which is something to be suitably defined. The implicit class idea scares me a bit. One issue is that it could turn invalid code into "working" code inadvertently. Can "floating" methods in the implicit class be declared scattered across multiple random source files or do they have to all be in one file? If so, which one? Is there a good reason why implicit class support should NOT be restricted to JEP 330 mode only? -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed Feb 15 16:41:29 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 15 Feb 2023 11:41:29 -0500 Subject: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> Message-ID: <98606fb0-5b8a-69c6-8f89-2f4c459dfebb@oracle.com> > Outside the scope of this JEP, but: a smarter launch protocol may be > useful for reasons beyond on-ramping. For example, instead of only > looking for default constructors, you could look for a constructor > taking an object of type LauchEnvironment, which is something to be > suitably defined. Yes, though we're dipping into that water cautiously.? One thing that this JEP opens up is the ability for abstract classes to contribute a main method: ??? abstract class TestCase { ??????? void main() { runTest(this.getClass()); } ??? } and then any test case becomes launchable: ??? class MyTestCase extends TestCase { ??????? // test case ??? } just by running ??? java MyTestCase This eliminates a whole category of contortions that frameworks have to provide (or worse, often don't provide) for running a single test case, service, etc from the command line. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron.pressler at oracle.com Wed Feb 15 17:16:33 2023 From: ron.pressler at oracle.com (Ron Pressler) Date: Wed, 15 Feb 2023 17:16:33 +0000 Subject: [External] : Re: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> Message-ID: <933663DE-FDE3-4A9C-9DFE-765AB37BDCBA@oracle.com> On 15 Feb 2023, at 16:37, Archie Cobbs > wrote: On Wed, Feb 15, 2023 at 10:17 AM Ron Pressler > wrote: I've published a JEP draft, Implicit Classes and Enhanced Main Methods (Preview) (https://openjdk.org/jeps/8302326) based on Brian?s article, Paving the On-Ramp (https://openjdk.org/projects/amber/design-notes/on-ramp). I like this. Comments: Outside the scope of this JEP, but: a smarter launch protocol may be useful for reasons beyond on-ramping. For example, instead of only looking for default constructors, you could look for a constructor taking an object of type LauchEnvironment, which is something to be suitably defined. The implicit class idea scares me a bit. One issue is that it could turn invalid code into "working" code inadvertently. It?s a compile-time error for an implicit class to be a member of a named package. So if a ?top-level? method is defined in a compilation unit that?s in a named package, that will be an error. Additionally, an implicit class must have a main method, and an implicit class cannot be directly referenced by name. Do you think that?s not enough protection? Can "floating" methods in the implicit class be declared scattered across multiple random source files or do they have to all be in one file? If so, which one? The compiler wraps every implicit-class compilation unit as a separate class, and those classes are unnamed, at least from the perspective of the Java _language_. As an implementation detail, javac will compile each to its own classfile, but they obviously can?t reference each other. Is there a good reason why implicit class support should NOT be restricted to JEP 330 mode only? Implicit classes are a language feature, while JEP 330 is a JDK implementation detail. Restricting implicit classes to source-code launching would introduce both a beginners? dialect and a beginners? toolchain, violating two of the JEPs stated anti-goals. The reason they are anti-goals is because they run counter to the goal of gradually growing the program (they would require switching dialect once you want a proper build). The proposed way is both orthogonal, and so easier to specify, and supports the goal of gradual growth. ? Ron -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Wed Feb 15 17:49:02 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Wed, 15 Feb 2023 11:49:02 -0600 Subject: [External] : Re: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <933663DE-FDE3-4A9C-9DFE-765AB37BDCBA@oracle.com> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <933663DE-FDE3-4A9C-9DFE-765AB37BDCBA@oracle.com> Message-ID: On Wed, Feb 15, 2023 at 11:16 AM Ron Pressler wrote: > > The implicit class idea scares me a bit. One issue is that it could turn > invalid code into "working" code inadvertently. > > > It?s a compile-time error for an implicit class to be a member of a named > package. So if a ?top-level? method is defined in a compilation unit that?s > in a named package, that will be an error. Additionally, an implicit class > must have a main method, and an implicit class cannot be directly > referenced by name. > > Do you think that?s not enough protection? > Yes - that helps a lot. I would mainly worry about "production" environments, where the unnamed package is unlikely to be in use. > > Is there a good reason why implicit class support should NOT be restricted > to JEP 330 mode only? > > > Implicit classes are a language feature, while JEP 330 is a JDK > implementation detail. Restricting implicit classes to source-code > launching would introduce both a beginners? dialect and a beginners? > toolchain, violating two of the JEPs stated anti-goals. The reason they are > anti-goals is because they run counter to the goal of gradually growing the > program (they would require switching dialect once you want a proper > build). The proposed way is both orthogonal, and so easier to specify, and > supports the goal of gradual growth. > Makes sense - thanks for clarifying. -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Wed Feb 15 18:18:45 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 15 Feb 2023 19:18:45 +0100 (CET) Subject: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> Message-ID: <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> > From: "Ron Pressler" > To: "amber-spec-experts" > Sent: Wednesday, February 15, 2023 5:14:21 PM > Subject: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) > Hi. > I've published a JEP draft, Implicit Classes and Enhanced Main Methods (Preview) > ( [ https://openjdk.org/jeps/8302326 | https://openjdk.org/jeps/8302326 ] ) > based on Brian?s article, Paving the On-Ramp ( [ > https://openjdk.org/projects/amber/design-notes/on-ramp | > https://openjdk.org/projects/amber/design-notes/on-ramp ] ). > System.out.println and possible improvements to the import experience in general > will be the subject of a separate JEP. What is the behaviors of the compiler for var hello() { } var hello() { return; } var hello() { return null; } var foo; var foo = null; record hello() { } record hello() { return; } record hello() { return null; } record foo; record foo = null; record main() { } record main() { return; } static record main() { } static record main() { return; } record main; record main = null; > Comments are welcome. > ? Ron R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron.pressler at oracle.com Wed Feb 15 23:52:24 2023 From: ron.pressler at oracle.com (Ron Pressler) Date: Wed, 15 Feb 2023 23:52:24 +0000 Subject: [External] : Re: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> Message-ID: <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> On 15 Feb 2023, at 18:18, Remi Forax > wrote: What is the behaviors of the compiler for var hello() { } var hello() { return; } var hello() { return null; } var foo; var foo = null; record hello() { } record hello() { return; } record hello() { return null; } record foo; record foo = null; record main() { } record main() { return; } static record main() { } static record main() { return; } record main; record main = null; All of these except for `record hello() {}`, `record main() {}`, and `static record main() {}` are compile-time errors. An implicit class is compiled as if the entire content of the file (except import statements) are enclosed in a final class declaration with some unknown name. Because there is no name, you can?t declare a constructor (or use a method reference to a static method). The meaning of all members is interpreted in the usual way. The only special rules are that an implicit class must be in the unnamed package and it must contain a main entry point (if it didn?t have an entry point there would be no way of using the class ? you can?t invoke a static method on it from some other class or instantiate it because it?s unnamed). ? Ron -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Thu Feb 16 21:41:13 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 16 Feb 2023 22:41:13 +0100 (CET) Subject: [External] : Re: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> Message-ID: <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> > From: "Ron Pressler" > To: "Remi Forax" > Cc: "amber-spec-experts" > Sent: Thursday, February 16, 2023 12:52:24 AM > Subject: Re: [External] : Re: JEP draft: Implicit Classes and Enhanced Main > Methods (Preview) >> On 15 Feb 2023, at 18:18, Remi Forax < [ mailto:forax at univ-mlv.fr | >> forax at univ-mlv.fr ] > wrote: >> What is the behaviors of the compiler for >> var hello() { } >> var hello() { return; } >> var hello() { return null; } >> var foo; >> var foo = null; >> record hello() { } >> record hello() { return; } >> record hello() { return null; } >> record foo; >> record foo = null; >> record main() { } >> record main() { return; } >> static record main() { } >> static record main() { return; } >> record main; >> record main = null; > All of these except for `record hello() {}`, `record main() {}`, and `static > record main() {}` are compile-time errors. > An implicit class is compiled as if the entire content of the file (except > import statements) are enclosed in a final class declaration with some unknown > name. Because there is no name, you can?t declare a constructor (or use a > method reference to a static method). The meaning of all members is interpreted > in the usual way. or refers to "this" by the name of the class. My questions was more about the error messages students will get when writing one of these lines. Usually students struggle not because they have make a mistake but because they are not able to understand how to fix it. > The only special rules are that an implicit class must be in the unnamed package > and it must contain a main entry point (if it didn?t have an entry point there > would be no way of using the class ? you can?t invoke a static method on it > from some other class or instantiate it because it?s unnamed). I still think that fields should not be allowed inside an implicit class, because when you remove the class declaration a field and a local variable are too similar and because an implicit class has no user defined constructor. Here is a series of examples showing how confusing it can be. Object var, record; void main() { System.out.println(var); // compiles } void main() { Object var, record; System.out.println(var); // does not compile } Object var, record; static void main() { System.out.println(var); // does not compile } static Object var, record; void main() { System.out.println(var); // compiles but awful } void main() { var var = 3; System.out.println(var); // compiles } var var = 3; // does not compile void main() { System.out.println(var); } Also conceptually, being able to define fields without constructors is problematic, because you are bypassing the the notion of encapsulation. Implicit class instance fields are more complex that usual class fields because of the lack of constructors. Teaching using a simpler model is great but not if as a student you have to unlearn something previously introduced. > ? Ron R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron.pressler at oracle.com Fri Feb 17 10:11:20 2023 From: ron.pressler at oracle.com (Ron Pressler) Date: Fri, 17 Feb 2023 10:11:20 +0000 Subject: [External] : Re: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> Message-ID: On 16 Feb 2023, at 21:41, forax at univ-mlv.fr wrote: I still think that fields should not be allowed inside an implicit class, because when you remove the class declaration a field and a local variable are too similar and because an implicit class has no user defined constructor. I think your general point has some merit ? I?ll get to that later ? but first let me address the concrete points you raise. Here is a series of examples showing how confusing it can be. How would any of those be made easier to understand by the presence of a class declaration when you don?t know what a class is? By the way, we should certainly look into making some error messages ? especially those encountered by beginners ? easier to understand. Also conceptually, being able to define fields without constructors is problematic, because you are bypassing the the notion of encapsulation. Encapsulation from what? Encapsulation is a programming-in-the-large notion, but even at the technical level, an implicit class is well encapsulated by virtue of it being unnamed (and the default access remains package). Implicit class instance fields are more complex that usual class fields because of the lack of constructors. I?m not sure I understand the relationship you make to constructors (BTW, you can define initializers). Python and JS, both also first language have a notion of shared variables that can be introduced before object fields. Clojure and ML, both functional languages, also have a similar notion of shared variables. Even Haskell has constants. Surely you?d agree that at least final fields ? constants ? are necessary to do any kind of nice programming? Teaching using a simpler model is great but not if as a student you have to unlearn something previously introduced. I wholeheartedly agree, but what is the thing that needs to be unlearned? But now back to where I think your general point has merit. I think final fields are a must, but one could certainly argue that non-final fields are not. You can certainly do a lot of programming without them. But I think that allowing final fields and disallowing non-final fields *in Java* would be weird, because to designate something as final you need extra syntax, so we?d reject syntactically simpler, valid, code and accept more complex one. Moreover, there are things that are easier to do and tech with mutable fields. However, there?s the matter of static, which you used in your examples but didn?t explicitly discuss. Because a an implicit class is effectively a singleton (plus, the class cannot be referenced by other classes), there is no useful difference between an instance field and a static field, so I think we should entertain the notion of disallowing static members ? fields, methods, or even member classes (although things that are implicitly static, such as records would obviously be allowed). One argument against that may be is that if an experienced Java programmer has an existing small program that they want to make prettier by turning into an implicit class ? implicit classes are mainly motivated by learners, but they?re not *just* for them ? then the process would be made harder by disallowing static members. In short, I think we must allow fields, but we can think about disallowing (explicitly) static members altogether. ? Ron -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron.pressler at oracle.com Fri Feb 17 16:05:37 2023 From: ron.pressler at oracle.com (Ron Pressler) Date: Fri, 17 Feb 2023 16:05:37 +0000 Subject: [External] : Re: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> Message-ID: I?d like to make another point about the general approach of this JEP. We try to avoid a beginners? dialect, but a beginners? *subset* is also not what we?re proposing. While the feature is primarily motivated by education, it is also a natural, perhaps even obvious, feature for Java that?s perfectly in tune with the existing features of the language. Classes, packages, and modules are all programming-in-the-large constructs, and every Java method resides in a class that resides in a package that resides in a module. Yet, when you don?t need encapsulation, an unnamed module is implicitly provided; when you don?t need package namespacing, an unnamed package is implicitly provided. It makes sense to do the same for classes even to reduce the need for programming-in-the-large declarations in small programs. Of course, helping students is a bigger motivation that makes significantly raises this feature?s priority. The important question as is whether or not this feature fulfils the motivation of helping beginners (of course, it?s not the only feature we can or will do to that end). I think the answer is yes. So then the remaining question is, would subsetting the language to forbid static members significantly help students? I?m not sure. ? Ron On 17 Feb 2023, at 10:11, Ron Pressler > wrote: On 16 Feb 2023, at 21:41, forax at univ-mlv.fr wrote: I still think that fields should not be allowed inside an implicit class, because when you remove the class declaration a field and a local variable are too similar and because an implicit class has no user defined constructor. I think your general point has some merit ? I?ll get to that later ? but first let me address the concrete points you raise. Here is a series of examples showing how confusing it can be. How would any of those be made easier to understand by the presence of a class declaration when you don?t know what a class is? By the way, we should certainly look into making some error messages ? especially those encountered by beginners ? easier to understand. Also conceptually, being able to define fields without constructors is problematic, because you are bypassing the the notion of encapsulation. Encapsulation from what? Encapsulation is a programming-in-the-large notion, but even at the technical level, an implicit class is well encapsulated by virtue of it being unnamed (and the default access remains package). Implicit class instance fields are more complex that usual class fields because of the lack of constructors. I?m not sure I understand the relationship you make to constructors (BTW, you can define initializers). Python and JS, both also first language have a notion of shared variables that can be introduced before object fields. Clojure and ML, both functional languages, also have a similar notion of shared variables. Even Haskell has constants. Surely you?d agree that at least final fields ? constants ? are necessary to do any kind of nice programming? Teaching using a simpler model is great but not if as a student you have to unlearn something previously introduced. I wholeheartedly agree, but what is the thing that needs to be unlearned? But now back to where I think your general point has merit. I think final fields are a must, but one could certainly argue that non-final fields are not. You can certainly do a lot of programming without them. But I think that allowing final fields and disallowing non-final fields *in Java* would be weird, because to designate something as final you need extra syntax, so we?d reject syntactically simpler, valid, code and accept more complex one. Moreover, there are things that are easier to do and tech with mutable fields. However, there?s the matter of static, which you used in your examples but didn?t explicitly discuss. Because a an implicit class is effectively a singleton (plus, the class cannot be referenced by other classes), there is no useful difference between an instance field and a static field, so I think we should entertain the notion of disallowing static members ? fields, methods, or even member classes (although things that are implicitly static, such as records would obviously be allowed). One argument against that may be is that if an experienced Java programmer has an existing small program that they want to make prettier by turning into an implicit class ? implicit classes are mainly motivated by learners, but they?re not *just* for them ? then the process would be made harder by disallowing static members. In short, I think we must allow fields, but we can think about disallowing (explicitly) static members altogether. ? Ron -------------- next part -------------- An HTML attachment was scrubbed... URL: From heidinga at redhat.com Fri Feb 17 16:56:49 2023 From: heidinga at redhat.com (Dan Heidinga) Date: Fri, 17 Feb 2023 11:56:49 -0500 Subject: [External] : Re: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> Message-ID: On Fri, Feb 17, 2023 at 11:05 AM Ron Pressler wrote: > I?d like to make another point about the general approach of this JEP. > > We try to avoid a beginners? dialect, but a beginners? *subset* is also > not what we?re proposing. While the feature is primarily motivated by > education, it is also a natural, perhaps even obvious, feature for Java > that?s perfectly in tune with the existing features of the language. > > Classes, packages, and modules are all programming-in-the-large > constructs, and every Java method resides in a class that resides in a > package that resides in a module. Yet, when you don?t need encapsulation, > an unnamed module is implicitly provided; when you don?t need package > namespacing, an unnamed package is implicitly provided. It makes sense to > do the same for classes even to reduce the need for > programming-in-the-large declarations in small programs. Of course, helping > students is a bigger motivation that makes significantly raises this > feature?s priority. > > The important question as is whether or not this feature fulfils the > motivation of helping beginners (of course, it?s not the only feature we > can or will do to that end). I think the answer is yes. So then the > remaining question is, would subsetting the language to forbid static > members significantly help students? I?m not sure. > Wouldn't forbidding static members impose a cliff on beginners? As they learn about static methods and fields and introduce the first static member to their implicit class, they'd be forced to grow a class structure around their program. Maybe that's a natural time to have to talk about defining a class? I think there's a benefit in letting students (and advanced users) use as much of the language as possible in implicit classes. Don't force them to define the class until they do something that requires the class to have a proper name. --Dan > > ? Ron > > On 17 Feb 2023, at 10:11, Ron Pressler wrote: > > > > On 16 Feb 2023, at 21:41, forax at univ-mlv.fr wrote: > > > I still think that fields should not be allowed inside an implicit class, > because when you remove the class declaration a field and a local variable > are too similar and because an implicit class has no user defined > constructor. > > > I think your general point has some merit ? I?ll get to that later ? but > first let me address the concrete points you raise. > > > Here is a series of examples showing how confusing it can be. > > > How would any of those be made easier to understand by the presence of a > class declaration when you don?t know what a class is? > > By the way, we should certainly look into making some error messages ? > especially those encountered by beginners ? easier to understand. > > Also conceptually, being able to define fields without constructors is > problematic, because you are bypassing the the notion of encapsulation. > > > > Encapsulation from what? Encapsulation is a programming-in-the-large > notion, but even at the technical level, an implicit class is well > encapsulated by virtue of it being unnamed (and the default access remains > package). > > Implicit class instance fields are more complex that usual class fields > because of the lack of constructors. > > > I?m not sure I understand the relationship you make to constructors (BTW, > you can define initializers). > > Python and JS, both also first language have a notion of shared variables > that can be introduced before object fields. Clojure and ML, both > functional languages, also have a similar notion of shared variables. Even > Haskell has constants. Surely you?d agree that at least final fields ? > constants ? are necessary to do any kind of nice programming? > > > Teaching using a simpler model is great but not if as a student you have > to unlearn something previously introduced. > > > I wholeheartedly agree, but what is the thing that needs to be unlearned? > > But now back to where I think your general point has merit. I think final > fields are a must, but one could certainly argue that non-final fields are > not. You can certainly do a lot of programming without them. But I think > that allowing final fields and disallowing non-final fields *in Java* would > be weird, because to designate something as final you need extra syntax, so > we?d reject syntactically simpler, valid, code and accept more complex one. > Moreover, there are things that are easier to do and tech with mutable > fields. > > However, there?s the matter of static, which you used in your examples but > didn?t explicitly discuss. Because a an implicit class is effectively a > singleton (plus, the class cannot be referenced by other classes), there is > no useful difference between an instance field and a static field, so I > think we should entertain the notion of disallowing static members ? > fields, methods, or even member classes (although things that are > implicitly static, such as records would obviously be allowed). > > One argument against that may be is that if an experienced Java programmer > has an existing small program that they want to make prettier by turning > into an implicit class ? implicit classes are mainly motivated by learners, > but they?re not *just* for them ? then the process would be made harder by > disallowing static members. > > In short, I think we must allow fields, but we can think about disallowing > (explicitly) static members altogether. > > ? Ron > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Fri Feb 17 17:20:08 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 17 Feb 2023 12:20:08 -0500 Subject: [External] : Re: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> Message-ID: Yeah, I liked the idea of restricting static members for about thirty seconds, and then came around to the same place Dan is.? It seems superficially attractive to say "if you need statics, you should be aware of classes", but I don't see how it really helps students, and the error messages that the user would get in this case ("it's time for you to grow up and declare a class!") are not likely to be all that educational.? Users may, for example, want to cut and paste snippets of Java code from blogs to try them out, that might have static in it, and there's no reason this shouldn't work. So after wrestling with Ron's question briefly, and being briefly tempted, I think the temptation is best resisted. I like Dan's rubric about "need to use the name", with the understanding that in order to create more than one instance, you need to use the name.? Having more than one instance of a class is a good time to understand that you are defining an abstraction, not just a simple program.? In the world where you get one implicit instance, it is still ambiguous whether this is a program or a class (which is good if you don't know what a class is.)? The need to understand classes will likely come through "I want more than one instance." (BTW I can imagine a world where records are taught before classes; a simplified class could need to describe "pair of name and grade", and they could use a "nested" record for that, and still not have to learn yet what a class really is.) On 2/17/2023 11:56 AM, Dan Heidinga wrote: > > > On Fri, Feb 17, 2023 at 11:05 AM Ron Pressler > wrote: > > I?d like to make another point about the general approach of this > JEP. > > We try to avoid a beginners? dialect, but a beginners? *subset* is > also not what we?re proposing. While the feature is primarily > motivated by education, it is also a natural, perhaps even > obvious, feature for Java that?s perfectly in tune with the > existing features of the language. > > Classes, packages, and modules are all programming-in-the-large > constructs, and every Java method resides in a class that resides > in a package that resides in a module. Yet, when you don?t need > encapsulation, an unnamed module is implicitly provided; when you > don?t need package namespacing, an unnamed package is implicitly > provided. It makes sense to do the same for classes even to reduce > the need for programming-in-the-large declarations in small > programs. Of course, helping students is a bigger motivation that > makes significantly raises this feature?s priority. > > The important question as is whether or not this feature fulfils > the motivation of helping beginners (of course, it?s not the only > feature we can or will do to that end). I think the answer is yes. > So then the remaining question is, would subsetting the language > to forbid static members significantly help students? I?m not sure. > > > Wouldn't forbidding static members impose a cliff on beginners?? As > they learn about static methods and fields and introduce the first > static member to their implicit class, they'd be forced to grow a > class structure around their program. Maybe that's a natural time to > have to talk about defining a class? > > I think there's a benefit in letting students (and advanced users) use > as much of the language as possible in implicit classes.? Don't force > them to define the class until they do something that requires the > class to have a proper name. > > --Dan > > > ? Ron > >> On 17 Feb 2023, at 10:11, Ron Pressler >> wrote: >> >> >> >>> On 16 Feb 2023, at 21:41, forax at univ-mlv.fr wrote: >>> >>> >>> I still think that fields should not be allowed inside an >>> implicit class, because when you remove the class declaration a >>> field and a local variable are too similar and because an >>> implicit class has no user defined constructor. >> >> I think your general point has some merit ? I?ll get to that >> later ? but first let me address the concrete points you raise. >> >>> >>> Here is a series of examples showing how confusing it can be. >>> >> >> How would any of those be made easier to understand by the >> presence of a class declaration when you don?t know what a class is? >> >> By the way, we should certainly look into making some error >> messages ? especially those encountered by beginners ? easier to >> understand. >> >>> Also conceptually, being able to define fields without >>> constructors is problematic, because you are bypassing the the >>> notion of encapsulation. >> >> >> Encapsulation from what? Encapsulation is a >> programming-in-the-large notion, but even at the technical level, >> an implicit class is well encapsulated by virtue of it being >> unnamed (and the default access remains package). >> >>> Implicit class instance fields are more complex that usual class >>> fields because of the lack of constructors. >> >> I?m not sure I understand the relationship you make to >> constructors (BTW, you can define initializers). >> >> Python and JS, both also first language have a notion of shared >> variables that can be introduced before object fields. Clojure >> and ML, both functional languages, also have a similar notion of >> shared variables. Even Haskell has constants. Surely you?d agree >> that at least final fields ? constants ? are necessary to do any >> kind of nice programming? >> >>> >>> Teaching using a simpler model is great but not if as a student >>> you have to unlearn something previously introduced. >> >> I wholeheartedly agree, but what is the thing that needs to be >> unlearned? >> >> But now back to where I think your general point has merit. I >> think final fields are a must, but one could certainly argue that >> non-final fields are not. You can certainly do a lot of >> programming without them. But I think that allowing final fields >> and disallowing non-final fields *in Java* would be weird, >> because to designate something as final you need extra syntax, so >> we?d reject syntactically simpler, valid, code and accept more >> complex one. Moreover, there are things that are easier to do and >> tech with mutable fields. >> >> However, there?s the matter of static, which you used in your >> examples but didn?t explicitly discuss. Because a an implicit >> class is effectively a singleton (plus, the class cannot be >> referenced by other classes), there is no useful difference >> between an instance field and a static field, so I think we >> should entertain the notion of disallowing static members ? >> fields, methods, or even member classes (although things that are >> implicitly static, such as records would obviously be allowed). >> >> One argument against that may be is that if an experienced Java >> programmer has an existing small program that they want to make >> prettier by turning into an implicit class ? implicit classes are >> mainly motivated by learners, but they?re not *just* for them ? >> then the process would be made harder by disallowing static members. >> >> In short, I think we must allow fields, but we can think about >> disallowing (explicitly) static members altogether. >> >> ? Ron >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Sat Feb 18 07:11:29 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Sat, 18 Feb 2023 08:11:29 +0100 (CET) Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> Message-ID: <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> > From: "Dan Heidinga" > To: "Ron Pressler" > Cc: "Remi Forax" , "amber-spec-experts" > > Sent: Friday, February 17, 2023 5:56:49 PM > Subject: Re: [External] : Re: JEP draft: Implicit Classes and Enhanced Main > Methods (Preview) > On Fri, Feb 17, 2023 at 11:05 AM Ron Pressler < [ mailto:ron.pressler at oracle.com > | ron.pressler at oracle.com ] > wrote: >> I?d like to make another point about the general approach of this JEP. >> We try to avoid a beginners? dialect, but a beginners? *subset* is also not what >> we?re proposing. While the feature is primarily motivated by education, it is >> also a natural, perhaps even obvious, feature for Java that?s perfectly in tune >> with the existing features of the language. >> Classes, packages, and modules are all programming-in-the-large constructs, and >> every Java method resides in a class that resides in a package that resides in >> a module. Yet, when you don?t need encapsulation, an unnamed module is >> implicitly provided; when you don?t need package namespacing, an unnamed >> package is implicitly provided. It makes sense to do the same for classes even >> to reduce the need for programming-in-the-large declarations in small programs. >> Of course, helping students is a bigger motivation that makes significantly >> raises this feature?s priority. >> The important question as is whether or not this feature fulfils the motivation >> of helping beginners (of course, it?s not the only feature we can or will do to >> that end). I think the answer is yes. So then the remaining question is, would >> subsetting the language to forbid static members significantly help students? >> I?m not sure. > Wouldn't forbidding static members impose a cliff on beginners? As they learn > about static methods and fields and introduce the first static member to their > implicit class, they'd be forced to grow a class structure around their > program. Maybe that's a natural time to have to talk about defining a class? > I think there's a benefit in letting students (and advanced users) use as much > of the language as possible in implicit classes. Don't force them to define the > class until they do something that requires the class to have a proper name. > --Dan yes. from my experience, the time to introduce the notion of class is when you start to have shared mutable state. What i do not like with the implicit class proposal is the fact that you can have fields without defining the class around. But i think there is a solution. What about the feature being renamed to "implicit record" instead of "implicit class" ? We have no discuss why the container of an implicit "class" has to be a class instead of an annotation, an interface, an enum or a record. Having the container to be an annotation is useless given that an annotation can not have a main. If the container is an interface, methods are abstract by default which is not what we want. If the container is an enum, then we are closer to the idea of Ron that it is a singleton, especially if the container defined one implicit enum member like "SINGLETON" . An enum can not be inherited and the default constructor is private which is are nice properties. if the container is a record with no component, it can not be inherited, the constructor is package visible and more importantly to me, a user can not defined instance fields ... I prefer implicit record to implicit class because with a record as container you can not introduce a shared mutable state by error, you have at least to write static in front of the field. I dread about students being able to write code like this String name; void setName(String name) { this.name = name; } void hello() { System.out.println(name); } void main() { setName("Bob"); ... hello(); } i.e to be able to declare mutable shared state without a class around (@Ron without class encapsulation). At least if the container is a record, "name" in the example above has to be static, from the student POV, an unusual variable. An implicit record has also the advantage that you do not have to introduce the notion of class to explain the notion of implicit container, given that records are far simpler at the beginning than class, having the implicit container being a record make sense because it's records all the way down. What do you think about having the implicit container being a record instead of a class ? >> ? Ron R?mi >>> On 17 Feb 2023, at 10:11, Ron Pressler < [ mailto:ron.pressler at oracle.com | >>> ron.pressler at oracle.com ] > wrote: >>>> On 16 Feb 2023, at 21:41, [ mailto:forax at univ-mlv.fr | >>>> forax at univ-mlv.fr ] wrote: >>>> I still think that fields should not be allowed inside an implicit class, >>>> because when you remove the class declaration a field and a local variable are >>>> too similar and because an implicit class has no user defined constructor. >>> I think your general point has some merit ? I?ll get to that later ? but first >>> let me address the concrete points you raise. >>>> Here is a series of examples showing how confusing it can be. >>> How would any of those be made easier to understand by the presence of a class >>> declaration when you don?t know what a class is? >>> By the way, we should certainly look into making some error messages ? >>> especially those encountered by beginners ? easier to understand. >>>> Also conceptually, being able to define fields without constructors is >>>> problematic, because you are bypassing the the notion of encapsulation. >>> Encapsulation from what? Encapsulation is a programming-in-the-large notion, but >>> even at the technical level, an implicit class is well encapsulated by virtue >>> of it being unnamed (and the default access remains package). >>>> Implicit class instance fields are more complex that usual class fields because >>>> of the lack of constructors. >>> I?m not sure I understand the relationship you make to constructors (BTW, you >>> can define initializers). >>> Python and JS, both also first language have a notion of shared variables that >>> can be introduced before object fields. Clojure and ML, both functional >>> languages, also have a similar notion of shared variables. Even Haskell has >>> constants. Surely you?d agree that at least final fields ? constants ? are >>> necessary to do any kind of nice programming? >>>> Teaching using a simpler model is great but not if as a student you have to >>>> unlearn something previously introduced. >>> I wholeheartedly agree, but what is the thing that needs to be unlearned? >>> But now back to where I think your general point has merit. I think final fields >>> are a must, but one could certainly argue that non-final fields are not. You >>> can certainly do a lot of programming without them. But I think that allowing >>> final fields and disallowing non-final fields *in Java* would be weird, because >>> to designate something as final you need extra syntax, so we?d reject >>> syntactically simpler, valid, code and accept more complex one. Moreover, there >>> are things that are easier to do and tech with mutable fields. >>> However, there?s the matter of static, which you used in your examples but >>> didn?t explicitly discuss. Because a an implicit class is effectively a >>> singleton (plus, the class cannot be referenced by other classes), there is no >>> useful difference between an instance field and a static field, so I think we >>> should entertain the notion of disallowing static members ? fields, methods, or >>> even member classes (although things that are implicitly static, such as >>> records would obviously be allowed). >>> One argument against that may be is that if an experienced Java programmer has >>> an existing small program that they want to make prettier by turning into an >>> implicit class ? implicit classes are mainly motivated by learners, but they?re >>> not *just* for them ? then the process would be made harder by disallowing >>> static members. >>> In short, I think we must allow fields, but we can think about disallowing >>> (explicitly) static members altogether. >>> ? Ron -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron.pressler at oracle.com Mon Feb 20 09:47:57 2023 From: ron.pressler at oracle.com (Ron Pressler) Date: Mon, 20 Feb 2023 09:47:57 +0000 Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> Message-ID: I was trying to understand how you tie shared variables to encapsulation and what you meant by something that students later need to unlearn, and I think I understand now. You?re okay with shared mutable state as long as it?s clear that it?s not shared with the whole world but only with some explicit unit, and since an implicit class appears to be the whole world, then its fields seem to be globally shared, and that?s what you want to avoid your students learning. Is that correct? Now, we?re not in the business of telling teachers how to teach, and I assume different teachers teach in different ways. Implicit classes are not exclusively a teaching construct, but a natural Java construct ? a natural extension of implicit modules and packages. Expert programmers may also appreciate implicit classes just as they appreciate JShell and launching source-code programs, both of which are also explicitly motivated, at least in part, by education (see JEPs 222 and 330). That natural Java construct *allows* teachers to teach in the order and style they choose without *forcing* classes on them. Some teachers may teach just basic control flow and (local) variables, perhaps records, and treat List, Map, and Set as built-in constructs without teaching any OOP in the first course and without teaching students how they can implement their own Lists etc. Some may choose to show shared variables (even if only to demonstrate their danger) while some may choose not to, although I assume everyone will teach constants. If you want to teach mutable fields only after introducing classes, that?s great and you can certainly do that (perhaps while enjoying the enhanced main and postponing static). But I don?t think the language should enforce a particular teaching style, where shared mutable state *must* be taught only in the context of classes. Even if you believe that doing otherwise is bad pedagogy, there is nothing that fundamentally ties shared variables to the ability to create class instances. It?s true that we don?t want to cause harm by letting beginners learn something that needs to later be unlearned, but that?s not the case even for those who do learn about mutable fields. If students begin with implicit classes and seem to think that fields (if taught them) ? or methods for that matter ? are shared with the whole world, they invariably later learn that their ?whole world? is actually a unit and that big programs are made by composing such units. They inevitably learn that because Java offers no other way. They *can?t* create a global variable, nor a global method, because Java simply doesn?t have those. Even if Java were to someday acquire package-level fields and methods (or even, hypothetically, module-level methods and fields), it still wouldn?t have a global namespace (not even for classes!). Learning that basic fact doesn?t require any unlearning, just contextualising. So we're giving teachers more freedom than ever before to teach Java in the manner each of them chooses, and I don?t think we?re inflicting any harm in the process. I think that restricting the abilities of implicit classes further forces a particular teaching style ? though some may consider it the only correct style ? and would also be a less natural Java construct and a less enjoyable one for experienced programmers. ? Ron On 18 Feb 2023, at 07:11, forax at univ-mlv.fr wrote: yes. from my experience, the time to introduce the notion of class is when you start to have shared mutable state. What i do not like with the implicit class proposal is the fact that you can have fields without defining the class around. But i think there is a solution. What about the feature being renamed to "implicit record" instead of "implicit class" ? We have no discuss why the container of an implicit "class" has to be a class instead of an annotation, an interface, an enum or a record. Having the container to be an annotation is useless given that an annotation can not have a main. If the container is an interface, methods are abstract by default which is not what we want. If the container is an enum, then we are closer to the idea of Ron that it is a singleton, especially if the container defined one implicit enum member like "SINGLETON" . An enum can not be inherited and the default constructor is private which is are nice properties. if the container is a record with no component, it can not be inherited, the constructor is package visible and more importantly to me, a user can not defined instance fields ... I prefer implicit record to implicit class because with a record as container you can not introduce a shared mutable state by error, you have at least to write static in front of the field. I dread about students being able to write code like this String name; void setName(String name) { this.name = name; } void hello() { System.out.println(name); } void main() { setName("Bob"); ... hello(); } i.e to be able to declare mutable shared state without a class around (@Ron without class encapsulation). At least if the container is a record, "name" in the example above has to be static, from the student POV, an unusual variable. An implicit record has also the advantage that you do not have to introduce the notion of class to explain the notion of implicit container, given that records are far simpler at the beginning than class, having the implicit container being a record make sense because it's records all the way down. What do you think about having the implicit container being a record instead of a class ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Mon Feb 20 12:08:47 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Mon, 20 Feb 2023 13:08:47 +0100 (CET) Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> Message-ID: <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> > From: "Ron Pressler" > To: "Remi Forax" > Cc: "Dan Heidinga" , "Brian Goetz" > , "amber-spec-experts" > Sent: Monday, February 20, 2023 10:47:57 AM > Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main > Methods (Preview) > I was trying to understand how you tie shared variables to encapsulation and > what you meant by something that students later need to unlearn, and I think I > understand now. You?re okay with shared mutable state as long as it?s clear > that it?s not shared with the whole world but only with some explicit unit, and > since an implicit class appears to be the whole world, then its fields seem to > be globally shared, and that?s what you want to avoid your students learning. > Is that correct? yes. But it's one of the arguments. The real problem is dangling fields. Conceptually fields are far more "attached" to a class than methods (at least until you explain classes) but syntactically with an implicit class, you do not see that. Allowing dangling fields force the teacher to explain what an implicit class is which defeat the teaching purpose of it. > Now, we?re not in the business of telling teachers how to teach, and I assume > different teachers teach in different ways. Implicit classes are not > exclusively a teaching construct, but a natural Java construct ? a natural > extension of implicit modules and packages. Agree, but there are some fundamentals, introducing fields without the notion of class is hard to envision. > Expert programmers may also appreciate implicit classes just as they appreciate > JShell and launching source-code programs, both of which are also explicitly > motivated, at least in part, by education (see JEPs 222 and 330). yes, Here we are discussing about ergonomics, i.e. is the "natural" extension is implicit class or implicit record ? With JEP 330, it's fear easier to create one file scripts written in Java instead of Python mostly because Python on Windows does not work as well as Python on Linux. I've seen several of those scripts on github, and there are not all using "class" as the top-level containers, some are using "interface", i've not seen a lot of scripts using records but record is a more novel construct. Implicit class is not necessary the right default. > That natural Java construct *allows* teachers to teach in the order and style > they choose without *forcing* classes on them. Some teachers may teach just > basic control flow and (local) variables, perhaps records, and treat List, Map, > and Set as built-in constructs without teaching any OOP in the first course and > without teaching students how they can implement their own Lists etc. Some may > choose to show shared variables (even if only to demonstrate their danger) > while some may choose not to, although I assume everyone will teach constants. > If you want to teach mutable fields only after introducing classes, that?s > great and you can certainly do that (perhaps while enjoying the enhanced main > and postponing static). But I don?t think the language should enforce a > particular teaching style, where shared mutable state *must* be taught only in > the context of classes. Even if you believe that doing otherwise is bad > pedagogy, there is nothing that fundamentally ties shared variables to the > ability to create class instances. Agree, i'm not suggesting that there is a right way to teach, i'm too old for that :) Before implicit class, introducing field declarations without classes is not something that was possible, so dangling fields is a new feature. As a teacher, the main reason to not allow dangling fields is that it creates confusion between local variables and fields which is a real issue students wrestle with. Also, as a side remark, implicit class/record also creates new challenges from the teaching perspective, by example, you have to postpone explaining static quite a bit otherwise if you explain that main() can be a static method too soon, students will call you because this kind of code does not work static void main() { var color = new Color("blue"); // oops } class Color(String name) { ... } My point is that while i agree that having an implicit container is a good idea, it does not make necessarily teaching easier, because an implicit container is a new feature that may interact badly with the rest of the features you want to teach. > It?s true that we don?t want to cause harm by letting beginners learn something > that needs to later be unlearned, but that?s not the case even for those who do > learn about mutable fields. If students begin with implicit classes and seem to > think that fields (if taught them) ? or methods for that matter ? are shared > with the whole world, they invariably later learn that their ?whole world? is > actually a unit and that big programs are made by composing such units. They > inevitably learn that because Java offers no other way. They *can?t* create a > global variable, nor a global method, because Java simply doesn?t have those. > Even if Java were to someday acquire package-level fields and methods (or even, > hypothetically, module-level methods and fields), it still wouldn?t have a > global namespace (not even for classes!). Learning that basic fact doesn?t > require any unlearning, just contextualising. Everything is encapsulated in Java, but dangling fields syntactically does not show that, that the issue. > So we're giving teachers more freedom than ever before to teach Java in the > manner each of them chooses, and I don?t think we?re inflicting any harm in the > process. I think that restricting the abilities of implicit classes further > forces a particular teaching style ? though some may consider it the only > correct style ? and would also be a less natural Java construct and a less > enjoyable one for experienced programmers. The point is to teach Java, not to have to teach yet another new feature. Offering new freedom also implies introducing new complexity. > ? Ron R?mi >> On 18 Feb 2023, at 07:11, [ mailto:forax at univ-mlv.fr | >> forax at univ-mlv.fr ] wrote: >> yes. >> from my experience, the time to introduce the notion of class is when you start >> to have shared mutable state. What i do not like with the implicit class >> proposal is the fact that you can have fields without defining the class >> around. >> But i think there is a solution. >> What about the feature being renamed to "implicit record" instead of "implicit >> class" ? We have no discuss why the container of an implicit "class" has to be >> a class instead of an annotation, an interface, an enum or a record. >> Having the container to be an annotation is useless given that an annotation can >> not have a main. >> If the container is an interface, methods are abstract by default which is not >> what we want. >> If the container is an enum, then we are closer to the idea of Ron that it is a >> singleton, especially if the container defined one implicit enum member like >> "SINGLETON" . An enum can not be inherited and the default constructor is >> private which is are nice properties. >> if the container is a record with no component, it can not be inherited, the >> constructor is package visible and more importantly to me, a user can not >> defined instance fields ... >> I prefer implicit record to implicit class because with a record as container >> you can not introduce a shared mutable state by error, you have at least to >> write static in front of the field. >> I dread about students being able to write code like this >> String name; >> void setName(String name) { this.name = name; } >> void hello() { System.out.println(name); } >> void main() { >> setName("Bob"); >> ... >> hello(); >> } >> i.e to be able to declare mutable shared state without a class around (@Ron >> without class encapsulation). >> At least if the container is a record, "name" in the example above has to be >> static, from the student POV, an unusual variable. >> An implicit record has also the advantage that you do not have to introduce the >> notion of class to explain the notion of implicit container, given that records >> are far simpler at the beginning than class, having the implicit container >> being a record make sense because it's records all the way down. >> What do you think about having the implicit container being a record instead of >> a class ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Mon Feb 20 16:02:14 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Mon, 20 Feb 2023 10:02:14 -0600 Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <2136214178.23753083.1676485125876.JavaMail.zimbra@u-pem.fr> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> Message-ID: On Mon, Feb 20, 2023 at 3:48 AM Ron Pressler wrote: > So we're giving teachers more freedom than ever before to teach Java in > the manner each of them chooses, and I don?t think we?re inflicting any > harm in the process. I think that restricting the abilities of implicit > classes further forces a particular teaching style ? though some may > consider it the only correct style ? and would also be a less natural Java > construct and a less enjoyable one for experienced programmers. > I agree with this. It's the teacher's job to gradually widen the student's exposure in a logical and natural way. It's not the language's job to provide a "one true path" for doing so. This change just provides more flexibility for the teacher. In my personal experience as a student, the ideal way for this process to play out is this: OK so I've learned some subset S of the domain. After working through some examples and problems within that domain, I come to my own intuitive, vague realization that a new concept X is needed ("Hmm... how am I supposed to ...?"). Then the teacher reveals the next incremental level of exposure S' ? S which guess what! just happens to contain X. Likely candidates for X: static fields... non-local (labeled) break/continue... threads... etc. -Arche -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Feb 20 18:57:53 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 20 Feb 2023 13:57:53 -0500 Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <9BE50AA3-A975-4329-911E-0BBE5E7F9CA1@oracle.com> <1833833492.24510423.1676583673273.JavaMail.zimbra@u-pem.fr> <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> Message-ID: <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> So, I think you're bringing a mental model of "field" that might not be warranted. In the context of an implicit class, all the members are effectively private, because the class is synthetic and therefore ordinary code can't call the constructor, access static members, use the class literal Foo.class, etc.? So the members of an unnamed class are accessible from the implicit class only, even if they are public (because the class name is a secret from everyone but the launcher.) So to that end, you can start by teaching about statements: ??? System.out.println("Foo!") and that statements live in methods ??? void main() { ? ?? ?? System.out.println("Foo!") ??? } and that methods can call methods: ??? void greet() { System.out.println("Foo!") ??? } ??? void main() { ? ?? ?? greet(); ??? } and that methods can access variables: ??? int greetCount = 0; void greet() { System.out.println("Foo!"); ??????? ++greetCount; ??? } ??? void main() { ? ?? ?? greet(); ??????? greet(); ??????? System.out.println(STR."Now I've said it \{greetCount} times"); ??? } From the perspective of a first-day student, the methods and variables are a sea of local members that can see each other. Then, the curtain is pulled back, to reveal that these variables and methods are actually instance members on some instance of some class, which can be given a name and operated on from the outside. On 2/20/2023 7:08 AM, forax at univ-mlv.fr wrote: > > > ------------------------------------------------------------------------ > > *From: *"Ron Pressler" > *To: *"Remi Forax" > *Cc: *"Dan Heidinga" , "Brian Goetz" > , "amber-spec-experts" > > *Sent: *Monday, February 20, 2023 10:47:57 AM > *Subject: *Re: Implicit Record Was: JEP draft: Implicit Classes > and Enhanced Main Methods (Preview) > > I was trying to understand how you tie shared variables to > encapsulation and what you meant by something that students later > need to unlearn, and I think I understand now. You?re okay with > shared mutable state as long as it?s clear that it?s not shared > with the whole world but only with some explicit unit, and since > an implicit class appears to be the whole world, then its fields > seem to be globally shared, and that?s what you want to avoid your > students learning. Is that correct? > > > yes. But it's one of the arguments. > > The real problem is dangling fields. Conceptually fields are far more > "attached" to a class than methods (at least until you explain > classes) but syntactically with an implicit class, you do not see > that. Allowing dangling fields force the teacher to explain what an > implicit class is which defeat the teaching purpose of it. > > > Now, we?re not in the business of telling teachers how to teach, > and I assume different teachers teach in different ways. Implicit > classes are not exclusively a teaching construct, but a natural > Java construct ? a natural extension of implicit modules and > packages. > > > Agree, but there are some fundamentals, introducing fields without the > notion of class is hard to envision. > > Expert programmers may also appreciate implicit classes just as > they appreciate JShell and launching source-code programs, both of > which are also explicitly motivated, at least in part, by > education (see JEPs 222 and 330). > > > yes, > Here we are discussing about ergonomics, i.e. is the "natural" > extension is implicit class or implicit record ? > With JEP 330, it's fear easier to create one file scripts written in > Java instead of Python mostly because Python on Windows does not work > as well as Python on Linux. I've seen several of those scripts on > github, and there are not all using "class" as the top-level > containers, some are using "interface", i've not seen a lot of scripts > using records but record is a more novel construct. Implicit class is > not necessary the right default. > > > That natural Java construct *allows* teachers to teach in the > order and style they choose without *forcing* classes on them. > Some teachers may teach just basic control flow and (local) > variables, perhaps records, and treat List, Map, and Set as > built-in constructs without teaching any OOP in the first course > and without teaching students how they can implement their own > Lists etc. Some may choose to show shared variables (even if only > to demonstrate their danger) while some may choose not to, > although I assume everyone will teach constants. If you want to > teach mutable fields only after introducing classes, that?s great > and you can certainly do that (perhaps while enjoying the enhanced > main and postponing static). But I don?t think the language should > enforce a particular teaching style, where shared mutable state > *must* be taught only in the context of classes. Even if you > believe that doing otherwise is bad pedagogy, there is nothing > that fundamentally ties shared variables to the ability to create > class instances. > > > Agree, i'm not suggesting that there is a right way to teach, i'm too > old for that :) > Before implicit class, introducing field declarations without classes > is not something that was possible, so dangling fields is a new > feature. As a teacher, the main reason to not allow dangling fields is > that it creates confusion between local variables and fields which is > a real issue students wrestle with. > > Also, as a side remark, implicit class/record also creates new > challenges from the teaching perspective, by example, you have to > postpone explaining static quite a bit otherwise if you explain that > main() can be a static method too soon, students will call you because > this kind of code does not work > > ? static void main() { > ??? var color = new Color("blue");? // oops > ? } > > ? class Color(String name) { > ??? ... > ? } > > > My point is that while i agree that having an implicit container is a > good idea, it does not make necessarily teaching easier, because an > implicit container is a new feature that may interact badly with the > rest of the features you want to teach. > > > It?s true that we don?t want to cause harm by letting beginners > learn something that needs to later be unlearned, but that?s not > the case even for those who do learn about mutable fields. If > students begin with implicit classes and seem to think that fields > (if taught them) ? or methods for that matter ? are shared with > the whole world, they invariably later learn that their ?whole > world? is actually a unit and that big programs are made by > composing such units. They inevitably learn that because Java > offers no other way. They *can?t* create a global variable, nor a > global method, because Java simply doesn?t have those. Even if > Java were to someday acquire package-level fields and methods (or > even, hypothetically, module-level methods and fields), it still > wouldn?t have a global namespace (not even for classes!). Learning > that basic fact doesn?t require any unlearning, just contextualising. > > > Everything is encapsulated in Java, but dangling fields syntactically > does not show that, that the issue. > > > So we're giving teachers more freedom than ever before to teach > Java in the manner each of them chooses, and I don?t think we?re > inflicting any harm in the process. I think that restricting the > abilities of implicit classes further forces a particular teaching > style ? though some may consider it the only correct style ? and > would also be a less natural Java construct and a less enjoyable > one for experienced programmers. > > > The point is to teach Java, not to have to teach yet another new > feature. Offering new freedom also implies introducing new complexity. > > > ? Ron > > > R?mi > > > > On 18 Feb 2023, at 07:11, forax at univ-mlv.fr wrote: > > > yes. > from my experience, the time to introduce the notion of class > is when you start to have shared mutable state. What i do not > like with the implicit class proposal is the fact that you can > have fields without defining the class around. > But i think there is a solution. > > What about the feature being renamed to "implicit record" > instead of "implicit class" ? We have no discuss why the > container of an implicit "class" has to be a class instead of > an annotation, an interface, an enum or a record. > > Having the container to be an annotation is useless given that > an annotation can not have a main. > If the container is an interface, methods are abstract by > default which is not what we want. > If the container is an enum, then we are closer to the idea of > Ron that it is a singleton, especially if the container > defined one implicit enum member like "SINGLETON" . An enum > can not be inherited and the default constructor is private > which is are nice properties. > if the container is a record with no component, it can not be > inherited, the constructor is package visible and more > importantly to me, a user can not defined instance fields ... > > I prefer implicit record to implicit class because with a > record as container you can not introduce a shared mutable > state by error, you have at least to write static in front of > the field. > > I dread about students being able to write code like this > > ? String name; > > ? void setName(String name) { this.name = name; } > ? void hello() { System.out.println(name); } > ? void main() { > ??? setName("Bob"); > ??? ... > ??? hello(); > ? } > > i.e to be able to declare mutable shared state without a class > around (@Ron without class encapsulation). > At least if the container is a record, "name" in the example > above has to be static, from the student POV, an unusual variable. > > An implicit record has also the advantage that you do not have > to introduce the notion of class to explain the notion of > implicit container, given that records are far simpler at the > beginning than class, having the implicit container being a > record make sense because it's records all the way down. > > What do you think about having the implicit container being a > record instead of a class ? > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Mon Feb 20 20:19:34 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Mon, 20 Feb 2023 21:19:34 +0100 (CET) Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> Message-ID: <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> > From: "Brian Goetz" > To: "Remi Forax" , "Ron Pressler" > Cc: "Dan Heidinga" , "amber-spec-experts" > > Sent: Monday, February 20, 2023 7:57:53 PM > Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main > Methods (Preview) > So, I think you're bringing a mental model of "field" that might not be > warranted. > In the context of an implicit class, all the members are effectively private, > because the class is synthetic and therefore ordinary code can't call the > constructor, access static members, use the class literal Foo.class, etc. So > the members of an unnamed class are accessible from the implicit class only, > even if they are public (because the class name is a secret from everyone but > the launcher.) > So to that end, you can start by teaching about statements: > System.out.println("Foo!") > and that statements live in methods > void main() { > System.out.println("Foo!") > } > and that methods can call methods: > void greet() { > System.out.println("Foo!") > } > void main() { > greet(); > } > and that methods can access variables: > int greetCount = 0; > void greet() { > System.out.println("Foo!"); > ++greetCount; > } > void main() { > greet(); > greet(); > System.out.println(STR."Now I've said it \{greetCount} times"); > } > From the perspective of a first-day student, the methods and variables are a sea > of local members that can see each other. > Then, the curtain is pulled back, to reveal that these variables and methods are > actually instance members on some instance of some class, which can be given a > name and operated on from the outside. As i said earlier, it does not work because fields and local variables have different semantics, fields are initialized with a default value while local variables need to be initialized before use. So the curtain is just a veil that will be pierced by any students moving declarations around. >From my personal experience, unifying local variable and field leads to more pain than gain, mostly because local variables are not shared while fields are. And as an anecdote, i've added a slide in my latest Valhalla presentation re-explaining the difference between local variables and fields because i had too many basic questions when introducing the concepts of scalarization and flattening. R?mi > On 2/20/2023 7:08 AM, [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] wrote: >>> From: "Ron Pressler" [ mailto:ron.pressler at oracle.com | >>> ] >>> To: "Remi Forax" [ mailto:forax at univ-mlv.fr | ] >>> Cc: "Dan Heidinga" [ mailto:heidinga at redhat.com | ] , >>> "Brian Goetz" [ mailto:brian.goetz at oracle.com | ] , >>> "amber-spec-experts" [ mailto:amber-spec-experts at openjdk.org | >>> ] >>> Sent: Monday, February 20, 2023 10:47:57 AM >>> Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main >>> Methods (Preview) >>> I was trying to understand how you tie shared variables to encapsulation and >>> what you meant by something that students later need to unlearn, and I think I >>> understand now. You?re okay with shared mutable state as long as it?s clear >>> that it?s not shared with the whole world but only with some explicit unit, and >>> since an implicit class appears to be the whole world, then its fields seem to >>> be globally shared, and that?s what you want to avoid your students learning. >>> Is that correct? >> yes. But it's one of the arguments. >> The real problem is dangling fields. Conceptually fields are far more "attached" >> to a class than methods (at least until you explain classes) but syntactically >> with an implicit class, you do not see that. Allowing dangling fields force the >> teacher to explain what an implicit class is which defeat the teaching purpose >> of it. >>> Now, we?re not in the business of telling teachers how to teach, and I assume >>> different teachers teach in different ways. Implicit classes are not >>> exclusively a teaching construct, but a natural Java construct ? a natural >>> extension of implicit modules and packages. >> Agree, but there are some fundamentals, introducing fields without the notion of >> class is hard to envision. >>> Expert programmers may also appreciate implicit classes just as they appreciate >>> JShell and launching source-code programs, both of which are also explicitly >>> motivated, at least in part, by education (see JEPs 222 and 330). >> yes, >> Here we are discussing about ergonomics, i.e. is the "natural" extension is >> implicit class or implicit record ? >> With JEP 330, it's fear easier to create one file scripts written in Java >> instead of Python mostly because Python on Windows does not work as well as >> Python on Linux. I've seen several of those scripts on github, and there are >> not all using "class" as the top-level containers, some are using "interface", >> i've not seen a lot of scripts using records but record is a more novel >> construct. Implicit class is not necessary the right default. >>> That natural Java construct *allows* teachers to teach in the order and style >>> they choose without *forcing* classes on them. Some teachers may teach just >>> basic control flow and (local) variables, perhaps records, and treat List, Map, >>> and Set as built-in constructs without teaching any OOP in the first course and >>> without teaching students how they can implement their own Lists etc. Some may >>> choose to show shared variables (even if only to demonstrate their danger) >>> while some may choose not to, although I assume everyone will teach constants. >>> If you want to teach mutable fields only after introducing classes, that?s >>> great and you can certainly do that (perhaps while enjoying the enhanced main >>> and postponing static). But I don?t think the language should enforce a >>> particular teaching style, where shared mutable state *must* be taught only in >>> the context of classes. Even if you believe that doing otherwise is bad >>> pedagogy, there is nothing that fundamentally ties shared variables to the >>> ability to create class instances. >> Agree, i'm not suggesting that there is a right way to teach, i'm too old for >> that :) >> Before implicit class, introducing field declarations without classes is not >> something that was possible, so dangling fields is a new feature. As a teacher, >> the main reason to not allow dangling fields is that it creates confusion >> between local variables and fields which is a real issue students wrestle with. >> Also, as a side remark, implicit class/record also creates new challenges from >> the teaching perspective, by example, you have to postpone explaining static >> quite a bit otherwise if you explain that main() can be a static method too >> soon, students will call you because this kind of code does not work >> static void main() { >> var color = new Color("blue"); // oops >> } >> class Color(String name) { >> ... >> } >> My point is that while i agree that having an implicit container is a good idea, >> it does not make necessarily teaching easier, because an implicit container is >> a new feature that may interact badly with the rest of the features you want to >> teach. >>> It?s true that we don?t want to cause harm by letting beginners learn something >>> that needs to later be unlearned, but that?s not the case even for those who do >>> learn about mutable fields. If students begin with implicit classes and seem to >>> think that fields (if taught them) ? or methods for that matter ? are shared >>> with the whole world, they invariably later learn that their ?whole world? is >>> actually a unit and that big programs are made by composing such units. They >>> inevitably learn that because Java offers no other way. They *can?t* create a >>> global variable, nor a global method, because Java simply doesn?t have those. >>> Even if Java were to someday acquire package-level fields and methods (or even, >>> hypothetically, module-level methods and fields), it still wouldn?t have a >>> global namespace (not even for classes!). Learning that basic fact doesn?t >>> require any unlearning, just contextualising. >> Everything is encapsulated in Java, but dangling fields syntactically does not >> show that, that the issue. >>> So we're giving teachers more freedom than ever before to teach Java in the >>> manner each of them chooses, and I don?t think we?re inflicting any harm in the >>> process. I think that restricting the abilities of implicit classes further >>> forces a particular teaching style ? though some may consider it the only >>> correct style ? and would also be a less natural Java construct and a less >>> enjoyable one for experienced programmers. >> The point is to teach Java, not to have to teach yet another new feature. >> Offering new freedom also implies introducing new complexity. >>> ? Ron >> R?mi >>>> On 18 Feb 2023, at 07:11, [ mailto:forax at univ-mlv.fr | >>>> forax at univ-mlv.fr ] wrote: >>>> yes. >>>> from my experience, the time to introduce the notion of class is when you start >>>> to have shared mutable state. What i do not like with the implicit class >>>> proposal is the fact that you can have fields without defining the class >>>> around. >>>> But i think there is a solution. >>>> What about the feature being renamed to "implicit record" instead of "implicit >>>> class" ? We have no discuss why the container of an implicit "class" has to be >>>> a class instead of an annotation, an interface, an enum or a record. >>>> Having the container to be an annotation is useless given that an annotation can >>>> not have a main. >>>> If the container is an interface, methods are abstract by default which is not >>>> what we want. >>>> If the container is an enum, then we are closer to the idea of Ron that it is a >>>> singleton, especially if the container defined one implicit enum member like >>>> "SINGLETON" . An enum can not be inherited and the default constructor is >>>> private which is are nice properties. >>>> if the container is a record with no component, it can not be inherited, the >>>> constructor is package visible and more importantly to me, a user can not >>>> defined instance fields ... >>>> I prefer implicit record to implicit class because with a record as container >>>> you can not introduce a shared mutable state by error, you have at least to >>>> write static in front of the field. >>>> I dread about students being able to write code like this >>>> String name; >>>> void setName(String name) { this.name = name; } >>>> void hello() { System.out.println(name); } >>>> void main() { >>>> setName("Bob"); >>>> ... >>>> hello(); >>>> } >>>> i.e to be able to declare mutable shared state without a class around (@Ron >>>> without class encapsulation). >>>> At least if the container is a record, "name" in the example above has to be >>>> static, from the student POV, an unusual variable. >>>> An implicit record has also the advantage that you do not have to introduce the >>>> notion of class to explain the notion of implicit container, given that records >>>> are far simpler at the beginning than class, having the implicit container >>>> being a record make sense because it's records all the way down. >>>> What do you think about having the implicit container being a record instead of >>>> a class ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Feb 20 20:33:34 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 20 Feb 2023 15:33:34 -0500 Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> Message-ID: <70b2bfa0-607e-0cc8-85c5-8040b56dd84e@oracle.com> > > As i said earlier, it does not work because fields and local variables > have different semantics, > fields are initialized with a default value while local variables need > to be initialized before use. > So the curtain is just a veil that will be pierced by any students > moving declarations around. Of course it "works", it just might not work how you would prefer it to. Prior to learning about fields, the user can perceive local variables (declared in a method) and "shared" variables (accessible to all members of the class.)? They can learn about their characteristics.? Then, when they learn about classes and fields and accessibility, they can learn that the variables they were calling "shared" are really fields.? The distinction between locals and fields is there from the beginning, though for most use cases, they will not notice the difference.? When they're ready to learn the fine differences, there's not anything to unlearn. > From my personal experience, unifying local variable and field leads > to more pain than gain, mostly because local Who said anything about unification of fields and locals?? Where did you get such an idea that this is what is being proposed? First students will learn about statements.? Then they will probably learn about local variables.? They can be taught that they disappear when the method exits, and each invocation of the method gets a fresh copy.? Then they can learn about multiple methods, and then that there are variables that can be shared across methods and retain their values across method invocations, and while their declaration syntax is the same (they're both variables, after all), the _place_ in which they are declared is different (which is what makes them shared), and shared variables have slightly different characteristics (though not so different they have to learn this immediately).? They can learn the characteristics of shared variables when it makes sense to teach this.? And when the curtain is pulled back, they learn all fields have the characteristics of these shared variables. -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Mon Feb 20 21:38:12 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Mon, 20 Feb 2023 22:38:12 +0100 (CET) Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <70b2bfa0-607e-0cc8-85c5-8040b56dd84e@oracle.com> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> <70b2bfa0-607e-0cc8-85c5-8040b56dd84e@oracle.com> Message-ID: <1063786217.26511085.1676929092386.JavaMail.zimbra@u-pem.fr> > From: "Brian Goetz" > To: "Remi Forax" > Cc: "Ron Pressler" , "Dan Heidinga" > , "amber-spec-experts" > Sent: Monday, February 20, 2023 9:33:34 PM > Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main > Methods (Preview) >> As i said earlier, it does not work because fields and local variables have >> different semantics, >> fields are initialized with a default value while local variables need to be >> initialized before use. >> So the curtain is just a veil that will be pierced by any students moving >> declarations around. > Of course it "works", it just might not work how you would prefer it to. var greetings = 0; does not work, void main() { int greetings; System.out.println(greetings); } does not work, void main() { static int greetings; System.out.println(greetings); } does not work, void main() { int greetings = 0; for(;;) { int greetings = 0; } } does not work too. Scope rules are different, being static is different, initialization rules are different, inference rules are different, even colors in IDEs are different. > Prior to learning about fields, the user can perceive local variables (declared > in a method) and "shared" variables (accessible to all members of the class.) > They can learn about their characteristics. Then, when they learn about classes > and fields and accessibility, they can learn that the variables they were > calling "shared" are really fields. The distinction between locals and fields > is there from the beginning, though for most use cases, they will not notice > the difference. When they're ready to learn the fine differences, there's not > anything to unlearn. >> From my personal experience, unifying local variable and field leads to more >> pain than gain, mostly because local > Who said anything about unification of fields and locals? Where did you get such > an idea that this is what is being proposed? You did, by re-using the term "variables" for both local variable and fields. > First students will learn about statements. Then they will probably learn about > local variables. They can be taught that they disappear when the method exits, > and each invocation of the method gets a fresh copy. Then they can learn about > multiple methods, and then that there are variables that can be shared across > methods and retain their values across method invocations, and while their > declaration syntax is the same (they're both variables, after all), the _place_ > in which they are declared is different (which is what makes them shared), and > shared variables have slightly different characteristics (though not so > different they have to learn this immediately). They can learn the > characteristics of shared variables when it makes sense to teach this. And when > the curtain is pulled back, they learn all fields have the characteristics of > these shared variables. Record components behave as you said, they have slightly different characteristics than local variables and it's hard to not notice the difference syntactically. record Hello(String name) { void hello() { System.out.println("hello " + name); } void bonjour() { System.out.println("bonjour " + name); } } Class fields are far more different than just the lifetime but have a very similar syntax. R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Feb 20 23:33:31 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 20 Feb 2023 18:33:31 -0500 Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <1063786217.26511085.1676929092386.JavaMail.zimbra@u-pem.fr> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <1440828976.25298762.1676704289209.JavaMail.zimbra@u-pem.fr> <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> <70b2bfa0-607e-0cc8-85c5-8040b56dd84e@oracle.com> <1063786217.26511085.1676929092386.JavaMail.zimbra@u-pem.fr> Message-ID: <3c5c7e85-cc8d-c6aa-1b77-e70235272047@oracle.com> You seem to have a very strange notion of what "works" means.? These all work just fine.? No one is suggesting that local and "shared" variables are unified.? If you find it confusing to teach fields early, then wait -- that's one of the choices. > Scope rules are different, being static is different, initialization > rules are different, inference rules are different, even colors in > IDEs are different. Correct, and well understood.? Your point? > You did, by re-using the term "variables" for both local variable and > fields. Sorry, no.? They are both variables, but they are different sorts. Just like "instance vs static" variables, or "final vs mutable" variables.? They are all variables (they have a name, and a type, and hold a value), and yet they each have different characteristics (and the characteristics can be combined; you can have shared final static variables, and local mutable variables, and....) I think you're taking a "I would prefer it work this way" and bootstrapping it into "the alternative is broken" (that's what "doesn't work" means.)? You should know by now that this is the best way to not have your arguments taken seriously! On 2/20/2023 4:38 PM, forax at univ-mlv.fr wrote: > > > ------------------------------------------------------------------------ > > *From: *"Brian Goetz" > *To: *"Remi Forax" > *Cc: *"Ron Pressler" , "Dan Heidinga" > , "amber-spec-experts" > > *Sent: *Monday, February 20, 2023 9:33:34 PM > *Subject: *Re: Implicit Record Was: JEP draft: Implicit Classes > and Enhanced Main Methods (Preview) > > > > As i said earlier, it does not work because fields and local > variables have different semantics, > fields are initialized with a default value while local > variables need to be initialized before use. > So the curtain is just a veil that will be pierced by any > students moving declarations around. > > > Of course it "works", it just might not work how you would prefer > it to. > > > ? var greetings = 0; > > does not work, > > ? void main() { > ??? int greetings; > ??? System.out.println(greetings); > ? } > > does not work, > > ? void main() { > ??? static int greetings; > ??? System.out.println(greetings); > ? } > > does not work, > > ? void main() { > ? ? int greetings = 0; > ??? for(;;) { > ????? int greetings = 0; > ??? } > ? } > > does not work too. > > Scope rules are different, being static is different, initialization > rules are different, inference rules are different, even colors in > IDEs are different. > > > > Prior to learning about fields, the user can perceive local > variables (declared in a method) and "shared" variables > (accessible to all members of the class.)? They can learn about > their characteristics.? Then, when they learn about classes and > fields and accessibility, they can learn that the variables they > were calling "shared" are really fields. The distinction between > locals and fields is there from the beginning, though for most use > cases, they will not notice the difference.? When they're ready to > learn the fine differences, there's not anything to unlearn. > > From my personal experience, unifying local variable and field > leads to more pain than gain, mostly because local > > > Who said anything about unification of fields and locals? Where > did you get such an idea that this is what is being proposed? > > > You did, by re-using the term "variables" for both local variable and > fields. > > > > First students will learn about statements.? Then they will > probably learn about local variables.? They can be taught that > they disappear when the method exits, and each invocation of the > method gets a fresh copy.? Then they can learn about multiple > methods, and then that there are variables that can be shared > across methods and retain their values across method invocations, > and while their declaration syntax is the same (they're both > variables, after all), the _place_ in which they are declared is > different (which is what makes them shared), and shared variables > have slightly different characteristics (though not so different > they have to learn this immediately).? They can learn the > characteristics of shared variables when it makes sense to teach > this.? And when the curtain is pulled back, they learn all fields > have the characteristics of these shared variables. > > > Record components behave as you said, they have slightly different > characteristics than local variables and it's hard to not notice the > difference syntactically. > > record Hello(String name) { > ? void hello() { > ??? System.out.println("hello " + name); > ? } > > ? void bonjour() { > ??? System.out.println("bonjour " + name); > ? } > } > > Class fields are far more different than just the lifetime but have a > very similar syntax. > > R?mi > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Tue Feb 21 07:09:03 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Tue, 21 Feb 2023 08:09:03 +0100 (CET) Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <3c5c7e85-cc8d-c6aa-1b77-e70235272047@oracle.com> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> <70b2bfa0-607e-0cc8-85c5-8040b56dd84e@oracle.com> <1063786217.26511085.1676929092386.JavaMail.zimbra@u-pem.fr> <3c5c7e85-cc8d-c6aa-1b77-e70235272047@oracle.com> Message-ID: <110091599.26613721.1676963343011.JavaMail.zimbra@u-pem.fr> > From: "Brian Goetz" > To: "Remi Forax" > Cc: "Ron Pressler" , "Dan Heidinga" > , "amber-spec-experts" > Sent: Tuesday, February 21, 2023 12:33:31 AM > Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main > Methods (Preview) > You seem to have a very strange notion of what "works" means. These all work > just fine. No one is suggesting that local and "shared" variables are unified. > If you find it confusing to teach fields early, then wait -- that's one of the > choices. >> Scope rules are different, being static is different, initialization rules are >> different, inference rules are different, even colors in IDEs are different. > Correct, and well understood. Your point? Implicit class remove the "class" shell, so you now have two syntactically identical things that are semantically different. IMO, introducing dangling fields, a new feature in Java, does not worth the confusion it creates. >> You did, by re-using the term "variables" for both local variable and fields. > Sorry, no. They are both variables, but they are different sorts. Just like > "instance vs static" variables, or "final vs mutable" variables. They are all > variables (they have a name, and a type, and hold a value), and yet they each > have different characteristics (and the characteristics can be combined; you > can have shared final static variables, and local mutable variables, and....) > I think you're taking a "I would prefer it work this way" and bootstrapping it > into "the alternative is broken" (that's what "doesn't work" means.) You should > know by now that this is the best way to not have your arguments taken > seriously! I think you are talking about variable in general, i'm focused on local variable and fields in the context of implicit class, hence the difficulty to understand each other. Implicit class makes the syntax of fields identical to the syntax of local variables and at the same time, the way to differentiate then is to explain what an implicit class is. Again, i'm not against the notion of implicit container, i just think that implicit record makes more sense than implicit class, and i would like we discuss about that, here is example where the container leaks, void main() { System.out.println(this); } what it should print ? regards, R?mi > On 2/20/2023 4:38 PM, [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] wrote: >>> From: "Brian Goetz" [ mailto:brian.goetz at oracle.com | ] >>> To: "Remi Forax" [ mailto:forax at univ-mlv.fr | ] >>> Cc: "Ron Pressler" [ mailto:ron.pressler at oracle.com | >>> ] , "Dan Heidinga" [ mailto:heidinga at redhat.com | ] , >>> "amber-spec-experts" [ mailto:amber-spec-experts at openjdk.org | >>> ] >>> Sent: Monday, February 20, 2023 9:33:34 PM >>> Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main >>> Methods (Preview) >>>> As i said earlier, it does not work because fields and local variables have >>>> different semantics, >>>> fields are initialized with a default value while local variables need to be >>>> initialized before use. >>>> So the curtain is just a veil that will be pierced by any students moving >>>> declarations around. >>> Of course it "works", it just might not work how you would prefer it to. >> var greetings = 0; >> does not work, >> void main() { >> int greetings; >> System.out.println(greetings); >> } >> does not work, >> void main() { >> static int greetings; >> System.out.println(greetings); >> } >> does not work, >> void main() { >> int greetings = 0; >> for(;;) { >> int greetings = 0; >> } >> } >> does not work too. >> Scope rules are different, being static is different, initialization rules are >> different, inference rules are different, even colors in IDEs are different. >>> Prior to learning about fields, the user can perceive local variables (declared >>> in a method) and "shared" variables (accessible to all members of the class.) >>> They can learn about their characteristics. Then, when they learn about classes >>> and fields and accessibility, they can learn that the variables they were >>> calling "shared" are really fields. The distinction between locals and fields >>> is there from the beginning, though for most use cases, they will not notice >>> the difference. When they're ready to learn the fine differences, there's not >>> anything to unlearn. >>>> From my personal experience, unifying local variable and field leads to more >>>> pain than gain, mostly because local >>> Who said anything about unification of fields and locals? Where did you get such >>> an idea that this is what is being proposed? >> You did, by re-using the term "variables" for both local variable and fields. >>> First students will learn about statements. Then they will probably learn about >>> local variables. They can be taught that they disappear when the method exits, >>> and each invocation of the method gets a fresh copy. Then they can learn about >>> multiple methods, and then that there are variables that can be shared across >>> methods and retain their values across method invocations, and while their >>> declaration syntax is the same (they're both variables, after all), the _place_ >>> in which they are declared is different (which is what makes them shared), and >>> shared variables have slightly different characteristics (though not so >>> different they have to learn this immediately). They can learn the >>> characteristics of shared variables when it makes sense to teach this. And when >>> the curtain is pulled back, they learn all fields have the characteristics of >>> these shared variables. >> Record components behave as you said, they have slightly different >> characteristics than local variables and it's hard to not notice the difference >> syntactically. >> record Hello(String name) { >> void hello() { >> System.out.println("hello " + name); >> } >> void bonjour() { >> System.out.println("bonjour " + name); >> } >> } >> Class fields are far more different than just the lifetime but have a very >> similar syntax. >> R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From heidinga at redhat.com Tue Feb 21 13:59:59 2023 From: heidinga at redhat.com (Dan Heidinga) Date: Tue, 21 Feb 2023 08:59:59 -0500 Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <110091599.26613721.1676963343011.JavaMail.zimbra@u-pem.fr> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> <70b2bfa0-607e-0cc8-85c5-8040b56dd84e@oracle.com> <1063786217.26511085.1676929092386.JavaMail.zimbra@u-pem.fr> <3c5c7e85-cc8d-c6aa-1b77-e70235272047@oracle.com> <110091599.26613721.1676963343011.JavaMail.zimbra@u-pem.fr> Message-ID: On Tue, Feb 21, 2023 at 2:09 AM wrote: > > > ------------------------------ > > *From: *"Brian Goetz" > *To: *"Remi Forax" > *Cc: *"Ron Pressler" , "Dan Heidinga" < > heidinga at redhat.com>, "amber-spec-experts" > > *Sent: *Tuesday, February 21, 2023 12:33:31 AM > *Subject: *Re: Implicit Record Was: JEP draft: Implicit Classes and > Enhanced Main Methods (Preview) > > You seem to have a very strange notion of what "works" means. These all > work just fine. No one is suggesting that local and "shared" variables are > unified. If you find it confusing to teach fields early, then wait -- > that's one of the choices. > > Scope rules are different, being static is different, initialization rules > are different, inference rules are different, even colors in IDEs are > different. > > > Correct, and well understood. Your point? > > > Implicit class remove the "class" shell, so you now have two syntactically > identical things that are semantically different. > IMO, introducing dangling fields, a new feature in Java, does not worth > the confusion it creates. > Remi, I'm slightly confused here. A local variable is declared inside a scope (the method) and a class variable (aka field) is declared in the implicit class. There's at least an obvious visible boundary around the local variable which provides the scoping. Students will by necessity need to understanding scoping fairly early when they deal with loops: void main() { for (int i = 0; i < 10; i++) { var double = i * 2; System.out.print("" + i + "..." + double); } } "dangling fields" is the wrong mental model for this - it's fields in an implicit scope. The key concept here (IMHO) is scoping which students will face even within a method. > > > > You did, by re-using the term "variables" for both local variable and > fields. > > > Sorry, no. They are both variables, but they are different sorts. Just > like "instance vs static" variables, or "final vs mutable" variables. They > are all variables (they have a name, and a type, and hold a value), and yet > they each have different characteristics (and the characteristics can be > combined; you can have shared final static variables, and local mutable > variables, and....) > > I think you're taking a "I would prefer it work this way" and > bootstrapping it into "the alternative is broken" (that's what "doesn't > work" means.) You should know by now that this is the best way to not have > your arguments taken seriously! > > > I think you are talking about variable in general, i'm focused on local > variable and fields in the context of implicit class, hence the difficulty > to understand each other. > Implicit class makes the syntax of fields identical to the syntax of local > variables and at the same time, the way to differentiate then is to explain > what an implicit class is. > As I said above, the way to differentiate them is to talk about scoping. A local is scoped to the method it is declared in. A field is scoped to be shared by all the methods in the file (and eventually refined to be within the class). > > Again, i'm not against the notion of implicit container, i just think that > implicit record makes more sense than implicit class, and i would like we > discuss about that, > here is example where the container leaks, > > void main() { > System.out.println(this); > } > > what it should print ? > Whatever is typically printed by Object::toString . I don't think the goal is to **hide** the implicit class - we're not making this.getClass() illegal - but to take the ceremony out of the presentation so that students (and other users) can write simple programs before they need to understand class structure. --Dan > > regards, > R?mi > > > > > > On 2/20/2023 4:38 PM, forax at univ-mlv.fr wrote: > > > > ------------------------------ > > *From: *"Brian Goetz" > *To: *"Remi Forax" > *Cc: *"Ron Pressler" , > "Dan Heidinga" , > "amber-spec-experts" > > *Sent: *Monday, February 20, 2023 9:33:34 PM > *Subject: *Re: Implicit Record Was: JEP draft: Implicit Classes and > Enhanced Main Methods (Preview) > > > > As i said earlier, it does not work because fields and local variables > have different semantics, > fields are initialized with a default value while local variables need to > be initialized before use. > So the curtain is just a veil that will be pierced by any students moving > declarations around. > > > Of course it "works", it just might not work how you would prefer it to. > > > var greetings = 0; > > does not work, > > void main() { > int greetings; > System.out.println(greetings); > } > > does not work, > > void main() { > static int greetings; > System.out.println(greetings); > } > > does not work, > > void main() { > int greetings = 0; > for(;;) { > int greetings = 0; > } > } > > does not work too. > > Scope rules are different, being static is different, initialization rules > are different, inference rules are different, even colors in IDEs are > different. > > > > Prior to learning about fields, the user can perceive local variables > (declared in a method) and "shared" variables (accessible to all members of > the class.) They can learn about their characteristics. Then, when they > learn about classes and fields and accessibility, they can learn that the > variables they were calling "shared" are really fields. The distinction > between locals and fields is there from the beginning, though for most use > cases, they will not notice the difference. When they're ready to learn > the fine differences, there's not anything to unlearn. > > From my personal experience, unifying local variable and field leads to > more pain than gain, mostly because local > > > Who said anything about unification of fields and locals? Where did you > get such an idea that this is what is being proposed? > > > You did, by re-using the term "variables" for both local variable and > fields. > > > > First students will learn about statements. Then they will probably learn > about local variables. They can be taught that they disappear when the > method exits, and each invocation of the method gets a fresh copy. Then > they can learn about multiple methods, and then that there are variables > that can be shared across methods and retain their values across method > invocations, and while their declaration syntax is the same (they're both > variables, after all), the _place_ in which they are declared is different > (which is what makes them shared), and shared variables have slightly > different characteristics (though not so different they have to learn this > immediately). They can learn the characteristics of shared variables when > it makes sense to teach this. And when the curtain is pulled back, they > learn all fields have the characteristics of these shared variables. > > > Record components behave as you said, they have slightly different > characteristics than local variables and it's hard to not notice the > difference syntactically. > > record Hello(String name) { > void hello() { > System.out.println("hello " + name); > } > > void bonjour() { > System.out.println("bonjour " + name); > } > } > > Class fields are far more different than just the lifetime but have a very > similar syntax. > > R?mi > > > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Tue Feb 21 14:21:08 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Tue, 21 Feb 2023 15:21:08 +0100 (CET) Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> <70b2bfa0-607e-0cc8-85c5-8040b56dd84e@oracle.com> <1063786217.26511085.1676929092386.JavaMail.zimbra@u-pem.fr> <3c5c7e85-cc8d-c6aa-1b77-e70235272047@oracle.com> <110091599.26613721.1676963343011.JavaMail.zimbra@u-pem.fr> Message-ID: <1148019164.27012709.1676989268521.JavaMail.zimbra@u-pem.fr> > From: "Dan Heidinga" > To: "Remi Forax" > Cc: "Brian Goetz" , "Ron Pressler" > , "amber-spec-experts" > > Sent: Tuesday, February 21, 2023 2:59:59 PM > Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main > Methods (Preview) > On Tue, Feb 21, 2023 at 2:09 AM < [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr > ] > wrote: >>> From: "Brian Goetz" < [ mailto:brian.goetz at oracle.com | brian.goetz at oracle.com ] >>> > >>> To: "Remi Forax" < [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] > >>> Cc: "Ron Pressler" < [ mailto:ron.pressler at oracle.com | ron.pressler at oracle.com >>> ] >, "Dan Heidinga" < [ mailto:heidinga at redhat.com | heidinga at redhat.com ] >, >>> "amber-spec-experts" < [ mailto:amber-spec-experts at openjdk.org | >>> amber-spec-experts at openjdk.org ] > >>> Sent: Tuesday, February 21, 2023 12:33:31 AM >>> Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main >>> Methods (Preview) >>> You seem to have a very strange notion of what "works" means. These all work >>> just fine. No one is suggesting that local and "shared" variables are unified. >>> If you find it confusing to teach fields early, then wait -- that's one of the >>> choices. >>>> Scope rules are different, being static is different, initialization rules are >>>> different, inference rules are different, even colors in IDEs are different. >>> Correct, and well understood. Your point? >> Implicit class remove the "class" shell, so you now have two syntactically >> identical things that are semantically different. >> IMO, introducing dangling fields, a new feature in Java, does not worth the >> confusion it creates. > Remi, I'm slightly confused here. A local variable is declared inside a scope > (the method) and a class variable (aka field) is declared in the implicit > class. There's at least an obvious visible boundary around the local variable > which provides the scoping. Students will by necessity need to understanding > scoping fairly early when they deal with loops: > void main() { > for (int i = 0; i < 10; i++) { > var double = i * 2; > System.out.print("" + i + "..." + double); > } > } > "dangling fields" is the wrong mental model for this - it's fields in an > implicit scope. The key concept here (IMHO) is scoping which students will face > even within a method. Your idea of scoping fails because it's not how Java works, by example with a record, int value = 42; record Foo() { void bar() { System.out.println(value); // does not compile } } void main() { System.out.println(value); // ok } >>>> You did, by re-using the term "variables" for both local variable and fields. >>> Sorry, no. They are both variables, but they are different sorts. Just like >>> "instance vs static" variables, or "final vs mutable" variables. They are all >>> variables (they have a name, and a type, and hold a value), and yet they each >>> have different characteristics (and the characteristics can be combined; you >>> can have shared final static variables, and local mutable variables, and....) >>> I think you're taking a "I would prefer it work this way" and bootstrapping it >>> into "the alternative is broken" (that's what "doesn't work" means.) You should >>> know by now that this is the best way to not have your arguments taken >>> seriously! >> I think you are talking about variable in general, i'm focused on local variable >> and fields in the context of implicit class, hence the difficulty to understand >> each other. >> Implicit class makes the syntax of fields identical to the syntax of local >> variables and at the same time, the way to differentiate then is to explain >> what an implicit class is. > As I said above, the way to differentiate them is to talk about scoping. A local > is scoped to the method it is declared in. A field is scoped to be shared by > all the methods in the file (and eventually refined to be within the class). As i said above, the scoping only works for a method or a class member, not member that are implicitly static (enum, interface or record). >> Again, i'm not against the notion of implicit container, i just think that >> implicit record makes more sense than implicit class, and i would like we >> discuss about that, >> here is example where the container leaks, >> void main() { >> System.out.println(this); >> } >> what it should print ? > Whatever is typically printed by Object::toString . It can also be Enum::toString or Record::toString. > I don't think the goal is to **hide** the implicit class - we're not making > this.getClass() illegal - but to take the ceremony out of the presentation so > that students (and other users) can write simple programs before they need to > understand class structure. agree, > --Dan R?mi >> regards, >> R?mi >>> On 2/20/2023 4:38 PM, [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] wrote: >>>>> From: "Brian Goetz" [ mailto:brian.goetz at oracle.com | ] >>>>> To: "Remi Forax" [ mailto:forax at univ-mlv.fr | ] >>>>> Cc: "Ron Pressler" [ mailto:ron.pressler at oracle.com | >>>>> ] , "Dan Heidinga" [ mailto:heidinga at redhat.com | ] , >>>>> "amber-spec-experts" [ mailto:amber-spec-experts at openjdk.org | >>>>> ] >>>>> Sent: Monday, February 20, 2023 9:33:34 PM >>>>> Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main >>>>> Methods (Preview) >>>>>> As i said earlier, it does not work because fields and local variables have >>>>>> different semantics, >>>>>> fields are initialized with a default value while local variables need to be >>>>>> initialized before use. >>>>>> So the curtain is just a veil that will be pierced by any students moving >>>>>> declarations around. >>>>> Of course it "works", it just might not work how you would prefer it to. >>>> var greetings = 0; >>>> does not work, >>>> void main() { >>>> int greetings; >>>> System.out.println(greetings); >>>> } >>>> does not work, >>>> void main() { >>>> static int greetings; >>>> System.out.println(greetings); >>>> } >>>> does not work, >>>> void main() { >>>> int greetings = 0; >>>> for(;;) { >>>> int greetings = 0; >>>> } >>>> } >>>> does not work too. >>>> Scope rules are different, being static is different, initialization rules are >>>> different, inference rules are different, even colors in IDEs are different. >>>>> Prior to learning about fields, the user can perceive local variables (declared >>>>> in a method) and "shared" variables (accessible to all members of the class.) >>>>> They can learn about their characteristics. Then, when they learn about classes >>>>> and fields and accessibility, they can learn that the variables they were >>>>> calling "shared" are really fields. The distinction between locals and fields >>>>> is there from the beginning, though for most use cases, they will not notice >>>>> the difference. When they're ready to learn the fine differences, there's not >>>>> anything to unlearn. >>>>>> From my personal experience, unifying local variable and field leads to more >>>>>> pain than gain, mostly because local >>>>> Who said anything about unification of fields and locals? Where did you get such >>>>> an idea that this is what is being proposed? >>>> You did, by re-using the term "variables" for both local variable and fields. >>>>> First students will learn about statements. Then they will probably learn about >>>>> local variables. They can be taught that they disappear when the method exits, >>>>> and each invocation of the method gets a fresh copy. Then they can learn about >>>>> multiple methods, and then that there are variables that can be shared across >>>>> methods and retain their values across method invocations, and while their >>>>> declaration syntax is the same (they're both variables, after all), the _place_ >>>>> in which they are declared is different (which is what makes them shared), and >>>>> shared variables have slightly different characteristics (though not so >>>>> different they have to learn this immediately). They can learn the >>>>> characteristics of shared variables when it makes sense to teach this. And when >>>>> the curtain is pulled back, they learn all fields have the characteristics of >>>>> these shared variables. >>>> Record components behave as you said, they have slightly different >>>> characteristics than local variables and it's hard to not notice the difference >>>> syntactically. >>>> record Hello(String name) { >>>> void hello() { >>>> System.out.println("hello " + name); >>>> } >>>> void bonjour() { >>>> System.out.println("bonjour " + name); >>>> } >>>> } >>>> Class fields are far more different than just the lifetime but have a very >>>> similar syntax. >>>> R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron.pressler at oracle.com Tue Feb 21 15:25:06 2023 From: ron.pressler at oracle.com (Ron Pressler) Date: Tue, 21 Feb 2023 15:25:06 +0000 Subject: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) In-Reply-To: <110091599.26613721.1676963343011.JavaMail.zimbra@u-pem.fr> References: <30B6BE7C-6266-4FB4-970C-FABEB502FE83@oracle.com> <1142141435.26252155.1676894927124.JavaMail.zimbra@u-pem.fr> <9a6714ad-9a69-f0eb-f173-534951fe95a8@oracle.com> <235253077.26502897.1676924374598.JavaMail.zimbra@u-pem.fr> <70b2bfa0-607e-0cc8-85c5-8040b56dd84e@oracle.com> <1063786217.26511085.1676929092386.JavaMail.zimbra@u-pem.fr> <3c5c7e85-cc8d-c6aa-1b77-e70235272047@oracle.com> <110091599.26613721.1676963343011.JavaMail.zimbra@u-pem.fr> Message-ID: <2D019858-DAF5-4A6D-8048-8F1123030E39@oracle.com> I don't see how fields and locals are more easily distinguished by the presence of a class declaration around them ? in both cases, things not inside the method belong to an outer scope ? nor do I understand why you?d want to emphasise the ?instanceness? of an implicit class instance by highlighting `this`. But what I think doesn?t matter; I?m sure that you teach well, and if you don?t want to teach fields before teaching classes ? don?t. But I don?t think that your style, however effective, is universal among teachers. Some even avoid teaching OOP in the first term. I think the criteria for judging this change are: 1. Does it promote a ?bad" programming style that would later be discouraged? 2. Does it give teachers significantly more freedom to teach how they choose and addresses the particular problems teachers have complained about? 3. Is it a natural extension of Java? I think that you agree that the answer to 1 is no and the answers to 2 and 3 is yes, but you point out that some styles of teaching may not be helped by every aspect of the change. I could agree with you completely yet still not see why it matters, unless there?s a way to allow *all* reasonable teaching styles while reducing possible confusion further. I don?t think that disallowing fields achieves that. For one, it makes defining constants very hard. For another, there are valid uses even of mutable shared variables that don?t involve classes. I don?t see how we can help one valid teaching style without harming another or making the feature less natural (e.g. it?s possible that making all members of an implicit class static would make some things easier, but it would harm the gradual-growth goal). Implicit classes are not meant as a ?subset of Java for teaching?. They?re a mechanism that allows teachers to choose what parts of Java they want to teach and when (and allows Java veterans to write small programs more pleasantly). In particular, it allows teachers such as yourself to choose when to introduce fields. ? Ron On 21 Feb 2023, at 07:09, forax at univ-mlv.fr wrote: ________________________________ From: "Brian Goetz" > To: "Remi Forax" > Cc: "Ron Pressler" >, "Dan Heidinga" >, "amber-spec-experts" > Sent: Tuesday, February 21, 2023 12:33:31 AM Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) You seem to have a very strange notion of what "works" means. These all work just fine. No one is suggesting that local and "shared" variables are unified. If you find it confusing to teach fields early, then wait -- that's one of the choices. Scope rules are different, being static is different, initialization rules are different, inference rules are different, even colors in IDEs are different. Correct, and well understood. Your point? Implicit class remove the "class" shell, so you now have two syntactically identical things that are semantically different. IMO, introducing dangling fields, a new feature in Java, does not worth the confusion it creates. You did, by re-using the term "variables" for both local variable and fields. Sorry, no. They are both variables, but they are different sorts. Just like "instance vs static" variables, or "final vs mutable" variables. They are all variables (they have a name, and a type, and hold a value), and yet they each have different characteristics (and the characteristics can be combined; you can have shared final static variables, and local mutable variables, and....) I think you're taking a "I would prefer it work this way" and bootstrapping it into "the alternative is broken" (that's what "doesn't work" means.) You should know by now that this is the best way to not have your arguments taken seriously! I think you are talking about variable in general, i'm focused on local variable and fields in the context of implicit class, hence the difficulty to understand each other. Implicit class makes the syntax of fields identical to the syntax of local variables and at the same time, the way to differentiate then is to explain what an implicit class is. Again, i'm not against the notion of implicit container, i just think that implicit record makes more sense than implicit class, and i would like we discuss about that, here is example where the container leaks, void main() { System.out.println(this); } what it should print ? regards, R?mi On 2/20/2023 4:38 PM, forax at univ-mlv.fr wrote: ________________________________ From: "Brian Goetz" To: "Remi Forax" Cc: "Ron Pressler" , "Dan Heidinga" , "amber-spec-experts" Sent: Monday, February 20, 2023 9:33:34 PM Subject: Re: Implicit Record Was: JEP draft: Implicit Classes and Enhanced Main Methods (Preview) As i said earlier, it does not work because fields and local variables have different semantics, fields are initialized with a default value while local variables need to be initialized before use. So the curtain is just a veil that will be pierced by any students moving declarations around. Of course it "works", it just might not work how you would prefer it to. var greetings = 0; does not work, void main() { int greetings; System.out.println(greetings); } does not work, void main() { static int greetings; System.out.println(greetings); } does not work, void main() { int greetings = 0; for(;;) { int greetings = 0; } } does not work too. Scope rules are different, being static is different, initialization rules are different, inference rules are different, even colors in IDEs are different. Prior to learning about fields, the user can perceive local variables (declared in a method) and "shared" variables (accessible to all members of the class.) They can learn about their characteristics. Then, when they learn about classes and fields and accessibility, they can learn that the variables they were calling "shared" are really fields. The distinction between locals and fields is there from the beginning, though for most use cases, they will not notice the difference. When they're ready to learn the fine differences, there's not anything to unlearn. From my personal experience, unifying local variable and field leads to more pain than gain, mostly because local Who said anything about unification of fields and locals? Where did you get such an idea that this is what is being proposed? You did, by re-using the term "variables" for both local variable and fields. First students will learn about statements. Then they will probably learn about local variables. They can be taught that they disappear when the method exits, and each invocation of the method gets a fresh copy. Then they can learn about multiple methods, and then that there are variables that can be shared across methods and retain their values across method invocations, and while their declaration syntax is the same (they're both variables, after all), the _place_ in which they are declared is different (which is what makes them shared), and shared variables have slightly different characteristics (though not so different they have to learn this immediately). They can learn the characteristics of shared variables when it makes sense to teach this. And when the curtain is pulled back, they learn all fields have the characteristics of these shared variables. Record components behave as you said, they have slightly different characteristics than local variables and it's hard to not notice the difference syntactically. record Hello(String name) { void hello() { System.out.println("hello " + name); } void bonjour() { System.out.println("bonjour " + name); } } Class fields are far more different than just the lifetime but have a very similar syntax. R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From angelos.bimpoudis at oracle.com Wed Feb 22 14:34:22 2023 From: angelos.bimpoudis at oracle.com (Angelos Bimpoudis) Date: Wed, 22 Feb 2023 14:34:22 +0000 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: Coming back to the topic of dominance for a moment before I circulate a revised draft spec. Dominance is the way of pattern matching to detect dead code (meaning that code on the RHS of a dominated case will never be executed, provably). Assume the example where Number dominates Integer--all values of Integer are going to be matched by a proceeding case, Number. This is a compile-time error. Additionally notice that all binding variables happen to be unused. switch (o) { case Number n -> 1; case String s -> 2; case Integer i -> 2; } Under this JEP this code could be rewritten blindly into: switch (o) { case Number _ -> 1; case String _, Integer _-> 2; } Under the definition of dead code above, the common case that was grouped together, -> 2, is not dead anymore. It can be reached via *case String _*, Integer _-> 2. As a result, the code above is correct. It just happens that the sub-pattern Integer _ will never be reachable. This can be a warning but the overall case is correct. An alternative interpretation would be to treat sub-patterns as "dead code". Under that interpretation the second case of the second example would be dominated because there is at least one preceding sub-pattern (or whole case label with one pattern as in this case) that dominates at least one of its sub-patterns (Integer _). That case could be rejected (symmetrically to the first example). This seems restrictive but also a valid direction. So, my question is what would be the pros and cons of each approach? Many, thanks, Aggelos ________________________________ From: Brian Goetz Sent: 26 January 2023 20:33 To: Angelos Bimpoudis ; amber-spec-experts Subject: Re: Draft JLS Spec about unnamed patterns and variables Small wording nit... in "an unnamed declaration can be used in place of the following declarations" I'm not sure "in place of" is the right wording; I think you may just want to say "in", since the grammar permits it in all of these places. (What you're really doing here is signalling that there are places the grammar allows it, but the semantics do not; you are going to call these out individually in the appropriate places.) Similar for the second "in place of" in this section. In 14.11.1, I might refactor the text a little further. The second sentence of the first paragraph below is about case constants only, but now comes after you talk about case patterns or case constants: A case label has either one or more case constants, or aone or more case patterns. Every case constant must be either (1) the null literal, (2) a constant expression (15.29), or (3) the name of an enum constant (8.9.1); otherwise a compile-time error occurs. A case label that has a null case constant may have an optional default. It is a compile-time error if for any case label with more than one case patterns, any of its case patterns declares one or more pattern variables. I suggest: A case label has either one or more case constants, or aone or more case patterns. For a case label with case constants, every case constant must be either (1) the null literal, (2) a constant expression (15.29), or (3) the name of an enum constant (8.9.1); otherwise a compile-time error occurs. A case label that has a null case constant may have an optional default. For a case label with case patterns, it is a compile-time error if any of its case patterns declares one or more pattern variables. I am not sure about the definition of dominance here. If I have: case Integer _, String _: A; case Number _ : B; Number dominates Integer, but it doesn't dominate Integer|String. I think you mean "if at least one of pi..pn dominates *all* of the patterns ri..rm, no? But I'm not even sure if this is the right formulation, because: sealed interface I permits A, B { } record A() implements I {} record B() implements I {} case A _, B _: ... case I i: ... The first case label dominates I. So I think you have to appeal to exhaustiveness: "A case label with case patterns p1...pm dominates another case label with case patterns q1...qm if the set of patterns { p1..pm } dominates each qi", no? You probably have to slightly refactor the second statement about "compile time error if dominance" accordingly. On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote: Dear experts, The first draft of the JLS spec about unnamed patterns and variables (https://openjdk.org/jeps/8294349) is available at: https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ Comments very much welcomed! Angelos -------------- next part -------------- An HTML attachment was scrubbed... URL: From amaembo at gmail.com Wed Feb 22 15:26:44 2023 From: amaembo at gmail.com (Tagir Valeev) Date: Wed, 22 Feb 2023 16:26:44 +0100 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: Hello! I think we should consider dead patterns as dead code, so this sample should not compile. With best regards, Tagir Valeev On Wed, Feb 22, 2023, 15:34 Angelos Bimpoudis wrote: > Coming back to the topic of dominance for a moment before I circulate a > revised draft spec. > > Dominance is the way of pattern matching to detect *dead code* (meaning > that code on the RHS of a dominated case will never be executed, provably). > > Assume the example where Number dominates Integer--all values of Integer are > going to be matched by a proceeding case, Number. This is a compile-time > error. Additionally notice that all binding variables happen to be unused. > > switch (o) { > case Number n -> 1; > case String s -> 2; > case Integer i -> 2; > } > > Under this JEP this code could be rewritten blindly into: > > switch (o) { > case Number _ -> 1; > case String _, Integer _-> 2; > } > > Under the definition of dead code above, the common case that was grouped > together, -> 2, is not dead anymore. It can be reached via *case String > _*, Integer _-> 2. As a result, the code above is correct. It just > happens that the sub-pattern Integer _ will never be reachable. This can > be a warning but the overall case is correct. > > An alternative interpretation would be to treat sub-patterns as "dead > code". Under that interpretation the second case of the second example > would be dominated because there is at least one preceding sub-pattern (or > whole case label with one pattern as in this case) that dominates at least > one of its sub-patterns (Integer _). That case could be rejected > (symmetrically to the first example). This seems restrictive but also a > valid direction. > > So, my question is what would be the pros and cons of each approach? > > > Many, thanks, > > Aggelos > > ------------------------------ > *From:* Brian Goetz > *Sent:* 26 January 2023 20:33 > *To:* Angelos Bimpoudis ; > amber-spec-experts > *Subject:* Re: Draft JLS Spec about unnamed patterns and variables > > Small wording nit... in "an unnamed declaration can be used in place of > the following declarations" > > I'm not sure "in place of" is the right wording; I think you may just want > to say "in", since the grammar permits it in all of these places. (What > you're really doing here is signalling that there are places the grammar > allows it, but the semantics do not; you are going to call these out > individually in the appropriate places.) > > Similar for the second "in place of" in this section. > > In 14.11.1, I might refactor the text a little further. The second > sentence of the first paragraph below is about case constants only, but now > comes after you talk about case patterns or case constants: > > A case label has either one or more case constants, or a*one or more* case > pattern*s*. Every case constant must be either (1) the null literal, (2) > a constant expression (15.29 > ), > or (3) the name of an enum constant (8.9.1 > ); > otherwise a compile-time error occurs. A case label that has a null case constant > may have an optional default. > > It is a compile-time error if for any case label with more than one case patterns, > any of its case patterns declares one or more pattern variables. > > > I suggest: > > A case label has either one or more case constants, or a*one or more* case > pattern*s*. > > *For a case label with case constants, *every case constant must be > either (1) the null literal, (2) a constant expression (15.29 > ), > or (3) the name of an enum constant (8.9.1 > ); > otherwise a compile-time error occurs. A case label that has a null case constant > may have an optional default. > > *For a case label with case patterns*, it is a compile-time error if any > of its case patterns declares one or more pattern variables. > > I am not sure about the definition of dominance here. If I have: > > case Integer _, String _: A; > case Number _ : B; > > Number dominates Integer, but it doesn't dominate Integer|String. I think > you mean "if at least one of pi..pn dominates *all* of the patterns ri..rm, > no? > > But I'm not even sure if this is the right formulation, because: > > sealed interface I permits A, B { } > record A() implements I {} > record B() implements I {} > > case A _, B _: ... > case I i: ... > > The first case label dominates I. So I think you have to appeal to > exhaustiveness: > > "A case label with case patterns p1...pm dominates another case label with > case patterns q1...qm if the set of patterns { p1..pm } dominates each qi", > no? > > You probably have to slightly refactor the second statement about "compile > time error if dominance" accordingly. > > > > > On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote: > > Dear experts, > > The first draft of the JLS spec about unnamed patterns and variables ( > https://openjdk.org/jeps/8294349) is available at: > > https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ > > Comments very much welcomed! > Angelos > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Wed Feb 22 15:38:51 2023 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Wed, 22 Feb 2023 09:38:51 -0600 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: On Wed, Feb 22, 2023 at 9:27 AM Tagir Valeev wrote: > I think we should consider dead patterns as dead code, so this sample > should not compile. > FWIW I agree. To me intuitively the second (grouping) example is just a "syntactically sugared" version of the first. Semantically, therefore, they should be treated the same way. -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed Feb 22 15:45:38 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 22 Feb 2023 10:45:38 -0500 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: <00cabddc-6382-2535-16a9-5ee4c4fd5591@oracle.com> It's a tricky question, because there's lots of ways to come at it.? For example, we do make a distinction between dead *statements* and dead code in general, and in particular conditionals can have lots of dead code. For example, in ??? if (true || destroyTheWorld()) { ... } we don't remark that `destroyTheWorld()` is dead code (though fine IDEs will call our attention with tasteful highlighting). We're pretty aggressive about avoiding _unreachable statements_, but considerably less aggressive about dead code in general. Thought experiment: what if we had union type patterns?? Then the case label `case String _, Integer _` would be like matching the the union type pattern `(String|Integer) _`: ??? case Number n: ... ??? case (String|Integer) _: ... Would javac then complain that `String|Integer` could be simplified to just `String` on the bsais of flow analysis? (IntelliJ would, of course.) I initially thought as Tagir did, but then Gavin turned me around and reminded me that it was not dead code, but unreachable statements that we try to avoid.? So now I am torn... On 2/22/2023 10:26 AM, Tagir Valeev wrote: > Hello! > > I think we should consider dead patterns as dead code, so this sample > should not compile. > > With best regards, > Tagir Valeev > > On Wed, Feb 22, 2023, 15:34 Angelos Bimpoudis > wrote: > > Coming back to the topic of dominance for a moment before I > circulate a revised draft spec. > > Dominance is the way of pattern matching to detect/dead > code/(meaning that code on the RHS of a dominated case will never > be executed, provably). > > Assume the example where|Number|dominates|Integer|--all values > of|Integer|are going to be matched by a proceeding case,|Number|. > This is a compile-time error. Additionally notice that all binding > variables happen to be unused. > > |switch (o) { ? ? ? case Number n -> 1; ? ? ? case String s -> 2; > ? ? ? case Integer i -> 2; } | > > Under this JEP this code could be rewritten blindly into: > > |switch (o) { ? ? ? case Number _ -> 1; ? ? ? case String _, > Integer _-> 2; } | > > Under the definition of dead code above, the common case that was > grouped together,|-> 2|, is not dead anymore. It can be reached > via|*case String _*, Integer _-> 2|. As a result, the code above > is correct. It just happens that the sub-pattern|Integer _|will > never be reachable. This can be a warning but the overall case is > correct. > > An alternative interpretation would be to treat sub-patterns as > "dead code". Under that interpretation the second|case|of the > second example would be dominated because there is at least one > preceding sub-pattern (or whole case label with one pattern as in > this case) that dominates at least one of its sub-patterns > (|Integer _|). That case could be rejected (symmetrically to the > first example). This seems restrictive but also a valid direction. > > So, my question is what would be the pros and cons of each approach? > > > Many, thanks, > > Aggelos > > > ------------------------------------------------------------------------ > *From:* Brian Goetz > *Sent:* 26 January 2023 20:33 > *To:* Angelos Bimpoudis ; > amber-spec-experts > *Subject:* Re: Draft JLS Spec about unnamed patterns and variables > Small wording nit...? in "an unnamed declaration can be used in > place of the following declarations" > > I'm not sure "in place of" is the right wording; I think you may > just want to say "in", since the grammar permits it in all of > these places.? (What you're really doing here is signalling that > there are places the grammar allows it, but the semantics do not; > you are going to call these out individually in the appropriate > places.) > > Similar for the second "in place of" in this section. > > In 14.11.1, I might refactor the text a little further.? The > second sentence of the first paragraph below is about case > constants only, but now comes after you talk about case patterns > or case constants: > >> A|case|label has either one or more|case|constants, ora*one or >> more*|case|pattern*s*. Every|case|constant must be either (1) >> the|null|literal, (2) a constant expression (15.29 >> ), >> or (3) the name of an enum constant (8.9.1 >> ); >> otherwise a compile-time error occurs. A|case|label that has >> a|null||case|constant may have an optional|default|. >> >> It is a compile-time error if for any|case|label with more than >> one|case|patterns, any of its|case|patterns declares one or more >> pattern variables. >> > > I suggest: > > A|case|label has either one or more|case|constants, ora*one or > more*|case|pattern*s*. > > /For a case label with case constants, /every|case|constant must > be either (1) the|null|literal, (2) a constant expression (15.29 > ), > or (3) the name of an enum constant (8.9.1 > ); > otherwise a compile-time error occurs. A|case|label that has > a|null||case|constant may have an optional|default|. > > /For a case label with case patterns/, it is a compile-time error > if any of its|case|patterns declares one or more pattern variables. > > I am not sure about the definition of dominance here.? If I have: > > ??? case Integer _, String _:? A; > ??? case Number _ : B; > > Number dominates Integer, but it doesn't dominate Integer|String.? > I think you mean "if at least one of pi..pn dominates *all* of the > patterns ri..rm, no? > > But I'm not even sure if this is the right formulation, because: > > ??? sealed interface I permits A, B { } > ??? record A() implements I {} > ??? record B() implements I {} > > ??? case A _, B _: ... > ??? case I i: ... > > The first case label dominates I.? So I think you have to appeal > to exhaustiveness: > > "A case label with case patterns p1...pm dominates another case > label with case patterns q1...qm if the set of patterns { p1..pm } > dominates each qi", no? > > You probably have to slightly refactor the second statement about > "compile time error if dominance" accordingly. > > > > > On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote: >> Dear experts, >> >> The first draft of the JLS spec about unnamed patterns and >> variables (https://openjdk.org/jeps/8294349) is available at: >> >> https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ >> >> Comments very much welcomed! >> Angelos > -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Wed Feb 22 16:07:27 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 22 Feb 2023 17:07:27 +0100 (CET) Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: <00cabddc-6382-2535-16a9-5ee4c4fd5591@oracle.com> References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> <00cabddc-6382-2535-16a9-5ee4c4fd5591@oracle.com> Message-ID: <577277629.27715816.1677082047731.JavaMail.zimbra@u-pem.fr> > From: "Brian Goetz" > To: "Tagir Valeev" , "Angelos Bimpoudis" > > Cc: "amber-spec-experts" > Sent: Wednesday, February 22, 2023 4:45:38 PM > Subject: Re: Draft JLS Spec about unnamed patterns and variables > It's a tricky question, because there's lots of ways to come at it. For example, > we do make a distinction between dead *statements* and dead code in general, > and in particular conditionals can have lots of dead code. > For example, in > if (true || destroyTheWorld()) { ... } > we don't remark that `destroyTheWorld()` is dead code (though fine IDEs will > call our attention with tasteful highlighting). We're pretty aggressive about > avoiding _unreachable statements_, but considerably less aggressive about dead > code in general. > Thought experiment: what if we had union type patterns? Then the case label > `case String _, Integer _` would be like matching the the union type pattern > `(String|Integer) _`: > case Number n: ... > case (String|Integer) _: ... > Would javac then complain that `String|Integer` could be simplified to just > `String` on the bsais of flow analysis? (IntelliJ would, of course.) At least, the compiler complains in a try/catch, by example try { ioCall(); } catch(IOException e) { ... } catch(FileNotFoundException | RuntimeException e) { ... } does not compile. > I initially thought as Tagir did, but then Gavin turned me around and reminded > me that it was not dead code, but unreachable statements that we try to avoid. > So now I am torn... R?mi > On 2/22/2023 10:26 AM, Tagir Valeev wrote: >> Hello! >> I think we should consider dead patterns as dead code, so this sample should not >> compile. >> With best regards, >> Tagir Valeev >> On Wed, Feb 22, 2023, 15:34 Angelos Bimpoudis < [ >> mailto:angelos.bimpoudis at oracle.com | angelos.bimpoudis at oracle.com ] > wrote: >>> Coming back to the topic of dominance for a moment before I circulate a revised >>> draft spec. >>> Dominance is the way of pattern matching to detect dead code (meaning that code >>> on the RHS of a dominated case will never be executed, provably). >>> Assume the example where Number dominates Integer --all values of Integer are >>> going to be matched by a proceeding case, Number . This is a compile-time >>> error. Additionally notice that all binding variables happen to be unused. >>> switch (o) { >>> ? ? ? case Number n -> 1; >>> ? ? ? case String s -> 2; >>> ? ? ? case Integer i -> 2; >>> } >>> Under this JEP this code could be rewritten blindly into: >>> switch (o) { >>> ? ? ? case Number _ -> 1; >>> ? ? ? case String _, Integer _-> 2; >>> } >>> Under the definition of dead code above, the common case that was grouped >>> together, -> 2 , is not dead anymore. It can be reached via *case String _*, >>> Integer _-> 2 . As a result, the code above is correct. It just happens that >>> the sub-pattern Integer _ will never be reachable. This can be a warning but >>> the overall case is correct. >>> An alternative interpretation would be to treat sub-patterns as "dead code". >>> Under that interpretation the second case of the second example would be >>> dominated because there is at least one preceding sub-pattern (or whole case >>> label with one pattern as in this case) that dominates at least one of its >>> sub-patterns ( Integer _ ). That case could be rejected (symmetrically to the >>> first example). This seems restrictive but also a valid direction. >>> So, my question is what would be the pros and cons of each approach? >>> Many, thanks, >>> Aggelos >>> From: Brian Goetz < [ mailto:brian.goetz at oracle.com | brian.goetz at oracle.com ] > >>> Sent: 26 January 2023 20:33 >>> To: Angelos Bimpoudis < [ mailto:angelos.bimpoudis at oracle.com | >>> angelos.bimpoudis at oracle.com ] >; amber-spec-experts < [ >>> mailto:amber-spec-experts at openjdk.java.net | >>> amber-spec-experts at openjdk.java.net ] > >>> Subject: Re: Draft JLS Spec about unnamed patterns and variables >>> Small wording nit... in "an unnamed declaration can be used in place of the >>> following declarations" >>> I'm not sure "in place of" is the right wording; I think you may just want to >>> say "in", since the grammar permits it in all of these places. (What you're >>> really doing here is signalling that there are places the grammar allows it, >>> but the semantics do not; you are going to call these out individually in the >>> appropriate places.) >>> Similar for the second "in place of" in this section. >>> In 14.11.1, I might refactor the text a little further. The second sentence of >>> the first paragraph below is about case constants only, but now comes after you >>> talk about case patterns or case constants: >>>> A case label has either one or more case constants, or a one or more case >>>> pattern s . Every case constant must be either (1) the null literal, (2) a >>>> constant expression ( [ >>>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.29 | >>>> 15.29 ] ), or (3) the name of an enum constant ( [ >>>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.9.1 | 8.9.1 >>>> ] ); otherwise a compile-time error occurs. A case label that has a null case >>>> constant may have an optional default . >>>> It is a compile-time error if for any case label with more than one case >>>> patterns, any of its case patterns declares one or more pattern variables. >>> I suggest: >>> A case label has either one or more case constants, or a one or more case >>> pattern s . >>> For a case label with case constants, every case constant must be either (1) the >>> null literal, (2) a constant expression ( [ >>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.29 | >>> 15.29 ] ), or (3) the name of an enum constant ( [ >>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.9.1 | 8.9.1 >>> ] ); otherwise a compile-time error occurs. A case label that has a null case >>> constant may have an optional default . >>> For a case label with case patterns , it is a compile-time error if any of its >>> case patterns declares one or more pattern variables. >>> I am not sure about the definition of dominance here. If I have: >>> case Integer _, String _: A; >>> case Number _ : B; >>> Number dominates Integer, but it doesn't dominate Integer|String. I think you >>> mean "if at least one of pi..pn dominates *all* of the patterns ri..rm, no? >>> But I'm not even sure if this is the right formulation, because: >>> sealed interface I permits A, B { } >>> record A() implements I {} >>> record B() implements I {} >>> case A _, B _: ... >>> case I i: ... >>> The first case label dominates I. So I think you have to appeal to >>> exhaustiveness: >>> "A case label with case patterns p1...pm dominates another case label with case >>> patterns q1...qm if the set of patterns { p1..pm } dominates each qi", no? >>> You probably have to slightly refactor the second statement about "compile time >>> error if dominance" accordingly. >>> On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote: >>>> Dear experts, >>>> The first draft of the JLS spec about unnamed patterns and variables ( [ >>>> https://openjdk.org/jeps/8294349 | https://openjdk.org/jeps/8294349 ] ) is >>>> available at: >>>> [ https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ | >>>> https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ ] >>>> Comments very much welcomed! >>>> Angelos -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed Feb 22 17:04:05 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 22 Feb 2023 12:04:05 -0500 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: <577277629.27715816.1677082047731.JavaMail.zimbra@u-pem.fr> References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> <00cabddc-6382-2535-16a9-5ee4c4fd5591@oracle.com> <577277629.27715816.1677082047731.JavaMail.zimbra@u-pem.fr> Message-ID: <6e59f3ab-1455-7fc8-e26c-81498d7fc8af@oracle.com> Good point (though I'd be wary of extrapolating too much from multicatch.) I think the discussion Aggelos was looking to stimulate is the one that leads to a more principled understanding of when we should and should not try to detect dead patterns.? There's no limit to what we *could* do, but we don't want to make these decisions on the basis of "hey, we could have an error here, cool", nor do we want to set in motion an endless whack-a-mole of "we complain about X, and X is like Y, but we don't complain about Y." The treatment of "domination" to detect dead cases is new with pattern matching (previously the only dead cases where "used the same constant twice".)? So to some extent we are left extrapolating from very little actual data. We do detect "same constant twice" even in lists: ??? switch (i) { ??????? case 1, 2 -> ... ??????? case 2, 3 -> ...?? // duplicate label ??? } But I'm not sure we want to bootstrap our way from that into trying too hard to detect impossible cases.? For example, suppose we had range patterns: ??? switch (i) { ??????? case 1: ... ??????? case 10: ... ??????? case 2..<=9: ... ??????? case 1..10: // dead ??? } Would we expect the compiler to do this analysis? On 2/22/2023 11:07 AM, Remi Forax wrote: > > > ------------------------------------------------------------------------ > > *From: *"Brian Goetz" > *To: *"Tagir Valeev" , "Angelos Bimpoudis" > > *Cc: *"amber-spec-experts" > *Sent: *Wednesday, February 22, 2023 4:45:38 PM > *Subject: *Re: Draft JLS Spec about unnamed patterns and variables > > It's a tricky question, because there's lots of ways to come at > it.? For example, we do make a distinction between dead > *statements* and dead code in general, and in particular > conditionals can have lots of dead code. > > For example, in > > ??? if (true || destroyTheWorld()) { ... } > > we don't remark that `destroyTheWorld()` is dead code (though fine > IDEs will call our attention with tasteful highlighting).? We're > pretty aggressive about avoiding _unreachable statements_, but > considerably less aggressive about dead code in general. > > Thought experiment: what if we had union type patterns? Then the > case label `case String _, Integer _` would be like matching the > the union type pattern `(String|Integer) _`: > > ??? case Number n: ... > ??? case (String|Integer) _: ... > > Would javac then complain that `String|Integer` could be > simplified to just `String` on the bsais of flow analysis?? > (IntelliJ would, of course.) > > > At least, the compiler complains in a try/catch, by example > > try { > ? ioCall(); > } catch(IOException e) { > ? ... > } catch(FileNotFoundException | RuntimeException e) { > ?... > } > > does not compile. > > > I initially thought as Tagir did, but then Gavin turned me around > and reminded me that it was not dead code, but unreachable > statements that we try to avoid.? So now I am torn... > > > R?mi > > > > On 2/22/2023 10:26 AM, Tagir Valeev wrote: > > Hello! > > I think we should consider dead patterns as dead code, so this > sample should not compile. > > With best regards, > Tagir Valeev > > On Wed, Feb 22, 2023, 15:34 Angelos Bimpoudis > wrote: > > Coming back to the topic of dominance for a moment before > I circulate a revised draft spec. > > Dominance is the way of pattern matching to detect/dead > code/(meaning that code on the RHS of a dominated case > will never be executed, provably). > > Assume the example where|Number|dominates|Integer|--all > values of|Integer|are going to be matched by a proceeding > case,|Number|. This is a compile-time error. Additionally > notice that all binding variables happen to be unused. > > |switch (o) { ? ? ? case Number n -> 1; ? ? ? case String > s -> 2; ? ? ? case Integer i -> 2; } | > > Under this JEP this code could be rewritten blindly into: > > |switch (o) { ? ? ? case Number _ -> 1; ? ? ? case String > _, Integer _-> 2; } | > > Under the definition of dead code above, the common case > that was grouped together,|-> 2|, is not dead anymore. It > can be reached via|*case String _*, Integer _-> 2|. As a > result, the code above is correct. It just happens that > the sub-pattern|Integer _|will never be reachable. This > can be a warning but the overall case is correct. > > An alternative interpretation would be to treat > sub-patterns as "dead code". Under that interpretation the > second|case|of the second example would be dominated > because there is at least one preceding sub-pattern (or > whole case label with one pattern as in this case) that > dominates at least one of its sub-patterns (|Integer _|). > That case could be rejected (symmetrically to the first > example). This seems restrictive but also a valid direction. > > So, my question is what would be the pros and cons of each > approach? > > > Many, thanks, > > Aggelos > > > ------------------------------------------------------------------------ > *From:* Brian Goetz > *Sent:* 26 January 2023 20:33 > *To:* Angelos Bimpoudis ; > amber-spec-experts > *Subject:* Re: Draft JLS Spec about unnamed patterns and > variables > Small wording nit...? in "an unnamed declaration can be > used in place of the following declarations" > > I'm not sure "in place of" is the right wording; I think > you may just want to say "in", since the grammar permits > it in all of these places.? (What you're really doing here > is signalling that there are places the grammar allows it, > but the semantics do not; you are going to call these out > individually in the appropriate places.) > > Similar for the second "in place of" in this section. > > In 14.11.1, I might refactor the text a little further.? > The second sentence of the first paragraph below is about > case constants only, but now comes after you talk about > case patterns or case constants: > > A|case|label has either one or more|case|constants, > ora*one or more*|case|pattern*s*. Every|case|constant > must be either (1) the|null|literal, (2) a constant > expression (15.29 > ), > or (3) the name of an enum constant (8.9.1 > ); > otherwise a compile-time error occurs. A|case|label > that has a|null||case|constant may have an > optional|default|. > > It is a compile-time error if for any|case|label with > more than one|case|patterns, any of its|case|patterns > declares one or more pattern variables. > > > I suggest: > > A|case|label has either one or more|case|constants, > ora*one or more*|case|pattern*s*. > > /For a case label with case constants, > /every|case|constant must be either (1) the|null|literal, > (2) a constant expression (15.29 > ), > or (3) the name of an enum constant (8.9.1 > ); > otherwise a compile-time error occurs. A|case|label that > has a|null||case|constant may have an optional|default|. > > /For a case label with case patterns/, it is a > compile-time error if any of its|case|patterns declares > one or more pattern variables. > > I am not sure about the definition of dominance here.? If > I have: > > ??? case Integer _, String _:? A; > ??? case Number _ : B; > > Number dominates Integer, but it doesn't dominate > Integer|String.? I think you mean "if at least one of > pi..pn dominates *all* of the patterns ri..rm, no? > > But I'm not even sure if this is the right formulation, > because: > > ??? sealed interface I permits A, B { } > ??? record A() implements I {} > ??? record B() implements I {} > > ??? case A _, B _: ... > ??? case I i: ... > > The first case label dominates I.? So I think you have to > appeal to exhaustiveness: > > "A case label with case patterns p1...pm dominates another > case label with case patterns q1...qm if the set of > patterns { p1..pm } dominates each qi", no? > > You probably have to slightly refactor the second > statement about "compile time error if dominance" accordingly. > > > > > On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote: > > Dear experts, > > The first draft of the JLS spec about unnamed patterns > and variables (https://openjdk.org/jeps/8294349) is > available at: > > https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ > > Comments very much welcomed! > Angelos > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Thu Feb 23 18:26:11 2023 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 23 Feb 2023 18:26:11 +0000 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: > Under this JEP this code could be rewritten blindly into: > > |switch (o) { ? ? ? case Number _ -> 1; ? ? ? case String _, Integer > _-> 2; } | > > Under the definition of dead code above, the common case that was > grouped together,|-> 2|, is not dead anymore. It can be reached > via|*case String _*, Integer _-> 2|. As a result, the code above is > correct. It just happens that the sub-pattern|Integer _|will never be > reachable. This can be a warning but the overall case is correct. > > An alternative interpretation would be to treat sub-patterns as "dead > code". Under that interpretation the second|case|of the second example > would be dominated because there is at least one preceding sub-pattern > (or whole case label with one pattern as in this case) that dominates > at least one of its sub-patterns (|Integer _|). That case could be > rejected (symmetrically to the first example). This seems restrictive > but also a valid direction. > > So, my question is what would be the pros and cons of each approach? > Actually, it seems to me that you can rewrite the above as follows, even w/o this JEP: |switch (o) { ? ? ? case Number n -> 1; ? ? ? case String s, Integer i-> 2; }| If you do, the compiler complains, but not because `Integer i` is unreacheable. But simply because we have fall-through between patterns. This is defined in 14.11.1: > t is a compile-time error if there is a statement in a switch block > that consists of switch-labeled statement groups for which both of the > following are true: > > 1. > > It is labeled with a switch label that introduces a pattern variable. > > 2. > > There is a statement preceding it in the switch block and that > statement can complete normally (14.22 > ). > > This condition is required to exclude the possibility of a switch > labeled statement being reached for which a pattern variable declared > in its switch label is in scope but without the pattern matching > having succeeded. For example, the statement labeled by the switch > label supporting the type pattern |Integer i| could be reached from > the preceding statement group, and so the pattern variable |i| will > not be initialized: > > || Now, you could make a case that the above restriction is unnecessary if we have unnamed pattern binding variables... and _if_ you go down that path, yes, you do end up with an issue when it comes to dominance. But do we want to change the fall-through restriction? Cheers Maurizio > > Many, thanks, > > Aggelos > > > ------------------------------------------------------------------------ > *From:* Brian Goetz > *Sent:* 26 January 2023 20:33 > *To:* Angelos Bimpoudis ; > amber-spec-experts > *Subject:* Re: Draft JLS Spec about unnamed patterns and variables > Small wording nit... in "an unnamed declaration can be used in place > of the following declarations" > > I'm not sure "in place of" is the right wording; I think you may just > want to say "in", since the grammar permits it in all of these > places.? (What you're really doing here is signalling that there are > places the grammar allows it, but the semantics do not; you are going > to call these out individually in the appropriate places.) > > Similar for the second "in place of" in this section. > > In 14.11.1, I might refactor the text a little further.? The second > sentence of the first paragraph below is about case constants only, > but now comes after you talk about case patterns or case constants: > >> A|case|label has either one or more|case|constants, ora*one or >> more*|case|pattern*s*. Every|case|constant must be either (1) >> the|null|literal, (2) a constant expression (15.29 >> ), >> or (3) the name of an enum constant (8.9.1 >> ); >> otherwise a compile-time error occurs. A|case|label that has >> a|null||case|constant may have an optional|default|. >> >> It is a compile-time error if for any|case|label with more than >> one|case|patterns, any of its|case|patterns declares one or more >> pattern variables. >> > > I suggest: > > A|case|label has either one or more|case|constants, ora*one or > more*|case|pattern*s*. > > /For a case label with case constants, /every|case|constant must be > either (1) the|null|literal, (2) a constant expression (15.29 > ), > or (3) the name of an enum constant (8.9.1 > ); > otherwise a compile-time error occurs. A|case|label that has > a|null||case|constant may have an optional|default|. > > /For a case label with case patterns/, it is a compile-time error if > any of its|case|patterns declares one or more pattern variables. > > I am not sure about the definition of dominance here.? If I have: > > ??? case Integer _, String _:? A; > ??? case Number _ : B; > > Number dominates Integer, but it doesn't dominate Integer|String.? I > think you mean "if at least one of pi..pn dominates *all* of the > patterns ri..rm, no? > > But I'm not even sure if this is the right formulation, because: > > ??? sealed interface I permits A, B { } > ??? record A() implements I {} > ??? record B() implements I {} > > ??? case A _, B _: ... > ??? case I i: ... > > The first case label dominates I.? So I think you have to appeal to > exhaustiveness: > > "A case label with case patterns p1...pm dominates another case label > with case patterns q1...qm if the set of patterns { p1..pm } dominates > each qi", no? > > You probably have to slightly refactor the second statement about > "compile time error if dominance" accordingly. > > > > > On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote: >> Dear experts, >> >> The first draft of the JLS spec about unnamed patterns and variables >> (https://openjdk.org/jeps/8294349 ) >> is available at: >> >> https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ >> >> >> Comments very much welcomed! >> Angelos > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu Feb 23 18:46:16 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 23 Feb 2023 13:46:16 -0500 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: The language about "fall through between patterns" was motivated by uncertainty about the scope of bindings.? We could have been more precise (allowing you to fall through if you don't use `s`) but that seemed to be just inviting questionable code, so it was coarsened. With the advent of binding-less patterns, it reopened the door here to both fall-through and case merging, but we really wanted the case merging.? So the spec could now be refined to "can't fall out of patterns _with bindings_." If you're asking "do we want to allow fall through here", well, while we are not big fans of fallthrough, we're also not big fans of "go out of our way to prohibit features we don't like", because that often leads to more complexity in the language.? So it seemed that treating these two things -- case merging and fall-through -- equally. On 2/23/2023 1:26 PM, Maurizio Cimadamore wrote: > >> Under this JEP this code could be rewritten blindly into: >> >> |switch (o) { ? ? ? case Number _ -> 1; ? ? ? case String _, Integer >> _-> 2; } | >> >> Under the definition of dead code above, the common case that was >> grouped together,|-> 2|, is not dead anymore. It can be reached >> via|*case String _*, Integer _-> 2|. As a result, the code above is >> correct. It just happens that the sub-pattern|Integer _|will never be >> reachable. This can be a warning but the overall case is correct. >> >> An alternative interpretation would be to treat sub-patterns as "dead >> code". Under that interpretation the second|case|of the second >> example would be dominated because there is at least one preceding >> sub-pattern (or whole case label with one pattern as in this case) >> that dominates at least one of its sub-patterns (|Integer _|). That >> case could be rejected (symmetrically to the first example). This >> seems restrictive but also a valid direction. >> >> So, my question is what would be the pros and cons of each approach? >> > Actually, it seems to me that you can rewrite the above as follows, > even w/o this JEP: > > > |switch (o) { ? ? ? case Number n -> 1; ? ? ? case String s, Integer > i-> 2; }| > > If you do, the compiler complains, but not because `Integer i` is > unreacheable. But simply because we have fall-through between patterns. > > > This is defined in 14.11.1: > >> t is a compile-time error if there is a statement in a switch block >> that consists of switch-labeled statement groups for which both of >> the following are true: >> >> 1. >> >> It is labeled with a switch label that introduces a pattern variable. >> >> 2. >> >> There is a statement preceding it in the switch block and that >> statement can complete normally (14.22 >> ). >> >> This condition is required to exclude the possibility of a switch >> labeled statement being reached for which a pattern variable declared >> in its switch label is in scope but without the pattern matching >> having succeeded. For example, the statement labeled by the switch >> label supporting the type pattern |Integer i| could be reached from >> the preceding statement group, and so the pattern variable |i| will >> not be initialized: >> >> || > Now, you could make a case that the above restriction is unnecessary > if we have unnamed pattern binding variables... and _if_ you go down > that path, yes, you do end up with an issue when it comes to dominance. > > > But do we want to change the fall-through restriction? > > > Cheers > Maurizio > > >> >> Many, thanks, >> >> Aggelos >> >> >> ------------------------------------------------------------------------ >> *From:* Brian Goetz >> *Sent:* 26 January 2023 20:33 >> *To:* Angelos Bimpoudis ; >> amber-spec-experts >> *Subject:* Re: Draft JLS Spec about unnamed patterns and variables >> Small wording nit... in "an unnamed declaration can be used in place >> of the following declarations" >> >> I'm not sure "in place of" is the right wording; I think you may just >> want to say "in", since the grammar permits it in all of these >> places.? (What you're really doing here is signalling that there are >> places the grammar allows it, but the semantics do not; you are going >> to call these out individually in the appropriate places.) >> >> Similar for the second "in place of" in this section. >> >> In 14.11.1, I might refactor the text a little further. The second >> sentence of the first paragraph below is about case constants only, >> but now comes after you talk about case patterns or case constants: >> >>> A|case|label has either one or more|case|constants, ora*one or >>> more*|case|pattern*s*. Every|case|constant must be either (1) >>> the|null|literal, (2) a constant expression (15.29 >>> ), >>> or (3) the name of an enum constant (8.9.1 >>> ); >>> otherwise a compile-time error occurs. A|case|label that has >>> a|null||case|constant may have an optional|default|. >>> >>> It is a compile-time error if for any|case|label with more than >>> one|case|patterns, any of its|case|patterns declares one or more >>> pattern variables. >>> >> >> I suggest: >> >> A|case|label has either one or more|case|constants, ora*one or >> more*|case|pattern*s*. >> >> /For a case label with case constants, /every|case|constant must be >> either (1) the|null|literal, (2) a constant expression (15.29 >> ), >> or (3) the name of an enum constant (8.9.1 >> ); >> otherwise a compile-time error occurs. A|case|label that has >> a|null||case|constant may have an optional|default|. >> >> /For a case label with case patterns/, it is a compile-time error if >> any of its|case|patterns declares one or more pattern variables. >> >> I am not sure about the definition of dominance here.? If I have: >> >> ??? case Integer _, String _:? A; >> ??? case Number _ : B; >> >> Number dominates Integer, but it doesn't dominate Integer|String.? I >> think you mean "if at least one of pi..pn dominates *all* of the >> patterns ri..rm, no? >> >> But I'm not even sure if this is the right formulation, because: >> >> ??? sealed interface I permits A, B { } >> ??? record A() implements I {} >> ??? record B() implements I {} >> >> ??? case A _, B _: ... >> ??? case I i: ... >> >> The first case label dominates I.? So I think you have to appeal to >> exhaustiveness: >> >> "A case label with case patterns p1...pm dominates another case label >> with case patterns q1...qm if the set of patterns { p1..pm } >> dominates each qi", no? >> >> You probably have to slightly refactor the second statement about >> "compile time error if dominance" accordingly. >> >> >> >> >> On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote: >>> Dear experts, >>> >>> The first draft of the JLS spec about unnamed patterns and variables >>> (https://openjdk.org/jeps/8294349 >>> ) is available at: >>> >>> https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ >>> >>> >>> Comments very much welcomed! >>> Angelos >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Thu Feb 23 18:53:21 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 23 Feb 2023 19:53:21 +0100 (CET) Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: <772542446.28508412.1677178401630.JavaMail.zimbra@u-pem.fr> > From: "Maurizio Cimadamore" > To: "Angelos Bimpoudis" , "Brian Goetz" > , "amber-spec-experts" > > Sent: Thursday, February 23, 2023 7:26:11 PM > Subject: Re: Draft JLS Spec about unnamed patterns and variables >> Under this JEP this code could be rewritten blindly into: >> switch (o) { >> ? ? ? case Number _ -> 1; >> ? ? ? case String _, Integer _-> 2; >> } >> Under the definition of dead code above, the common case that was grouped >> together, -> 2 , is not dead anymore. It can be reached via *case String _*, >> Integer _-> 2 . As a result, the code above is correct. It just happens that >> the sub-pattern Integer _ will never be reachable. This can be a warning but >> the overall case is correct. >> An alternative interpretation would be to treat sub-patterns as "dead code". >> Under that interpretation the second case of the second example would be >> dominated because there is at least one preceding sub-pattern (or whole case >> label with one pattern as in this case) that dominates at least one of its >> sub-patterns ( Integer _ ). That case could be rejected (symmetrically to the >> first example). This seems restrictive but also a valid direction. >> So, my question is what would be the pros and cons of each approach? > Actually, it seems to me that you can rewrite the above as follows, even w/o > this JEP: > switch (o) { > ? ? ? case Number n -> 1; > ? ? ? case String s, Integer i-> 2; > } > If you do, the compiler complains, but not because `Integer i` is unreacheable. > But simply because we have fall-through between patterns. > This is defined in 14.11.1: >> t is a compile-time error if there is a statement in a switch block that >> consists of switch-labeled statement groups for which both of the following are >> true: >> 1. >> It is labeled with a switch label that introduces a pattern variable. >> 2. >> There is a statement preceding it in the switch block and that statement can >> complete normally ( [ >> https://docs.oracle.com/javase/specs/jls/se18/html/jls-14.html#jls-14.22 | >> 14.22 ] ). >> This condition is required to exclude the possibility of a switch labeled >> statement being reached for which a pattern variable declared in its switch >> label is in scope but without the pattern matching having succeeded. For >> example, the statement labeled by the switch label supporting the type pattern >> Integer i could be reached from the preceding statement group, and so the >> pattern variable i will not be initialized: > Now, you could make a case that the above restriction is unnecessary if we have > unnamed pattern binding variables... and _if_ you go down that path, yes, you > do end up with an issue when it comes to dominance. > But do we want to change the fall-through restriction? yes, for me a type pattern with an unnamed variable does not introduce a pattern variable, '_' is just a notation for no variable, thus i believe, this rule does not apply. > Cheers > Maurizio regards, R?mi >> Many, thanks, >> Aggelos >> From: Brian Goetz [ mailto:brian.goetz at oracle.com | ] >> Sent: 26 January 2023 20:33 >> To: Angelos Bimpoudis [ mailto:angelos.bimpoudis at oracle.com | >> ] ; amber-spec-experts [ >> mailto:amber-spec-experts at openjdk.java.net | >> ] >> Subject: Re: Draft JLS Spec about unnamed patterns and variables >> Small wording nit... in "an unnamed declaration can be used in place of the >> following declarations" >> I'm not sure "in place of" is the right wording; I think you may just want to >> say "in", since the grammar permits it in all of these places. (What you're >> really doing here is signalling that there are places the grammar allows it, >> but the semantics do not; you are going to call these out individually in the >> appropriate places.) >> Similar for the second "in place of" in this section. >> In 14.11.1, I might refactor the text a little further. The second sentence of >> the first paragraph below is about case constants only, but now comes after you >> talk about case patterns or case constants: >>> A case label has either one or more case constants, or a one or more case >>> pattern s . Every case constant must be either (1) the null literal, (2) a >>> constant expression ( [ >>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.29 | >>> 15.29 ] ), or (3) the name of an enum constant ( [ >>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.9.1 | 8.9.1 >>> ] ); otherwise a compile-time error occurs. A case label that has a null case >>> constant may have an optional default . >>> It is a compile-time error if for any case label with more than one case >>> patterns, any of its case patterns declares one or more pattern variables. >> I suggest: >> A case label has either one or more case constants, or a one or more case >> pattern s . >> For a case label with case constants, every case constant must be either (1) the >> null literal, (2) a constant expression ( [ >> https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.29 | >> 15.29 ] ), or (3) the name of an enum constant ( [ >> https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.9.1 | 8.9.1 >> ] ); otherwise a compile-time error occurs. A case label that has a null case >> constant may have an optional default . >> For a case label with case patterns , it is a compile-time error if any of its >> case patterns declares one or more pattern variables. >> I am not sure about the definition of dominance here. If I have: >> case Integer _, String _: A; >> case Number _ : B; >> Number dominates Integer, but it doesn't dominate Integer|String. I think you >> mean "if at least one of pi..pn dominates *all* of the patterns ri..rm, no? >> But I'm not even sure if this is the right formulation, because: >> sealed interface I permits A, B { } >> record A() implements I {} >> record B() implements I {} >> case A _, B _: ... >> case I i: ... >> The first case label dominates I. So I think you have to appeal to >> exhaustiveness: >> "A case label with case patterns p1...pm dominates another case label with case >> patterns q1...qm if the set of patterns { p1..pm } dominates each qi", no? >> You probably have to slightly refactor the second statement about "compile time >> error if dominance" accordingly. >> On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote: >>> Dear experts, >>> The first draft of the JLS spec about unnamed patterns and variables ( [ >>> https://openjdk.org/jeps/8294349 | https://openjdk.org/jeps/8294349 ] ) is >>> available at: >>> [ https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ | >>> https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ ] >>> Comments very much welcomed! >>> Angelos -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Thu Feb 23 19:27:58 2023 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 23 Feb 2023 19:27:58 +0000 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: On 23/02/2023 18:46, Brian Goetz wrote: > but we really wanted the case merging. Gotcha. I just wanted to point out that there are two questions here (one about fall-through and one about domination), and when reading the emails it was not obvious to me that a change in how fall-through was defined was being proposed. If merging unrelated type tests is a goal, I think there should be an example for it in the JEP under "Motivation". Maurizio -------------- next part -------------- An HTML attachment was scrubbed... URL: From angelos.bimpoudis at oracle.com Fri Feb 24 16:23:01 2023 From: angelos.bimpoudis at oracle.com (Angelos Bimpoudis) Date: Fri, 24 Feb 2023 16:23:01 +0000 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: The main takeaways: * case Number _ can fall out to other patterns since it doesn't introduce any bindings (adjustment in the spec draft is needed) * case Number _ dominates case String _, Integer _ (adjustment is not needed in current draft, but I will double check before I circulate the revised version). Thanks for all the comments! Thought experiment: what if we had union type patterns? Then the case label `case String _, Integer _` would be like matching the the union type pattern `(String|Integer) _`: case Number n: ... case (String|Integer) _: ... Would javac then complain that `String|Integer` could be simplified to just `String` on the bsais of flow analysis? (IntelliJ would, of course.) I initially thought as Tagir did, but then Gavin turned me around and reminded me that it was not dead code, but unreachable statements that we try to avoid. So now I am torn... Would union type patterns imply the existence of union types? If yes, then, the second case could even exist with a binding, correct? In your example the LUB is Object so even the case (String|Integer) x : x.getClass() can work. The difficult scenario would arise with the case (Customer|Human) x : x.getName(); If the first case in your example did not introduce a binding, would both case be equal with Number | (String | Integer)? Union types a la Ceylon support this (http://web.mit.edu/ceylon_v1.3.3/ceylon-1.3.3/doc/en/spec/html_single/#uniontypes). On the other hand in Ceylon, the switch needs to be exhaustive and? all cases need to be disjoint. So this switch would be invalid. hm.. ________________________________ From: Maurizio Cimadamore Sent: 23 February 2023 20:27 To: Brian Goetz ; Angelos Bimpoudis ; amber-spec-experts Subject: Re: Draft JLS Spec about unnamed patterns and variables On 23/02/2023 18:46, Brian Goetz wrote: but we really wanted the case merging. Gotcha. I just wanted to point out that there are two questions here (one about fall-through and one about domination), and when reading the emails it was not obvious to me that a change in how fall-through was defined was being proposed. If merging unrelated type tests is a goal, I think there should be an example for it in the JEP under "Motivation". Maurizio -------------- next part -------------- An HTML attachment was scrubbed... URL: From gavin.bierman at oracle.com Tue Feb 28 16:15:06 2023 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Tue, 28 Feb 2023 16:15:06 +0000 Subject: Third draft spec for String Templates (JEP 430) now available In-Reply-To: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> References: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> Message-ID: <12D00B25-7539-49AE-BB6E-C00DA3E38DEE@oracle.com> Following the feedback, a small update of the String Templates Spec is now available: https://cr.openjdk.org/~gbierman/jep430/jep430-20230222/specs/string-templates-jls.html Any further comments welcomed! Thanks, Gavin On 9 Feb 2023, at 15:28, Gavin Bierman > wrote: Dear experts: A new, updated spec covering JEP 430 (String Templates) is now available at: https://cr.openjdk.java.net/~gbierman/jep430/latest This is a substantial rewrite: it now covers more fully how templates are tokenized, how to deal with ambiguities, and how text block templates are dealt with. Comments welcomed! Gavin -------------- next part -------------- An HTML attachment was scrubbed... URL: From angelos.bimpoudis at oracle.com Tue Feb 28 16:21:18 2023 From: angelos.bimpoudis at oracle.com (Angelos Bimpoudis) Date: Tue, 28 Feb 2023 16:21:18 +0000 Subject: Draft JLS Spec about primitive types in patterns, instanceof, and switch Message-ID: Dear experts, The first draft of the JLS spec about primitive types in patterns, instanceof, and switch (draft JEP at https://openjdk.org/jeps/8288476) is available at: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ Comments very much welcomed! Angelos -------------- next part -------------- An HTML attachment was scrubbed... URL: From angelos.bimpoudis at oracle.com Tue Feb 28 16:21:34 2023 From: angelos.bimpoudis at oracle.com (Angelos Bimpoudis) Date: Tue, 28 Feb 2023 16:21:34 +0000 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: Updated draft spec. Includes a small number of fixes and a correct "rebase" on top of the JLS changes resulting from JEP 432 (Record Patterns (Second Preview)) and JEP 433 (Pattern Matching for switch (Fourth Preview)) that covers Maurizio's point. https://cr.openjdk.org/~abimpoudis/unnamed/latest/ (please note that the based URL has been slightly changed ^^) Comments are always very much welcomed! Best, Angelos ________________________________ From: Angelos Bimpoudis Sent: 24 February 2023 17:23 To: Maurizio Cimadamore ; Brian Goetz ; amber-spec-experts Subject: Re: Draft JLS Spec about unnamed patterns and variables The main takeaways: * case Number _ can fall out to other patterns since it doesn't introduce any bindings (adjustment in the spec draft is needed) * case Number _ dominates case String _, Integer _ (adjustment is not needed in current draft, but I will double check before I circulate the revised version). Thanks for all the comments! Thought experiment: what if we had union type patterns? Then the case label `case String _, Integer _` would be like matching the the union type pattern `(String|Integer) _`: case Number n: ... case (String|Integer) _: ... Would javac then complain that `String|Integer` could be simplified to just `String` on the bsais of flow analysis? (IntelliJ would, of course.) I initially thought as Tagir did, but then Gavin turned me around and reminded me that it was not dead code, but unreachable statements that we try to avoid. So now I am torn... Would union type patterns imply the existence of union types? If yes, then, the second case could even exist with a binding, correct? In your example the LUB is Object so even the case (String|Integer) x : x.getClass() can work. The difficult scenario would arise with the case (Customer|Human) x : x.getName(); If the first case in your example did not introduce a binding, would both case be equal with Number | (String | Integer)? Union types a la Ceylon support this (http://web.mit.edu/ceylon_v1.3.3/ceylon-1.3.3/doc/en/spec/html_single/#uniontypes). On the other hand in Ceylon, the switch needs to be exhaustive and? all cases need to be disjoint. So this switch would be invalid. hm.. ________________________________ From: Maurizio Cimadamore Sent: 23 February 2023 20:27 To: Brian Goetz ; Angelos Bimpoudis ; amber-spec-experts Subject: Re: Draft JLS Spec about unnamed patterns and variables On 23/02/2023 18:46, Brian Goetz wrote: but we really wanted the case merging. Gotcha. I just wanted to point out that there are two questions here (one about fall-through and one about domination), and when reading the emails it was not obvious to me that a change in how fall-through was defined was being proposed. If merging unrelated type tests is a goal, I think there should be an example for it in the JEP under "Motivation". Maurizio -------------- next part -------------- An HTML attachment was scrubbed... URL: From gavin.bierman at oracle.com Tue Feb 28 16:21:42 2023 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Tue, 28 Feb 2023 16:21:42 +0000 Subject: Draft JEPs for Patterns in switch and Record Patterns Message-ID: <322686D2-BD86-4F05-BA33-C4017C772DB5@oracle.com> Hello, We are planning to finalize the two pattern matching JEPs in JDK 21. Drafts of these final JEPs are available here: Pattern matching for switch: https://openjdk.org/jeps/8300542 Record patterns: https://openjdk.org/jeps/8300541 We're proposing some small changes from the preview versions about to appear in JDK 20. These include: - We're dropping parenthesized patterns. They were leftover from a previous version of patterns, and they weren't used very much. They complicate the spec for not a lot of gain. - We're going to support case labels that are the qualified name of enum constants, and allow switches over non-enum types to have enum case labels provided they use the qualified names of the enum constants and these labels are assignment compatible with the switch type. - We're dropping the support for record patterns in the header of enhanced for statements. These will re-appear in a separate forthcoming JEP. Please take a look at these new JEPs and give us your feedback (either on this list or directly to me). Thanks, Gavin From forax at univ-mlv.fr Tue Feb 28 17:09:04 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 28 Feb 2023 18:09:04 +0100 (CET) Subject: Draft JEPs for Patterns in switch and Record Patterns In-Reply-To: <322686D2-BD86-4F05-BA33-C4017C772DB5@oracle.com> References: <322686D2-BD86-4F05-BA33-C4017C772DB5@oracle.com> Message-ID: <6918508.521390.1677604144441.JavaMail.zimbra@u-pem.fr> ----- Original Message ----- > From: "Gavin Bierman" > To: "amber-dev" > Cc: "amber-spec-experts" > Sent: Tuesday, February 28, 2023 5:21:42 PM > Subject: Draft JEPs for Patterns in switch and Record Patterns > Hello, > > We are planning to finalize the two pattern matching JEPs in JDK 21. Drafts of > these final JEPs are available here: > > Pattern matching for switch: https://openjdk.org/jeps/8300542 > Record patterns: https://openjdk.org/jeps/8300541 > > We're proposing some small changes from the preview versions about to appear in > JDK 20. These include: > > - We're dropping parenthesized patterns. They were leftover from a previous > version of patterns, and they weren't used very much. They complicate the spec > for not a lot of gain. And reuse parenthesis as the syntax for tuple patterns (whatever it is exactly). > > - We're going to support case labels that are the qualified name of enum > constants, and allow switches over non-enum types to have enum case labels > provided they use the qualified names of the enum constants and these labels > are assignment compatible with the switch type. I wonder if we can not extends the unqualified enum value syntax to any sealed hierarchy that contains an enum with that constant. By example, sealed interface HList permits Cons, Nil {} enum Nil implements HList { NIL } record Cons(int val, HList next) implements HList {} HList list = ... switch(list) { case NIL -> ... // the compiler can replace it by Nil.NIL if there is only one enum value named NIL in the hierarchy ... } Perhaps it's a step too far ? > > - We're dropping the support for record patterns in the header of enhanced for > statements. These will re-appear in a separate forthcoming JEP. I hope that enhanced for and destructuring assignment will have the same semantics. > > Please take a look at these new JEPs and give us your feedback (either on this > list or directly to me). > > Thanks, > Gavin Thanks, R?mi From alex.buckley at oracle.com Tue Feb 28 18:37:04 2023 From: alex.buckley at oracle.com (Alex Buckley) Date: Tue, 28 Feb 2023 10:37:04 -0800 Subject: Third draft spec for String Templates (JEP 430) now available In-Reply-To: <12D00B25-7539-49AE-BB6E-C00DA3E38DEE@oracle.com> References: <00A12ECB-155D-4EFE-B257-D05C998387CD@oracle.com> <12D00B25-7539-49AE-BB6E-C00DA3E38DEE@oracle.com> Message-ID: <5b74e6f9-508a-548e-a674-35135a680243@oracle.com> 1. Escape sequences are legal in fragments, so 3.10.7 should open with something like: "In character literals, string literals, and text blocks (?3.10.4, ?3.10.5, ?3.10.6), +and in fragments of a template (3.13),+ the escape sequences allow for ..." 2. 3.10.7 goes on to say that "An escape sequence in the content of a character literal, string literal, or text block is interpreted by ...". This statement constitutes one half of a two-part exposition of interpretation, the other half being found in 3.10.4/5/6 where `String.translateEscapes` is mentioned. Two-way exposition is hard to write, expensive to maintain, but helpful to read. 3.13 is upfront that StringTemplateBegin, StringTemplateMid, and StringTemplateEnd tokens enjoy interpretation, so let's get them named in 3.10.7. 3.13 is less upfront about TextBlockTemplateBegin, TextBlockTemplateMid, and TextBlockTemplateEnd tokens, let me set them aside for now. 3. 3.10.7 should end with a note that the character sequence \{ is not an escape sequence but rather has meaning in a template (3.13). 4. In 3.13, consider "A fragment ~consists of~ +represents+ a non-expression part of a template." (Ch.3 is big on "representing", or perhaps "denoting", things.) This sentence would work well in the opening paragraph of the section. 5. 15.8.6 needs more polishing, per the mail I sent about it last time. I'll discuss offline. Alex On 2/28/2023 8:15 AM, Gavin Bierman wrote: > Following the feedback, a small update of the String Templates Spec is > now available: > > https://cr.openjdk.org/~gbierman/jep430/jep430-20230222/specs/string-templates-jls.html > > Any further comments welcomed! > > Thanks, > Gavin > > >> On 9 Feb 2023, at 15:28, Gavin Bierman > > wrote: >> >> Dear experts: >> >> A new, updated spec covering JEP 430 (String Templates) is now >> available at: >> >> https://cr.openjdk.java.net/~gbierman/jep430/latest >> >> >> This is a substantial rewrite: it now covers more fully how templates >> are tokenized, how to deal with ambiguities, and how text block >> templates are dealt with. >> >> Comments welcomed! >> Gavin > From brian.goetz at oracle.com Tue Feb 28 20:09:36 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 28 Feb 2023 15:09:36 -0500 Subject: Draft JLS Spec about unnamed patterns and variables In-Reply-To: References: <6a57f58c-6f91-612b-ec48-9213e85e168c@oracle.com> Message-ID: In 14.11.1, you say: > *For a case label with case patterns, it is a compile-time error if > any of its case patterns declares one or more pattern variables.* But don't you really mean "For a case label with _more than one_ case patterns, it is ..."? I could see this being implicit in the "s" at the end of "case patterns", but this would be a pretty subtle distinction. The following text has a typo: "more than case patterns" -> "more than ONE case pattern". I see that you've switched horses on domination; now any "dead pattern" is an error.? I am fine with this (though Gavin did make a good argument for the alternative.) In 14.11.1.2, we talk about resolution of patterns.? If any of the patterns resolves to an any pattern, then it will dominate the others.? I believe this is already handled by the text about "if one dominates the others" so that case is already handled, good. You commit here to strict left-to-right evaluation of patterns when there are multiple patterns on a case.? This is reasonable, but bear in mind that such L2R commitments do potentially interfere with folding optimizations if any of the patterns involve imperative code such as accessors or deconstructors. `when (Boolean) null` -- yuck :)? Well spotted. The text around any patterns and resolution in 14.30.1 seems like it could still be simplified a bit. On 2/28/2023 11:21 AM, Angelos Bimpoudis wrote: > Updated draft spec. > > Includes a small number of fixes and a correct "rebase" on top of the > JLS changes resulting from JEP 432 (Record Patterns (Second Preview)) > and JEP 433 (Pattern Matching for switch (Fourth Preview)) that covers > Maurizio's point. > > https://cr.openjdk.org/~abimpoudis/unnamed/latest/ > > (please note that the based URL has been slightly changed ^^) > > Comments are always very much welcomed! > > Best, > Angelos > > ------------------------------------------------------------------------ > *From:* Angelos Bimpoudis > *Sent:* 24 February 2023 17:23 > *To:* Maurizio Cimadamore ; Brian > Goetz ; amber-spec-experts > > *Subject:* Re: Draft JLS Spec about unnamed patterns and variables > > The main takeaways: > > * case Number _ can fall out to other patterns since it doesn't > introduce any bindings (adjustment in the spec draft is needed) > * case Number _ dominates case String _, Integer _ (adjustment is > not needed in current draft, but I will double check before I > circulate the revised version). > > Thanks for all the comments! > > Thought experiment: what if we had union type patterns? ?Then the > case label `case String _, Integer _` would be like matching the > the union type pattern `(String|Integer) _`: > > ? ? case Number n: ... > ? ? case (String|Integer) _: ... > > Would javac then complain that `String|Integer` could be > simplified to just `String` on the bsais of flow analysis? > ?(IntelliJ would, of course.) > > I initially thought as Tagir did, but then Gavin turned me around > and reminded me that it was not dead code, but unreachable > statements that we try to avoid. ?So now I am torn... > > Would union type patterns imply the existence of union types? If yes, > then, the second case could even exist with a binding, correct? In > your example the LUB is Object so even the case (String|Integer) x : > x.getClass() can work. The difficult scenario would arise with the > case (Customer|Human) x : x.getName(); > > If the first case in your example did not introduce a binding, would > both case be equal with Number | (String | Integer)? Union types a la > Ceylon support this > (http://web.mit.edu/ceylon_v1.3.3/ceylon-1.3.3/doc/en/spec/html_single/#uniontypes). > On the other hand in Ceylon, the switch needs to be exhaustive *and*? > all cases need to be disjoint. So this switch would be invalid. hm.. > > ------------------------------------------------------------------------ > *From:* Maurizio Cimadamore > *Sent:* 23 February 2023 20:27 > *To:* Brian Goetz ; Angelos Bimpoudis > ; amber-spec-experts > > *Subject:* Re: Draft JLS Spec about unnamed patterns and variables > > > On 23/02/2023 18:46, Brian Goetz wrote: >> but we really wanted the case merging. > > Gotcha. > > I just wanted to point out that there are two questions here (one > about fall-through and one about domination), and when reading the > emails it was not obvious to me that a change in how fall-through was > defined was being proposed. > > If merging unrelated type tests is a goal, I think there should be an > example for it in the JEP under "Motivation". > > Maurizio > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Tue Feb 28 20:29:05 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 28 Feb 2023 15:29:05 -0500 Subject: Draft JEPs for Patterns in switch and Record Patterns In-Reply-To: <6918508.521390.1677604144441.JavaMail.zimbra@u-pem.fr> References: <322686D2-BD86-4F05-BA33-C4017C772DB5@oracle.com> <6918508.521390.1677604144441.JavaMail.zimbra@u-pem.fr> Message-ID: In fact, the plan is to move destructuring-for into the destructuring-assignment JEP. On 2/28/2023 12:09 PM, Remi Forax wrote: > I hope that enhanced for and destructuring assignment will have the same semantics. -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Tue Feb 28 21:30:05 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 28 Feb 2023 22:30:05 +0100 (CET) Subject: Draft JEPs for Patterns in switch and Record Patterns In-Reply-To: References: <322686D2-BD86-4F05-BA33-C4017C772DB5@oracle.com> Message-ID: <1668423924.590526.1677619805010.JavaMail.zimbra@u-pem.fr> ----- Original Message ----- > From: "John Hendrikx" > To: "Gavin Bierman" , "amber-dev" > Cc: "amber-spec-experts" > Sent: Tuesday, February 28, 2023 10:11:39 PM > Subject: Re: Draft JEPs for Patterns in switch and Record Patterns > In https://openjdk.org/jeps/8300542, the example in "Improved support > for enum constant case labels" seems to be incorrect. > > I think the `goodEnumSwitch2`: > > static void goodEnumSwitch2(Currency c) { > > Should use `Coin` as parameter: > > static void goodEnumSwitch2(Coin c) { > > Also, the enum is called `Coin`, but `Coins` is used a qualifier in > several places. > > --John Also s.equalsIgnoreCase("YES") is better than s.toUpperCase().equals("YES") R?mi > > ------ Original Message ------ > From "Gavin Bierman" > To "amber-dev at openjdk.org" > Cc "amber-spec-experts" > Date 28/02/2023 17:21:42 > Subject Draft JEPs for Patterns in switch and Record Patterns > >>Hello, >> >>We are planning to finalize the two pattern matching JEPs in JDK 21. Drafts of >>these final JEPs are available here: >> >>Pattern matching for switch: https://openjdk.org/jeps/8300542 >>Record patterns: https://openjdk.org/jeps/8300541 >> >>We're proposing some small changes from the preview versions about to appear in >>JDK 20. These include: >> >>- We're dropping parenthesized patterns. They were leftover from a previous >>version of patterns, and they weren't used very much. They complicate the spec >>for not a lot of gain. >> >>- We're going to support case labels that are the qualified name of enum >>constants, and allow switches over non-enum types to have enum case labels >>provided they use the qualified names of the enum constants and these labels >>are assignment compatible with the switch type. >> >>- We're dropping the support for record patterns in the header of enhanced for >>statements. These will re-appear in a separate forthcoming JEP. >> >>Please take a look at these new JEPs and give us your feedback (either on this >>list or directly to me). >> >>Thanks, >>Gavin