Reader mail bag

Remi Forax forax at univ-mlv.fr
Thu Nov 30 20:21:01 UTC 2017


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