Named parameters [was: Re: Reader mail bag]
forax at univ-mlv.fr
forax at univ-mlv.fr
Thu Nov 30 23:14:01 UTC 2017
You want is to be able to use named parameters as builders.
In my opinion, this is really hard to combine with the overriding rules.
But like @SafeVarargs, we can limit named parameters to constuctors, static methods, private methods and final methods.
indy can bridge overriding too but it means you need to express the inlining cache with indy too, you can not as i've proposed to just permute the argument with indy but let the VM do the method invocation. Using indy to manage the inlining cache will require a lot of work tuning to get the same perf as we have actually.
Rémi
----- Mail original -----
> De: "Brian Goetz" <brian.goetz at oracle.com>
> À: "Guy Steele" <guy.steele at oracle.com>, "Remi Forax" <forax at univ-mlv.fr>
> Cc: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Envoyé: Jeudi 30 Novembre 2017 22:41:53
> Objet: Re: Named parameters [was: Re: Reader mail bag]
> All of this, and: what happens when a client compiles against a given
> named method signature, and then, through separate compilation, the
> method signature changes, say, to add a new parameter? Dealing with
> this in some form seems essential, as, the most common cases where you
> want to invoke by name is when a method has many parameters (especially
> if many of those are optional), and, if a method has 17 parameters,
> surely some day it will have 18. And users will expect that adding a
> new parameter with a default is compatible. (Indy provides a nice
> mechanism for sewing up this gap, but, we need to outline the
> requirements and the compatibility guarantees.)
>
> On 11/30/2017 3:56 PM, Guy Steele wrote:
>> Thanks, Remi, this is an excellent start! And it may be where we want to end
>> up.
>>
>> But when the time comes that we dig into a serious discussion of putting named
>> method parameters into Java, I would like to see a broader exploration of the
>> design space before we settle on a specific design.
>>
>> I’ve seen a lot of other designs for a lot of other languages, each with pros
>> and cons.
>>
>> There are at least four more-or-less orthogonal properties a method parameter
>> can have:
>>
>> (1) May it be specified by name (rather than by position) at the call site?
>> If so, can it be specified _either_ by name or by position?
>>
>> (2) May the corresponding actual argument be omitted at the call site?
>> If so, what happens?
>> System-specified default value (such as zero or null) is supplied.
>> Programmer-specified default value is supplied.
>> Value is a compile-time constant.
>> Value is recomputed at call time.
>> Can this computation depend on other argument values (such as those to the
>> left)?
>> No value is supplied.
>> A separate mechanism allows inquiry as to whether an actual argument was
>> provided.
>> The parameter type is actually an option type (choice; if no value is supplied,
>> you get an empty value).
>>
>> (3) May the corresponding actual argument be duplicated at the call site?
>> (This may make little sense for Java, but is used extensively in Common Lisp,
>> where name-value lists may be built dynamically and then fed to `apply`;
>> allowing duplications makes it easy to override a default by just sticking a
>> new name-value pair onto the front of a list.)
>>
>> (4) May the actual arguments be permuted at the call site—that is, appear in an
>> order other than the order in which they are declared in the method
>> declaration?
>> (Typically the answer is “no” for positional parameters, but may be “yes” or
>> “no” for named parameters.)
>> (If a call contains both positional and named arguments, one can ask whether the
>> named arguments may be mixed in among the positional ones [yech!] or must be
>> kept separate, such as always appearing to the right of the positional
>> arguments.)
>>
>> For each of the preceding four questions, there are these meta-questions:
>> Is the answer to the question the same for all parameters whatsoever?
>> Is the answer to the question the same for all parameters of the same kind (such
>> as named or positional)?
>> Is the answer to the question the same for all parameters in a single method
>> declaration?
>> Is the answer to the question the same for all parameters of the same kind (such
>> as named or positional) in a single method declaration?
>>
>> In addition, there is the question of exactly what combinations of positional,
>> optional positional, named, and/or optional named parameters may be used within
>> a single method declaration.
>> And there is the question of what combinations of combinations may appear within
>> an overload set.
>>
>> Many of these questions are in fact answered by specific choices in the proposal
>> below. I’m just looking to seeing (eventually) a thorough discussion of the
>> rationale for each choice. I provide this list of questions as one possible
>> starting point for that discussion.
>>
>> —Guy
>>
>>> On Nov 30, 2017, at 3:21 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>>>
>>> My note on named parameters:
>>> Supporting real named parameters that works with overriding and backward
>>> compatibility is hard, but i believe there is a sweet spot.
>>>
>>> - a method can declare to support named parameters by using a new modifier
>>> 'named'.
>>> so - all parameters are named or none are, you can not mix positional and named
>>> parameters like in Ruby.
>>> - a method is either support positional parameters or named parameters but not
>>> both at the same time.
>>> if there are several overloads, you can only have one named overload with the
>>> same number of parameters,
>>> which means that counting the number of parameters is enough to know which
>>> method can be called.
>>> a varargs method can not be named.
>>>
>>> - when overriding a method, a named method can not override a non named method.
>>> overriding a named method with a non named method is allowed to ease the
>>> transition but emit a warning.
>>> a named method that overrides another named method need to have the same
>>> parameters with the same name at the same position.
>>>
>>> - at call site, a named method has to be called using the syntax "name:
>>> argument" for each arguments
>>> by example:
>>> ThreadGroup main = ...
>>> new ThreadGroup(parent: main, name: "my group");
>>> if a named method is called with positional arguments, the compiler emit a
>>> warning
>>>
>>> - at compile time,
>>> a declaration site, all parameter named are stored in the Parameter attribute.
>>> a callsite, the compile insert an invokedynamic to the NamedParameterMetaFactory
>>> with a method handle ref on the declared named method and the names of all
>>> arguments in the order of the call.
>>> a runtime, the NamedParameterMetaFactory verifies that the number of named
>>> argument is the same and are a permutation of the declared parameters that are
>>> retrieved by cracking the method handle ref as a MethodHandleInfo and calling
>>> getParameters on the corresponding Constructor/Method, once the permutation is
>>> calculated, the NamedParameterMetaFactory returns a ConstantCallSite on the
>>> constant method handle (the method handle ref) permuted using
>>> MethodHandles.permuteArguments.
>>>
>>> To summarize, this let us use named parameters if the API designer want to allow
>>> that,
>>> there is a path for upgrading a method that uses positional parameters to use
>>> named parameters, but not in the other way (like varargs),
>>> not supporting permutations between overridden methods make thing far simpler
>>> that they are otherwise.
>>>
>>> cheers,
>>> Rémi
>>>
>>> ----- Mail original -----
>>>> De: "Brian Goetz" <brian.goetz at oracle.com>
>>>> À: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
>>>> Envoyé: Jeudi 30 Novembre 2017 19:29:41
>>>> Objet: Reader mail bag
>>>> We've gotten two submissions to the amber-spec-comments list.
>>>>
>>>> 1. "Forcing a pattern match", at:
>>>> http://mail.openjdk.java.net/pipermail/amber-spec-comments/2017-November/000000.html
>>>>
>>>> 2. "Named parameters in data classes", at:
>>>> http://mail.openjdk.java.net/pipermail/amber-spec-comments/2017-November/000003.html
>>>>
>>>>
>>>> I think the first asks for an alternate form of the "matches" operator
>>>> which would fail with a CCE, rather than evaluating to false, if the
>>>> match fails. This would be essentially saying, "This should match; if
>>>> it doesn't, that's an error." I think that's what's being asked, but
>>>> then he talks about an "unnecessary instanceof check", which makes me
>>>> wonder whether this is really just about optimization.
>>>>
>>>> To be clear, the instanceof check is neither expensive nor unnecessary.
>>>> (Though we can optimize these away when we know the static type of the
>>>> target; if x is a Foo, then "x matches Foo f" can be statically
>>>> strength-reduced to "x != null".)
>>>>
>>>> Note that the "if member.getKind() == VARIABLE" is merely a manual
>>>> optimization; you could easily leave that out and just match against
>>>> VariableTree. What we'd rather focus on is how to get to:
>>>>
>>>> switch (member) {
>>>> case BlockTree bt: ...
>>>> case VariableTree vt: ...
>>>> }
>>>>
>>>> while allowing the pattern to capture the quicker pre-test (kind ==
>>>> BLOCK) and maintain the performance without making the user worry about
>>>> this. We have some ideas here, but I don't think this "forcing" idea
>>>> really offers a lot.
>>>>
>>>>
>>>> The second (named parameters) was a question I was expecting.
>>>>
>>>> I agree that being able to invoke constructors and methods by name can
>>>> sometimes result in easier-to-read code, especially when some parameters
>>>> have a sensible default value. (This is also a more complicated feature
>>>> than anyone gives it credit for, so it's not the "gimme" it is often
>>>> assumed to be.)
>>>>
>>>> However, data classes is not the place to cram in this feature; this
>>>> should be a feature that stands on its own, and applies to all classes,
>>>> data- or not. One of the design goals for data classes is that a data
>>>> class should be essentially a "macro" for a class you could write by
>>>> hand; this allows easy migration from existing classes to data classes
>>>> (if they meet the requirements) and from data classes to full classes if
>>>> they expand to no longer fit the data class profile. The more that
>>>> *uses* of data classes or their members are different from the
>>>> corresponding use of regular classes, the more difficult this migration
>>>> becomes. (This is not unlike the design mandate with default methods;
>>>> from the client perspective, they're just ordinary virtual methods, and
>>>> you can't tell whether the method was implemented directly or inherited
>>>> -- they're just methods.)
>>>>
>>>> So, while named parameters are a reasonable feature to explore, trying
>>>> to staple them onto data classes would be a mistake. They are their own
> >>> feature. We're open to exploring it, but we've got our plate full for now.
More information about the amber-spec-experts
mailing list