<div dir="ltr"><div>Hello expert,</div><div><br></div><div>One more design space point that allows beginner friendly arrangement of concepts is to extend the Java compilation unit to always allow top-level method declarations.</div><div><br></div><div>Top-level methods are always static and can not be public.</div><div><div></div><div>There is still a value for advanced java-developers:
these methods allow a succinct way to write private static
utility-methods to be used from the normal class.</div></div><div><br></div><div>It's not hard to imagine that normal Java code inside the my/company/pkg/Test.java file can contain:<br></div><div><br></div><div>````<br></div><div>package my.company.pkg;</div><div><br></div><div>import ...;</div><div>import ...;</div><div><br></div><div>void helper1(HiddenClass hiddenClass) {</div><div> ...<br></div><div>}</div><div><br></div><div><div>void helper2() {</div><div> ...<br></div><div>}</div><div><br><br></div></div><div>public class Test {</div><div> record NormalInnerDeclaration() {}<br></div><div>}</div><div>class HiddenClass {</div><div>}<br></div><div>````<br></div><div><br></div><div><div>The semantics of this is that only the code inside the compilation unit can call `helper1` or `helper2`, nobody else can.</div></div><div>Semantically there is no enclosing class, there is no name that can be used to disambiguate method name: Test.helper1() is not the top level method and can not be used to reference `helper1` method, only the stand-alone name `helper1` can.</div><div></div><div><br></div><div>For the beginners this means that they can write a file with the `.java` suffix and use the unnamed package and they should never care about class names or exact file name.<br></div><div><br></div><div>````</div><div>void main() {</div><div> ...<br></div><div>}</div><div><br></div><div>void quicksort() {</div><div>}</div><div><br></div><div>record MyRecord {</div><div>}<br></div><div>````<br></div><div><br></div><div>We can extend the Java mechanism to run a single file to look up top-level static methods. Having some `excersise1.java` we can execute it with the simple</div><div><br></div><div>````</div><div> $ java excersise1.java</div><div>````<br></div><div><br></div><div>Technically in JVM this method can be implemented as something like a companion Utility class in the same nest. For the `my/company/pkg/Test.java` source file we may get `my/company/pkg/Test.class` and `my/company/pkg/Test$utilitycompanion.class` or something like this.<br></div><div><br></div><div>When a beginner progresses towards large-scale organization of code, they still don't need to unlearn to use top-level methods, they will stay always available.</div><div><br></div><div>--</div><div><div dir="ltr" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>Victor Nazarov<br></div></div></div></div></div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Sep 29, 2022 at 3:37 AM Brian Goetz <<a href="mailto:brian.goetz@oracle.com" target="_blank">brian.goetz@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">
<div>
<br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div>
<div>A major design goal of yours seems clear: to get there
without rendering Java source files
explicitly bimorphic ("class" source files all look like
this, "main" source files all look like that). Instead you
have a set of independent features that can compose to get
you there in a "smooth ramp". The design looks heavily
influenced by that goal.</div>
</div>
</div>
</blockquote>
<br>
Yes, I sometimes call this "telescoping", because there's a chain of
"x is short for y is short for z". For example, with lambdas:<br>
<br>
x -> e<br>
<br>
is-short-for<br>
<br>
(x) -> e <br>
<br>
is-short-for<br>
<br>
(var x) -> e <br>
<br>
is-short-for<br>
<br>
(int x) -> e // or whatever the arg is<br>
<br>
As a design convention, it enables a mental model where there is
really just one form, with varying things you could leave out.
Early in the Lambda days, we saw articles like "there are N forms of
lambda expressions", and that stuff infuriates me, it is as if
people go out of their way to find more complex mental models than
necessary. <br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div>
<div>As my program grows and gets more complex, I will make
changes like</div>
<div><br>
</div>
<div>* use more other libraries</div>
<div>* add args to main()</div>
<div>* add helper methods</div>
<div>* add constants</div>
<div>* create new classes and use them from here<br>
</div>
<div><br>
</div>
<div>But: when and why would I be motivated to change *this*
code *itself* to "become" a class, become instantiable,
acquire instance state, etc. etc.? I don't imagine ever
having that urge. main() is just main()! It's just a way in.
Isn't it literally just a way to (a) transfer control back
and forth and (b) hand me args?</div>
</div>
</div>
</blockquote>
<br>
This doesn't seem like such a leap to me. You might start out
hardcoding a file path that will be read. Then you might decide to
let that be passed in (so you add the args parameter to main). Then
you might want to treat the filename to be read as a field so it can
be shared across methods, so you turn it into a constructor
parameter. One could imagine "introduce X" refactorings to do all
of these. The process of hardcoding to main() parameter to
constructor argument is a natural sedimentation of things finding
their right level. (And even if you don't do all of this, knowing
that its an ordinary class (like an enum or a record) just with a
concise syntax means you don't have to learn new concepts. I don't
want Foo classes and Bar classes.)<br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div>
<div class="gmail_quote"><br>
<div>Note I was only reacting to "static bad!" here. I would
be happy if *that* argument were dropped, but you do still
have another valid argument: that `static` is another
backward default, and the viral burden of putting it not
just on main() but every helper method you factor out is
pure nuisance. (I'd suggest mentioning the viral nature of
this particular burden higher/more prominently in the doc,
as it's currently out of place under the "unnamed classes"
section.)</div>
<div><br>
</div>
<div>(That doesn't mean "so let's do it"; I still hope to
see that benefit carefully measured against the drawbacks.
Btw, *some* of those drawbacks might be eased by
disallowing an explicit constructor... and jeez, please
disallow type parameters too... I'm leaving the exact
meaning of "disallow" undefined here.)</div>
</div>
</div>
</div>
</blockquote>
<br>
Indeed, I intend that there are no explicit constructors or instance
initializers here. (There can't be constructors, because the class
is unnamed!) I think I said somewhere "such classes can contain
..." and didn't list constructors, but I should have been more
explicit. <br>
<br>
<blockquote type="cite">
<div dir="ltr"><br>
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><font size="4"><font face="monospace">## Unnamed
classes<br>
<br>
In a simple program, the `class` declaration often
doesn't help either, because<br>
other classes (if there are any) are not going to
reference it by name, and we<br>
don't extend a superclass or implement any interfaces.</font></font></div>
</blockquote>
<div><br>
</div>
<div>How do I tell `java` which class file to load and call
main() on? Class name based on file name, I guess?</div>
</div>
</div>
</blockquote>
<br>
Sadly yes. More sad stories coming on this front, Jim can tell. <br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_quote"><br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><font size="4"><font face="monospace">If we say an
"unnamed<br>
class" consists of member declarations without a class
header, then our Hello<br>
World program becomes:<br>
<br>
```<br>
void main() { <br>
System.out.println("Hello World");<br>
}<br>
```<br>
</font></font></div>
</blockquote>
<div><br>
</div>
<div><br>
</div>
<div>One or more class annotations could appear below
package/imports?<br>
</div>
</div>
</div>
</blockquote>
<br>
No package statement (unnamed classes live in the unnamed package),
but imports are OK. No class annotations. No type variables. No
superclasses. <br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><font size="4"><font face="monospace"> Such source
files can still have fields, methods, and even nested
classes, </font></font></div>
</blockquote>
<div><br>
</div>
<div>Do those get compiled to real nested classes, nested
inside an unnamed class? So if I edit a "regular" `Foo.java`
file, go down below the last `}` and add a `main` function
there, does that cause the whole `Foo` class above to be
reinterpreted as "nested inside an unnamed class" instead of
top-level?</div>
</div>
</div>
</blockquote>
<br>
To be discussed!<br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_quote">This is my notion of a natural
progression:
<div><br>
</div>
<div>1. Write procedural code: calling static methods, using
existing data types, soon calling their instance methods</div>
<div>2. Proceed to creating your own types (from simple data
types onward) and using them too</div>
<div>3. One day learn that your main() function is actually a
method of an instantiable type too... at pub trivia night,
then promptly forget it</div>
</div>
</div>
</blockquote>
<br>
Right.<br>
<br>
<br>
<br>
</div>
</blockquote></div>