Array patterns (and varargs patterns)

Brian Goetz brian.goetz at oracle.com
Sun Jan 10 19:50:39 UTC 2021


> I am a little confused by the expression on the matcher, i.e the 
> Integer.parseInt(var i) - it is not clear what is happening there and 
> I don't think I have seen it before. Can someone explain what is being 
> expressed by that case label?

This is a _nested pattern_.  One of the powerful things about patterns 
is that they compose; when I say:

     if (p instanceof Point(int x, int y)) { ... }

the `int x` and `int y` that are the "arguments" of the deconstructor 
are actually _nested patterns_.  What this means is:

    - test if p is a Point;
    - if so, cast to Point, and invoke its (int, int) deconstruction 
pattern, which yields ints for the x and y components
    - further match the resulting components to the patterns `int x` and 
`int y`, which happen to be total on `int`, and bind their target 
without reinterpretation.

We can compose more interesting patterns.  Suppose I have a record 
Point(int x, int y) , and a record Circle(Point center, int radius).  
Then I can match:

     if (shape instanceof Circle(Point(var x, var y) p, int r)) { ... }

This tests for circle-hood, extracts center and radius, and then further 
matches the center against Point(var x, var y), which happens to be 
total on Point.

So the nested patterns inside the STring[] { ... } are matched against 
the elements of the array.  Now, what does `Integer.parseInt(var i)` 
mean?  This is an example of a _static pattern_, which we don't have 
yet, but is part of the long-term story -- this is a (partial) pattern 
which applies to a String, which tries to parse the string as an int, 
and if so, binds the int.  In this way, we can compose the destructuring 
of the String array with the (possible) conversion from String to int, 
and either the whole thing matches (the thing is a string array, it has 
two elements, the first one can be parsed to an int, and we extract the 
int), or none of it does.

> Is it "match a String array with two elements the second of which is a 
> valid Integer represented as a String value"?

Yes :)

The code for this pattern would live in Integer, as a declared pattern, 
when such a thing is supported.

Cheers,
-Brian

> Here is the snippet:
>      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); }
>      }
> Regards
> Swaranga
>
>
> On Wed, Jan 6, 2021 at 8:44 AM Brian Goetz <brian.goetz at oracle.com 
> <mailto:brian.goetz at oracle.com>> wrote:
>
>
>
>     > Other languages have patent matching on head and tail of lists.
>     Adding
>     > this may mean there should be additional syntax.
>
>     I alluded to this in my mail, hoping that people wouldn't allow
>     themselves to be distracted by this particular siren song:
>
>     <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>
>
>     The idiom of "match a list by matching (head, tail)", which works
>     great
>     in Lisp and Haskell, is that (a) the representation of lists in
>     Lisp and
>     Haskell is a cons-cell, and (b) these language have tail-call
>     elimination, so that processing a list by recursion in this manner is
>     natural, efficient, and doesn't SOE.  Java has neither of these, so
>     grafting the illusion of this model when the runtime is not suited
>     to it
>     is just moving the problem one foot down the road, but ultimately
>     is not
>     going to be satisfying.  The performance will be poor, and we'll
>     SOE on
>     lists longer than a few tens of thousands of elements.
>
>     The bottom line here is that idioms from Language X are very much
>     connected to _the rest of language X_.  Ignoring this rarely works
>     out
>     well.
>
>     > Another issue is if the array is shorter say 0 length and one has:
>     >
>     >        if (arr instanceof int[] { var a, var b, ... }) { ... }
>     >
>     > Will this be an ArrayIndexOutOfBoundException or another
>     exception? If
>     > it is a reference type `a` and `b` can be null.
>
>     No.  Pattern matching is inherently conditional; the match above says
>     "does `arr` match this array pattern".  Matching the array pattern
>     means
>     being an array, _and_ having the right number of elements, _and_
>     having
>     those elements match the nested patterns. Matching should never throw
>     (though, once we allow users to write patterns that have code in
>     them,
>     it will be possible to do things like NPE, but those are bugs.)
>
>     >
>     >
>     > On Wed, 6 Jan 2021 at 15:31, Gavin Bierman
>     <gavin.bierman at oracle.com <mailto:gavin.bierman at oracle.com>
>     > <mailto:gavin.bierman at oracle.com
>     <mailto:gavin.bierman at oracle.com>>> wrote:
>     >
>     >     This is a feature that other languages call an “as pattern”,
>     >     because you are adding a new pattern variable binding to another
>     >     pattern (Standard ML used “as”, Haskell uses “@“ but calls it an
>     >     as pattern). It’s on our list of things to consider; part of the
>     >     consideration is whether it merits special syntax along with the
>     >     parsing issues of not having special syntax.
>     >
>     >     Gavin
>     >
>     >     > On 6 Jan 2021, at 05:44, Suminda Sirinath Salpitikorala
>     >     Dharmasena <sirinath1978m at gmail.com
>     <mailto:sirinath1978m at gmail.com>
>     >     <mailto:sirinath1978m at gmail.com
>     <mailto:sirinath1978m at gmail.com>>> wrote:
>     >     >
>     >     > Can we have something like:
>     >     >
>     >     >        if (arr instanceof String[] { var a, var b, ... }
>     >     stringArray) {
>     >     > ... }
>     >     >
>     >     > `stringArray` is optional but if present this will referrer to
>     >     the whole
>     >     > array.
>     >     >
>     >     >>
>     >
>



More information about the amber-dev mailing list