<div dir="ltr"><div style="font-family:monospace" class="gmail_default">You may be right that we are delving into tangential waters.</div><div style="font-family:monospace" class="gmail_default"><br></div><div style="font-family:monospace" class="gmail_default">I'll leave it at this -- I think this feature, as implemented, is perfectly approachable for new students doing it my way. I see a smooth ramp all the way up doing it the functional way. However, I do acknowledge that, if you take a state based approach, then there is a non-trivial speed bump near the halfway point.</div><div style="font-family:monospace" class="gmail_default"><br></div><div style="font-family:monospace" class="gmail_default">As for whether or not to remove it and how, I leave to you all. But if we were to remove it the way Ethan suggested, my strategy loses nothing. If the change doesn't hurt me and helps him, then I have no problem with it.<br></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jun 2, 2024 at 6:17 PM Olexandr Rotan <<a href="mailto:rotanolexandr842@gmail.com">rotanolexandr842@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto">Not sure if this conversation haven't shifted from its topic yet, but I would argue with the point that state is bad and you should prefer static methods wherever it is possible.<div dir="auto"><br></div><div dir="auto">There is a few layers to it. First and foremost, keeping some information in object state instead of passing it ap and down through long invocation chains is just simply better for readability. Extracting object is a most common refactoring to eliminate triads and higher order methods.</div><div dir="auto"><br></div><div dir="auto">Secondly, mutability isn't something inheritendly bad. What is bad is shared mutability. When mutations of state are encapsulated properly inside of the owning object, they aren't harmful at all. Moreover, properly dealing with state and mutability is one of the most important skills for developer. There is more to purity then just immutability, and furthermore, purity does not forbid mutability.</div><div dir="auto"><br></div><div dir="auto">Lastly, if students you are teaching would ever decide to become commercial developers, they would be inevitably struck with a fact that static methods here are almost considered antipattern and discarded in favor of singletone.</div><div dir="auto"><br></div><div dir="auto">So, to conclude, it is not about how far you can go without state, it is about how far you should go. Not even mentioning the fact that static methods provide no guarantee of purity, and instance methods do not imply impurity. Functional style now is so exaggerated people often forget why oop took over the world in the first place</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jun 3, 2024, 00:06 David Alayachew <<a href="mailto:davidalayachew@gmail.com" rel="noreferrer noreferrer" target="_blank">davidalayachew@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:monospace">Sometimes, I don't get the choice to avoid state. But when the opportunity arises/the assignment doesn't require it, I will even encourage the student to undo some work TO AVOID using state.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">So no, if I get the chance, I avoid it every chance I get.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">As for static methods, I don't usually get to choose for them. The choice has usually been made, and there's a cost to undoing too much of their work.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">That said, most of what we work with is instance methods with as little state as possible.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">But to be clear, the most interaction they have with INSTANCES is calling it in their main method. Again, the goal is to get them using functional for as long as possible.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Sad to see dev.java on the list, but I have to agree with you. Never considered it to be a beginner resource though.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">And as for being forced to eventually introduce state, you'd be shocked just how far we can go with it lol. I can usually get them to GUI's before I get forced into it. And even then, I don't let them introduce any state of their own, just modifying a JFrame and stuff along that order, which is incredibly easy to maintain for the kids.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jun 2, 2024 at 3:36 PM Ethan McCue <<a href="mailto:ethan@mccue.dev" rel="noreferrer noreferrer noreferrer" target="_blank">ethan@mccue.dev</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><font face="arial, sans-serif">I'm pondering a bit so this isn't too deep of a response<br><br>> Their JumboClassA is very big and unwieldy, and they want to use parts of it for JumboClassB, and maybe other things I've introduced them to at that point. If I haven't already, I introduce them to the Math class, show them how it works, let them make a HelloWorld that does something meaningless, let them call it in their existing class, let them call it in another project, let them make a Math2, and then from there, they usually feel comfortable enough to try and extract a method from what they were actually doing into a pure, static function.<br><br>Are you saying that you only have them write static methods to start with? Like<br><br>class JumboClassA {<br>    static int code() {<br>        return JumboClassB.compute() + 1;<br>    }<br>}<br><br>class JumboClassB {<br>    static int compute() {<br>        return 0;<br>    }<br>}<br><br>If so, do you oft get around to instances and instance state?<br><br>> Long story short, you and I approach tutoring in WILDLY different ways.<br><br>Also in different contexts. I spend most of my time in one of a few discord channels answering questions and that sometimes leads to people who I tutor over a longer period of time. We mostly get people who are either struggling with an existing curriculum and try to do course correction (I started making a shortlist of the bad college curriculums we are exposed to).<br><br>So the things we notice are that current curriculums either<br>* Have ordering issues within them. Explaining JPA before SQL, Abstract classes before interfaces, Large program design before small, etc.<br>* Have no clear next steps. Most intro courses, after taking a deep sigh of relief for having gotten a successful for loop out of a teenager, just sorta end. <br><br>So we have very few Java courses (that we know of) to point people to that actually explain the topics they introduce in the order they will be encountered. (See <a href="https://dev.java/learn/" rel="noreferrer noreferrer noreferrer" target="_blank">https://dev.java/learn/</a> , <a href="https://www.baeldung.com/java-tutorial" rel="noreferrer noreferrer noreferrer" target="_blank">https://www.baeldung.com/java-tutorial</a>, <a href="https://www.geeksforgeeks.org/java/" rel="noreferrer noreferrer noreferrer" target="_blank">https://www.geeksforgeeks.org/java/</a> for examples of terrible tutorials)<br><br>And after we give them something like <a href="https://java-programming.mooc.fi/" rel="noreferrer noreferrer noreferrer" target="_blank">https://java-programming.mooc.fi/</a> and they finish we have nowhere to go from there. That's part of why I think topic order matters so much. <br><br>> I have only tutored one student using this implicit class feature so far, and we are nowhere near this point yet.<br><br>Take notes on how that progresses + any differences from your previous approach.<br><br>> I guess what I am saying is that, since I don't really depend on static or instance level state, I just don't have this problem. And by the time I do, they have gotten so used to doing functional, that any interaction with global state stands out as something to watch out for.<br><br>I went to Northeastern and their intro curriculum starts you with Racket doing really rigid comments that drills in sum types + recursion. Then they introduce Java without mutation at all for 80% of the 2nd semester. You only get mutation at the end and at that point your brain was broken from all the purity you forget how.<br><br>So I get it. But eventually those concepts need to be introduced.</font></div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jun 2, 2024 at 12:06 AM David Alayachew <<a href="mailto:davidalayachew@gmail.com" rel="noreferrer noreferrer noreferrer" target="_blank">davidalayachew@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div style="font-family:monospace">Well, I definitely see the discrepancy now. Yes, this makes a lot of sense.</div><div style="font-family:monospace"><br></div><div style="font-family:monospace">Apologies for not recognizing your point earlier, I had assumed that you
 were talking about some fundamental execution change that the kid needs to be aware of. I didn't realize 
that you were talking about potholes that the kid might fall into.

</div><div style="font-family:monospace"><br></div><div style="font-family:monospace">Long story short, you and I approach tutoring in WILDLY different ways.<br></div><div style="font-family:monospace"><br></div><div style="font-family:monospace">First and foremost, the concept of introducing instance state this early on is dangerous in my eyes. If you have a kid that can dance at that tempo, then you truly have a gifted kid. But from my 10+ years of tutoring, EVERY SINGLE TIME I try to introduce them to the idea of having state ANYWHERE except for inside of a method, things fall apart. It will be a long time before I ever try and get this kid to try and manage state at the instance level.<br><br>I approach it very differently.<br><br>I start off teaching these kids to approach problems with a functional mindset. Pure functions everywhere. This usually ends up creating a big, singular essay of a function, and once they start to feel the strain from that, I show them how to thread their state in through methods and return values.<br><br>Anyways, back to my example from 2 emails ago.<br><br>Their JumboClassA is very big and unwieldy, and they want to use parts of it for JumboClassB, and maybe other things I've introduced them to at that point. If I haven't already, I introduce them to the Math class, show them how it works, let them make a HelloWorld that does something meaningless, let them call it in their existing class, let them call it in another project, let them make a Math2, and then from there, they usually feel comfortable enough to try and extract a method from what they were actually doing into a pure, static function.<br><br>I have only tutored one student using this implicit class feature so far, and we are nowhere near this point yet. But I expect that the only thing that will change before I get there is explaining to them how, in order to use their methods outside of the class, they need to give the class an explicit name. I foresee no pain points with that. After all, how can you reference a class that does not have an explicit name? And I expect them to understand the unidirectionality of that. A class without a name can use methods from a class WITH a name. But the reverse is false. I'm actually sorted of excited to spring that onto the kids and see how they react lol.<br><br>Really, the only issue I ever run into is when kids ask me, what is static useful for anyways? They usually feel like they only need static or instance methods.<br><br>I guess what I am saying is that, since I don't really depend on static or instance level state, I just don't have this problem. And by the time I do, they have gotten so used to doing functional, that any interaction with global state stands out as something to watch out for. From there, they understand how much of an ordeal it is to work with state, and exactly how dangerous and error-prone that it is that I can usually get them to turn their alertness up to 11 whenever the need arises.</div><div style="font-family:monospace"><br></div><div style="font-family:monospace">Let me first get your perspective though before I continue my point. What are your thoughts on this?</div><div style="font-family:monospace"><br></div><div style="font-family:monospace">And apologies for not responding to your points individually. Our assumptions are on opposite ends, so there is very little that I can directly respond to.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jun 1, 2024 at 11:22 PM Ethan McCue <<a href="mailto:ethan@mccue.dev" rel="noreferrer noreferrer noreferrer" target="_blank">ethan@mccue.dev</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I really should find a better example / adapt something in an existing curriculum - but:<br><br>Mutation 1: Make b static<br><br>i<font face="monospace">nt count = 0;<br><br>class A {<br>    static void b() {<br>         count++;<br>         c();<br>         new D();<br>    }<br>}<br><br>void c() {<br>    println("" + count);<br>}<br><br>class D {}<br><br>void main() {<br>    new A().b();<br>}<br></font><br><a href="https://run.mccue.dev/?runtime=latest&release=22&preview=enabled&gist=be416fe8e6df84c81c0f5526f0e28aef" rel="noreferrer noreferrer noreferrer" target="_blank">https://run.mccue.dev/?runtime=latest&release=22&preview=enabled&gist=be416fe8e6df84c81c0f5526f0e28aef</a><br><br>Mutation 2: Make c static<br><br>i<font face="monospace">nt count = 0;<br><br>class A {<br>    void b() {<br>         count++;<br>         c();<br>         new D();<br>    }<br>}<br><br>static void c() {<br>    println("" + count);<br>}<br><br>class D {}<br><br>void main() {<br>    new A().b();<br>}<br></font><br><a href="https://run.mccue.dev/?runtime=latest&release=22&preview=enabled&gist=b71e9b94cff6099afb5153abffdbc3e9" rel="noreferrer noreferrer noreferrer" target="_blank">https://run.mccue.dev/?runtime=latest&release=22&preview=enabled&gist=b71e9b94cff6099afb5153abffdbc3e9</a><br><br>Mutation 3: (for fun) Make A a record<br><br><font face="monospace">int count = 0;<br><br>record A() {<br>    void b() {<br>         count++;<br>         c();<br>         new D();<br>    }<br>}<br><br>void c() {<br>    println("" + count);<br>}<br><br>class D {}<br><br>void main() {<br>    new A().b();<br>}</font><br><br><a href="https://run.mccue.dev/?runtime=latest&release=22&preview=enabled&gist=cb5bf4664bf83ffc8ee4e5fe85abadb6" rel="noreferrer noreferrer noreferrer" target="_blank">https://run.mccue.dev/?runtime=latest&release=22&preview=enabled&gist=cb5bf4664bf83ffc8ee4e5fe85abadb6</a><br><br>Maybe it's just a failure of imagination, but I don't know how to introduce <font face="monospace">static</font> methods and fields into someone's arsenal without either<br>* pulling the veil and explaining the anonymous class. This requires static imports. We've looped.<br>* leaving them with guidance like "you can't make classes, records work though. I'll tell you later why. Just do math type stuff here."<br><br>Then there is the confounding factor of *why* they would want a static method. In "real code" we use static methods and fields for<br><br>* globals<br>* "pure" logic<br>* factory methods<br><br>Before they move to another file, they already have globals and they can already put pure logic at the top level. Factory methods only make sense once you've introduced large program topics like visibility.<br><br>I.E. you only need factory methods if<br><br>1. You want to hide a constructor<br><br><font face="monospace">class Point {<br>    private Point(int x, int y) {}<br><br>    static Point of(int x, int y) {<br>        return new Point(x, y);<br>    }<br>}</font><br><br>But this is a nuanced api topic and isn't even relevant when everything is a nestmate. Really a "large program" sort of choice.<br><br>2. You want to create through an interface<br><br><font face="monospace">interface LinkedList {<br>    int size();<br><br>    static LinkedList empty() {<br>        return new EmptyList();<br>    }<br><br>    static LinkedList notEmpty(int head, LinkedList tail) {<br><br>    }<br>}<br><br>class EmptyList implements LinkedList {<br>    <a class="gmail_plusreply" id="m_9104799716759814058m_-6002528785556090652m_3579273392417863317m_7778705461295288563m_2801011631851076742m_-5624316778494470119m_2738765686462762099plusReplyChip-0" rel="noreferrer noreferrer noreferrer">@Override<br></a>    public int size() {<br>       return 0;<br>    }<br>}<br></font><br>But as you see from the code you need to have <font face="monospace">public</font> to teach interfaces. You can gloss over it (my school did) but it's there. Even then "why not just new EmptyList()" has an answer really rooted in (again) large program concerns. You make code for potentially an external audience and need to give a "good" API.<br><br>3. You want otherwise incompatible overloads<br><br><font face="monospace">class Point {<br>    Point(int x, int y) {}<br><br>    static Point ofX(int x) {<br>        return new Point(x, 0);<br>    }<br><br>    static Point ofY(int y) {<br>        return new Point(0, y);<br>    }<br>}<br></font><br>Which does work a little. But it doesn't really give a good opener for static imports. The method names you'd give here are like ofX, fromX. You would want to use those qualified every time. You also activate the footguns I showed above.<br><br><font face="monospace">int pointsMade = 0;</font><br><br><font face="monospace">class Point {</font><br><font face="monospace">    Point(int x, int y) {}</font><br><br><font face="monospace">    static Point ofX(int x) {</font><br><font face="monospace">        pointsMade++;</font><br><font face="monospace">        return new Point(x, 0);</font><br><font face="monospace">    }</font><br><br><font face="monospace">    static Point ofY(int y) {</font><br><font face="monospace">        pointsMade++;</font><br><font face="monospace">        return new Point(0, y);</font><br><font face="monospace">    }</font><br><font face="monospace">}</font><br><br><font face="monospace">--</font><br><br><font face="arial, sans-serif">> </font><span style="font-family:monospace">I would always start by taking one of their projects, ask them to tweak in a subtle, but difficult way, then let them run headfirst into the problem. Once they start to feel the strain, I would introduce them to the concepts of classes.<br></span><br>I think this is what I am missing. Without going into large or multi-file program design there isn't much reason to use static anything. <font face="arial, sans-serif"><i>In addition</i> to that there are mechanical difficulties that can only be explained properly once you reach a 2nd file.<br></font><br>I.E. - "you were actually using a class until now. For true globals use static fields", "For methods you can call anywhere use static" are the explanations I want to give. Both of those explanations need multiple files already in place to make sense.<br><br>Does that track?<br><br><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jun 1, 2024 at 10:47 PM David Alayachew <<a href="mailto:davidalayachew@gmail.com" rel="noreferrer noreferrer noreferrer" target="_blank">davidalayachew@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div style="font-family:monospace">Heh, we're both unpaid :P I tutor folks from my university and church, as well as a couple of friends and family. Slowing down now though because of workload at work.<br><br>But back to the point.<br><br>> I think the problem is that without static "global"<br>> fields are always accessible and all the nested classes<br>> in their program are instansable from anywhere.<br>><br>> Once you have a static method, a method on a record, a<br>> method on an enum, or a static inner class this is no<br>> longer the case.<br><br>Apologies, maybe I missed the memo. I have been out of touch with this (and all other JEP's) because of my insane workload for the past couple of months.<br><br>Why would adding a static method change any of the logic?<br><br>I took your example in Java 22, added a static method, and everything worked dandy.<br><br>Am I missing something?</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jun 1, 2024 at 9:28 PM Ethan McCue <<a href="mailto:ethan@mccue.dev" rel="noreferrer noreferrer noreferrer" target="_blank">ethan@mccue.dev</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div>I am also basically just a tutor, just unpaid.<div dir="auto"><br></div><div dir="auto">I think the problem is that without static "global" fields are always accessible and all the nested classes in their program are instansable from anywhere.</div><div dir="auto"><br></div><div dir="auto">Once you have a static method, a method on a record, a method on an enum, or a static inner class this is no longer the case.</div><div dir="auto"><br></div><div dir="auto">Trite example of the mechanics I'm referencing:</div><div dir="auto"><br></div><div dir="auto">int count = 0;</div><div dir="auto"><br></div><div dir="auto">class A {</div><div dir="auto">    void b() {</div><div dir="auto">         count++;</div><div dir="auto">         c();</div><div dir="auto">         new D();</div><div dir="auto">    }</div><div dir="auto">}</div><div dir="auto"><br></div><div dir="auto">void c() {</div><div dir="auto">    println("" + count);</div><div dir="auto">}</div><div dir="auto"><br></div><div dir="auto">class D {}</div><div dir="auto"><br></div><div dir="auto">void main() {</div><div dir="auto">    new A().b();</div><div dir="auto">}</div><div dir="auto"><br></div>So when you show static methods, I think you need to understand why count++; and c(); and new D(); would not function.</div><div dir="auto"><br></div><div dir="auto">That requires knowing that you are actually in an anonymous class. That requires we get past import static <a href="http://java.io.IO" rel="noreferrer noreferrer noreferrer" target="_blank">java.io.IO</a>. That's the loop.</div><div dir="auto"><br></div><div dir="auto"><br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">On Sat, Jun 1, 2024, 8:59 PM David Alayachew <<a href="mailto:davidalayachew@gmail.com" rel="noreferrer noreferrer noreferrer" target="_blank">davidalayachew@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><span class="gmail_default" style="font-family:monospace">Maybe I am missing something, but a static import seems like the natural next step to teaching a student who made it that far.</span></div><div><span class="gmail_default" style="font-family:monospace"><br></span></div><div><span class="gmail_default" style="font-family:monospace">If a student feels the need to break out of the bounds of an implicitly declared class, they must first understand what a class is going to save them from. In this case, it is allowing code they right to be reused else where.</span></div><div><span class="gmail_default" style="font-family:monospace"><br></span></div><div><span class="gmail_default" style="font-family:monospace">I am only a tutor, not a full-blown teacher, but when tutoring folks in this exact subject, I would always start by taking one of their projects, ask them to tweak in a subtle, but difficult way, then let them run headfirst into the problem. Once they start to feel the strain, I would introduce them to the concepts of classes.</span></div><div><span class="gmail_default" style="font-family:monospace"><br></span></div><div><span class="gmail_default" style="font-family:monospace">I would start by showing them how to create a simple pure function, similar to java.lang.Math. From there, we would make a few pure functions that are unrelated to their current task, and then have them get comfortable with that concept.</span></div><div><span class="gmail_default" style="font-family:monospace"><br></span></div><div><span class="gmail_default" style="font-family:monospace">Then, we would make another pure function that is being done repeatedly in their "JumboClass1" and "JumboClass2", and then have them get comfortable using this helper method in both versions.</span></div><div><span class="gmail_default" style="font-family:monospace"><br></span></div><div><span class="gmail_default" style="font-family:monospace">In my mind, this is naturally where the student would discover that they need to do a static import. In which case, they are in the middle of understanding a class, they understand imports, and they understand static methods fairly well. So, a static import has been well prepared for them.</span></div><div><span class="gmail_default" style="font-family:monospace"><br></span></div><div><span class="gmail_default" style="font-family:monospace">For me, this is a neat and clean introduction. Maybe I am missing something?<br></span></div><div><span class="gmail_default" style="font-family:monospace"></span></div><div><span class="gmail_default" style="font-family:monospace"></span></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jun 1, 2024 at 6:43 PM Ron Pressler <<a href="mailto:ron.pressler@oracle.com" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank">ron.pressler@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi.<br>
<br>
Without getting into the merits of not implicitly importing anything, let me just point out that the following is a valid program under the current JEP:<br>
<br>
    void main() {<br>
        IO.println(“Hello, world!”);<br>
    }<br>
<br>
As is this one:<br>
<br>
    import module java.base;<br>
<br>
    void main() {<br>
        IO.println(“Hello, world!”);<br>
    }<br>
<br>
In other words, the fact that there are implicit imports doesn’t mean that you can’t ignore them or add them explicitly. if you find teaching this to be easier, you can. So even if you don’t find implicit imports helpful, they may be helpful to other teachers, who may not want to start with some import incantation that necessarily implies some programming-in-the-large concept.<br>
<br>
But I think that your unease mostly stems from the extra magic that implicit classes enjoy, and which isn’t strictly necessitated by their primary quality of being implicitly declared classes, and that extra magic differentiates them from regular compilation units along some other axis; is that right?<br>
<br>
— Ron<br>
<br>
<br>
<br>
> On 1 Jun 2024, at 23:14, Ethan McCue <<a href="mailto:ethan.mccue@lumanu.com" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank">ethan.mccue@lumanu.com</a>> wrote:<br>
> <br>
> Hi all,<br>
> <br>
> I'm following the development of JEP 477[1] and I feel the need to question the impetus for the implicit static imports.<br>
> <br>
> As of now[2] any program like this<br>
> <br>
> void main() {<br>
>     println("Hello, world");<br>
> }<br>
> <br>
> Is equivalent to<br>
> <br>
> import static java.io.IO.print;<br>
> import static java.io.IO.println;<br>
> import static java.io.IO.writeln;<br>
> <br>
> import module java.base;<br>
> <br>
> final class Main {<br>
>     void main() {<br>
>         println("Hello, world");<br>
>     }<br>
> }<br>
> <br>
> Where all the methods in <a href="http://java.io.IO" rel="noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank">java.io.IO</a> delegate to newly added equivalent methods in java.io.Console.[3]<br>
> <br>
> Aside from muddying that API up (now there is readln and readLine + println and printLine which...what) I'm still concerned on how those implicit imports will affect the transition to named classes.<br>
> <br>
> Assume we start a student out here<br>
> <br>
> void main() {<br>
>     println("Hello, world");<br>
> }<br>
> <br>
> You can get through conditionals, loops, variables, methods, and return types before touching classes or access specifiers.<br>
> <br>
> int compute() {<br>
>     int total = 0;<br>
>     for (int i = 0; i < 10; i++) {<br>
>         total += i;<br>
>     }<br>
>     return total;<br>
> }<br>
> <br>
> void main() {<br>
>     println("Hello: " + compute());<br>
> }<br>
> <br>
> You can even talk about records and enums in a hand wavey way. Enums are "one of these options", Records are "if you want to return two things."<br>
> <br>
> enum Pirate {<br>
>    BLACKBEARD,<br>
>    OTHER<br>
> }<br>
> <br>
> record Pos(int x, int y) {}<br>
> <br>
> Pos treasure(Pirate pirate) {<br>
>     switch (pirate) {<br>
>         case BLACKBEARD -><br>
>             return new Pos(5, 5);<br>
>         case OTHER -><br>
>             return new Pos(0, 0);<br>
>     }<br>
> }<br>
> <br>
> void main() {<br>
>     println(treasure(Pirate.OTHER));<br>
> }<br>
> <br>
> So it is reasonable for a student to have made a relatively complex program before having to get to that point, but I think you do need to explain what exactly is going on with the anonymous main class when you introduce multi file programs.<br>
> <br>
> As originally pitched, this transition would have just meant wrapping the whole program in class Main {}, but now to make the transition from<br>
> <br>
> void main() {<br>
>     // Arbitrary code<br>
> }<br>
> <br>
> to <br>
> <br>
> class Main {<br>
>     void main() {<br>
>         // Arbitrary code<br>
>     }<br>
> }<br>
> <br>
> In a robust way, you need to add those imports to the top. You can skip the final since the semantics of extension haven't been relevant yet.<br>
> <br>
> import static java.io.IO.*;<br>
> <br>
> import module java.base;<br>
> <br>
> class Main {<br>
>     void main() {<br>
>         // Arbitrary code<br>
>     }<br>
> }<br>
> <br>
> My gripe is that the concepts introduced here - static, module, and * imports  - would have had no place to be introduced earlier.<br>
> <br>
> If you have folks write static methods on inner classes, the metaphor of a "global field" that otherwise exists in the simple-main world goes away.<br>
> <br>
> // For every program up until this, they could freely access this from anywhere<br>
> int count = 0;<br>
> <br>
> // And they could freely make an instance of any inner class<br>
> class Other {}<br>
> <br>
> class Pos {<br>
>     static Pos of(int x, int y) {<br>
>         // So the rules they are used to don't apply anymore<br>
>         // and the explanation as to why really lies *after* they understand<br>
>         // what an anonymous main class is and does<br>
>         // ...<br>
>     }<br>
> }<br>
> <br>
> void main() {<br>
>    // ... <br>
> }<br>
> <br>
> If you have folks *use* static methods that is fine - the hand-waving of Math.max doesn't seem to trip anyone up - but I can't figure out how to topologically sort topics such that import static makes any sense before going through multi-file programs. <br>
> <br>
> I have a similar concern with import module, but that can be hand waved as "gets you everything from this library" so I am less concerned. Still don't fully understand the desire to have it be implicit, but less concerned. <br>
> <br>
> Just as a hypothetical, say <a href="http://java.io.IO" rel="noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank">java.io.IO</a> was <a href="http://java.lang.IO" rel="noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank">java.lang.IO</a>. No new import rules needed and now IO is available to all programs.<br>
> <br>
> void main() {<br>
>     IO.printLine("Hello, world");<br>
> }<br>
> <br>
> While this does introduce something not explained - static method access - it feels easier to hand-wave away than import static java.io.IO.*; would be. It calls the printLine method, it comes from IO. IO means "Input/Output". That's a workable metaphor and can be glanced over in the same way as Math.max<br>
> <br>
> The transition from here to classes can again be "it's the same as if you had class Main {} around it" instead of "it's the same as if you had class Main {} around it and these imports. A static import imports a static method. A static method is a method attached to the class itself instead of the instance.... etc."<br>
> <br>
> Also, IO. feels like a different kind of unexplained boilerplate than public static void main(String[] args) {}. There is a lot of ground you need to cover before access modifiers, static methods, or command line arguments make any sort of sense. When you have someone write IO they are in that moment producing output and will soon take input.<br>
> <br>
> What am I overlooking?<br>
> <br>
> <br>
> [1]: <a href="https://openjdk.org/jeps/477" rel="noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank">https://openjdk.org/jeps/477</a><br>
> [2]: <a href="https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/IO.html" rel="noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank">https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/IO.html</a><br>
> [3] <a href="https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/Console.html#print(java.lang.Object)" rel="noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank">https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/Console.html#print(java.lang.Object)</a><br>
<br>
</blockquote></div>
</blockquote></div></div></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>