summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorKazuki Tsujimoto <kazuki@callcc.net>2020-12-22 02:08:32 +0900
committerKazuki Tsujimoto <kazuki@callcc.net>2020-12-22 02:08:57 +0900
commit5c0abe2d94c545275079a862dc36bb163953010a (patch)
tree6d6947271772694a2688bf684f85e85f35c564d6 /doc
parent208f7d7c801c83facab4c24a36ed5e5b49b75377 (diff)
Update documentation for pattern matching
Diffstat (limited to 'doc')
-rw-r--r--doc/syntax/pattern_matching.rdoc55
1 files changed, 37 insertions, 18 deletions
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc
index a4af301..323f7ca 100644
--- a/doc/syntax/pattern_matching.rdoc
+++ b/doc/syntax/pattern_matching.rdoc
@@ -15,15 +15,15 @@ Pattern matching in Ruby is implemented with the +case+/+in+ expression:
...
end
-(Note that +in+ and +when+ branches can *not* be mixed in one +case+ expression.)
+(Note that +in+ and +when+ branches can NOT be mixed in one +case+ expression.)
-or with the +=>+ operator and the +in+ operator, which can be used in a standalone expression:
+or with the <code>=></code> operator and the +in+ operator, which can be used in a standalone expression:
<expression> => <pattern>
<expression> in <pattern>
-Pattern matching is _exhaustive_: if variable doesn't match pattern (in a separate +in+ clause), or doesn't matches any branch of +case+ expression (and +else+ branch is absent), +NoMatchingPatternError+ is raised.
+The +case+/+in+ expression is _exhaustive_: if the value of the expression doesn't match any branch of +case+ expression (and +else+ branch is absent), +NoMatchingPatternError+ is raised.
Therefore, +case+ expression might be used for conditional matching and unpacking:
@@ -39,7 +39,7 @@ Therefore, +case+ expression might be used for conditional matching and unpackin
end
# Prints: "Connect with user 'admin'"
-whilst the +=>+ operator is most useful when expected data structure is known beforehand, to just unpack parts of it:
+whilst the <code>=></code> operator is most useful when expected data structure is known beforehand, to just unpack parts of it:
config = {db: {user: 'admin', password: 'abc123'}}
@@ -48,7 +48,7 @@ whilst the +=>+ operator is most useful when expected data structure is known be
puts "Connect with user '#{user}'"
# Prints: "Connect with user 'admin'"
-+<expression> in <pattern>+ is the same as +case <expression>; in <pattern>; true; else false; end+.
+<code><expression> in <pattern></code> is the same as <code>case <expression>; in <pattern>; true; else false; end</code>.
You can use it when you only want to know if a pattern has been matched or not:
users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}]
@@ -65,12 +65,12 @@ Patterns can be:
* find pattern: <code>[*variable, <subpattern>, <subpattern>, <subpattern>, ..., *variable]</code>; (<em>Find pattern</em>)
* hash pattern: <code>{key: <subpattern>, key: <subpattern>, ...}</code>; (<em>Hash pattern</em>)
* combination of patterns with <code>|</code>; (<em>Alternative pattern</em>)
-* variable capture: <code>variable</code> or <code><pattern> => variable</code>; (<em>Variable pattern</em>, <em>As pattern</em>)
+* variable capture: <code><pattern> => variable</code> or <code>variable</code>; (<em>As pattern</em>, <em>Variable pattern</em>)
Any pattern can be nested inside array/find/hash patterns where <code><subpattern></code> is specified.
Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter).
-Hash patterns match hashes, or objects that respond to +deconstruct_keys+ (see below about the latter). Note that only symbol keys are supported for hash patterns, at least for now.
+Hash patterns match hashes, or objects that respond to +deconstruct_keys+ (see below about the latter). Note that only symbol keys are supported for hash patterns.
An important difference between array and hash patterns behavior is arrays match only a _whole_ array
@@ -92,6 +92,24 @@ while the hash matches even if there are other keys besides specified part:
end
#=> "matched"
+<code>{}</code> is the only exclusion from this rule. It matches iff an empty hash is given:
+
+ case {a: 1, b: 2, c: 3}
+ in {}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+ case {}
+ in {}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
There is also a way to specify there should be no other keys in the matched hash except those explicitly specified by pattern, with <code>**nil</code>:
case {a: 1, b: 2}
@@ -122,7 +140,7 @@ Both array and hash patterns support "rest" specification:
end
#=> "matched"
-In +case+ (but not in +=>+ and +in+) expression, parentheses around both kinds of patterns could be omitted
+In +case+ (but not in <code>=></code> and +in+) expression, parentheses around both kinds of patterns could be omitted:
case [1, 2]
in Integer, Integer
@@ -140,7 +158,7 @@ In +case+ (but not in +=>+ and +in+) expression, parentheses around both kinds o
end
#=> "matched"
-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.
+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]
in [*, String, String, *]
@@ -187,7 +205,7 @@ If no additional check is required, only binding some part of the data to a vari
end
#=> "matched: 1"
-For hash patterns, even a simpler form exists: key-only specification (without any value) binds the local variable with the key's name, too:
+For hash patterns, even a simpler form exists: key-only specification (without any sub-pattern) binds the local variable with the key's name, too:
case {a: 1, b: 2, c: 3}
in a:
@@ -235,17 +253,17 @@ Binding to variables currently does NOT work for alternative patterns joined wit
end
# SyntaxError (illegal variable in alternative pattern (a))
-<code>_</code> is the only exclusion from this rule: it still binds the first match to local variable <code>_</code>, but allowed to be used in alternative patterns:
+Variables that start with <code>_</code> are the only exclusions from this rule:
case {a: 1, b: 2}
- in {a: _} | Array
- "matched: #{_}"
+ in {a: _, b: _foo} | Array
+ "matched: #{_}, #{_foo}"
else
"not matched"
end
# => "matched: 1"
-It is, though, not advised to reuse bound value, as <code>_</code> pattern's goal is to signify discarded value.
+It is, though, not advised to reuse bound value, as these pattern's goal is to signify discarded value.
== Variable pinning
@@ -262,7 +280,7 @@ Due to variable binding feature, existing local variable can't be straightforwar
# expected: "not matched. expectation was: 18"
# real: "matched. expectation was: 1" -- local variable just rewritten
-For this case, the pin operator <code>^</code> can be used, to tell Ruby "just use this value as a part of pattern"
+For this case, the pin operator <code>^</code> can be used, to tell Ruby "just use this value as a part of pattern":
expectation = 18
case [1, 2]
@@ -294,9 +312,9 @@ One important usage of variable pinning is specifying the same value should happ
end
#=> "not matched"
-== Matching non-primitive objects: +deconstruct_keys+ and +deconstruct+
+== Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+
-As already mentioned above, hash and array/find patterns besides literal arrays and hashes will try to match any object implementing +deconstruct+ (for array/find patterns) or +deconstruct_keys+ (for hash patterns).
+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).
class Point
def initialize(x, y)
@@ -315,7 +333,7 @@ As already mentioned above, hash and array/find patterns besides literal arrays
end
case Point.new(1, -2)
- in px, Integer # subpatterns and variable binding works
+ in px, Integer # sub-patterns and variable binding works
"matched: #{px}"
else
"not matched"
@@ -418,6 +436,7 @@ So, only subsequently loaded files or `eval`-ed code is affected by switching th
Alternatively, command-line key <code>-W:no-experimental</code> can be used to turn off "experimental" feature warnings.
== Appendix A. Pattern syntax
+
Approximate syntax is:
pattern: value_pattern