> From: "Dan Heidinga" <[email protected]> > To: "Remi Forax" <[email protected]> > Cc: "Brian Goetz" <[email protected]>, "Ron Pressler" > <[email protected]>, "amber-spec-experts" > <[email protected]> > 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:[email protected] | > [email protected] > ] > wrote: >>> From: "Brian Goetz" < [ mailto:[email protected] | >>> [email protected] ] >>> > >>> To: "Remi Forax" < [ mailto:[email protected] | [email protected] ] > >>> Cc: "Ron Pressler" < [ mailto:[email protected] | >>> [email protected] >>> ] >, "Dan Heidinga" < [ mailto:[email protected] | [email protected] ] >>> >, >>> "amber-spec-experts" < [ mailto:[email protected] | >>> [email protected] ] > >>> 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:[email protected] | [email protected] ] >>> wrote: >>>>> From: "Brian Goetz" [ mailto:[email protected] | >>>>> <[email protected]> ] >>>>> To: "Remi Forax" [ mailto:[email protected] | <[email protected]> ] >>>>> Cc: "Ron Pressler" [ mailto:[email protected] | >>>>> <[email protected]> >>>>> ] , "Dan Heidinga" [ mailto:[email protected] | <[email protected]> ] >>>>> , >>>>> "amber-spec-experts" [ mailto:[email protected] | >>>>> <[email protected]> ] >>>>> 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
