<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="+1"><font face="monospace">Here's the first half of an
        *extremely rough* doc-in-progress that starts to show more of
        the syntax of the declaration of a pattern -- but does yet not
        dive into the _body_ of a pattern (which we should still leave
        for a later discussion).  This is still more about object model
        than directly about syntax; many people have been asking "I'm
        having a hard time imagining what this looks like in a class
        file", so this should help a bit.  It also fleshes out some of
        the requirements, specifically patterns delegating to other
        patterns.  <br>
        <br>
        <br>
        <br>
        ## Beyond built-in patterns<br>
        <br>
        Related documents have explored a number of built-in pattern
        types, where the<br>
        compiler knows enough about the pattern semantics to implement
        them directly,<br>
        such as type patterns or record deconstruction patterns. 
        However, we also wish<br>
        to support direct declaration of patterns as class members, such
        as<br>
        deconstruction patterns for non-record classes, static patterns,
        and instance<br>
        patterns.<br>
        <br>
        Given a pattern match like:<br>
        <br>
        ```<br>
        if (p instanceof Point(int x, int y)) { ... }<br>
        ```<br>
        <br>
        assuming the pattern matches, we need to capture somewhere how
        the bindings  `x`<br>
        and `y` are extracted from the `Point`.  If `Point` is a record,
        we can do this<br>
        without help from the user, but otherwise, someone is going to
        need to write<br>
        some code somewhere to capture the applicability test and state
        extraction<br>
        corresponding to this pattern.  (One can imagine various
        "tricks" for doing so<br>
        (i.e., extracting fields, calling getters, etc), but these
        tricks quickly run<br>
        out of gas for classes whose state is not trivially and
        transparently coupled to<br>
        its API.)  We'll call the various forms of this _member
        patterns_, which are<br>
        expressed as a new kind of class member.<br>
        <br>
        > Member patterns are executable class members, just like
        constructors and<br>
        > methods.<br>
        <br>
        Abstractly, a pattern operates on a single target parameter
        (which for instance<br>
        and deconstruction patterns is just the receiver), and either
        succeeds or fails<br>
        based on some condition.  If it succeeds, it produces zero or
        more output values<br>
        (the destructured components, or _bindings_.)<br>
        <br>
        #### Pattern declarations in other languages<br>
        <br>
        We may be able to obtain some inspiration by looking at what
        other languages do.<br>
        By the late 1990s, pattern matching over structural types
        (sequences and tuples)<br>
        was a common feature of functional languages; languages that
        supported nominal<br>
        product types (e.g., Haskell) also supported pattern matching
        over nominal<br>
        product types.  In the mid-2000s, languages like
        [F#][fs-patterns] and<br>
        [Scala][scala-patterns] extended the notion to additionally
        apply to abstract<br>
        data types (those whose concrete representation was not
        necessary known to the<br>
        client.) However, in both F# and Scala, patterns remain
        distinctly `static`<br>
        entities; they are not a first-class part of the object
        hierarchy, and remain at<br>
        the periphery of the object model.<br>
        <br>
        Scala takes the approach of modeling patterns as static methods
        with the name<br>
        `unapply`.  An `unapply` method takes a single parameter (type
        checked against<br>
        the matchee) and has some flexibility in its return type; it can
        return<br>
        `boolean` if there are no bindings, or `Option[T]` (where `T` is
        often a tuple<br>
        type) to carry the binding parameters.  A matcher for
        `Point(x,y)` would look<br>
        like:<br>
        <br>
        ```<br>
        object Point {<br>
            Option[Tuple[int, int]] unapply() { ... }<br>
        }<br>
        ```<br>
        <br>
        This is a pragmatic approach, with pros and cons.  It is nice
        that it is just an<br>
        ordinary method, which can be called either directly or through
        a pattern match.<br>
        On the other hand, there is lots of magic -- the language
        imputes special<br>
        semantics based on method name, enclosing class, argument list,
        and return type.<br>
        Also, because these methods are effectively static, there is no
        ability to<br>
        overload, override, have abstract patterns, etc.  <br>
        <br>
        C# takes a more principled, but also more limited, approach.  As
        of C# 9, a<br>
        class can write one or more `Deconstruct` methods (magic name),
        using `out`<br>
        parameters to receive the bindings (a feature already present in
        C#).  A<br>
        `Deconstruct` method must be total (the deconstruction cannot
        fail), and there<br>
        is no way to write instance or abstract patterns (though the
        equivalent of some<br>
        static patterns can be achieved with extension methods.)<br>
        <br>
        Both of these approaches are adding patterns "around the edges";
        we are<br>
        proposing a pattern matching model that integrates much more
        deeply into the<br>
        object model.<br>
        <br>
        #### Deconstruction patterns in Java<br>
        <br>
        The simplest form of pattern is a _deconstruction pattern_,
        which is the dual of<br>
        a constructor.  And, just as constructors are an odd mix of
        instance and static<br>
        behavior -- they are instance members (they have a receiver) but
        are not<br>
        inherited and can only be accessed through their class name --
        their duals have<br>
        the exact same odd mix.  Another oddity of constructors is that
        they don't  have<br>
        names -- the name supplied at the instantiate site is the name
        of a class,  not<br>
        a class member.  It makes sense for deconstruction patterns to
        also share this<br>
        characteristic.<br>
        <br>
        The target of a deconstruction pattern is obvious -- it is the
        receiver.<br>
        Deconstruction patterns are _total_ on their target type -- as
        long as the<br>
        target is valid as a receiver, the pattern always succeeds. 
        We'd like for the<br>
        arity, types, order, and names of the binding variables to be
        manifest in the<br>
        declaration code, as this is part of the classes API, and for
        the similarity<br>
        with the corresponding constructor, if there is one, to be
        obvious both at the<br>
        declaration and use site.  This might look like:<br>
        <br>
        ```{.java}<br>
        class Point {<br>
            int x, y;<br>
        <br>
            Point(int x, int y) {<br>
                // constructor body<br>
            }<br>
        <br>
            deconstructor(int x, int y) {<br>
              // deconstructor body<br>
            }<br>
        }<br>
        ```<br>
        <br>
        There is a strong symmetry between the declarations of the
        constructor and<br>
        deconstructor.  The constructor takes as arguments `x` and `y`
        and produces a<br>
        `Point`; the deconstructor takes a `Point` and produces as
        bindings `x` and `y`,<br>
        and the declaration of the argument list of the constructor and
        the binding list<br>
        of the deconstructor are syntactically similar.  The locution<br>
        `deconstructor(BINDINGS)` is meant to evoke the notion of
        "returning" the<br>
        specified set of bindings.  For classes that model entities more
        or less<br>
        transparently, as `Point` does, it is entirely reasonable to
        match constructors<br>
        with deconstructors whose binding lists correspond to the
        constructor parameter<br>
        list.<br>
        <br>
        There is also a symmetry between the creation of an object with
        a constructor,<br>
        and the destructuring of an object with a deconstruction
        pattern.  A client<br>
        matches against a deconstruction pattern as follows:<br>
        <br>
        ```<br>
        case Point(var x, var y):<br>
        ```<br>
        <br>
        Here, we interpret `Point` as a class name, and look in the
        `Point` class for a<br>
        deconstruction pattern with compatible binding arity and types
        -- analogously to<br>
        how we interpret the instance creation expression `new Point(x,
        y)`.  <br>
        <br>
        We've left out the declaration of the body for now; we'll return
        to this after<br>
        our tour of the member pattern model.  But it's important to
        note that, just as<br>
        the constructor is free to perform defensive copying on the
        inputs, the<br>
        deconstructor needs a way to do the same with the bindings.  <br>
        <br>
        Deconstruction patterns are unusual in that they are always
        _total_; if the<br>
        target is of the correct type, the deconstruction pattern should
        always complete<br>
        successfully.  However, not all patterns are total; a pattern
        like<br>
        `Optional.of(var x)` will only match a subset of instances of
        `Optional`.  As a<br>
        simplifying approximation, we'll say that all other member
        pattern are partial;<br>
        the bodies of these patterns will need a way to denote this as
        well.<br>
        <br>
        There's also no reason that deconstruction patterns cannot
        appear in interfaces,<br>
        as long the interface supports enough API to implement it.  For
        example, we<br>
        might want `Map.Entry` to support a deconstruction pattern that
        yields key and<br>
        value:<br>
        <br>
        ```<br>
        interface Entry<K,V> {<br>
            K getKey();<br>
            V getValue();<br>
        <br>
            deconstructor(K key, V value) {<br>
                // invoke getKey() and getValue() and bind them
        appropriately<br>
            }<br>
        }<br>
        ```<br>
        <br>
        This would allow us to iterate through the elements of a `Map`
        more directly:<br>
        <br>
        ```<br>
        for (Map.Entry(var k, var v) : map.entrySet()) {<br>
            // use k and v<br>
        }<br>
        ```<br>
        <br>
        #### Instance patterns<br>
        <br>
        The next simplest form of pattern declarations are _instance
        patterns_, which<br>
        are duals of instance methods.  As with deconstruction patterns,
        the target of<br>
        an instance pattern is the receiver, but unlike deconstruction
        patterns,<br>
        instance patterns can be partial.  An instance pattern
        declaration looks like:<br>
        <br>
        ```<br>
        class Class<T> {<br>
            public pattern(Class<?> componentType) arrayClass() {<br>
                ... body ...<br>
            }<br>
        }<br>
        ```<br>
        <br>
        A significant difference from deconstruction patterns is that
        instance patterns<br>
        have names (just as instance methods do); later, we'll see that
        they can also<br>
        have input arguments.<br>
        <br>
        At the use site, instance patterns are usually unqualified,
        referring to an<br>
        instance pattern on the static type of the match target.  So if
        we have a<br>
        `Class` in hand, we can match on those classes that represent
        arrays as:<br>
        <br>
        ```<br>
        switch (clazz) {<br>
            case arrayClass(var componentType):<br>
        }<br>
        ```<br>
        <br>
        #### Static patterns<br>
        <br>
        Static patterns are slightly more complicated than instance
        patterns, because<br>
        they lack a receiver -- and so the match target must be
        identified some other<br>
        way.  We can do this by indicating the target type and name as a
        pattern<br>
        parameter.  The duality between the "receiver" and the first
        parameter of a<br>
        static method is not only well-known to the JVM), but also has
        precedent in the<br>
        language: the method reference `Foo::bar` could refer to a
        static method of<br>
        `Foo` or to an instance method (an "unbound method reference"),
        in which case<br>
        the first argument becomes the receiver.<br>
        <br>
        ```<br>
        class Optional<T> {<br>
            static<T> Optional<T> of(T t) { ... }<br>
        <br>
            static<T> pattern(T t) of(Optional<T> target) {
        ... }<br>
        <br>
            static<T> Optional<T> empty() { ... }<br>
        <br>
            static<T> pattern() empty(Optional<T> target) {
        ... }<br>
        }<br>
        ```<br>
        <br>
        This leads to the familiar symmetry at the use site: we
        construct `Optional`<br>
        instances with `Optional.empty()` and `Optional.of(t)`, and
        match against them<br>
        like:<br>
        <br>
        ```<br>
        switch (opt) {<br>
            case Optional.of(var t): ...<br>
            case Optional.empty(): ...<br>
        }<br>
        ```<br>
        <br>
        #### Patterns with input arguments<br>
        <br>
        Pattern matching fuse a test with zero or more conditional
        extractions, which is<br>
        something we already do all the time.  Regular expression
        parsing is an example<br>
        of this combination -- when we match against a regular
        expression, we get both a<br>
        boolean result (did it match), and, if it did, we can then
        extract the "groups"<br>
        bounded by `(...)` in the regular expression.  It would be nice
        if we could<br>
        represent a regular expression as  an ordinary pattern match,
        rather than using<br>
        an ad-hoc calling sequence, while still delegating to the same
        underlying<br>
        regular expression library.  So how do we turn a regular
        expression into a<br>
        pattern?  <br>
        <br>
        We already have almost all the tools needed; a regular
        expression is like a<br>
        pattern which binds a `String...`, whose target is a `String`. 
        We could, for<br>
        each regular expression, write a static pattern:<br>
        <br>
        ```<br>
        Pattern asbs = Pattern.compile("(a*)(b*)");<br>
        <br>
        static pattern(String...) asbsMatch(String target) { ...<br>
            ... use asbs to match target, and extract the groups ...<br>
        }<br>
        ```<br>
        <br>
        This works -- we could ask if a string matches the pattern
        `asbsMatch()`,  and<br>
        bind the groups if so (further refining with nested patterns if
        we like.)  But<br>
        it seems a little clunky to have to write this method for every
        regular<br>
        expression; we'd like to write it once, and parameterize it with
        the regular<br>
        expression we want.  This means we need to be able to specify an
        additional<br>
        input argument beyond the match target.   This might be
        declared:<br>
        <br>
        ```<br>
        static pattern(String... groups) regex(String target, String
        regex) {<br>
            ... use regex library to match against regex, extract
        bindings ...<br>
        }<br>
        ```<br>
        <br>
        Here, the first parameter denotes the target of the match (as
        before);  the<br>
        remaining parameters must be passed at the use site.  This might
        be written:<br>
        <br>
        ```<br>
        String AS_AND_BS = "(a*)(b*)";<br>
        case regex(AS_AND_BS, String[] { var aString, var bString }):<br>
        ```<br>
        <br>
        where the first "parameter" is the input parameter, and the
        second is a nested<br>
        pattern that matches the sole binding variable.  This is easy
        enough for<br>
        compilers to work out, but not so great for humans; it is not
        always obvious<br>
        where the data ends and the patterns begin.   (This gets worse
        if there are<br>
        syntactic constructs that could be either arguments or nested
        patterns, such as<br>
        denoting constant patterns with literals.)   So it is probably
        preferable to<br>
        syntactically reflect the two different sorts of arguments, such
        as:<br>
        <br>
        ```<br>
        case regex(AS_AND_BS)(String[] { var aString, var bString }):<br>
        ```<br>
        <br>
        If a pattern has two argument lists, the first is the input
        arguments, and the<br>
        second receives the bindings.  If the first list is empty, as it
        usually is,<br>
        it can be omitted.  Since our regex pattern is a varargs
        pattern, we could also<br>
        elide the `String[]` pattern scaffolding:<br>
        <br>
        ```<br>
        case regex(AS_AND_BS)(String aString, String bString):<br>
        ```<br>
        <br>
        We would likely want to enforce the requirement that expressions
        used as input<br>
        arguments be _effectively final_, to eliminate any confusion
        about the timing<br>
        of when they are evaluated.  <br>
        <br>
        #### Alternatives to Map::get<br>
        <br>
        The `Map::get` method takes a key and returns the corresponding
        value, if the<br>
        mapping is present in the map, or `null` if the mapping is not
        present.  This is<br>
        a problematic API choice for a number of reasons.  First, if the
        map supports<br>
        null values, it is impossible to distinguish a mapping to null
        from<br>
        mapping-not-present; if we try to distinguish between these
        cases with<br>
        `Map::containsKey`,  we risk a possible race condition.  And, as
        we integrate<br>
        inline classes and primitives into the generic type system as we
        are in<br>
        Project Valhalla, for some types, `null` will not be available
        as a sentinel.  <br>
        <br>
        If we had patterns in the language when we designed Collections,
        we might have<br>
        reached for a pattern, which captures both the "is the mapping
        present", and<br>
        "if so, what is the key mapped to" in one go:<br>
        <br>
        ```<br>
        interface Map {<br>
            pattern(V value) withMapping(K key);<br>
        }<br>
        ```<br>
        <br>
        and clients would be required to confront this conditionality
        directly:<br>
        <br>
        ```<br>
        if (m instanceof Map.withMapping(k)(var v)) { ... use v ... }<br>
        ```<br>
        <br>
        ## Composition<br>
        <br>
        Just as constructors compose (a subclass constructor can
        delegate to a<br>
        superclass constructor, and constructors/factories can delegate
        to<br>
        constructors/factories for their components), patterns should
        compose as well.  <br>
        Let's gather some requirements for composition of pattern
        declarations.<br>
        <br>
        ```<br>
        class A {<br>
            private int a;<br>
        <br>
            public A(int a) { this.a = a; }<br>
            public deconstructor(int a) { ... }<br>
        }<br>
        <br>
        class B extends A {<br>
            private int b;<br>
        <br>
            public B(int a, int b) { super(a); this.b = b; }<br>
        <br>
            public pattern(int a, int b) {<br>
                // want to delegate to superclass deconstructor<br>
            }<br>
        }<br>
        ```<br>
        <br>
        The class `A` was designed for subclassing, and subclass
        constructors will<br>
        delegate to constructors in `A`.  Since deconstruction is the
        dual of<br>
        construction, it stands to reason that the deconstruction
        pattern in `B` can<br>
        delegate to the deconstruction pattern in `A`, and then add
        whatever B-specific<br>
        deconstruction logic is needed.<br>
        <br>
        If we use composition instead of inheritance, we have a similar
        requirement.  In<br>
        this next example, class `D` has two members of type `C`, and
        `D`'s constructor<br>
        delegates to the  `B` constructor; we would want its
        deconstructor to be able<br>
        to do the same thing.  <br>
        <br>
        ```<br>
        class C {<br>
            private int c;<br>
        <br>
            public C(int c) { this.c = c; }<br>
            public deconstructor(int c) {  ... }<br>
        }<br>
        <br>
        class D {<br>
            C c1;<br>
            C c2;<br>
        <br>
            public D(int x, y) {<br>
                this.c1 = new C(x);<br>
                this.c2 = new C(y);<br>
            }<br>
        <br>
            public deconstructor(int x, int y) {<br>
                // delegate to C pattern to extract x from c1 and y from
        c2<br>
            }<br>
        }<br>
        ```<br>
        <br>
        In these examples, we've composed deconstruction (total)
        patterns into bigger<br>
        patterns, so we didn't have to worry about what happens when the
        inner pattern<br>
        fails.  But we also want to be able to compose partial patterns
        into partial<br>
        patterns.  For example, suppose we have:<br>
        <br>
        ```<br>
        interface Shape {<br>
      </font></font><font size="+1"><font face="monospace"><font size="+1"><font face="monospace"><br>
                // if component is visible, provide bounds<br>
          </font></font>    public pattern(Rect bound) visibleShape();<br>
        }<br>
        ```<br>
        <br>
        And suppose we have a class that represents the composition of
        two shapes; we<br>
        would like it to implement the `visibleShape()` pattern by
        delegating to the<br>
        `visibleShape()` pattern for each of the shapes, fail if either
        of these fail,<br>
        and if both succeed, return the bounding rectangle for both
        shapes:<br>
        <br>
        ```<br>
        class CompoundShape implements Shape {<br>
            Shape s1 = ...<br>
            Shape s2 = ...<br>
        <br>
            public pattern(Rect r) visibleShape() {<br>
                ...<br>
                if (s1 instanceof visibleShape(var r1)<br>
                    && s2 instanceof visibleShape(var r2)) {<br>
                        // succeed with boundingRect(r1, r2)<br>
                }<br>
                else {<br>
                    // fail<br>
                }<br>
            }<br>
        }<br>
        ```<br>
        <br>
      </font></font>
  </body>
</html>