diff options
Diffstat (limited to 'doc/syntax/pattern_matching.rdoc')
| -rw-r--r-- | doc/syntax/pattern_matching.rdoc | 80 |
1 files changed, 52 insertions, 28 deletions
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc index 69756369fb..06aae26d49 100644 --- a/doc/syntax/pattern_matching.rdoc +++ b/doc/syntax/pattern_matching.rdoc @@ -140,7 +140,7 @@ Both array and hash patterns support "rest" specification: end #=> "matched" -In +case+ (but not in <code>=></code> and +in+) expressions, parentheses around both kinds of patterns could be omitted: +Parentheses around both kinds of patterns could be omitted: case [1, 2] in Integer, Integer @@ -158,6 +158,12 @@ In +case+ (but not in <code>=></code> and +in+) expressions, parentheses around end #=> "matched" + [1, 2] => a, b + [1, 2] in a, b + + {a: 1, b: 2, c: 3} => a: + {a: 1, b: 2, c: 3} in a: + Find pattern is similar to array pattern but it can be used to check if the given object has any elements that match the pattern: case ["a", 1, "b", "c", 2] @@ -215,7 +221,7 @@ For hash patterns, even a simpler form exists: key-only specification (without a end #=> "matched: 1" -Binding works for nested patterns as well: +\Binding works for nested patterns as well: case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]} in name:, friends: [{name: first_friend}, *] @@ -241,17 +247,17 @@ The "rest" part of a pattern also can be bound to a variable: else "not matched" end - #=> "matched: 1, {:b=>2, :c=>3}" + #=> "matched: 1, {b: 2, c: 3}" -Binding to variables currently does NOT work for alternative patterns joined with <code>|</code>: +\Binding to variables currently does NOT work for alternative patterns joined with <code>|</code>: case {a: 1, b: 2} in {a: } | Array + # ^ SyntaxError (variable capture in alternative pattern) "matched: #{a}" else "not matched" end - # SyntaxError (illegal variable in alternative pattern (a)) Variables that start with <code>_</code> are the only exclusions from this rule: @@ -312,6 +318,33 @@ One important usage of variable pinning is specifying that the same value should end #=> "not matched" +In addition to pinning local variables, you can also pin instance, global, and class variables: + + $gvar = 1 + class A + @ivar = 2 + @@cvar = 3 + case [1, 2, 3] + in ^$gvar, ^@ivar, ^@@cvar + "matched" + else + "not matched" + end + #=> "matched" + end + +You can also pin the result of arbitrary expressions using parentheses: + + a = 1 + b = 2 + case 3 + in ^(a + b) + "matched" + else + "not matched" + end + #=> "matched" + == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ As already mentioned above, array, find, and hash patterns besides literal arrays and hashes will try to match any object implementing +deconstruct+ (for array/find patterns) or +deconstruct_keys+ (for hash patterns). @@ -382,9 +415,15 @@ Additionally, when matching custom classes, the expected class can be specified end #=> "matched: 1" +These core and library classes implement deconstruction: + +* MatchData#deconstruct and MatchData#deconstruct_keys; +* Time#deconstruct_keys, Date#deconstruct_keys, DateTime#deconstruct_keys. + == Guard clauses -+if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: ++if+ can be used to attach an additional condition (guard clause) when the pattern matches in +case+/+in+ expressions. +This condition may use bound variables: case [1, 2] in a, b if b == a*2 @@ -412,28 +451,10 @@ Additionally, when matching custom classes, the expected class can be specified end #=> "matched" -== Current feature status - -As of Ruby 3.0, one-line pattern matching and find patterns are considered _experimental_: its syntax can change in the future. Every time you use these features in code, a warning will be printed: - - [0] => [*, 0, *] - # warning: Find pattern is experimental, and the behavior may change in future versions of Ruby! - # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! - -To suppress this warning, one may use the Warning::[]= method: - - Warning[:experimental] = false - eval('[0] => [*, 0, *]') - # ...no warning printed... - -Note that pattern-matching warnings are raised at compile time, so this will not suppress the warning: - - Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted - [0] => [*, 0, *] - -So, only subsequently loaded files or `eval`-ed code is affected by switching the flag. +Note that <code>=></code> and +in+ operator can not have a guard clause. +The following examples is parsed as a standalone expression with modifier +if+. -Alternatively, the command line option <code>-W:no-experimental</code> can be used to turn off "experimental" feature warnings. + [1, 2] in a, b if b == a*2 == Appendix A. Pattern syntax @@ -449,7 +470,10 @@ Approximate syntax is: value_pattern: literal | Constant - | ^variable + | ^local_variable + | ^instance_variable + | ^class_variable + | ^global_variable | ^(expression) variable_pattern: variable |
