Issue #14912 has been updated by dsisnero (Dominic Sisneros).


"The patterns are run in sequence until the first one that matches."

This means O(n) time for matching. If we are adding this with changes to compiler, we should try to compile it to hash lookup O(1) time

Does this allow nesting of patterns Do patterns compose or nest?

def simplify(n)
case n
in IntNode(n) 
  then n
in NegNode( Negnode n) then
   simplify( NegNode.new( simplify (n) )
in AddNode(IntNode(0), right) then
   simplify(right)
in MulNode(IntNode(1) right) then
   simplify(right)

etc

Java is going to get pattern matching also and has some good ideas

https://www.youtube.com/watchv=n3_8YcYKScw&list=PLX8CzqL3ArzXJ2EGftrmz4SzS6NRr6p2n&index=1&t=907s

and 

http://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html

Their proposal includes nesting and also is O(1) time.

Not sure how much translates though.











 

----------------------------------------
Feature #14912: Introduce pattern matching syntax
https://bugs.ruby-lang.org/issues/14912#change-73754

* Author: ktsj (Kazuki Tsujimoto)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
I propose new pattern matching syntax.

# Pattern syntax
Here's a summary of pattern syntax.

```
# case version
case expr
in pat [if|unless cond]
  ...
in pat [if|unless cond]
  ...
else
  ...
end

pat: var                                                   # Variable pattern. It matches any value, and binds the variable name to that value.
   | literal                                               # Value pattern. The pattern matches an object such that pattern === object.
   | Constant                                              # Ditto.
   | var_                                                  # Ditto. It is equivalent to pin operator in Elixir.
   | (pat, ..., *var, pat, ..., id:, id: pat, ..., **var)  # Deconstructing pattern. See below for more details.
   | pat(pat, ...)                                         # Ditto. Syntactic sugar of (pat, pat, ...).
   | pat, ...                                              # Ditto. You can omit the parenthesis (top-level only). 
   | pat | pat | ...                                       # Alternative pattern. The pattern matches if any of pats match.
   | pat => var                                            # As pattern. Bind the variable to the value if pat match.

# one-liner version
$(pat, ...) = expr                                         # Deconstructing pattern.
```

The patterns are run in sequence until the first one that matches.
If no pattern matches and no else clause, NoMatchingPatternError exception is raised.

## Deconstructing pattern
This is similar to Extractor in Scala.

The patten matches if:

* An object have #deconstruct method
* Return value of #deconstruct method must be Array or Hash, and it matches sub patterns of this

```
class Array
  alias deconstruct itself
end

case [1, 2, 3, d: 4, e: 5, f: 6]
in a, *b, c, d:, e: Integer | Float => i, **f
  p a #=> 1
  p b #=> [2]
  p c #=> 3
  p d #=> 4
  p i #=> 5
  p f #=> {f: 6}
  e   #=> NameError
end
```

This pattern can be used as one-liner version like destructuring assignment.

```
class Hash
  alias deconstruct itself
end

$(x:, y: (_, z)) = {x: 0, y: [1, 2]}
p x #=> 0
p z #=> 2
```

# Sample code
```
class Struct
  def deconstruct; [self] + values; end
end

A = Struct.new(:a, :b)
case A[0, 1]
in (A, 1, 1)
  :not_match
in A(x, 1) # Syntactic sugar of above
  p x #=> 0
end
```

```
require 'json'

$(x:, y: (_, z)) = JSON.parse('{"x": 0, "y": [1, 2]}', symbolize_names: true)
p x #=> 0
p z #=> 2
```

# Implementation
* https://github.com/k-tsj/ruby/tree/pm2.7-prototype
   * Test code: https://github.com/k-tsj/ruby/blob/pm2.7-prototype/test_syntax.rb

# Design policy
* Keep compatibility
   * Don't define new reserved words
   * 0 conflict in parse.y. It passes test/test-all
* Be Ruby-ish
   * Powerful Array, Hash support
   * Encourage duck typing style
   * etc
* Optimize syntax for major use case
   * You can see several real use cases of pattern matching at following links :)
      * https://github.com/k-tsj/power_assert/blob/8e9e0399a032936e3e3f3c1f06e0d038565f8044/lib/power_assert.rb#L106
      * https://github.com/k-tsj/pattern-match/network/dependents




-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>