Array patterns (and varargs patterns)

Tagir Valeev amaembo at gmail.com
Thu Jan 7 04:50:30 UTC 2021


Hello!

While I like the idea in general, what is annoying is the necessity to
repeat the expression type in every pattern:
switch (limitString.split(":")) {
        case String[] { var _, Integer.parseInt(var i) } ->
setMultilineLimit(DEPTH, i);
        case String[] { Integer.parseInt(var i) } ->
setMultilineLimit(LENGTH, i);
        default -> { setMultilineLimit(DEPTH, -1);
setMultilineLimit(LENGTH, -1); }
}

Repetition of String[] looks noisy, and it doesn't add much
information for the code reader. I'm not sure what could be done here.
Probably a placeholder in the pattern to replace a selector type, like
this:
switch (limitString.split(":")) {
        case _ { var _, Integer.parseInt(var i) } ->
setMultilineLimit(DEPTH, i);
        case _ { Integer.parseInt(var i) } -> setMultilineLimit(LENGTH, i);
        default -> { setMultilineLimit(DEPTH, -1);
setMultilineLimit(LENGTH, -1); }
}

But it looks ugly...

With best regards,
Tagir Valeev.

On Wed, Jan 6, 2021 at 1:48 AM Brian Goetz <brian.goetz at oracle.com> wrote:
>
> As we get into the next round of pattern matching, I'd like to opportunistically attach another sub-feature: array patterns.  (This also bears on the question of "how would varargs patterns work", which I'll address below, though they might come later.)
>
> ## Array Patterns
>
> If we want to create a new array, we do so with an array construction expression:
>
>     new String[] { "a", "b" }
>
> Since each form of aggregation should have its dual in destructuring, the natural way to represent an array pattern (h/t to AlanM for suggesting this) is:
>
>     if (arr instanceof String[] { var a, var b }) { ... }
>
> Here, the applicability test is: "are you an instanceof of String[], with length = 2", and if so, we cast to String[], extract the two elements, and match them to the nested patterns `var a` and `var b`.   This is the natural analogue of deconstruction patterns for arrays, complete with nesting.
>
> Since an array can have more elements, we likely need a way to say "length >= 2" rather than simply "length == 2".  There are multiple syntactic ways to get there, for now I'm going to write
>
>     if (arr instanceof String[] { var a, var b, ... })
>
> to indicate "more".  The "..." matches zero or more elements and binds nothing.
>
> <digression>
> People are immediately going to ask "can I bind something to the remainder"; I think this is mostly an "attractive distraction", and would prefer to not have this dominate the discussion.
> </digression>
>
> Here's an example from the JDK that could use this effectively:
>
> String[] limits = limitString.split(":");
> try {
>     switch (limits.length) {
>         case 2: {
>             if (!limits[1].equals("*"))
>                 setMultilineLimit(MultilineLimit.DEPTH, Integer.parseInt(limits[1]));
>         }
>         case 1: {
>             if (!limits[0].equals("*"))
>                 setMultilineLimit(MultilineLimit.LENGTH, Integer.parseInt(limits[0]));
>         }
>     }
> }
> catch(NumberFormatException ex) {
>     setMultilineLimit(MultilineLimit.DEPTH, -1);
>     setMultilineLimit(MultilineLimit.LENGTH, -1);
> }
>
> becomes (eventually)
>
>     switch (limitString.split(":")) {
>         case String[] { var _, Integer.parseInt(var i) } -> setMultilineLimit(DEPTH, i);
>         case String[] { Integer.parseInt(var i) } -> setMultilineLimit(LENGTH, i);
>         default -> { setMultilineLimit(DEPTH, -1); setMultilineLimit(LENGTH, -1); }
>     }
>
> Note how not only does this become more compact, but the unchecked "NumberFormatException" is folded into the match, rather than being a separate concern.
>
>
> ## Varargs patterns
>
> Having array patterns offers us a natural way to interpret deconstruction patterns for varargs records.  Assume we have:
>
>     void m(X... xs) { }
>
> Then a varargs invocation
>
>     m(a, b, c)
>
> is really sugar for
>
>     m(new X[] { a, b, c })
>
> So the dual of a varargs invocation, a varargs match, is really a match to an array pattern.  So for a record
>
>     record R(X... xs) { }
>
> a varargs match:
>
>     case R(var a, var b, var c):
>
> is really sugar for an array match:
>
>     case R(X[] { var a, var b, var c }):
>
> And similarly, we can use our "more arity" indicator:
>
>     case R(var a, var b, var c, ...):
>
> to indicate that there are at least three elements.
>
>


More information about the amber-spec-experts mailing list