Named parameters [was: Re: Reader mail bag]

Brian Goetz brian.goetz at
Thu Nov 30 21:41:53 UTC 2017

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> 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>
>>> À: "amber-spec-experts" <amber-spec-experts at>
>>> 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:
>>> 2.  "Named parameters in data classes", at:
>>> 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-observers mailing list