<p>How do different languages do pattern matching? In Rust it's</p>
<pre class="lang-rust prettyprint-override"><code>match x {
    y =&gt; ...,
    z =&gt; ...
}
</code></pre>
<p>However in ocaml it's</p>
<pre class="lang-ocaml prettyprint-override"><code>match x with
| y -&gt; ...
| z -&gt; ...
</code></pre>
<p>I'm wondering about some unique approaches to pattern matching.</p>

<syntax><pattern-matching>
What are some approaches for pattern matching?
CC BY-SA 4.0
2023-05-23T09:57:51.197Z
The word "approaches" is vague; it could encompasses syntax, semantics and/or implementation details. The examples you've given are just different syntaxes and your question is tagged syntax, but the existing answers have mostly focused on semantics. I think the question would be improved if it asked specifically about semantics.
kaya3
<p>Pattern matching syntax is somewhat uniform across languages. Sometimes you'll see <code>if</code>/<code>else</code> with single patterns, which may look like <code>if let Some(x) = y {}</code> (Rust), <code>if(Some(var x) is y) {}</code> (C#) or some variation of this.</p>
<p>Meanwhile,</p>
<h1>Egison</h1>
<p><a href="https://www.egison.org/" rel="nofollow noreferrer">Egison</a> is a language that qualifies itself as <em>Pattern-Match-Oriented</em>.<br />
An extensive SE answer would require to copy/paste Egi's entire thesis, so I'll try to summarise some interesting features.</p>
<pre><code>def twinPrimes :=
    matchAll primes as list integer with
        | _ ++ $p :: #(p + 2) :: _ -&gt; (p, p + 2)

take 6 twinPrimes
-- [(3, 5), (5, 7), (11, 13), (17, 19), (29, 31), (41, 43)]
</code></pre>
<p>As you can see here, there exists a basic language that should be familiar (<code>matchAll xs with &lt;pattern&gt; -&gt; &lt;expr&gt;</code>), however</p>
<ul>
<li>Matching expressions may return one or <em>multiple</em> matches (<code>match</code> and <code>matchAll</code>, as do RegEx+),</li>
<li>Patterns may be self-referential (<code>$p :: #(p + 2)</code> matches <code>0, 2</code> but not <code>1, 2</code>),</li>
<li><em>Matchers</em> (the <code>as list integer</code> part above) are <strong>user-defined</strong> relations between the input and output.</li>
</ul>
<p>This last point in particular allows to specify arbitrary matching strategies.<br />
Here is an example of a pattern match ignoring the order of pairs:</p>
<pre><code>def unorderedPair m :=
    matcher
        | ($, $) as (m, m) with
            | ($x, $y) -&gt; [(x, y), (y, x)]
        | $ as (eq) with
            | $x -&gt; [$x]
</code></pre>
<p>which can be used as</p>
<pre><code>matchAll (2, 5) as unorderedPair with
    | (#5, $x) -&gt; x
</code></pre>
<p>resulting in <code>2</code> due to the <code>(#5, $x)</code> branch attempting both possible order and succeeding with one.</p>
<h1>Active Patterns</h1>
<p><a href="https://en.wikibooks.org/wiki/F_Sharp_Programming/Active_Patterns" rel="nofollow noreferrer">F#'s Active Patterns</a> are a another pattern matching language where the matching logic is user-defined in functions with funky names like <code>(|Even|Odd|)</code>, which may furthermore be <em>parametrised</em>.<br />
In those names, essentially each possible branch is named after the bar-separated identifiers.</p>
<p>For example,</p>
<pre class="lang-fs prettyprint-override"><code>let (|Even|Odd|) n =
    if n % 2 = 0 then
        Even
    else
        Odd

do
    match 42 with
        | Even -&gt; printfn &quot;success&quot;
        | Odd -&gt; printfn &quot;?&quot;
</code></pre>
<p>Those functions being parametrisable allow to define arbitrary sublanguages, such as,</p>
<pre class="lang-fs prettyprint-override"><code>type MSpec&lt;'a&gt; =
    | Req of 'a
    | Opt of 'a

//xs is our parameter, ys is what we match against
let (|M|_|)&lt;'a when 'a : equality&gt; (xs: MSpec&lt;'a&gt; list) (ys: 'a list) =
    let rec f (xs': MSpec&lt;'a&gt; list) (ys': 'a list) =
        match xs' with
        | [] -&gt;
            List.isEmpty ys'
        | (Opt xhd) :: xtl -&gt;
            match ys' with
            | yhd :: ytl -&gt;
                if xhd = yhd then
                    f xtl ytl
                else
                    f xtl ys'
            | _ -&gt;
                f xtl ys'
        | (Req xhd) :: xtl -&gt;
            match ys' with
            | yhd :: ytl -&gt; 
                if xhd = yhd then
                    f xtl ytl
                else
                    false
            | _ -&gt;
                false
    in
    if f xs ys then Some () else None
</code></pre>
<pre class="lang-fs prettyprint-override"><code>let g = function
| M [Opt 1; Req 2; Req 3] -&gt; printfn &quot;matches\n&quot;
| _ -&gt; printfn &quot;nop\n&quot;

do
    g [1; 2; 3] //matches
    g [2; 3]    //matches
    g [4; 2; 3] //nop
</code></pre>
<p>which should be reminiscent of RegExp's <code>1?23</code>, and where a name with an underscore branch (<code>(|M|_|)</code>) uses Some/None.</p>

CC BY-SA 4.0
2023-05-23T03:16:12.537Z
2023-05-23T18:08:19.907Z
2023-05-23T18:08:19.907Z
Longinus
<p>A unique pattern matching approach is the idris2/idris <a href="https://idris2.readthedocs.io/en/latest/tutorial/views.html" rel="nofollow noreferrer">with rule</a>.</p>
<p>The unique feature is that the item being matched is viewed as an added argument of the function, and when matching/destructing this &quot;argument&quot;, <em>the &quot;existing/original arguments&quot; can be affected as well</em>. Here is an example function from the above documentation for converting a natural number to its binary representation (as a list of Bool's):</p>
<pre><code>natToBin : Nat -&gt; List Bool
natToBin Z = Nil
natToBin k with (parity k)
   natToBin (j + j)     | Even = False :: natToBin j
   natToBin (S (j + j)) | Odd  = True  :: natToBin j
</code></pre>
<p>where the parity of k (<code>parity k</code>) is matched (either <code>Even</code> or <code>Odd</code>). What's special is that depending on whether <code>parity k</code> is <code>Even</code> or <code>Odd</code>, the existing argument <code>k</code> is also refined/changed to <code>j + j</code> (when <code>Even</code>) or <code>1 + j + j</code> (when <code>Odd</code>). This is different from most languages where you match a variable/expression by itself.</p>
<p>Additional details and definitions are in the documentation linked above.</p>

CC BY-SA 4.0
2023-05-23T11:38:37.687Z
2023-05-23T11:38:37.687Z
tinlyx
<h2>Pattern matching in Papyri</h2>
<p><a href="https://kaya3.github.io/papyri" rel="nofollow noreferrer">Papyri</a> is a dynamically-typed pure-functional programmable markup language which compiles to HTML. (Disclosure: I am the author of Papyri.)</p>
<p>The main things distinguishing Papyri from other languages are that the syntax is constrained to mostly be a superset of HTML, and HTML content (tags, text, and sequences) is a first-class data type, so the pattern-matching has to support it.</p>
<p>A <a href="https://kaya3.github.io/papyri/tutorial.html#pattern_matching" rel="nofollow noreferrer">pattern match expression</a> in Papyri looks like this:</p>
<pre><code>@match scrutinee {
    pattern1 -&gt; branch1,
    pattern2 -&gt; branch2,
    # ...
}
</code></pre>
<p>This is broadly similar to matching in other languages:</p>
<ul>
<li>It's an expression so it results in a value and each branch must be an expression.</li>
<li>Patterns are in order of priority, so if more than one pattern could match then the earliest one is used.</li>
<li>A pattern can bind names to values extracted from the scrutinee, which are then in scope within the branch associated with that pattern.</li>
<li>Since it's a dynamic language, there is no static check to ensure the patterns are exhaustive; it's an error at runtime if the scrutinee doesn't match any of them.</li>
<li>&quot;Or&quot; patterns; <code>pattern1 | pattern2</code> is a pattern which matches if either of the sub-patterns matches ─ again, in order of priority.</li>
<li>&quot;Spread&quot; patterns; for example, <code>[$head, *$tail]</code> matches a list with at least one element.</li>
</ul>
<p>Some more unusual things about pattern-matching in Papyri:</p>
<ul>
<li>HTML tag patterns, like <code>&lt;$tag_name id=$id&gt; $body &lt;/&gt;</code>. This would match a tag of any name, with an <code>id</code> attribute and no other attributes, and any contents; these would be bound to the variables <code>$tag_name</code>, <code>$id</code> and <code>$body</code> respectively, but they could be arbitrary other patterns.</li>
<li>HTML content patterns, like <code>{Hello, &lt;span&gt;$name&lt;/span&gt;!}</code>. This would match an HTML sequence consisting of the text <code>&quot;Hello, &quot;</code>, a span tag with no attributes and any contents, and the text <code>&quot;!&quot;</code>.</li>
<li>Equality patterns, like <code>=$x</code>. This matches if the value equals the result of the given expression. The expression may use variables which are bound already by other parts of the same pattern.</li>
<li>&quot;And&quot; patterns, like <code>pattern1 &amp; pattern2</code>. This matches if both patterns individually match; it is useful for things like <code>$x &amp; [$a, $b, $c]</code>, where you want to bind a list to the name <code>$x</code> while also binding its members to other names.</li>
</ul>

CC BY-SA 4.0
2023-05-23T10:30:59.823Z
2023-05-23T10:36:06.837Z
2023-05-23T10:36:06.837Z
kaya3
<h2>Repurpose <code>switch</code></h2>
<p>This is what Swift does. From <a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow#Where" rel="nofollow noreferrer"><em>The Swift Programming Language</em></a>:</p>
<blockquote>
<pre class="lang-swift prettyprint-override"><code>let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print(&quot;(\(x), \(y)) is on the line x == y&quot;)
case let (x, y) where x == -y:
    print(&quot;(\(x), \(y)) is on the line x == -y&quot;)
case let (x, y):
    print(&quot;(\(x), \(y)) is just some arbitrary point&quot;)
}
// Prints &quot;(1, -1) is on the line x == -y&quot;
</code></pre>
</blockquote>
<p>In terms of the implementation, pattern matching calls the operator <code>~=</code>.</p>
<p>However, Swift only lets you destructure tuples and enums, not structs. TSPL has <a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/patterns" rel="nofollow noreferrer">a patterns chapter</a> that lists all the valid patterns.</p>

CC BY-SA 4.0
2023-05-23T02:41:14.783Z
2023-05-23T02:41:14.783Z
Bbrk24
# What are some approaches for pattern matching?
Posted by: username_0 on 2023-05-23
How do different languages do pattern matching? In Rust it's
match x {
    y => ...,
    z => ...
}

However in ocaml it's
match x with
| y -> ...
| z -> ...

I'm wondering about some unique approaches to pattern matching.
**Tags:** syntax pattern-matching
> **Comments:**
> **username_1**: The word "approaches" is vague; it could encompasses syntax, semantics and/or implementation details. The examples you've given are just different syntaxes and your question is tagged syntax, but the existing answers have mostly focused on semantics. I think the question would be improved if it asked specifically about semantics.  
---
## 4 answers
### Answer by username_2 on 2023-05-23. Score: 4
Pattern matching syntax is somewhat uniform across languages. Sometimes you'll see if/else with single patterns, which may look like if let Some(x) = y {} (Rust), if(Some(var x) is y) {} (C#) or some variation of this.
Meanwhile,
Egison
Egison is a language that qualifies itself as Pattern-Match-Oriented.
An extensive SE answer would require to copy/paste Egi's entire thesis, so I'll try to summarise some interesting features.
def twinPrimes :=
    matchAll primes as list integer with
        | _ ++ $p :: #(p + 2) :: _ -> (p, p + 2)

take 6 twinPrimes
-- [(3, 5), (5, 7), (11, 13), (17, 19), (29, 31), (41, 43)]

As you can see here, there exists a basic language that should be familiar (matchAll xs with  -> ), however

Matching expressions may return one or multiple matches (match and matchAll, as do RegEx+),
Patterns may be self-referential ($p :: #(p + 2) matches 0, 2 but not 1, 2),
Matchers (the as list integer part above) are user-defined relations between the input and output.

This last point in particular allows to specify arbitrary matching strategies.
Here is an example of a pattern match ignoring the order of pairs:
def unorderedPair m :=
    matcher
        | ($, $) as (m, m) with
            | ($x, $y) -> [(x, y), (y, x)]
        | $ as (eq) with
            | $x -> [$x]

which can be used as
matchAll (2, 5) as unorderedPair with
    | (#5, $x) -> x

resulting in 2 due to the (#5, $x) branch attempting both possible order and succeeding with one.
Active Patterns
F#'s Active Patterns are a another pattern matching language where the matching logic is user-defined in functions with funky names like (|Even|Odd|), which may furthermore be parametrised.
In those names, essentially each possible branch is named after the bar-separated identifiers.
For example,
let (|Even|Odd|) n =
    if n % 2 = 0 then
        Even
    else
        Odd

do
    match 42 with
        | Even -> printfn "success"
        | Odd -> printfn "?"

Those functions being parametrisable allow to define arbitrary sublanguages, such as,
type MSpec<'a> =
    | Req of 'a
    | Opt of 'a

//xs is our parameter, ys is what we match against
let (|M|_|)<'a when 'a : equality> (xs: MSpec<'a> list) (ys: 'a list) =
    let rec f (xs': MSpec<'a> list) (ys': 'a list) =
        match xs' with
        | [] ->
            List.isEmpty ys'
        | (Opt xhd) :: xtl ->
            match ys' with
            | yhd :: ytl ->
                if xhd = yhd then
                    f xtl ytl
                else
                    f xtl ys'
            | _ ->
                f xtl ys'
        | (Req xhd) :: xtl ->
            match ys' with
            | yhd :: ytl -> 
                if xhd = yhd then
                    f xtl ytl
                else
                    false
            | _ ->
                false
    in
    if f xs ys then Some () else None

let g = function
| M [Opt 1; Req 2; Req 3] -> printfn "matches\n"
| _ -> printfn "nop\n"

do
    g [1; 2; 3] //matches
    g [2; 3]    //matches
    g [4; 2; 3] //nop

which should be reminiscent of RegExp's 1?23, and where a name with an underscore branch ((|M|_|)) uses Some/None.
---
### Answer by username_3 on 2023-05-23. Score: 3
A unique pattern matching approach is the idris2/idris with rule.
The unique feature is that the item being matched is viewed as an added argument of the function, and when matching/destructing this "argument", the "existing/original arguments" can be affected as well. Here is an example function from the above documentation for converting a natural number to its binary representation (as a list of Bool's):
natToBin : Nat -> List Bool
natToBin Z = Nil
natToBin k with (parity k)
   natToBin (j + j)     | Even = False :: natToBin j
   natToBin (S (j + j)) | Odd  = True  :: natToBin j

where the parity of k (parity k) is matched (either Even or Odd). What's special is that depending on whether parity k is Even or Odd, the existing argument k is also refined/changed to j + j (when Even) or 1 + j + j (when Odd). This is different from most languages where you match a variable/expression by itself.
Additional details and definitions are in the documentation linked above.
---
### Answer by username_4 on 2023-05-23. Score: 3
Repurpose switch
This is what Swift does. From The Swift Programming Language:

let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    print("(\(x), \(y)) is just some arbitrary point")
}
// Prints "(1, -1) is on the line x == -y"


In terms of the implementation, pattern matching calls the operator ~=.
However, Swift only lets you destructure tuples and enums, not structs. TSPL has a patterns chapter that lists all the valid patterns.
---
### Answer by username_1 on 2023-05-23. Score: 1
Pattern matching in Papyri
Papyri is a dynamically-typed pure-functional programmable markup language which compiles to HTML. (Disclosure: I am the author of Papyri.)
The main things distinguishing Papyri from other languages are that the syntax is constrained to mostly be a superset of HTML, and HTML content (tags, text, and sequences) is a first-class data type, so the pattern-matching has to support it.
A pattern match expression in Papyri looks like this:
@match scrutinee {
    pattern1 -> branch1,
    pattern2 -> branch2,
    # ...
}

This is broadly similar to matching in other languages:

It's an expression so it results in a value and each branch must be an expression.
Patterns are in order of priority, so if more than one pattern could match then the earliest one is used.
A pattern can bind names to values extracted from the scrutinee, which are then in scope within the branch associated with that pattern.
Since it's a dynamic language, there is no static check to ensure the patterns are exhaustive; it's an error at runtime if the scrutinee doesn't match any of them.
"Or" patterns; pattern1 | pattern2 is a pattern which matches if either of the sub-patterns matches ─ again, in order of priority.
"Spread" patterns; for example, [$head, *$tail] matches a list with at least one element.

Some more unusual things about pattern-matching in Papyri:

HTML tag patterns, like <$tag_name id=$id> $body . This would match a tag of any name, with an id attribute and no other attributes, and any contents; these would be bound to the variables $tag_name, $id and $body respectively, but they could be arbitrary other patterns.
HTML content patterns, like {Hello, $name!}. This would match an HTML sequence consisting of the text "Hello, ", a span tag with no attributes and any contents, and the text "!".
Equality patterns, like =$x. This matches if the value equals the result of the given expression. The expression may use variables which are bound already by other parts of the same pattern.
"And" patterns, like pattern1 & pattern2. This matches if both patterns individually match; it is useful for things like $x & [$a, $b, $c], where you want to bind a list to the name $x while also binding its members to other names.
---
