Named parameters [was: Re: Reader mail bag]

Kevin Bourrillion kevinb at google.com
Wed Dec 6 19:46:58 UTC 2017


Yes, sometimes you can't choose a good default, or you hurt users by
changing your default. But that's not the common case. The common case is
that default values are extremely useful, letting an API designer *allow* a
customization without *requiring* it. If you look at the preponderance of
(a) telescoping method/constructor signatures and (b) builders, it's quite
plain that this is a frequent need. In fact, I'd say that the *best* thing
about supporting named parameters is that it allows for parameters to be
optional.

Google's codebase is about 743% made up of Builders*, and our interest in a
named/optional parameters feature is directly proportional to how many of
these builders we think it could eliminate. :-)

*figure may be exaggerated slightly




On Thu, Nov 30, 2017 at 6:32 PM, <forax at univ-mlv.fr> wrote:

> I will just anwser on the default argument part.
>
> Java already has a way to specify default argument using several overloads
> with a different numbers of argument, it's curbersome but it should not be
> too easy to specify default values.
> I believe that default argument are evil for two main reasons.
>
> It's like playing God, it's not the user of an API that specifies the
> default value, it's the creator of the API, so it's the creator the API
> saying to the world, i know how you will using my API, here are the default
> value you want. I tink we should be more humble when developing APIs and
> not pretend that we know what the good default are for all our users.
>
> Defaults are also part of the contract but people tends to think loosely
> about that part, defaults are implicit, so a part of the configuration of
> an object or a method in not visible at callsite, this leads to
> misunderstanding between what a user of a method think the method does and
> what the method really do.
>
> So i'm all for named parameters if it makes a method call easier to
> understand, if it makes method call harder to understand by introducing
> implicit values, i think i prefer the statu quo.
>
> Rémi
>
> ----- Mail original -----
> > De: "Guy Steele" <guy.steele at oracle.com>
> > À: "Remi Forax" <forax at univ-mlv.fr>
> > Cc: "Brian Goetz" <brian.goetz at oracle.com>, "amber-spec-experts" <
> amber-spec-experts at openjdk.java.net>
> > Envoyé: Jeudi 30 Novembre 2017 21:56:27
> > Objet: Named parameters [was: Re: Reader mail bag]
>
> > 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.
>



-- 
Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20171206/c5994172/attachment-0001.html>


More information about the amber-spec-experts mailing list