3 Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables.
5 Pattern matching in Ruby is implemented with the +case+/+in+ expression:
18 (Note that +in+ and +when+ branches can NOT be mixed in one +case+ expression.)
20 Or with the <code>=></code> operator and the +in+ operator, which can be used in a standalone expression:
22 <expression> => <pattern>
24 <expression> in <pattern>
26 The +case+/+in+ expression is _exhaustive_: if the value of the expression does not match any branch of the +case+ expression (and the +else+ branch is absent), +NoMatchingPatternError+ is raised.
28 Therefore, the +case+ expression might be used for conditional matching and unpacking:
30 config = {db: {user: 'admin', password: 'abc123'}}
33 in db: {user:} # matches subhash and puts matched value in variable user
34 puts "Connect with user '#{user}'"
35 in connection: {username: }
36 puts "Connect with user '#{username}'"
38 puts "Unrecognized structure of config"
40 # Prints: "Connect with user 'admin'"
42 whilst the <code>=></code> operator is most useful when the expected data structure is known beforehand, to just unpack parts of it:
44 config = {db: {user: 'admin', password: 'abc123'}}
46 config => {db: {user:}} # will raise if the config's structure is unexpected
48 puts "Connect with user '#{user}'"
49 # Prints: "Connect with user 'admin'"
51 <code><expression> in <pattern></code> is the same as <code>case <expression>; in <pattern>; true; else false; end</code>.
52 You can use it when you only want to know if a pattern has been matched or not:
54 users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}]
55 users.any? {|user| user in {name: /B/, age: 20..} } #=> true
57 See below for more examples and explanations of the syntax.
63 * any Ruby object (matched by the <code>===</code> operator, like in +when+); (<em>Value pattern</em>)
64 * array pattern: <code>[<subpattern>, <subpattern>, <subpattern>, ...]</code>; (<em>Array pattern</em>)
65 * find pattern: <code>[*variable, <subpattern>, <subpattern>, <subpattern>, ..., *variable]</code>; (<em>Find pattern</em>)
66 * hash pattern: <code>{key: <subpattern>, key: <subpattern>, ...}</code>; (<em>Hash pattern</em>)
67 * combination of patterns with <code>|</code>; (<em>Alternative pattern</em>)
68 * variable capture: <code><pattern> => variable</code> or <code>variable</code>; (<em>As pattern</em>, <em>Variable pattern</em>)
70 Any pattern can be nested inside array/find/hash patterns where <code><subpattern></code> is specified.
72 Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter).
73 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.
75 An important difference between array and hash pattern behavior is that arrays match only a _whole_ array:
85 while the hash matches even if there are other keys besides the specified part:
87 case {a: 1, b: 2, c: 3}
95 <code>{}</code> is the only exclusion from this rule. It matches only if an empty hash is given:
97 case {a: 1, b: 2, c: 3}
113 There is also a way to specify there should be no other keys in the matched hash except those explicitly specified by the pattern, with <code>**nil</code>:
116 in {a: Integer, **nil} # this will not match the pattern having keys other than a:
118 in {a: Integer, b: Integer, **nil}
123 #=> "matched a whole"
125 Both array and hash patterns support "rest" specification: