Comments/Feature Requests regarding JEP 305: Pattern Matching

Brian Goetz brian.goetz at oracle.com
Thu Jul 6 18:27:22 UTC 2017


There are really at least three separate requests here.

1.  Don't make me provide a name if I don't need one.

2.  Please provide flow-typing so that I can just reuse the target.  
(And with instanceof too, thanks.)

3.  Don't make me provide unique names for every binding.

#1 is well in hand; you can always use an unnamed binding (_), and we 
may make bindings optional as well.

#2 sounds nice, but runs out of gas pretty quickly.  Sometimes the 
switch target is not a variable, but an expression; repeating the 
expression is undesirable (especially if there are side-effects.)

#3 is taken care of by our scoping rules.  You can re-use binding 
variable names:

     case Integer x:
     case Double x:
     case Float x:

A variant of #2 would be to allow the user to explicitly re-use (and 
hence shadow) the target:

     switch (p) {
         case Integer p:
         case Double p:
         case Float p:
     }

We might consider that, as it is in line with another shadowing-related 
change we're making as part of Lambda Leftovers.

On 7/5/2017 4:34 PM, William Shackleford wrote:
> In the examples provided in the  JEP it looks as though it would always be
> required to provide new
> variable names each time a pattern match is used.
>
> Could we eliminate the new variable names or make them optional?
> As written it doesn't seem to completely provide the benefits of flow
> typing.
>
> This would have the following benefits.
>
> 1. It is more compact.
> 2. It reduces the number of variable names you need to think of when
> writing code.
> 3. It reduces the chances of needing one variable name to shadow another.
> 4. It is easier to see if a variable is used or modified if it is only
> referenced with one name.
>
>
> For example
>
> String formatted;
> switch (p) {
>      case Integer i: formatted = String.format("int %d", i); break;
>      case Byte b:    formatted = String.format("byte %d", b); break;
>      case Long l:    formatted = String.format("long %d", l); break;
>      case Double d:  formatted = String.format(“double %f", d); break;
>      case String s:  formatted = String.format("String %s", s); break
>      default:        formatted = obj.toString();
> }
>
> would change to
>
>
> String formatted;
> switch (p) {
>      case Integer: formatted = String.format("int %d", p); break;
>      case Byte:    formatted = String.format("byte %d", p); break;
>      case Long:    formatted = String.format("long %d", p); break;
>      case Double:  formatted = String.format(“double %f", p); break;
>      case String:  formatted = String.format("String %s", p); break
>      default:        formatted = p.toString();
> }
>
>
> In the second one if i,b,l,d,s are other variables in scope there is no
> chance of misunderstanding that they have been shadowed by the new
> variables. If you look for where is p used, the answer in both cases is all
> the format calls but thats easier to
> see at a glance in the second example.  Generally the variable name p would
> give one insight into the source or purpose of that variable which is lost
> if you change to a variable name chosen just to indicate the type, or the
> variable names end up too long if one always appends the type info to the
> source and/or purpose info in the name.
>
>
> Also :
>
>      int eval(Node n) {
>          switch(n) {
>              case IntNode(int i): return i;
>              case NegNode(Node n): return -eval(n);
>              case AddNode(Node left, Node right): return eval(left) +
> eval(right);
>              case MulNode(Node left, Node right): return eval(left) *
> eval(right);
>              default: throw new IllegalStateException(n);
>          };
>      }
>
>
>
> could be written more concisely as
>
>
>      int eval(Node n) {
>          switch(n) {
>              case IntNode: return n.i;
>              case NegNode: return -eval(n.n);
>              case AddNode: return eval(n.left) + eval(n.right);
>              case MulNode: return eval(n.left) * eval(n.right);
>              default: throw new IllegalStateException(n);
>          };
>      }
>
>
> In addition to being more concise:
>   n is not both used as the positive part of the NegNode and as the input
> parameter.
> It works with classes that have more fields/methods than constructor
> arguments.
> It seems to me that is better to consistently use a single syntax style
> rather than having one for classes
> that have only one or two fields that happen to match the constructor
> arguments and another more
> general style. This is especially true given that it doesn't even seem to
> make the code more concise.
>
>
> -- Will



More information about the amber-dev mailing list