Re: JEP 445 (Unnamed classes): It’s.. still weird (structurally typed).
Remi Forax
forax at univ-mlv.fr
Tue May 9 19:40:23 UTC 2023
> From: "Brian Goetz" <brian.goetz at oracle.com>
> To: "Reinier Zwitserloot" <reinier at projectlombok.org>, "amber-dev"
> <amber-dev at openjdk.java.net>
> Sent: Tuesday, May 9, 2023 7:42:19 PM
> Subject: Re: JEP 445 (Unnamed classes): It’s.. still weird (structurally typed).
> Yes, when the glass is 99% full, it is often tempting to focus on that last 1%.
> This is natural.
> The points you raise here are sensible, but you sort of answer your own
> question: the TerminalInteractive interface is a significant exercise in API
> design, which would likely run into other tradeoffs that we don't love. We are
> not a mere small step away from "closing that last 1%", we are reopening a
> whole can of worms, with a pretty limited payback (and one for which its not
> even obvious it meets the "beginner-friendly" requirement.)
> Stephen tried a similar exploration with "entry points", and ran into a similar
> degree of "poor return on incremental complexity."
> As the "Paving" document outlined, this project started out with deliberately
> modest goals -- small adjustments for smoothing out the main class declaration
> and launch model, not "design a new launch model." This was not a mere
> budgetary compromise (though we are ever mindful that every minute spent on one
> project is a minute not spent on another, and that we're working with limited
> complexity budgets in multiple dimensions), but also a recognition of the fact
> that there are some practical aspects here and some spiral-off-into-blue-sky
> aspects, and we will be resisting the temptation of the latter. We already
> thought through a number of the "could we go farther" prior to proposing the
> project (including all the things you have suggested, and more), and concluded
> that this was the sweet spot.
>> These concepts can be handwaved away as out of scope, but if that’s done I don’t
>> think this JEP fully accomplishes what it should.
> This is a valid opinion! But I don't think you've fully thought out what you're
> saying. (Don't worry, though, you'd be in good company; the opinion of "I think
> you should do more" is common and commonly expressed, and most folks who do so
> make the same mistake.)
> You think that by expressing this opinion, that the only reasonable responses on
> our part are either:
> A: Great, you convinced us, we'll do as you ask
> B: Yes, you're right, but we're going to do the wrong thing anyway
> What you (and others who play this card) don't realize is: you are actually
> arguing for "Let's cancel this project right now, because what we can
> reasonably deliver is not good enough."
> It's fine to express "I wish we could do more", or even "Here's something more
> that I think we could do at minimal incremental cost." But when you frame the
> argument as "if you don't do more, you have failed" (that's what "doesn't
> accomplish what it should" means), you are arguing "let's cancel the project."
> Personally, I don't think this project is remotely a failure if we stop where we
> set out to stop. But I recognize that others might feel differently. But if you
> mean to be pulling the emergency brake cord, you should be clear about that!
>> the very first API they run into (Namely, Scanner)
> I don't agree that every student will run into Scanner so early, but I do agree
> that Scanner could use a redesign. But that doesn't need to be coupled to this
> JEP; that's a straightforward library improvement that can be an ordinary RFE,
> and surely doesn't need language support.
>> the rest of JEP445 doesn’t seem to accomplish meaningful change
> because JEP 445 is focused on the language aspects. The library aspects are
> separate.
Hi Brian, i agree with what you are saying, but Reiner is right on one point, students will run into Scanner pretty early, when we introduce loops in our curriculum, working on files redirected into stdin is the source of numerous exercises.
Rémi
> On 5/5/2023 5:06 PM, Reinier Zwitserloot wrote:
>> JEP 445 does a ton of work cleaning up that experience of ‘meeting java for the
>> first time’. I fear the herculean effort required for the bazillion tutorials
>> and books out there to adopt this new style, but no time like the present to
>> start that work.
>> But, java is just about the least structurally typed language I’m aware of. It
>> even insists functions have a type name (lambdas aren’t legit unless context
>> allows the compiler to treat them as a functional interface).
>> There are only 4 exceptions baked into java itself:
>> (1) main().
>> (2) agentmain().
>> (3) serialization, which brings in 5x structural typing (serialVersionUID field,
>> writeReplace, readResolve, writeObject, and readObject).
>> (4) The beanspec. Clearly the JDK doesn’t care about it given that records
>> decided to go with property() instead of getProperty() .
>> Given the repeated strong discouragement from OpenJDK about those last 2, that
>> really just leaves main and agentmain, and given that agents are more or less
>> rocket science (in the sense that only quite seasoned java programmers are
>> likely to ever get assigned the job of writing an agent), that really just
>> leaves main() as the one and only place in the entire java ecosystem where
>> structural typing is a thing .
>> Which is really, really, weird. It’s the very first method someone being
>> introduced to java is ever going to write, and it therefore -immediately- sends
>> new programmers down the wrong path. When you meet java for the first time, you
>> meet an aspect of java that is literally not how anything else in java works.
>> The reasons for it are obvious enough: Like switch syntax, it’s a holdover from
>> C - it was familiar to C programmers, java did indeed manage to become one of
>> the most popular languages in fairly short order and during a time when C was
>> incredibly popular, so this is no complaint about java’s past choices: Who
>> knows where java would be today if it hadn’t chosen to emulate C syntax as much
>> as possible even in cases where it was a highly dubious choice, even in
>> historical context (who likes original switch syntax? Surely that was always
>> horrible. This structural typing thing similarly is just bizarre).
>> But, if a JEP comes along to fix it, let’s… fix it. If possible. Which may just
>> be too difficult, in the sense that fixing it requires even more deviation from
>> what java programmers are used to. Then again, the point of JEP445 is surely
>> mostly about those new to java and far less to cater to the needs of seasoned
>> java programmers who are just slapping together a quick one-off script in java;
>> they have tools that generate this stuff for you and/or have jshell or similar
>> already installed if they run into this situation of needing a quickly
>> fire-and-forget stand-alone java app more than once in a blue moon.
>> Should look something like:
>> package java.lang;
>> public interface Application {
>> void main() throws Exception;
>> }
>> and to use, of course:
>> class MyApp implements Application {
>> public void main() {
>> }
>> }
>> An obvious issue here is that it eliminates some of the gains JEP445 just set up
>> for us. Even taking into account that in the vein of JEP445, class MyApp
>> implements Application is made optional, the lang spec still requires you to
>> make that main method public. Decreeing via JEP that you don’t have to is
>> perhaps pushing things a little too close into the “voodoo magic” column.
>> But, it does open up an opportunity to fix the rest of those first minutes of
>> meeting java in a far cleaner fashion.
>> Scanner is 90%+ suggested as the thing to use when writing keyboard-interactive
>> apps, and keyboard-interactive apps are 90%+ of all first-steps java apps.
>> SOURCE: Answering a ton of questions on stack overflow, and searching the web
>> for some java tutorials, all of which mention Scanner very early on. Which is a
>> problem - because as far as I can tell Scanner was never designed primarily for
>> keyboard input! - Or at least I hope not or it can vie for the dubious honour
>> of being the most unfit-for-stated-purpose core API library vs, I guess,
>> java.util.Calendar or some other sordid historic artefact of the core libs.
>> If Application is set up to look something like this:
>> public interface TerminalInteractive {
>> int promptInt(String prompt);
>> String promptString(String prompt);
>> String promptPassword(String prompt);
>> void print(String text); // no more need for printf due to JEP about formatters,
>> maybe?
>> void exit(int returnCode);
>> // you get the idea
>> // possibly some command line parsing tooling is appropriate here, too?
>> }
>> and Application itself is turned into:
>> public abstract class Application {
>> protected TerminalInteractive terminal;
>> protected abstract void main();
>> }
>> with an additional rule that on boot a JVM will properly initialize the terminal
>> field (or terminal is exposed in some other fashion to Application classes, the
>> above is to serve as inspiration and not a fully fleshed out proposal), all
>> those pesky issues with first-steps java (or at least, 90%+ of what beginners
>> are asking questions about) disappear. It also gets rid of some more utterly
>> unlike anything else in the entire ecosystem aspects of java, such as System.in
>> and System.out and System.err which are public static fields (very rare in the
>> java ecosystem), marked final, which are nevertheless not at all final but you
>> have to modify them using System.setOut and friends which is - unique. In a bad
>> way. Even just writing System.out.println ends up not looking like anything
>> else in the ecosystem and is sending folks learning java down the wrong path.
>> Nothing in java is like this. If you start designing APIs, do not design them
>> like System.out .
>> I’m not sure it’s worthwhile talking about simplifying main classes if ‘how does
>> one emit text and read stuff from the command line’ is not just ‘out of scope’
>> but ‘beyond even considering’, given that it seems self evident that virtually
>> all main apps break down into one of two camps:
>> (1) They are merely the entrypoint to hundreds of thousands+ lines of code, such
>> as a webserver that reads in routing tables and starts serving, or, say,
>> Eclipse, or IntelliJ. Trying to simplify them is irrelevant; not at all what
>> JEP445 is targeting, surely.
>> (2) A very simple app, possibly (probably) somebody learning java. In which case
>> terminal interaction is virtually guaranteed to be very relevant.
>> These concepts can be handwaved away as out of scope, but if that’s done I don’t
>> think this JEP fully accomplishes what it should. Teaching someone how to write
>> ‘hello world’ in java will still involve multiple completely bizarre (in the
>> sense that nothing in the java ecosystem works like that) concepts. And will
>> soon lead to very commonly asked questions because the very first API they run
>> into (Namely, Scanner) is very badly written API for the needs that these first
>> steps programmers have. JEP445 as-is is still useful: Getting rid of static is
>> very worthwhile (again, dealing with newbie questions is the primary source for
>> this, as static causes a ton of confusion and leads very significant
>> first-steps java programmers down the wrong path, making everything they write
>> static because if they do not “the compiler complains about 'something
>> something something static context’"), but other than allowing main to be
>> non-static, the rest of JEP445 doesn’t seem to accomplish meaningful change
>> without addressing structural typing and the API used to interact with
>> sysout/err/in.
>> Treating the JEP as merely steps along the way to perfection feels like making a
>> choice that OpenJDK will later regret, by enshrining into spec even further the
>> notion of a structurally typed main method.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230509/1bda9d21/attachment-0001.htm>
More information about the amber-dev
mailing list