minimal value types proposal
john.r.rose at oracle.com
Thu Sep 1 05:52:48 UTC 2016
On Aug 31, 2016, at 9:46 PM, Dan Smith <daniel.smith at oracle.com> wrote:
> I'll probably have something else to add tomorrow (although, honestly, I'm cool with however you want to do this—just weighing in on how things look from where I sit). But maybe you can clarify this one thing for me:
>> On Aug 31, 2016, at 6:14 PM, John Rose <john.r.rose at oracle.com> wrote:
>>> It's a given that you have statics (see your Int128 declaration, for example). If instance methods are practically free after that, fine. But if not, there's no particular reason to support them. We don't have polymorphism (for Q types, anyway -- I'm assuming no automatic boxes, per (1)), and it's just as easy -- easier, in fact -- for a client to do "invokestatic Val.m(QVal;)I" as it is to do "invokedynamic [vinvoke ...]".
>> That's true, if we can settle on a stable enough translation strategy
>> that we can map virtual-appearing APIs to static methods. The indy
>> trick would let us put off some of that. Why put it off? Well, static
>> methods are already standard API points, and binding them from
>> fluent (x.f()) calls as well will come as a surprise, because of the alias.
>> Removing fluent calls is not a deal-breaker, but it will feel like
>> a cut, and too many such cuts will make the prototype programming
>> model too difficult even for super-users.
> I don't understand what "virtual-appearing APIs" and "fluent calls" mean in this context. Maybe I have the wrong idea of what we're talking about?
To explain the ad hoc terminology:
A static-method API has calls of this form: C.foo(x, y, z) or foo(x,
y, z) after static import. A fluent-style API has calls of the form
x.foo(y, z), and makes call chaining easy (important for "withers").
(Is there a better term for x.foo() than "fluent"? "Method postfix" as
opposed to "method prefix"?)
Also, by "virtual-appearing" I mean fluent or method-postfix (x.foo(y,z)).
> My presumptions: we're defining a bytecode format. There is zero Java language support. In that context, the syntax of bytecode method invocations is never "fluent"—you always have to spell out everything. The difference between 'invokestatic' and 'vinvoke' is minimal, and there is no ergonomic benefit to one or the other; meanwhile, both of these have plenty of ergonomic benefits over 'invokedynamic', if we really care about that, because all you need is a Methodref, not a complicated bootstrap method table. But I really don't think ergonomics of the bytecode format are a significant concern right now?
> I get the feeling you've skipped ahead to some sort of language support, but it's unclear what you intend it to look like.
I think the earliest decisions here have an effect on the practical
shape of the APIs folks will use at first, and even effect the cost
of getting to the right language design.
Here's why. But, first I have to admit: These are all at most
Whatever is the shape of the version-0 boxes, is the version-0 API
from the source-code viewpoint. I.e., there is a real source-code
shape for working with value types, derived from box-shape.
After that (version 0.1) javac can add whatever syntax and
translation strategy it wants for value-types. Maybe it can use a
non-dot syntax for member selection, in which case it makes zero
difference whether the L-type had static or non-static members,
because neither invocation syntax will apply.
But I'm assuming (maybe wrongly?) that will correlate with the
box-wise syntax. I.e., a non-static on the value's L-type API will
morph to a non-static on the Q-type API (when that boots up), and
likewise for statics.
So if you work with the boxes only with awkward static method
invocation APIs, that's the default we'll start with for values too.
So goes the reasoning. I'd like to avoid that chain of events, one
way or another.
One way is for us to say, "no, there is no such correlation", but I'm
dubious. People will code with L-types (because that's the only
option in today's unmodified compiler), then they will want their code
to recompile and work on Q-types when they come online. Isn't it
better, if we can contrive it just as easily, to supply APIs, even
from the start, that are closer to the APIs we want? That's a very
weak requirement, but I want to grab some if I can.
P.S. As you know, one of my pet peeves about Java today
is that subtle interactions between phasing of type inference
and name resolution force you to use static, prefix methods
even when one would prefer to use the fluent, postfix syntax.
It irks me when I have to make a method static just for type
inference reasons, when the API looks better non-static.
In the grand scheme of things it's tolerable, but I don't want to
let it happen unless I must. Ending up with value types that use
prefix, static method syntax would be more of that sort of irk.
When you have to just get over it and use some noxious language
misfeature, would that be called an "irkaround"?
More information about the valhalla-spec-observers