summaryrefslogtreecommitdiff
path: root/doc/syntax/pattern_matching.rdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/syntax/pattern_matching.rdoc')
-rw-r--r--doc/syntax/pattern_matching.rdoc81
1 files changed, 53 insertions, 28 deletions
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc
index 9f6954f1cb..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,11 @@ Approximate syntax is:
value_pattern: literal
| Constant
- | ^variable
+ | ^local_variable
+ | ^instance_variable
+ | ^class_variable
+ | ^global_variable
+ | ^(expression)
variable_pattern: variable