From 801fe52627f857ce31c4648da3d5efd8699a59cb Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 14:41:42 +0900 Subject: [PATCH 01/43] =?UTF-8?q?ruby/ruby=20=E3=81=AE=20rdoc=20=E3=81=8B?= =?UTF-8?q?=E3=82=89=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3=E3=83=9E=E3=83=83?= =?UTF-8?q?=E3=83=81=E9=96=A2=E9=80=A3=E3=81=AE=E3=83=89=E3=82=AD=E3=83=A5?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=E5=8E=9F=E6=96=87=E3=82=92?= =?UTF-8?q?=E3=82=B3=E3=83=94=E3=83=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### 原文の場所 - pattern_matching.rd - cf. https://github.com/ruby/ruby/blob/v3_2_0/doc/syntax/pattern_matching.rdoc - control.rd - cf. https://github.com/ruby/ruby/commit/281b3500580f9ec93ee17679c648eaeb4a47f8b6 ### pattern_matching.rd の配置に関して ## pattern_matching.rd の配置に関して rurema/doctree の `refm/doc/spec` 配下と ruby/ruby の `doc/syntax` 配下が似たようなファイル構成になっているため、 pattern_matching.rd も `refm/doc/spec` に配置した また今後可能なら doc 配下のファイルやクラス・モジュール・ライブラリのヘッドラインに rdoc へのリンクを追加したいと思っているが、その場合にディレクトリ・ファイル構成を ruby/ruby に寄せておくほうが実装しやすいのではという思惑もある --- refm/doc/spec/control.rd | 14 + refm/doc/spec/pattern_matching.rd | 540 ++++++++++++++++++++++++++++++ 2 files changed, 554 insertions(+) create mode 100644 refm/doc/spec/pattern_matching.rd diff --git a/refm/doc/spec/control.rd b/refm/doc/spec/control.rd index f353d9e5bb..364c330c9b 100644 --- a/refm/doc/spec/control.rd +++ b/refm/doc/spec/control.rd @@ -230,6 +230,20 @@ case は、条件が成立した when 節、(あるいは else 節) の最後に評価した式の結果を返します。いずれの条件も成り立たなければ nil を返します。 +Since Ruby 2.7, +case+ expressions also provide a more powerful experimental +pattern matching feature via the +in+ keyword: + + case {a: 1, b: 2, c: 3} + in a: Integer => m + "matched: #{m}" + else + "not matched" + end + # => "matched: 1" + +The pattern matching syntax is described on +{its own page}[rdoc-ref:syntax/pattern_matching.rdoc]. + === 繰り返し ====[a:while] while diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd new file mode 100644 index 0000000000..b7d614770c --- /dev/null +++ b/refm/doc/spec/pattern_matching.rd @@ -0,0 +1,540 @@ += Pattern matching + +Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. + +Pattern matching in Ruby is implemented with the +case+/+in+ expression: + + case + in + ... + in + ... + in + ... + else + ... + end + +(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: + + => + + in + +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. + +Therefore, the +case+ expression might be used for conditional matching and unpacking: + + config = {db: {user: 'admin', password: 'abc123'}} + + case config + in db: {user:} # matches subhash and puts matched value in variable user + puts "Connect with user '#{user}'" + in connection: {username: } + puts "Connect with user '#{username}'" + else + puts "Unrecognized structure of config" + end + # Prints: "Connect with user 'admin'" + +whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: + + config = {db: {user: 'admin', password: 'abc123'}} + + config => {db: {user:}} # will raise if the config's structure is unexpected + + puts "Connect with user '#{user}'" + # Prints: "Connect with user 'admin'" + + in is the same as case ; in ; true; else false; end. +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}] + users.any? {|user| user in {name: /B/, age: 20..} } #=> true + +See below for more examples and explanations of the syntax. + +== Patterns + +Patterns can be: + +* any Ruby object (matched by the === operator, like in +when+); (Value pattern) +* array pattern: [, , , ...]; (Array pattern) +* find pattern: [*variable, , , , ..., *variable]; (Find pattern) +* hash pattern: {key: , key: , ...}; (Hash pattern) +* combination of patterns with |; (Alternative pattern) +* variable capture: => variable or variable; (As pattern, Variable pattern) + +Any pattern can be nested inside array/find/hash patterns where 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. + +An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: + + case [1, 2, 3] + in [Integer, Integer] + "matched" + else + "not matched" + end + #=> "not matched" + +while the hash matches even if there are other keys besides the specified part: + + case {a: 1, b: 2, c: 3} + in {a: Integer} + "matched" + else + "not matched" + end + #=> "matched" + +{} is the only exclusion from this rule. It matches only if 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 the pattern, with **nil: + + case {a: 1, b: 2} + in {a: Integer, **nil} # this will not match the pattern having keys other than a: + "matched a part" + in {a: Integer, b: Integer, **nil} + "matched a whole" + else + "not matched" + end + #=> "matched a whole" + +Both array and hash patterns support "rest" specification: + + case [1, 2, 3] + in [Integer, *] + "matched" + else + "not matched" + end + #=> "matched" + + case {a: 1, b: 2, c: 3} + in {a: Integer, **} + "matched" + else + "not matched" + end + #=> "matched" + +Parentheses around both kinds of patterns could be omitted: + + case [1, 2] + in Integer, Integer + "matched" + else + "not matched" + end + #=> "matched" + + case {a: 1, b: 2, c: 3} + in a: Integer + "matched" + else + "not matched" + 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] + in [*, String, String, *] + "matched" + else + "not matched" + end + +== Variable binding + +Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): + + case [1, 2] + in Integer => a, Integer + "matched: #{a}" + else + "not matched" + end + #=> "matched: 1" + + case {a: 1, b: 2, c: 3} + in a: Integer => m + "matched: #{m}" + else + "not matched" + end + #=> "matched: 1" + +If no additional check is required, for only binding some part of the data to a variable, a simpler form could be used: + + case [1, 2] + in a, Integer + "matched: #{a}" + else + "not matched" + end + #=> "matched: 1" + + case {a: 1, b: 2, c: 3} + in a: m + "matched: #{m}" + else + "not matched" + end + #=> "matched: 1" + +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: + "matched: #{a}" + else + "not matched" + end + #=> "matched: 1" + +Binding works for nested patterns as well: + + case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]} + in name:, friends: [{name: first_friend}, *] + "matched: #{first_friend}" + else + "not matched" + end + #=> "matched: Jane" + +The "rest" part of a pattern also can be bound to a variable: + + case [1, 2, 3] + in a, *rest + "matched: #{a}, #{rest}" + else + "not matched" + end + #=> "matched: 1, [2, 3]" + + case {a: 1, b: 2, c: 3} + in a:, **rest + "matched: #{a}, #{rest}" + else + "not matched" + end + #=> "matched: 1, {:b=>2, :c=>3}" + +Binding to variables currently does NOT work for alternative patterns joined with |: + + case {a: 1, b: 2} + in {a: } | Array + "matched: #{a}" + else + "not matched" + end + # SyntaxError (illegal variable in alternative pattern (a)) + +Variables that start with _ are the only exclusions from this rule: + + case {a: 1, b: 2} + in {a: _, b: _foo} | Array + "matched: #{_}, #{_foo}" + else + "not matched" + end + # => "matched: 1, 2" + +It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value. + +== Variable pinning + +Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: + + expectation = 18 + + case [1, 2] + in expectation, *rest + "matched. expectation was: #{expectation}" + else + "not matched. expectation was: #{expectation}" + end + # expected: "not matched. expectation was: 18" + # real: "matched. expectation was: 1" -- local variable just rewritten + +For this case, the pin operator ^ can be used, to tell Ruby "just use this value as part of the pattern": + + expectation = 18 + case [1, 2] + in ^expectation, *rest + "matched. expectation was: #{expectation}" + else + "not matched. expectation was: #{expectation}" + end + #=> "not matched. expectation was: 18" + +One important usage of variable pinning is specifying that the same value should occur in the pattern several times: + + jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]} + john = {school: 'high', schools: [{id: 1, level: 'middle'}]} + + case jane + in school:, schools: [*, {id:, level: ^school}] # select the last school, level should match + "matched. school: #{id}" + else + "not matched" + end + #=> "matched. school: 2" + + case john # the specified school level is "high", but last school does not match + in school:, schools: [*, {id:, level: ^school}] + "matched. school: #{id}" + else + "not matched" + 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). + + class Point + def initialize(x, y) + @x, @y = x, y + end + + def deconstruct + puts "deconstruct called" + [@x, @y] + end + + def deconstruct_keys(keys) + puts "deconstruct_keys called with #{keys.inspect}" + {x: @x, y: @y} + end + end + + case Point.new(1, -2) + in px, Integer # sub-patterns and variable binding works + "matched: #{px}" + else + "not matched" + end + # prints "deconstruct called" + "matched: 1" + + case Point.new(1, -2) + in x: 0.. => px + "matched: #{px}" + else + "not matched" + end + # prints: deconstruct_keys called with [:x] + #=> "matched: 1" + ++keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: + + case Point.new(1, -2) + in x: 0.. => px, **rest + "matched: #{px}" + else + "not matched" + end + # prints: deconstruct_keys called with nil + #=> "matched: 1" + +Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with === + + class SuperPoint < Point + end + + case Point.new(1, -2) + in SuperPoint(x: 0.. => px) + "matched: #{px}" + else + "not matched" + end + #=> "not matched" + + case SuperPoint.new(1, -2) + in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed + "matched: #{px}" + else + "not matched" + end + #=> "matched: 1" + +== Guard clauses + ++if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: + + case [1, 2] + in a, b if b == a*2 + "matched" + else + "not matched" + end + #=> "matched" + + case [1, 1] + in a, b if b == a*2 + "matched" + else + "not matched" + end + #=> "not matched" + ++unless+ works, too: + + case [1, 1] + in a, b unless b == a*2 + "matched" + else + "not matched" + end + #=> "matched" + +== Current feature status + +As of Ruby 3.1, 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. + +Alternatively, the command line option -W:no-experimental can be used to turn off "experimental" feature warnings. + +== Appendix A. Pattern syntax + +Approximate syntax is: + + pattern: value_pattern + | variable_pattern + | alternative_pattern + | as_pattern + | array_pattern + | find_pattern + | hash_pattern + + value_pattern: literal + | Constant + | ^local_variable + | ^instance_variable + | ^class_variable + | ^global_variable + | ^(expression) + + variable_pattern: variable + + alternative_pattern: pattern | pattern | ... + + as_pattern: pattern => variable + + array_pattern: [pattern, ..., *variable] + | Constant(pattern, ..., *variable) + | Constant[pattern, ..., *variable] + + find_pattern: [*variable, pattern, ..., *variable] + | Constant(*variable, pattern, ..., *variable) + | Constant[*variable, pattern, ..., *variable] + + hash_pattern: {key: pattern, key:, ..., **variable} + | Constant(key: pattern, key:, ..., **variable) + | Constant[key: pattern, key:, ..., **variable] + +== Appendix B. Some undefined behavior examples + +To leave room for optimization in the future, the specification contains some undefined behavior. + +Use of a variable in an unmatched pattern: + + case [0, 1] + in [a, 2] + "not matched" + in b + "matched" + in c + "not matched" + end + a #=> undefined + c #=> undefined + +Number of +deconstruct+, +deconstruct_keys+ method calls: + + $i = 0 + ary = [0] + def ary.deconstruct + $i += 1 + self + end + case ary + in [0, 1] + "not matched" + in [0] + "matched" + end + $i #=> undefined From 263d9c1a557c2ee887976208aa6dd31d84515959 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 15:08:21 +0900 Subject: [PATCH 02/43] =?UTF-8?q?=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E9=96=A2=E9=80=A3=E3=81=AE=E3=83=89?= =?UTF-8?q?=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=E3=82=B5?= =?UTF-8?q?=E3=83=B3=E3=83=97=E3=83=AB=E3=82=B3=E3=83=BC=E3=83=89=E3=81=AB?= =?UTF-8?q?=E3=82=B7=E3=83=B3=E3=82=BF=E3=83=83=E3=82=AF=E3=82=B9=E3=83=8F?= =?UTF-8?q?=E3=82=A4=E3=83=A9=E3=82=A4=E3=83=88=E3=82=92=E9=81=A9=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #@samplecode から #@end までは COPY が実行できる最小範囲を基準にした --- refm/doc/spec/control.rd | 2 + refm/doc/spec/pattern_matching.rd | 92 +++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/refm/doc/spec/control.rd b/refm/doc/spec/control.rd index 364c330c9b..83616b23c7 100644 --- a/refm/doc/spec/control.rd +++ b/refm/doc/spec/control.rd @@ -233,6 +233,7 @@ nil を返します。 Since Ruby 2.7, +case+ expressions also provide a more powerful experimental pattern matching feature via the +in+ keyword: +#@samplecode case {a: 1, b: 2, c: 3} in a: Integer => m "matched: #{m}" @@ -240,6 +241,7 @@ pattern matching feature via the +in+ keyword: "not matched" end # => "matched: 1" +#@end The pattern matching syntax is described on {its own page}[rdoc-ref:syntax/pattern_matching.rdoc]. diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index b7d614770c..e7f40e51a7 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -27,6 +27,7 @@ The +case+/+in+ expression is _exhaustive_: if the value of the expression does Therefore, the +case+ expression might be used for conditional matching and unpacking: +#@samplecode config = {db: {user: 'admin', password: 'abc123'}} case config @@ -38,21 +39,26 @@ Therefore, the +case+ expression might be used for conditional matching and unpa puts "Unrecognized structure of config" end # Prints: "Connect with user 'admin'" +#@end whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: +#@samplecode config = {db: {user: 'admin', password: 'abc123'}} config => {db: {user:}} # will raise if the config's structure is unexpected puts "Connect with user '#{user}'" # Prints: "Connect with user 'admin'" +#@end in is the same as case ; in ; true; else false; end. You can use it when you only want to know if a pattern has been matched or not: +#@samplecode users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}] users.any? {|user| user in {name: /B/, age: 20..} } #=> true +#@end See below for more examples and explanations of the syntax. @@ -74,6 +80,7 @@ Hash patterns match hashes, or objects that respond to +deconstruct_keys+ (see b An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: +#@samplecode case [1, 2, 3] in [Integer, Integer] "matched" @@ -81,9 +88,11 @@ An important difference between array and hash pattern behavior is that arrays m "not matched" end #=> "not matched" +#@end while the hash matches even if there are other keys besides the specified part: +#@samplecode case {a: 1, b: 2, c: 3} in {a: Integer} "matched" @@ -91,9 +100,11 @@ while the hash matches even if there are other keys besides the specified part: "not matched" end #=> "matched" +#@end {} is the only exclusion from this rule. It matches only if an empty hash is given: +#@samplecode case {a: 1, b: 2, c: 3} in {} "matched" @@ -101,7 +112,9 @@ while the hash matches even if there are other keys besides the specified part: "not matched" end #=> "not matched" +#@end +#@samplecode case {} in {} "matched" @@ -109,9 +122,11 @@ while the hash matches even if there are other keys besides the specified part: "not matched" end #=> "matched" +#@end 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 **nil: +#@samplecode case {a: 1, b: 2} in {a: Integer, **nil} # this will not match the pattern having keys other than a: "matched a part" @@ -121,9 +136,11 @@ There is also a way to specify there should be no other keys in the matched hash "not matched" end #=> "matched a whole" +#@end Both array and hash patterns support "rest" specification: +#@samplecode case [1, 2, 3] in [Integer, *] "matched" @@ -131,7 +148,9 @@ Both array and hash patterns support "rest" specification: "not matched" end #=> "matched" +#@end +#@samplecode case {a: 1, b: 2, c: 3} in {a: Integer, **} "matched" @@ -139,9 +158,11 @@ Both array and hash patterns support "rest" specification: "not matched" end #=> "matched" +#@end Parentheses around both kinds of patterns could be omitted: +#@samplecode case [1, 2] in Integer, Integer "matched" @@ -149,7 +170,9 @@ Parentheses around both kinds of patterns could be omitted: "not matched" end #=> "matched" +#@end +#@samplecode case {a: 1, b: 2, c: 3} in a: Integer "matched" @@ -157,26 +180,44 @@ Parentheses around both kinds of patterns could be omitted: "not matched" end #=> "matched" +#@end +#@samplecode [1, 2] => a, b +#@end + +#@samplecode [1, 2] in a, b +#@end +#@samplecode {a: 1, b: 2, c: 3} => a: +#@end + +#@# このコメントの前後のコードブロックを1つにまとめると +#@# {a: 1, b: 2, c: 3} => a: {a: 1, b: 2, c: 3} in a: +#@# と解釈されて duplicated key name で SyntaxError になってしまうのでやむを得ず別々のコードブロックにしている + +#@samplecode {a: 1, b: 2, c: 3} in a: +#@end 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: +#@samplecode case ["a", 1, "b", "c", 2] in [*, String, String, *] "matched" else "not matched" end +#@end == Variable binding Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): +#@samplecode case [1, 2] in Integer => a, Integer "matched: #{a}" @@ -184,7 +225,9 @@ Besides deep structural checks, one of the very important features of the patter "not matched" end #=> "matched: 1" +#@end +#@samplecode case {a: 1, b: 2, c: 3} in a: Integer => m "matched: #{m}" @@ -192,9 +235,11 @@ Besides deep structural checks, one of the very important features of the patter "not matched" end #=> "matched: 1" +#@end If no additional check is required, for only binding some part of the data to a variable, a simpler form could be used: +#@samplecode case [1, 2] in a, Integer "matched: #{a}" @@ -202,7 +247,9 @@ If no additional check is required, for only binding some part of the data to a "not matched" end #=> "matched: 1" +#@end +#@samplecode case {a: 1, b: 2, c: 3} in a: m "matched: #{m}" @@ -210,9 +257,11 @@ If no additional check is required, for only binding some part of the data to a "not matched" end #=> "matched: 1" +#@end 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: +#@samplecode case {a: 1, b: 2, c: 3} in a: "matched: #{a}" @@ -220,9 +269,11 @@ For hash patterns, even a simpler form exists: key-only specification (without a "not matched" end #=> "matched: 1" +#@end Binding works for nested patterns as well: +#@samplecode case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]} in name:, friends: [{name: first_friend}, *] "matched: #{first_friend}" @@ -230,9 +281,11 @@ Binding works for nested patterns as well: "not matched" end #=> "matched: Jane" +#@end The "rest" part of a pattern also can be bound to a variable: +#@samplecode case [1, 2, 3] in a, *rest "matched: #{a}, #{rest}" @@ -240,7 +293,9 @@ The "rest" part of a pattern also can be bound to a variable: "not matched" end #=> "matched: 1, [2, 3]" +#@end +#@samplecode case {a: 1, b: 2, c: 3} in a:, **rest "matched: #{a}, #{rest}" @@ -248,9 +303,11 @@ The "rest" part of a pattern also can be bound to a variable: "not matched" end #=> "matched: 1, {:b=>2, :c=>3}" +#@end Binding to variables currently does NOT work for alternative patterns joined with |: +#@samplecode case {a: 1, b: 2} in {a: } | Array "matched: #{a}" @@ -258,9 +315,11 @@ Binding to variables currently does NOT work for alternative patterns joined wit "not matched" end # SyntaxError (illegal variable in alternative pattern (a)) +#@end Variables that start with _ are the only exclusions from this rule: +#@samplecode case {a: 1, b: 2} in {a: _, b: _foo} | Array "matched: #{_}, #{_foo}" @@ -268,6 +327,7 @@ Variables that start with _ are the only exclusions from this rule: "not matched" end # => "matched: 1, 2" +#@end It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value. @@ -275,6 +335,7 @@ It is, though, not advised to reuse the bound value, as this pattern's goal is t Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: +#@samplecode expectation = 18 case [1, 2] @@ -285,9 +346,11 @@ Due to the variable binding feature, existing local variable can not be straight end # expected: "not matched. expectation was: 18" # real: "matched. expectation was: 1" -- local variable just rewritten +#@end For this case, the pin operator ^ can be used, to tell Ruby "just use this value as part of the pattern": +#@samplecode expectation = 18 case [1, 2] in ^expectation, *rest @@ -296,9 +359,11 @@ For this case, the pin operator ^ can be used, to tell Ruby "just u "not matched. expectation was: #{expectation}" end #=> "not matched. expectation was: 18" +#@end One important usage of variable pinning is specifying that the same value should occur in the pattern several times: +#@samplecode jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]} john = {school: 'high', schools: [{id: 1, level: 'middle'}]} @@ -317,9 +382,11 @@ One important usage of variable pinning is specifying that the same value should "not matched" end #=> "not matched" +#@end In addition to pinning local variables, you can also pin instance, global, and class variables: +#@samplecode $gvar = 1 class A @ivar = 2 @@ -332,9 +399,11 @@ In addition to pinning local variables, you can also pin instance, global, and c end #=> "matched" end +#@end You can also pin the result of arbitrary expressions using parentheses: +#@samplecode a = 1 b = 2 case 3 @@ -344,11 +413,13 @@ You can also pin the result of arbitrary expressions using parentheses: "not matched" end #=> "matched" +#@end == 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). +#@samplecode class Point def initialize(x, y) @x, @y = x, y @@ -382,9 +453,11 @@ As already mentioned above, array, find, and hash patterns besides literal array end # prints: deconstruct_keys called with [:x] #=> "matched: 1" +#@end +keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: +#@samplecode case Point.new(1, -2) in x: 0.. => px, **rest "matched: #{px}" @@ -393,9 +466,11 @@ As already mentioned above, array, find, and hash patterns besides literal array end # prints: deconstruct_keys called with nil #=> "matched: 1" +#@end Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with === +#@samplecode class SuperPoint < Point end @@ -414,11 +489,13 @@ Additionally, when matching custom classes, the expected class can be specified "not matched" end #=> "matched: 1" +#@end == Guard clauses +if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: +#@samplecode case [1, 2] in a, b if b == a*2 "matched" @@ -426,7 +503,9 @@ Additionally, when matching custom classes, the expected class can be specified "not matched" end #=> "matched" +#@end +#@samplecode case [1, 1] in a, b if b == a*2 "matched" @@ -434,9 +513,11 @@ Additionally, when matching custom classes, the expected class can be specified "not matched" end #=> "not matched" +#@end +unless+ works, too: +#@samplecode case [1, 1] in a, b unless b == a*2 "matched" @@ -444,25 +525,32 @@ Additionally, when matching custom classes, the expected class can be specified "not matched" end #=> "matched" +#@end == Current feature status As of Ruby 3.1, 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: +#@samplecode [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! +#@end To suppress this warning, one may use the Warning::[]= method: +#@samplecode Warning[:experimental] = false eval('[0] => [*, 0, *]') # ...no warning printed... +#@end Note that pattern-matching warnings are raised at compile time, so this will not suppress the warning: +#@samplecode Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted [0] => [*, 0, *] +#@end So, only subsequently loaded files or `eval`-ed code is affected by switching the flag. @@ -512,6 +600,7 @@ To leave room for optimization in the future, the specification contains some un Use of a variable in an unmatched pattern: +#@samplecode case [0, 1] in [a, 2] "not matched" @@ -522,9 +611,11 @@ Use of a variable in an unmatched pattern: end a #=> undefined c #=> undefined +#@end Number of +deconstruct+, +deconstruct_keys+ method calls: +#@samplecode $i = 0 ary = [0] def ary.deconstruct @@ -538,3 +629,4 @@ Number of +deconstruct+, +deconstruct_keys+ method calls: "matched" end $i #=> undefined +#@end From 636647774802c7d1a6de57178caa6e888df954d2 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 15:11:48 +0900 Subject: [PATCH 03/43] =?UTF-8?q?=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E9=96=A2=E9=80=A3=E3=81=AE=E3=83=89?= =?UTF-8?q?=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=83=87=E3=83=B3=E3=83=88=E3=82=92=E6=95=B4=E5=BD=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 素の rdoc と bitclust の文法の違いを反映するため - サンプルコード・整形済みテキストの行頭の余分なインデントを削除 - 箇条書きのスタイルを適用するためインデントを追加 --- refm/doc/spec/control.rd | 14 +- refm/doc/spec/pattern_matching.rd | 672 +++++++++++++++--------------- 2 files changed, 343 insertions(+), 343 deletions(-) diff --git a/refm/doc/spec/control.rd b/refm/doc/spec/control.rd index 83616b23c7..17ec5efdec 100644 --- a/refm/doc/spec/control.rd +++ b/refm/doc/spec/control.rd @@ -234,13 +234,13 @@ Since Ruby 2.7, +case+ expressions also provide a more powerful experimental pattern matching feature via the +in+ keyword: #@samplecode - case {a: 1, b: 2, c: 3} - in a: Integer => m - "matched: #{m}" - else - "not matched" - end - # => "matched: 1" +case {a: 1, b: 2, c: 3} +in a: Integer => m + "matched: #{m}" +else + "not matched" +end +# => "matched: 1" #@end The pattern matching syntax is described on diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index e7f40e51a7..5d596ba444 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -4,60 +4,60 @@ Pattern matching is a feature allowing deep matching of structured values: check Pattern matching in Ruby is implemented with the +case+/+in+ expression: - case - in - ... - in - ... - in - ... - else - ... - end + case + in + ... + in + ... + in + ... + else + ... + end (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: - => + => - in + in 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. Therefore, the +case+ expression might be used for conditional matching and unpacking: #@samplecode - config = {db: {user: 'admin', password: 'abc123'}} +config = {db: {user: 'admin', password: 'abc123'}} - case config - in db: {user:} # matches subhash and puts matched value in variable user - puts "Connect with user '#{user}'" - in connection: {username: } - puts "Connect with user '#{username}'" - else - puts "Unrecognized structure of config" - end - # Prints: "Connect with user 'admin'" +case config +in db: {user:} # matches subhash and puts matched value in variable user + puts "Connect with user '#{user}'" +in connection: {username: } + puts "Connect with user '#{username}'" +else + puts "Unrecognized structure of config" +end +# Prints: "Connect with user 'admin'" #@end whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: #@samplecode - config = {db: {user: 'admin', password: 'abc123'}} +config = {db: {user: 'admin', password: 'abc123'}} - config => {db: {user:}} # will raise if the config's structure is unexpected +config => {db: {user:}} # will raise if the config's structure is unexpected - puts "Connect with user '#{user}'" - # Prints: "Connect with user 'admin'" +puts "Connect with user '#{user}'" +# Prints: "Connect with user 'admin'" #@end in is the same as case ; in ; true; else false; end. You can use it when you only want to know if a pattern has been matched or not: #@samplecode - users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}] - users.any? {|user| user in {name: /B/, age: 20..} } #=> true +users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}] +users.any? {|user| user in {name: /B/, age: 20..} } #=> true #@end See below for more examples and explanations of the syntax. @@ -66,12 +66,12 @@ See below for more examples and explanations of the syntax. Patterns can be: -* any Ruby object (matched by the === operator, like in +when+); (Value pattern) -* array pattern: [, , , ...]; (Array pattern) -* find pattern: [*variable, , , , ..., *variable]; (Find pattern) -* hash pattern: {key: , key: , ...}; (Hash pattern) -* combination of patterns with |; (Alternative pattern) -* variable capture: => variable or variable; (As pattern, Variable pattern) + * any Ruby object (matched by the === operator, like in +when+); (Value pattern) + * array pattern: [, , , ...]; (Array pattern) + * find pattern: [*variable, , , , ..., *variable]; (Find pattern) + * hash pattern: {key: , key: , ...}; (Hash pattern) + * combination of patterns with |; (Alternative pattern) + * variable capture: => variable or variable; (As pattern, Variable pattern) Any pattern can be nested inside array/find/hash patterns where is specified. @@ -81,117 +81,117 @@ Hash patterns match hashes, or objects that respond to +deconstruct_keys+ (see b An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: #@samplecode - case [1, 2, 3] - in [Integer, Integer] - "matched" - else - "not matched" - end - #=> "not matched" +case [1, 2, 3] +in [Integer, Integer] + "matched" +else + "not matched" +end +#=> "not matched" #@end while the hash matches even if there are other keys besides the specified part: #@samplecode - case {a: 1, b: 2, c: 3} - in {a: Integer} - "matched" - else - "not matched" - end - #=> "matched" +case {a: 1, b: 2, c: 3} +in {a: Integer} + "matched" +else + "not matched" +end +#=> "matched" #@end {} is the only exclusion from this rule. It matches only if an empty hash is given: #@samplecode - case {a: 1, b: 2, c: 3} - in {} - "matched" - else - "not matched" - end - #=> "not matched" +case {a: 1, b: 2, c: 3} +in {} + "matched" +else + "not matched" +end +#=> "not matched" #@end #@samplecode - case {} - in {} - "matched" - else - "not matched" - end - #=> "matched" +case {} +in {} + "matched" +else + "not matched" +end +#=> "matched" #@end 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 **nil: #@samplecode - case {a: 1, b: 2} - in {a: Integer, **nil} # this will not match the pattern having keys other than a: - "matched a part" - in {a: Integer, b: Integer, **nil} - "matched a whole" - else - "not matched" - end - #=> "matched a whole" +case {a: 1, b: 2} +in {a: Integer, **nil} # this will not match the pattern having keys other than a: + "matched a part" +in {a: Integer, b: Integer, **nil} + "matched a whole" +else + "not matched" +end +#=> "matched a whole" #@end Both array and hash patterns support "rest" specification: #@samplecode - case [1, 2, 3] - in [Integer, *] - "matched" - else - "not matched" - end - #=> "matched" +case [1, 2, 3] +in [Integer, *] + "matched" +else + "not matched" +end +#=> "matched" #@end #@samplecode - case {a: 1, b: 2, c: 3} - in {a: Integer, **} - "matched" - else - "not matched" - end - #=> "matched" +case {a: 1, b: 2, c: 3} +in {a: Integer, **} + "matched" +else + "not matched" +end +#=> "matched" #@end Parentheses around both kinds of patterns could be omitted: #@samplecode - case [1, 2] - in Integer, Integer - "matched" - else - "not matched" - end - #=> "matched" +case [1, 2] +in Integer, Integer + "matched" +else + "not matched" +end +#=> "matched" #@end #@samplecode - case {a: 1, b: 2, c: 3} - in a: Integer - "matched" - else - "not matched" - end - #=> "matched" +case {a: 1, b: 2, c: 3} +in a: Integer + "matched" +else + "not matched" +end +#=> "matched" #@end #@samplecode - [1, 2] => a, b +[1, 2] => a, b #@end #@samplecode - [1, 2] in a, b +[1, 2] in a, b #@end #@samplecode - {a: 1, b: 2, c: 3} => a: +{a: 1, b: 2, c: 3} => a: #@end #@# このコメントの前後のコードブロックを1つにまとめると @@ -199,18 +199,18 @@ Parentheses around both kinds of patterns could be omitted: #@# と解釈されて duplicated key name で SyntaxError になってしまうのでやむを得ず別々のコードブロックにしている #@samplecode - {a: 1, b: 2, c: 3} in a: +{a: 1, b: 2, c: 3} in a: #@end 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: #@samplecode - case ["a", 1, "b", "c", 2] - in [*, String, String, *] - "matched" - else - "not matched" - end +case ["a", 1, "b", "c", 2] +in [*, String, String, *] + "matched" +else + "not matched" +end #@end == Variable binding @@ -218,115 +218,115 @@ Find pattern is similar to array pattern but it can be used to check if the give Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): #@samplecode - case [1, 2] - in Integer => a, Integer - "matched: #{a}" - else - "not matched" - end - #=> "matched: 1" +case [1, 2] +in Integer => a, Integer + "matched: #{a}" +else + "not matched" +end +#=> "matched: 1" #@end #@samplecode - case {a: 1, b: 2, c: 3} - in a: Integer => m - "matched: #{m}" - else - "not matched" - end - #=> "matched: 1" +case {a: 1, b: 2, c: 3} +in a: Integer => m + "matched: #{m}" +else + "not matched" +end +#=> "matched: 1" #@end If no additional check is required, for only binding some part of the data to a variable, a simpler form could be used: #@samplecode - case [1, 2] - in a, Integer - "matched: #{a}" - else - "not matched" - end - #=> "matched: 1" +case [1, 2] +in a, Integer + "matched: #{a}" +else + "not matched" +end +#=> "matched: 1" #@end #@samplecode - case {a: 1, b: 2, c: 3} - in a: m - "matched: #{m}" - else - "not matched" - end - #=> "matched: 1" +case {a: 1, b: 2, c: 3} +in a: m + "matched: #{m}" +else + "not matched" +end +#=> "matched: 1" #@end 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: #@samplecode - case {a: 1, b: 2, c: 3} - in a: - "matched: #{a}" - else - "not matched" - end - #=> "matched: 1" +case {a: 1, b: 2, c: 3} +in a: + "matched: #{a}" +else + "not matched" +end +#=> "matched: 1" #@end Binding works for nested patterns as well: #@samplecode - case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]} - in name:, friends: [{name: first_friend}, *] - "matched: #{first_friend}" - else - "not matched" - end - #=> "matched: Jane" +case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]} +in name:, friends: [{name: first_friend}, *] + "matched: #{first_friend}" +else + "not matched" +end +#=> "matched: Jane" #@end The "rest" part of a pattern also can be bound to a variable: #@samplecode - case [1, 2, 3] - in a, *rest - "matched: #{a}, #{rest}" - else - "not matched" - end - #=> "matched: 1, [2, 3]" +case [1, 2, 3] +in a, *rest + "matched: #{a}, #{rest}" +else + "not matched" +end +#=> "matched: 1, [2, 3]" #@end #@samplecode - case {a: 1, b: 2, c: 3} - in a:, **rest - "matched: #{a}, #{rest}" - else - "not matched" - end - #=> "matched: 1, {:b=>2, :c=>3}" +case {a: 1, b: 2, c: 3} +in a:, **rest + "matched: #{a}, #{rest}" +else + "not matched" +end +#=> "matched: 1, {:b=>2, :c=>3}" #@end Binding to variables currently does NOT work for alternative patterns joined with |: #@samplecode - case {a: 1, b: 2} - in {a: } | Array - "matched: #{a}" - else - "not matched" - end - # SyntaxError (illegal variable in alternative pattern (a)) +case {a: 1, b: 2} +in {a: } | Array + "matched: #{a}" +else + "not matched" +end +# SyntaxError (illegal variable in alternative pattern (a)) #@end Variables that start with _ are the only exclusions from this rule: #@samplecode - case {a: 1, b: 2} - in {a: _, b: _foo} | Array - "matched: #{_}, #{_foo}" - else - "not matched" - end - # => "matched: 1, 2" +case {a: 1, b: 2} +in {a: _, b: _foo} | Array + "matched: #{_}, #{_foo}" +else + "not matched" +end +# => "matched: 1, 2" #@end It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value. @@ -336,83 +336,83 @@ It is, though, not advised to reuse the bound value, as this pattern's goal is t Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: #@samplecode - expectation = 18 +expectation = 18 - case [1, 2] - in expectation, *rest - "matched. expectation was: #{expectation}" - else - "not matched. expectation was: #{expectation}" - end - # expected: "not matched. expectation was: 18" - # real: "matched. expectation was: 1" -- local variable just rewritten +case [1, 2] +in expectation, *rest + "matched. expectation was: #{expectation}" +else + "not matched. expectation was: #{expectation}" +end +# expected: "not matched. expectation was: 18" +# real: "matched. expectation was: 1" -- local variable just rewritten #@end For this case, the pin operator ^ can be used, to tell Ruby "just use this value as part of the pattern": #@samplecode - expectation = 18 - case [1, 2] - in ^expectation, *rest - "matched. expectation was: #{expectation}" - else - "not matched. expectation was: #{expectation}" - end - #=> "not matched. expectation was: 18" +expectation = 18 +case [1, 2] +in ^expectation, *rest + "matched. expectation was: #{expectation}" +else + "not matched. expectation was: #{expectation}" +end +#=> "not matched. expectation was: 18" #@end One important usage of variable pinning is specifying that the same value should occur in the pattern several times: #@samplecode - jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]} - john = {school: 'high', schools: [{id: 1, level: 'middle'}]} +jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]} +john = {school: 'high', schools: [{id: 1, level: 'middle'}]} - case jane - in school:, schools: [*, {id:, level: ^school}] # select the last school, level should match - "matched. school: #{id}" - else - "not matched" - end - #=> "matched. school: 2" +case jane +in school:, schools: [*, {id:, level: ^school}] # select the last school, level should match + "matched. school: #{id}" +else + "not matched" +end +#=> "matched. school: 2" - case john # the specified school level is "high", but last school does not match - in school:, schools: [*, {id:, level: ^school}] - "matched. school: #{id}" - else - "not matched" - end - #=> "not matched" +case john # the specified school level is "high", but last school does not match +in school:, schools: [*, {id:, level: ^school}] + "matched. school: #{id}" +else + "not matched" +end +#=> "not matched" #@end In addition to pinning local variables, you can also pin instance, global, and class variables: #@samplecode - $gvar = 1 - class A - @ivar = 2 - @@cvar = 3 - case [1, 2, 3] - in ^$gvar, ^@ivar, ^@@cvar - "matched" - else - "not matched" - end - #=> "matched" +$gvar = 1 +class A + @ivar = 2 + @@cvar = 3 + case [1, 2, 3] + in ^$gvar, ^@ivar, ^@@cvar + "matched" + else + "not matched" end + #=> "matched" +end #@end You can also pin the result of arbitrary expressions using parentheses: #@samplecode - a = 1 - b = 2 - case 3 - in ^(a + b) - "matched" - else - "not matched" - end - #=> "matched" +a = 1 +b = 2 +case 3 +in ^(a + b) + "matched" +else + "not matched" +end +#=> "matched" #@end == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ @@ -420,75 +420,75 @@ You can also pin the result of arbitrary expressions using parentheses: 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). #@samplecode - class Point - def initialize(x, y) - @x, @y = x, y - end - - def deconstruct - puts "deconstruct called" - [@x, @y] - end - - def deconstruct_keys(keys) - puts "deconstruct_keys called with #{keys.inspect}" - {x: @x, y: @y} - end +class Point + def initialize(x, y) + @x, @y = x, y end - case Point.new(1, -2) - in px, Integer # sub-patterns and variable binding works - "matched: #{px}" - else - "not matched" + def deconstruct + puts "deconstruct called" + [@x, @y] end - # prints "deconstruct called" - "matched: 1" - case Point.new(1, -2) - in x: 0.. => px - "matched: #{px}" - else - "not matched" + def deconstruct_keys(keys) + puts "deconstruct_keys called with #{keys.inspect}" + {x: @x, y: @y} end - # prints: deconstruct_keys called with [:x] - #=> "matched: 1" +end + +case Point.new(1, -2) +in px, Integer # sub-patterns and variable binding works + "matched: #{px}" +else + "not matched" +end +# prints "deconstruct called" +"matched: 1" + +case Point.new(1, -2) +in x: 0.. => px + "matched: #{px}" +else + "not matched" +end +# prints: deconstruct_keys called with [:x] +#=> "matched: 1" #@end +keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: #@samplecode - case Point.new(1, -2) - in x: 0.. => px, **rest - "matched: #{px}" - else - "not matched" - end - # prints: deconstruct_keys called with nil - #=> "matched: 1" +case Point.new(1, -2) +in x: 0.. => px, **rest + "matched: #{px}" +else + "not matched" +end +# prints: deconstruct_keys called with nil +#=> "matched: 1" #@end Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with === #@samplecode - class SuperPoint < Point - end +class SuperPoint < Point +end - case Point.new(1, -2) - in SuperPoint(x: 0.. => px) - "matched: #{px}" - else - "not matched" - end - #=> "not matched" +case Point.new(1, -2) +in SuperPoint(x: 0.. => px) + "matched: #{px}" +else + "not matched" +end +#=> "not matched" - case SuperPoint.new(1, -2) - in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed - "matched: #{px}" - else - "not matched" - end - #=> "matched: 1" +case SuperPoint.new(1, -2) +in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed + "matched: #{px}" +else + "not matched" +end +#=> "matched: 1" #@end == Guard clauses @@ -496,35 +496,35 @@ Additionally, when matching custom classes, the expected class can be specified +if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: #@samplecode - case [1, 2] - in a, b if b == a*2 - "matched" - else - "not matched" - end - #=> "matched" +case [1, 2] +in a, b if b == a*2 + "matched" +else + "not matched" +end +#=> "matched" #@end #@samplecode - case [1, 1] - in a, b if b == a*2 - "matched" - else - "not matched" - end - #=> "not matched" +case [1, 1] +in a, b if b == a*2 + "matched" +else + "not matched" +end +#=> "not matched" #@end +unless+ works, too: #@samplecode - case [1, 1] - in a, b unless b == a*2 - "matched" - else - "not matched" - end - #=> "matched" +case [1, 1] +in a, b unless b == a*2 + "matched" +else + "not matched" +end +#=> "matched" #@end == Current feature status @@ -532,24 +532,24 @@ Additionally, when matching custom classes, the expected class can be specified As of Ruby 3.1, 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: #@samplecode - [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! +[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! #@end To suppress this warning, one may use the Warning::[]= method: #@samplecode - Warning[:experimental] = false - eval('[0] => [*, 0, *]') - # ...no warning printed... +Warning[:experimental] = false +eval('[0] => [*, 0, *]') +# ...no warning printed... #@end Note that pattern-matching warnings are raised at compile time, so this will not suppress the warning: #@samplecode - Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted - [0] => [*, 0, *] +Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted +[0] => [*, 0, *] #@end So, only subsequently loaded files or `eval`-ed code is affected by switching the flag. @@ -601,32 +601,32 @@ To leave room for optimization in the future, the specification contains some un Use of a variable in an unmatched pattern: #@samplecode - case [0, 1] - in [a, 2] - "not matched" - in b - "matched" - in c - "not matched" - end - a #=> undefined - c #=> undefined +case [0, 1] +in [a, 2] + "not matched" +in b + "matched" +in c + "not matched" +end +a #=> undefined +c #=> undefined #@end Number of +deconstruct+, +deconstruct_keys+ method calls: #@samplecode - $i = 0 - ary = [0] - def ary.deconstruct - $i += 1 - self - end - case ary - in [0, 1] - "not matched" - in [0] - "matched" - end - $i #=> undefined +$i = 0 +ary = [0] +def ary.deconstruct + $i += 1 + self +end +case ary +in [0, 1] + "not matched" +in [0] + "matched" +end +$i #=> undefined #@end From c2de8c03922db54519c838e1a7c7dbbfe2761df9 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 15:15:24 +0900 Subject: [PATCH 04/43] =?UTF-8?q?=E3=83=88=E3=83=83=E3=83=97=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=81=AE=E7=9B=AE=E6=AC=A1=E3=81=AB=E3=83=91?= =?UTF-8?q?=E3=82=BF=E3=83=BC=E3=83=B3=E3=83=9E=E3=83=83=E3=83=81=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refm/doc/index.rd | 1 + 1 file changed, 1 insertion(+) diff --git a/refm/doc/index.rd b/refm/doc/index.rd index bc548fa784..2b4df3072f 100644 --- a/refm/doc/index.rd +++ b/refm/doc/index.rd @@ -67,6 +67,7 @@ Ruby の文法: * [[d:spec/control]] * [[d:spec/call]] * [[d:spec/def]] + * [[d:spec/pattern_matching]] その他: * [[d:spec/m17n]] From 221c5d10f7f87fd90618dc0c9e06adef810d7d33 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 15:15:44 +0900 Subject: [PATCH 05/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=88=E3=83=AB=E3=81=A8=E5=86=92=E9=A0=AD?= =?UTF-8?q?=E9=83=A8=E3=82=92=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している - unpack は Python に「アンパック」という用語があるのでとりあえずそのまま「アンパック」と訳している - cf. https://docs.python.org/ja/3/tutorial/datastructures.html#tuples-and-sequences --- refm/doc/spec/pattern_matching.rd | 45 ++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 5d596ba444..b17abf6375 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -1,8 +1,11 @@ -= Pattern matching +#@# = Pattern matching += パターンマッチ -Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. +#@# Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. +パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチングを可能にする機能です。 -Pattern matching in Ruby is implemented with the +case+/+in+ expression: +#@# Pattern matching in Ruby is implemented with the +case+/+in+ expression: +Rubyでのパターンマッチは +case+/+in+ 式を用いて実装されています。 case in @@ -15,52 +18,64 @@ 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.) ++in+ 節と +when+ 節は1つの +case+ 式の中に混ぜて書くことはできません。 -Or with the => operator and the +in+ operator, which can be used in a standalone expression: +#@# Or with the => operator and the +in+ operator, which can be used in a standalone expression: +=> 演算子と +in+ 演算子で、単体の式で使用することも可能です。 => in -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. +#@# 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. ++case+/+in+ 式は _網羅的_ です。もし +case+ 式の値がどの節にもマッチせず +else+ 節がない場合、+NoMatchingPatternError+ が raise されます。 -Therefore, the +case+ expression might be used for conditional matching and unpacking: +#@# Therefore, the +case+ expression might be used for conditional matching and unpacking: +そのため、条件付きのマッチングやアンパックに +case+ 式が使われることがあります。 #@samplecode config = {db: {user: 'admin', password: 'abc123'}} case config -in db: {user:} # matches subhash and puts matched value in variable user +#@# in db: {user:} # matches subhash and puts matched value in variable user +in db: {user:} # ネストしたハッシュにマッチしマッチした値が変数 user に代入されます puts "Connect with user '#{user}'" in connection: {username: } puts "Connect with user '#{username}'" else puts "Unrecognized structure of config" end -# Prints: "Connect with user 'admin'" +#@# # Prints: "Connect with user 'admin'" +# "Connect with user 'admin'" が出力されます #@end -whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: +#@# whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: +一方、=> 演算子は、期待されるデータ構造があらかじめ分かっている場合に、その一部をアンパックするのに有効です。 #@samplecode config = {db: {user: 'admin', password: 'abc123'}} -config => {db: {user:}} # will raise if the config's structure is unexpected +#@# config => {db: {user:}} # will raise if the config's structure is unexpected +config => {db: {user:}} # config の構造が予期しないものだった場合は例外が raise されます puts "Connect with user '#{user}'" -# Prints: "Connect with user 'admin'" +#@# # Prints: "Connect with user 'admin'" +# Connect with user 'admin'" が出力されます #@end - in is the same as case ; in ; true; else false; end. -You can use it when you only want to know if a pattern has been matched or not: +#@# in is the same as case ; in ; true; else false; end. + in ; in ; true; else false; end と等価です。 +#@# You can use it when you only want to know if a pattern has been matched or not: +パターンにマッチするかどうかだけを知りたいときに使えます。 #@samplecode users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}] users.any? {|user| user in {name: /B/, age: 20..} } #=> true #@end -See below for more examples and explanations of the syntax. +#@# See below for more examples and explanations of the syntax. +構文の詳細な例と説明は以下を参照してください。 == Patterns From eb19c6fe0adfc3e0515da255a978918400e0132f Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 16:05:53 +0900 Subject: [PATCH 06/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE=20Patte?= =?UTF-8?q?rns(=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3)=20=E3=82=92=E7=BF=BB?= =?UTF-8?q?=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している - パターンの名称にアルファベットが含まれる場合は頭文字大文字で統一している - respond to に関しては「実装もオブジェクト自体が持つ」のと「応答できる」だと意味が異なり、どのように翻訳するか迷ったが注記を追加し Object#respond_to? へのリンクを追加することで respond to の意味での『〜を持つ』だということを説明した - rest に関しては rest parameter の日本語名に合わせて「残余」と訳した - cf. https://secret-garden.hatenablog.com/entry/2022/03/11/210246 - ただ「残余」とだけ書かれていても分かりづらいため、カッコつきで rest も併記してみた --- refm/doc/spec/pattern_matching.rd | 61 +++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index b17abf6375..5fbd08ff68 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -77,23 +77,39 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true #@# See below for more examples and explanations of the syntax. 構文の詳細な例と説明は以下を参照してください。 -== Patterns +#@# == Patterns +== パターン -Patterns can be: +#@# Patterns can be: +パターンで利用できるものには次のものがあります。 - * any Ruby object (matched by the === operator, like in +when+); (Value pattern) - * array pattern: [, , , ...]; (Array pattern) - * find pattern: [*variable, , , , ..., *variable]; (Find pattern) - * hash pattern: {key: , key: , ...}; (Hash pattern) - * combination of patterns with |; (Alternative pattern) - * variable capture: => variable or variable; (As pattern, Variable pattern) +#@# * any Ruby object (matched by the === operator, like in +when+); (Value pattern) + * Ruby のオブジェクト (+when+ での場合のように === 演算子にマッチするもの) (Value パターン) +#@# * array pattern: [, , , ...]; (Array pattern) + * Array パターン: [, , , ...] (Array パターン) +#@# * find pattern: [*variable, , , , ..., *variable]; (Find pattern) + * Find パターン: [*variable, , , , ..., *variable] (Find パターン) +#@# * hash pattern: {key: , key: , ...}; (Hash pattern) + * Hash パターン: {key: , key: , ...} (Hash パターン) +#@# * combination of patterns with |; (Alternative pattern) + * | でのパターンの組み合わせ (Alternative パターン) +#@# * variable capture: => variable or variable; (As pattern, Variable pattern) + * 変数のキャプチャ: => variable または variable (As パターン, Variable パターン) -Any pattern can be nested inside array/find/hash patterns where is specified. +#@# Any pattern can be nested inside array/find/hash patterns where is specified. +Array/Find/Hash パターンの中に と書かれている場所では任意のパターンをネストさせることができます。 -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. +#@# Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter). +Array パターン と Find パターン は配列か +deconstruct+ を持つオブジェクトにマッチします。(+deconstruct+ については後ほど説明します) -An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: +#@# 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. +Hash パターン はハッシュか +deconstruct_keys+ メソッドを持つオブジェクトにマッチします。(+deconstruct_keys+ については後ほど説明します) Hash パターン で利用できるキーはシンボルのみです。 + +#@# 原文にないが補足のため追加 +※ deconstruct や deconstruct_keys を扱う際の『〜を持つ』の定義は [[m:Object#respond_to?]] と同様です。 + +#@# An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: +Array パターン と Hash パターン の挙動の重要な違いは Array パターンは配列の _全ての_ 要素がマッチする必要があるということです。 #@samplecode case [1, 2, 3] @@ -105,7 +121,8 @@ end #=> "not matched" #@end -while the hash matches even if there are other keys besides the specified part: +#@# while the hash matches even if there are other keys besides the specified part: +一方 Hash パターン は一部の key だけ指定している場合(指定している key 以外にも key が存在する場合)でもマッチします。 #@samplecode case {a: 1, b: 2, c: 3} @@ -117,7 +134,8 @@ end #=> "matched" #@end -{} is the only exclusion from this rule. It matches only if an empty hash is given: +#@# {} is the only exclusion from this rule. It matches only if an empty hash is given: +{} だけはこのルールの例外です。{} は空のハッシュのみマッチします。 #@samplecode case {a: 1, b: 2, c: 3} @@ -139,11 +157,13 @@ end #=> "matched" #@end -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 **nil: +#@# 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 **nil: +また、パターンで明示的に指定されたキー以外にキーが存在しないケースにマッチングさせたい場合、**nil を指定する方法もあります。 #@samplecode case {a: 1, b: 2} -in {a: Integer, **nil} # this will not match the pattern having keys other than a: +#@# in {a: Integer, **nil} # this will not match the pattern having keys other than a: +in {a: Integer, **nil} # これは a: 以外に key を持つパターンのためマッチしません "matched a part" in {a: Integer, b: Integer, **nil} "matched a whole" @@ -153,7 +173,8 @@ end #=> "matched a whole" #@end -Both array and hash patterns support "rest" specification: +#@# Both array and hash patterns support "rest" specification: +Array パターン と Hash パターン ともに "残余"(rest) の部分にマッチする構文をサポートしています。 #@samplecode case [1, 2, 3] @@ -175,7 +196,8 @@ end #=> "matched" #@end -Parentheses around both kinds of patterns could be omitted: +#@# Parentheses around both kinds of patterns could be omitted: +Array パターン や Hash パターン は両端の []{} といったカッコを省略できます。 #@samplecode case [1, 2] @@ -217,7 +239,8 @@ end {a: 1, b: 2, c: 3} in a: #@end -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: +Find パターン は Array パターン に似ていますが、オブジェクトの一部の要素がマッチしていることを検査できます。 #@samplecode case ["a", 1, "b", "c", 2] From c3f7ef165b2ce6a91546e2f6ba2bb038e3544739 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Mon, 2 Jan 2023 00:54:48 +0900 Subject: [PATCH 07/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE=20Varia?= =?UTF-8?q?ble=20binding(=E5=A4=89=E6=95=B0=E3=81=AE=E6=9D=9F=E7=B8=9B)=20?= =?UTF-8?q?=E3=82=92=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している - パターンの名称にアルファベットが含まれる場合は頭文字大文字で統一している - rest に関しては rest parameter の日本語名に合わせて「残余」と訳した - cf. https://secret-garden.hatenablog.com/entry/2022/03/11/210246 - ただ「残余」とだけ書かれていても分かりづらいため、カッコつきで rest も併記してみた --- refm/doc/spec/pattern_matching.rd | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 5fbd08ff68..7322fd65bf 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -251,9 +251,11 @@ else end #@end -== Variable binding +#@# == Variable binding +== 変数の束縛 -Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): +#@# Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): +深い構造検査の他のパターンマッチの重要な機能の1つにマッチした部分のローカル変数への束縛があります。束縛の基本的な形はマッチしたパターンの後ろに => 変数名 と書くことです。(この形は rescue 節で rescue ExceptionClass => var の形で例外をローカル変数に格納する形に似ています) #@samplecode case [1, 2] @@ -275,7 +277,8 @@ end #=> "matched: 1" #@end -If no additional check is required, for only binding some part of the data to a variable, a simpler form could be used: +#@# If no additional check is required, for only binding some part of the data to a variable, a simpler form could be used: +追加のチェックが不要で変数への束縛だけがしたい場合は、より簡潔な記法が利用できます。 #@samplecode case [1, 2] @@ -297,7 +300,8 @@ end #=> "matched: 1" #@end -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: +#@# 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: +Hash パターンにもより簡潔な記法があります。チェックが不要で変数への束縛のみ行いたい場合、キー名だけを指定することでキー名と同じ変数に値を束縛することができます。 #@samplecode case {a: 1, b: 2, c: 3} @@ -309,7 +313,8 @@ end #=> "matched: 1" #@end -Binding works for nested patterns as well: +#@# Binding works for nested patterns as well: +ネストしたパターンの場合も同様に値の束縛を利用できます。 #@samplecode case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]} @@ -321,7 +326,8 @@ end #=> "matched: Jane" #@end -The "rest" part of a pattern also can be bound to a variable: +#@# The "rest" part of a pattern also can be bound to a variable: +パターンの "残余"(rest) の部分も同様に変数に束縛できます。 #@samplecode case [1, 2, 3] @@ -343,7 +349,8 @@ end #=> "matched: 1, {:b=>2, :c=>3}" #@end -Binding to variables currently does NOT work for alternative patterns joined with |: +#@# Binding to variables currently does NOT work for alternative patterns joined with |: +変数への束縛は現状、| で結合される Alternative パターン と同時には利用できません。 #@samplecode case {a: 1, b: 2} @@ -355,7 +362,8 @@ end # SyntaxError (illegal variable in alternative pattern (a)) #@end -Variables that start with _ are the only exclusions from this rule: +#@# Variables that start with _ are the only exclusions from this rule: +_ で始まる変数は例外で、Alternative パターン と同時に利用することができます。 #@samplecode case {a: 1, b: 2} @@ -367,7 +375,8 @@ end # => "matched: 1, 2" #@end -It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value. +#@# It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value. +しかし、_ で始まる変数の目的は利用しない値を意味するので、束縛された値を再利用することはオススメしません。 == Variable pinning From 58bf05c709d552767b778d484c424a91ff894065 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 16:28:02 +0900 Subject: [PATCH 08/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE=20Varia?= =?UTF-8?q?ble=20pinning(=E5=A4=89=E6=95=B0=E3=81=AE=E3=83=94=E3=83=B3?= =?UTF-8?q?=E7=95=99=E3=82=81)=20=E3=82=92=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している --- refm/doc/spec/pattern_matching.rd | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 7322fd65bf..70a05fc595 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -378,9 +378,11 @@ end #@# It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value. しかし、_ で始まる変数の目的は利用しない値を意味するので、束縛された値を再利用することはオススメしません。 -== Variable pinning +#@# == Variable pinning +== 変数のピン留め -Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: +#@# Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: +変数の束縛の機能では存在しているローカル変数をサブパターンとしてそのまま利用することはできません。 #@samplecode expectation = 18 @@ -392,10 +394,12 @@ else "not matched. expectation was: #{expectation}" end # expected: "not matched. expectation was: 18" -# real: "matched. expectation was: 1" -- local variable just rewritten +#@# # real: "matched. expectation was: 1" -- local variable just rewritten +# real: "matched. expectation was: 1" -- ローカル変数が上書かれている #@end -For this case, the pin operator ^ can be used, to tell Ruby "just use this value as part of the pattern": +#@# For this case, the pin operator ^ can be used, to tell Ruby "just use this value as part of the pattern": +この場合、Ruby に「この値をパターンの部品として利用するよ」ということを伝えるためにピン演算子 ^ を利用することができます。 #@samplecode expectation = 18 @@ -408,7 +412,8 @@ end #=> "not matched. expectation was: 18" #@end -One important usage of variable pinning is specifying that the same value should occur in the pattern several times: +#@# One important usage of variable pinning is specifying that the same value should occur in the pattern several times: +ピン演算子の重要な用途の1つはパターンに複数回出てくる値を明記することです。 #@samplecode jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]} @@ -422,7 +427,8 @@ else end #=> "matched. school: 2" -case john # the specified school level is "high", but last school does not match +#@# case john # the specified school level is "high", but last school does not match +case john # 指定された school の level は "high" だが、最後の school はマッチしない in school:, schools: [*, {id:, level: ^school}] "matched. school: #{id}" else @@ -431,7 +437,8 @@ end #=> "not matched" #@end -In addition to pinning local variables, you can also pin instance, global, and class variables: +#@# In addition to pinning local variables, you can also pin instance, global, and class variables: +ローカル変数に加えてインスタンス変数やグローバル変数、クラス変数に対してもピン演算子は利用できます。 #@samplecode $gvar = 1 @@ -448,7 +455,8 @@ class A end #@end -You can also pin the result of arbitrary expressions using parentheses: +#@# You can also pin the result of arbitrary expressions using parentheses: +また、カッコを使って任意の式に対してピン演算子を利用できます #@samplecode a = 1 From 95ae9351f5494f31e2d1c966e5b558f293b3cc6a Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 16:42:58 +0900 Subject: [PATCH 09/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE=20Match?= =?UTF-8?q?ing=20non-primitive=20objects(=E3=83=97=E3=83=AA=E3=83=9F?= =?UTF-8?q?=E3=83=86=E3=82=A3=E3=83=96=E3=81=AA=E3=82=AA=E3=83=96=E3=82=B8?= =?UTF-8?q?=E3=82=A7=E3=82=AF=E3=83=88=E4=BB=A5=E5=A4=96=E3=81=A8=E3=81=AE?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E3=83=B3=E3=82=B0)=20=E3=82=92?= =?UTF-8?q?=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している - パターンの名称にアルファベットが含まれる場合は頭文字大文字で統一している --- refm/doc/spec/pattern_matching.rd | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 70a05fc595..1f5f3449da 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -470,9 +470,11 @@ end #=> "matched" #@end -== Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ +#@# == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ +== プリミティブなオブジェクト以外とのマッチング: +deconstruct+ と +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). +#@# 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). +既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは +deconstruct+ (これは Array/Find パターンで利用されます) か +deconstruct_keys+ (これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 #@samplecode class Point @@ -492,12 +494,14 @@ class Point end case Point.new(1, -2) -in px, Integer # sub-patterns and variable binding works +#@# in px, Integer # sub-patterns and variable binding works +in px, Integer # サブパターンと変数への束縛も動きます "matched: #{px}" else "not matched" end -# prints "deconstruct called" +#@# # prints "deconstruct called" +# "deconstruct called" が出力されます "matched: 1" case Point.new(1, -2) @@ -506,11 +510,13 @@ in x: 0.. => px else "not matched" end -# prints: deconstruct_keys called with [:x] +#@# # prints: deconstruct_keys called with [:x] +# "deconstruct_keys called with [:x]" が出力されます #=> "matched: 1" #@end -+keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: +#@# +keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: ++keys+ はマッチしたクラスの中で最適化の余地を残して +deconstruct_keys+ へと渡されます。もし全てのハッシュの表現の計算に高い負荷がかかる場合、必要なサブハッシュのみ計算されるかもしれません。**rest パターンが使われている場合、+keys+ の値として +nil+ が渡されます。 #@samplecode case Point.new(1, -2) @@ -519,11 +525,13 @@ in x: 0.. => px, **rest else "not matched" end -# prints: deconstruct_keys called with nil +#@# # prints: deconstruct_keys called with nil +# "deconstruct_keys called with nil" が出力されます #=> "matched: 1" #@end -Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with === +#@# Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with === +加えて、カスタムクラスにマッチするとき、期待されるクラスはパターンの部品として明記され === で検査されます #@samplecode class SuperPoint < Point @@ -538,7 +546,8 @@ end #=> "not matched" case SuperPoint.new(1, -2) -in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed +#@# in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed +in SuperPoint[x: 0.. => px] # [] や () といったカッコは許容されます "matched: #{px}" else "not matched" From 1905a52cb639118cb37fe1694f84a27f213d439d Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 16:46:06 +0900 Subject: [PATCH 10/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE=20Guard?= =?UTF-8?q?=20clauses(=E3=82=AC=E3=83=BC=E3=83=89=E7=AF=80)=20=E3=82=92?= =?UTF-8?q?=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している --- refm/doc/spec/pattern_matching.rd | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 1f5f3449da..1c088b0e12 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -555,9 +555,11 @@ end #=> "matched: 1" #@end -== Guard clauses +#@# == 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. This condition may use bound variables: +もしパターンマッチのときに +if+ を用いて追加の条件(ガード節)を指定した場合、変数への束縛がされた状態で条件の判定が行われます。 #@samplecode case [1, 2] @@ -579,7 +581,8 @@ end #=> "not matched" #@end -+unless+ works, too: +#@# +unless+ works, too: ++unless+ も利用できます。 #@samplecode case [1, 1] From 7d5b4985cab341a2b4561fe78ba70cecc8b7144a Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 20:31:53 +0900 Subject: [PATCH 11/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE=20Curre?= =?UTF-8?q?nt=20feature=20status(=E6=A9=9F=E8=83=BD=E3=81=AE=E7=8F=BE?= =?UTF-8?q?=E7=8A=B6)=20=E3=82=92=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している - Ruby 3.2 ではおそらくこの節は不要だがまだ ruby/ruby 側でマージされていないため分岐は入れていない - cf. https://github.com/ruby/ruby/pull/7052 --- refm/doc/spec/pattern_matching.rd | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 1c088b0e12..fc16cb605e 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -594,9 +594,11 @@ end #=> "matched" #@end -== Current feature status +#@# == Current feature status +== 機能の現状 -As of Ruby 3.1, 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: +#@# As of Ruby 3.1, 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: +Ruby 3.1 の時点では、Find パターンは _experimental_ と考えられます。Find パターンのシンタックスは将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 #@samplecode [0] => [*, 0, *] @@ -604,24 +606,29 @@ As of Ruby 3.1, find patterns are considered _experimental_: its syntax can chan # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! #@end -To suppress this warning, one may use the Warning::[]= method: +#@# To suppress this warning, one may use the Warning::[]= method: +この警告を抑制したければ、Warning::[]= メソッドが利用できます。 #@samplecode Warning[:experimental] = false eval('[0] => [*, 0, *]') -# ...no warning printed... +#@# # ...no warning printed... +# ...警告は出力されない... #@end -Note that pattern-matching warnings are raised at compile time, so this will not suppress the warning: +#@# Note that pattern-matching warnings are raised at compile time, so this will not suppress the warning: +パターンマッチの警告はコンパイル時に発生するため、以下のような場合は警告は抑制できません。 #@samplecode Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted [0] => [*, 0, *] #@end -So, only subsequently loaded files or `eval`-ed code is affected by switching the flag. +#@# So, only subsequently loaded files or `eval`-ed code is affected by switching the flag. +つまり、フラグの切り替えによって影響を受けるのは切り替え以降に load されたファイルや `eval` されたコードに限られます。 -Alternatively, the command line option -W:no-experimental can be used to turn off "experimental" feature warnings. +#@# Alternatively, the command line option -W:no-experimental can be used to turn off "experimental" feature warnings. +代わりに、コマンドラインオプションとして -W:no-experimental を渡すことで "experimental" な機能に対する警告を出力させないようにできます。 == Appendix A. Pattern syntax From 86fa8d0d55f3df7fba056d23202947b059459723 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 20:37:19 +0900 Subject: [PATCH 12/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE=20Appen?= =?UTF-8?q?dix(=E4=BB=98=E8=A8=98)=20=E3=82=92=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している --- refm/doc/spec/pattern_matching.rd | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index fc16cb605e..357bcf6ac8 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -630,9 +630,11 @@ Warning[:experimental] = false # At the time this line is evaluated, the parsing #@# Alternatively, the command line option -W:no-experimental can be used to turn off "experimental" feature warnings. 代わりに、コマンドラインオプションとして -W:no-experimental を渡すことで "experimental" な機能に対する警告を出力させないようにできます。 -== Appendix A. Pattern syntax +#@# == Appendix A. Pattern syntax +== 付記A: パターンのシンタックス -Approximate syntax is: +#@# Approximate syntax is: +おおよその構文は以下のとおりです。 pattern: value_pattern | variable_pattern @@ -668,13 +670,14 @@ Approximate syntax is: | Constant(key: pattern, key:, ..., **variable) | Constant[key: pattern, key:, ..., **variable] -== Appendix B. Some undefined behavior examples +#@# == Appendix B. Some undefined behavior examples +== 付記B: `未定義` の振る舞いの例 -To leave room for optimization in the future, the specification contains some undefined behavior. +#@# To leave room for optimization in the future, the specification contains some undefined behavior. +将来的な最適化の余地を残すため、仕様には一部 `未定義` の振る舞いが含まれています。 -Use of a variable in an unmatched pattern: - -#@samplecode +#@# Use of a variable in an unmatched pattern: +#@samplecode マッチしなかったパターンの中での変数の利用 case [0, 1] in [a, 2] "not matched" @@ -687,9 +690,8 @@ a #=> undefined c #=> undefined #@end -Number of +deconstruct+, +deconstruct_keys+ method calls: - -#@samplecode +#@# Number of +deconstruct+, +deconstruct_keys+ method calls: +#@samplecode deconstruct や deconstruct_keys が呼び出された回数 $i = 0 ary = [0] def ary.deconstruct From 870481de52cae0ab9fd4f8c2ca80ede151f72944 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 21:16:04 +0900 Subject: [PATCH 13/43] =?UTF-8?q?=E5=88=B6=E5=BE=A1=E6=A7=8B=E9=80=A0=20?= =?UTF-8?q?=E3=81=AE=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3=E3=83=9E=E3=83=83?= =?UTF-8?q?=E3=83=81=E3=81=AE=E9=83=A8=E5=88=86=E3=82=92=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 翻訳する際、原文は対応箇所を把握しやすくするため bitclust のコメント機能を使って残している --- refm/doc/spec/control.rd | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/refm/doc/spec/control.rd b/refm/doc/spec/control.rd index 17ec5efdec..639b126206 100644 --- a/refm/doc/spec/control.rd +++ b/refm/doc/spec/control.rd @@ -230,8 +230,9 @@ case は、条件が成立した when 節、(あるいは else 節) の最後に評価した式の結果を返します。いずれの条件も成り立たなければ nil を返します。 -Since Ruby 2.7, +case+ expressions also provide a more powerful experimental -pattern matching feature via the +in+ keyword: +#@# Since Ruby 2.7, +case+ expressions also provide a more powerful experimental +#@# pattern matching feature via the +in+ keyword: +Ruby 2.7 からは +case+ 式は +in+ キーワードを通じてより強力なパターンマッチ構文を提供しています。 #@samplecode case {a: 1, b: 2, c: 3} @@ -243,8 +244,9 @@ end # => "matched: 1" #@end -The pattern matching syntax is described on -{its own page}[rdoc-ref:syntax/pattern_matching.rdoc]. +#@# The pattern matching syntax is described on +#@# {its own page}[rdoc-ref:syntax/pattern_matching.rdoc]. +パターンマッチ構文については[[d:spec/pattern_matching]]で説明しています。 === 繰り返し From 7400520bc2750cdd70a9f63c555f9718d84604c0 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 23:29:48 +0900 Subject: [PATCH 14/43] =?UTF-8?q?=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E9=96=A2=E9=80=A3=E3=81=AE=E3=83=89?= =?UTF-8?q?=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=20code?= =?UTF-8?q?=20=E3=82=BF=E3=82=B0=E3=82=92=E4=BA=8C=E9=87=8D=E3=81=8B?= =?UTF-8?q?=E3=81=8E=E6=8B=AC=E5=BC=A7=E3=81=AB=E7=BD=AE=E6=8F=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 素の rdoc と bitclust の文法の違いを反映するため --- refm/doc/spec/pattern_matching.rd | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 357bcf6ac8..aa86865430 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -22,7 +22,7 @@ Rubyでのパターンマッチは +case+/+in+ 式を用いて実装されてい +in+ 節と +when+ 節は1つの +case+ 式の中に混ぜて書くことはできません。 #@# Or with the => operator and the +in+ operator, which can be used in a standalone expression: -=> 演算子と +in+ 演算子で、単体の式で使用することも可能です。 +『=>』 演算子と +in+ 演算子で、単体の式で使用することも可能です。 => @@ -51,7 +51,7 @@ end #@end #@# whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: -一方、=> 演算子は、期待されるデータ構造があらかじめ分かっている場合に、その一部をアンパックするのに有効です。 +一方、『=>』 演算子は、期待されるデータ構造があらかじめ分かっている場合に、その一部をアンパックするのに有効です。 #@samplecode config = {db: {user: 'admin', password: 'abc123'}} @@ -65,7 +65,7 @@ puts "Connect with user '#{user}'" #@end #@# in is the same as case ; in ; true; else false; end. - in ; in ; true; else false; end と等価です。 +『 in 』 は 『; in ; true; else false; end』 と等価です。 #@# You can use it when you only want to know if a pattern has been matched or not: パターンにマッチするかどうかだけを知りたいときに使えます。 @@ -84,20 +84,20 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true パターンで利用できるものには次のものがあります。 #@# * any Ruby object (matched by the === operator, like in +when+); (Value pattern) - * Ruby のオブジェクト (+when+ での場合のように === 演算子にマッチするもの) (Value パターン) + * Ruby のオブジェクト (+when+ での場合のように 『===』 演算子にマッチするもの) (Value パターン) #@# * array pattern: [, , , ...]; (Array pattern) - * Array パターン: [, , , ...] (Array パターン) + * Array パターン: 『[, , , ...]』 (Array パターン) #@# * find pattern: [*variable, , , , ..., *variable]; (Find pattern) - * Find パターン: [*variable, , , , ..., *variable] (Find パターン) + * Find パターン: 『[*variable, , , , ..., *variable]』 (Find パターン) #@# * hash pattern: {key: , key: , ...}; (Hash pattern) - * Hash パターン: {key: , key: , ...} (Hash パターン) + * Hash パターン: 『{key: , key: , ...}』 (Hash パターン) #@# * combination of patterns with |; (Alternative pattern) - * | でのパターンの組み合わせ (Alternative パターン) + * 『|』 でのパターンの組み合わせ (Alternative パターン) #@# * variable capture: => variable or variable; (As pattern, Variable pattern) - * 変数のキャプチャ: => variable または variable (As パターン, Variable パターン) + * 変数のキャプチャ: 『 => variable』 または 『variable』 (As パターン, Variable パターン) #@# Any pattern can be nested inside array/find/hash patterns where is specified. -Array/Find/Hash パターンの中に と書かれている場所では任意のパターンをネストさせることができます。 +Array/Find/Hash パターンの中に 『』 と書かれている場所では任意のパターンをネストさせることができます。 #@# Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter). Array パターン と Find パターン は配列か +deconstruct+ を持つオブジェクトにマッチします。(+deconstruct+ については後ほど説明します) @@ -135,7 +135,7 @@ end #@end #@# {} is the only exclusion from this rule. It matches only if an empty hash is given: -{} だけはこのルールの例外です。{} は空のハッシュのみマッチします。 +『{}』 だけはこのルールの例外です。『{}』 は空のハッシュのみマッチします。 #@samplecode case {a: 1, b: 2, c: 3} @@ -158,7 +158,7 @@ end #@end #@# 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 **nil: -また、パターンで明示的に指定されたキー以外にキーが存在しないケースにマッチングさせたい場合、**nil を指定する方法もあります。 +また、パターンで明示的に指定されたキー以外にキーが存在しないケースにマッチングさせたい場合、『**nil』 を指定する方法もあります。 #@samplecode case {a: 1, b: 2} @@ -197,7 +197,7 @@ end #@end #@# Parentheses around both kinds of patterns could be omitted: -Array パターン や Hash パターン は両端の []{} といったカッコを省略できます。 +Array パターン や Hash パターン は両端の 『[]』 や 『{}』 といったカッコを省略できます。 #@samplecode case [1, 2] @@ -255,7 +255,7 @@ end == 変数の束縛 #@# Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): -深い構造検査の他のパターンマッチの重要な機能の1つにマッチした部分のローカル変数への束縛があります。束縛の基本的な形はマッチしたパターンの後ろに => 変数名 と書くことです。(この形は rescue 節で rescue ExceptionClass => var の形で例外をローカル変数に格納する形に似ています) +深い構造検査の他のパターンマッチの重要な機能の1つにマッチした部分のローカル変数への束縛があります。束縛の基本的な形はマッチしたパターンの後ろに 『=> 変数名』 と書くことです。(この形は rescue 節で 『rescue ExceptionClass => var』 の形で例外をローカル変数に格納する形に似ています) #@samplecode case [1, 2] @@ -350,7 +350,7 @@ end #@end #@# Binding to variables currently does NOT work for alternative patterns joined with |: -変数への束縛は現状、| で結合される Alternative パターン と同時には利用できません。 +変数への束縛は現状、『|』 で結合される Alternative パターン と同時には利用できません。 #@samplecode case {a: 1, b: 2} @@ -363,7 +363,7 @@ end #@end #@# Variables that start with _ are the only exclusions from this rule: -_ で始まる変数は例外で、Alternative パターン と同時に利用することができます。 +『_』 で始まる変数は例外で、Alternative パターン と同時に利用することができます。 #@samplecode case {a: 1, b: 2} @@ -376,7 +376,7 @@ end #@end #@# It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value. -しかし、_ で始まる変数の目的は利用しない値を意味するので、束縛された値を再利用することはオススメしません。 +しかし、『_』 で始まる変数の目的は利用しない値を意味するので、束縛された値を再利用することはオススメしません。 #@# == Variable pinning == 変数のピン留め @@ -399,7 +399,7 @@ end #@end #@# For this case, the pin operator ^ can be used, to tell Ruby "just use this value as part of the pattern": -この場合、Ruby に「この値をパターンの部品として利用するよ」ということを伝えるためにピン演算子 ^ を利用することができます。 +この場合、Ruby に「この値をパターンの部品として利用するよ」ということを伝えるためにピン演算子 『^』 を利用することができます。 #@samplecode expectation = 18 @@ -516,7 +516,7 @@ end #@end #@# +keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: -+keys+ はマッチしたクラスの中で最適化の余地を残して +deconstruct_keys+ へと渡されます。もし全てのハッシュの表現の計算に高い負荷がかかる場合、必要なサブハッシュのみ計算されるかもしれません。**rest パターンが使われている場合、+keys+ の値として +nil+ が渡されます。 ++keys+ はマッチしたクラスの中で最適化の余地を残して +deconstruct_keys+ へと渡されます。もし全てのハッシュの表現の計算に高い負荷がかかる場合、必要なサブハッシュのみ計算されるかもしれません。『**rest』 パターンが使われている場合、+keys+ の値として +nil+ が渡されます。 #@samplecode case Point.new(1, -2) @@ -531,7 +531,7 @@ end #@end #@# Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with === -加えて、カスタムクラスにマッチするとき、期待されるクラスはパターンの部品として明記され === で検査されます +加えて、カスタムクラスにマッチするとき、期待されるクラスはパターンの部品として明記され 『===』 で検査されます #@samplecode class SuperPoint < Point @@ -628,7 +628,7 @@ Warning[:experimental] = false # At the time this line is evaluated, the parsing つまり、フラグの切り替えによって影響を受けるのは切り替え以降に load されたファイルや `eval` されたコードに限られます。 #@# Alternatively, the command line option -W:no-experimental can be used to turn off "experimental" feature warnings. -代わりに、コマンドラインオプションとして -W:no-experimental を渡すことで "experimental" な機能に対する警告を出力させないようにできます。 +代わりに、コマンドラインオプションとして 『-W:no-experimental』 を渡すことで "experimental" な機能に対する警告を出力させないようにできます。 #@# == Appendix A. Pattern syntax == 付記A: パターンのシンタックス From 140c056ec852951175a1d011cf2612966defa5f0 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 23:51:56 +0900 Subject: [PATCH 15/43] =?UTF-8?q?=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E9=96=A2=E9=80=A3=E3=81=AE=E3=83=89?= =?UTF-8?q?=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=20=5F=20?= =?UTF-8?q?=E3=81=A8=20em=20=E3=82=BF=E3=82=B0=20(=E3=82=A4=E3=82=BF?= =?UTF-8?q?=E3=83=AA=E3=83=83=E3=82=AF=E4=BD=93)=20=E3=82=92=E3=81=8B?= =?UTF-8?q?=E3=81=8E=E6=8B=AC=E5=BC=A7=E3=81=AB=E7=BD=AE=E6=8F=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 素の rdoc と bitclust の文法の違いを反映するため --- refm/doc/spec/pattern_matching.rd | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index aa86865430..b3c1d0181a 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -29,7 +29,7 @@ Rubyでのパターンマッチは +case+/+in+ 式を用いて実装されてい in #@# 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. -+case+/+in+ 式は _網羅的_ です。もし +case+ 式の値がどの節にもマッチせず +else+ 節がない場合、+NoMatchingPatternError+ が raise されます。 ++case+/+in+ 式は 「網羅的」 です。もし +case+ 式の値がどの節にもマッチせず +else+ 節がない場合、+NoMatchingPatternError+ が raise されます。 #@# Therefore, the +case+ expression might be used for conditional matching and unpacking: そのため、条件付きのマッチングやアンパックに +case+ 式が使われることがあります。 @@ -84,17 +84,17 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true パターンで利用できるものには次のものがあります。 #@# * any Ruby object (matched by the === operator, like in +when+); (Value pattern) - * Ruby のオブジェクト (+when+ での場合のように 『===』 演算子にマッチするもの) (Value パターン) + * Ruby のオブジェクト (+when+ での場合のように 『===』 演算子にマッチするもの) (「Value パターン」) #@# * array pattern: [, , , ...]; (Array pattern) - * Array パターン: 『[, , , ...]』 (Array パターン) + * Array パターン: 『[, , , ...]』 (「Array パターン」) #@# * find pattern: [*variable, , , , ..., *variable]; (Find pattern) - * Find パターン: 『[*variable, , , , ..., *variable]』 (Find パターン) -#@# * hash pattern: {key: , key: , ...}; (Hash pattern) - * Hash パターン: 『{key: , key: , ...}』 (Hash パターン) + * Find パターン: 『[*variable, , , , ..., *variable]』 (「Find パターン」) +#@# * hash pattern: {key: , key: , ...} (Hash pattern) + * Hash パターン: 『{key: , key: , ...}』 (「Hash パターン」) #@# * combination of patterns with |; (Alternative pattern) - * 『|』 でのパターンの組み合わせ (Alternative パターン) + * 『|』 でのパターンの組み合わせ (「Alternative パターン」) #@# * variable capture: => variable or variable; (As pattern, Variable pattern) - * 変数のキャプチャ: 『 => variable』 または 『variable』 (As パターン, Variable パターン) + * 変数のキャプチャ: 『 => variable』 または 『variable』 (「As パターン」, 「Variable パターン」) #@# Any pattern can be nested inside array/find/hash patterns where is specified. Array/Find/Hash パターンの中に 『』 と書かれている場所では任意のパターンをネストさせることができます。 @@ -109,7 +109,7 @@ Hash パターン はハッシュか +deconstruct_keys+ メソッドを持つオ ※ deconstruct や deconstruct_keys を扱う際の『〜を持つ』の定義は [[m:Object#respond_to?]] と同様です。 #@# An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: -Array パターン と Hash パターン の挙動の重要な違いは Array パターンは配列の _全ての_ 要素がマッチする必要があるということです。 +Array パターン と Hash パターン の挙動の重要な違いは Array パターンは配列の 「全ての」 要素がマッチする必要があるということです。 #@samplecode case [1, 2, 3] @@ -598,7 +598,7 @@ end == 機能の現状 #@# As of Ruby 3.1, 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: -Ruby 3.1 の時点では、Find パターンは _experimental_ と考えられます。Find パターンのシンタックスは将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 +Ruby 3.1 の時点では、Find パターンは 「experimental」 と考えられます。Find パターンのシンタックスは将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 #@samplecode [0] => [*, 0, *] From 89757fb4676d49f49a9d885a5e9de1dfbc389cad Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sun, 1 Jan 2023 23:56:14 +0900 Subject: [PATCH 16/43] =?UTF-8?q?=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E9=96=A2=E9=80=A3=E3=81=AE=E3=83=89?= =?UTF-8?q?=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=20+=20(?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=97=E3=83=A9=E3=82=A4=E3=82=BF=E3=83=BC?= =?UTF-8?q?=E4=BD=93)=20=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 素の rdoc と bitclust の文法の違いを反映するため --- refm/doc/spec/control.rd | 2 +- refm/doc/spec/pattern_matching.rd | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/refm/doc/spec/control.rd b/refm/doc/spec/control.rd index 639b126206..c241b05d6e 100644 --- a/refm/doc/spec/control.rd +++ b/refm/doc/spec/control.rd @@ -232,7 +232,7 @@ nil を返します。 #@# Since Ruby 2.7, +case+ expressions also provide a more powerful experimental #@# pattern matching feature via the +in+ keyword: -Ruby 2.7 からは +case+ 式は +in+ キーワードを通じてより強力なパターンマッチ構文を提供しています。 +Ruby 2.7 からは case 式は in キーワードを通じてより強力なパターンマッチ構文を提供しています。 #@samplecode case {a: 1, b: 2, c: 3} diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index b3c1d0181a..6ba22d26bd 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -5,7 +5,7 @@ パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチングを可能にする機能です。 #@# Pattern matching in Ruby is implemented with the +case+/+in+ expression: -Rubyでのパターンマッチは +case+/+in+ 式を用いて実装されています。 +Rubyでのパターンマッチは case/in 式を用いて実装されています。 case in @@ -19,20 +19,20 @@ Rubyでのパターンマッチは +case+/+in+ 式を用いて実装されてい end #@# (Note that +in+ and +when+ branches can NOT be mixed in one +case+ expression.) -+in+ 節と +when+ 節は1つの +case+ 式の中に混ぜて書くことはできません。 +in 節と when 節は1つの case 式の中に混ぜて書くことはできません。 #@# Or with the => operator and the +in+ operator, which can be used in a standalone expression: -『=>』 演算子と +in+ 演算子で、単体の式で使用することも可能です。 +『=>』 演算子と in 演算子で、単体の式で使用することも可能です。 => in #@# 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. -+case+/+in+ 式は 「網羅的」 です。もし +case+ 式の値がどの節にもマッチせず +else+ 節がない場合、+NoMatchingPatternError+ が raise されます。 +case/in 式は 「網羅的」 です。もし case 式の値がどの節にもマッチせず else 節がない場合、NoMatchingPatternError が raise されます。 #@# Therefore, the +case+ expression might be used for conditional matching and unpacking: -そのため、条件付きのマッチングやアンパックに +case+ 式が使われることがあります。 +そのため、条件付きのマッチングやアンパックに case 式が使われることがあります。 #@samplecode config = {db: {user: 'admin', password: 'abc123'}} @@ -84,7 +84,7 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true パターンで利用できるものには次のものがあります。 #@# * any Ruby object (matched by the === operator, like in +when+); (Value pattern) - * Ruby のオブジェクト (+when+ での場合のように 『===』 演算子にマッチするもの) (「Value パターン」) + * Ruby のオブジェクト (when での場合のように 『===』 演算子にマッチするもの) (「Value パターン」) #@# * array pattern: [, , , ...]; (Array pattern) * Array パターン: 『[, , , ...]』 (「Array パターン」) #@# * find pattern: [*variable, , , , ..., *variable]; (Find pattern) @@ -100,10 +100,10 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true Array/Find/Hash パターンの中に 『』 と書かれている場所では任意のパターンをネストさせることができます。 #@# Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter). -Array パターン と Find パターン は配列か +deconstruct+ を持つオブジェクトにマッチします。(+deconstruct+ については後ほど説明します) +Array パターン と Find パターン は配列か deconstruct を持つオブジェクトにマッチします。(deconstruct については後ほど説明します) #@# 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. -Hash パターン はハッシュか +deconstruct_keys+ メソッドを持つオブジェクトにマッチします。(+deconstruct_keys+ については後ほど説明します) Hash パターン で利用できるキーはシンボルのみです。 +Hash パターン はハッシュか deconstruct_keys を持つオブジェクトにマッチします。(deconstruct_keys については後ほど説明します) Hash パターン で利用できるキーはシンボルのみです。 #@# 原文にないが補足のため追加 ※ deconstruct や deconstruct_keys を扱う際の『〜を持つ』の定義は [[m:Object#respond_to?]] と同様です。 @@ -471,10 +471,10 @@ end #@end #@# == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ -== プリミティブなオブジェクト以外とのマッチング: +deconstruct+ と +deconstruct_keys+ +== プリミティブなオブジェクト以外とのマッチング: deconstruct と 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). -既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは +deconstruct+ (これは Array/Find パターンで利用されます) か +deconstruct_keys+ (これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 +既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは deconstruct (これは Array/Find パターンで利用されます) か deconstruct_keys (これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 #@samplecode class Point @@ -516,7 +516,7 @@ end #@end #@# +keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: -+keys+ はマッチしたクラスの中で最適化の余地を残して +deconstruct_keys+ へと渡されます。もし全てのハッシュの表現の計算に高い負荷がかかる場合、必要なサブハッシュのみ計算されるかもしれません。『**rest』 パターンが使われている場合、+keys+ の値として +nil+ が渡されます。 +keys はマッチしたクラスの中で最適化の余地を残して deconstruct_keys へと渡されます。もし全てのハッシュの表現の計算に高い負荷がかかる場合、必要なサブハッシュのみ計算されるかもしれません。『**rest』 パターンが使われている場合、keys の値として nil が渡されます。 #@samplecode case Point.new(1, -2) @@ -559,7 +559,7 @@ end == ガード節 #@# +if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: -もしパターンマッチのときに +if+ を用いて追加の条件(ガード節)を指定した場合、変数への束縛がされた状態で条件の判定が行われます。 +もしパターンマッチのときに if を用いて追加の条件(ガード節)を指定した場合、変数への束縛がされた状態で条件の判定が行われます。 #@samplecode case [1, 2] @@ -582,7 +582,7 @@ end #@end #@# +unless+ works, too: -+unless+ も利用できます。 +unless も利用できます。 #@samplecode case [1, 1] From 7efedd6c6952787b90c12a888694473bfe8dbf99 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Mon, 2 Jan 2023 17:33:56 +0900 Subject: [PATCH 17/43] =?UTF-8?q?=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E9=96=A2=E9=80=A3=E3=81=AE=E3=83=89?= =?UTF-8?q?=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=E8=A6=8B?= =?UTF-8?q?=E5=87=BA=E3=81=97=E3=83=AC=E3=83=99=E3=83=AB=E3=82=92=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 見出しレベル2だと見た目の主張が強すぎるため - 他のドキュメントでも見出しレベル2を飛ばして見出しレベル3を利用するケースが多そうだった - cf. https://github.com/rurema/doctree/blob/a770b9a74b1e8d1e0918e97fc390f9ae00cfec19/refm/doc/spec/control.rd - https://github.com/rurema/doctree/blob/a770b9a74b1e8d1e0918e97fc390f9ae00cfec19/refm/doc/spec/def.rd --- refm/doc/spec/pattern_matching.rd | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 6ba22d26bd..a1a48315dc 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -78,7 +78,7 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true 構文の詳細な例と説明は以下を参照してください。 #@# == Patterns -== パターン +=== パターン #@# Patterns can be: パターンで利用できるものには次のものがあります。 @@ -252,7 +252,7 @@ end #@end #@# == Variable binding -== 変数の束縛 +=== 変数の束縛 #@# Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): 深い構造検査の他のパターンマッチの重要な機能の1つにマッチした部分のローカル変数への束縛があります。束縛の基本的な形はマッチしたパターンの後ろに 『=> 変数名』 と書くことです。(この形は rescue 節で 『rescue ExceptionClass => var』 の形で例外をローカル変数に格納する形に似ています) @@ -379,7 +379,7 @@ end しかし、『_』 で始まる変数の目的は利用しない値を意味するので、束縛された値を再利用することはオススメしません。 #@# == Variable pinning -== 変数のピン留め +=== 変数のピン留め #@# Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: 変数の束縛の機能では存在しているローカル変数をサブパターンとしてそのまま利用することはできません。 @@ -471,7 +471,7 @@ end #@end #@# == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ -== プリミティブなオブジェクト以外とのマッチング: deconstruct と deconstruct_keys +=== プリミティブなオブジェクト以外とのマッチング: deconstruct と 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). 既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは deconstruct (これは Array/Find パターンで利用されます) か deconstruct_keys (これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 @@ -556,7 +556,7 @@ end #@end #@# == Guard clauses -== ガード節 +=== ガード節 #@# +if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: もしパターンマッチのときに if を用いて追加の条件(ガード節)を指定した場合、変数への束縛がされた状態で条件の判定が行われます。 @@ -595,7 +595,7 @@ end #@end #@# == Current feature status -== 機能の現状 +=== 機能の現状 #@# As of Ruby 3.1, 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: Ruby 3.1 の時点では、Find パターンは 「experimental」 と考えられます。Find パターンのシンタックスは将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 @@ -631,7 +631,7 @@ Warning[:experimental] = false # At the time this line is evaluated, the parsing 代わりに、コマンドラインオプションとして 『-W:no-experimental』 を渡すことで "experimental" な機能に対する警告を出力させないようにできます。 #@# == Appendix A. Pattern syntax -== 付記A: パターンのシンタックス +=== 付記A: パターンのシンタックス #@# Approximate syntax is: おおよその構文は以下のとおりです。 @@ -671,7 +671,7 @@ Warning[:experimental] = false # At the time this line is evaluated, the parsing | Constant[key: pattern, key:, ..., **variable] #@# == Appendix B. Some undefined behavior examples -== 付記B: `未定義` の振る舞いの例 +=== 付記B: `未定義` の振る舞いの例 #@# To leave room for optimization in the future, the specification contains some undefined behavior. 将来的な最適化の余地を残すため、仕様には一部 `未定義` の振る舞いが含まれています。 From 5d72994366493d8df6820f523c2a3cd3be712406 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Mon, 2 Jan 2023 22:00:09 +0900 Subject: [PATCH 18/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE?= =?UTF-8?q?=E5=8E=9F=E6=96=87=E3=81=A7=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=A2=E3=82=A6=E3=83=88=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E8=BF=94=E3=82=8A=E5=80=A4?= =?UTF-8?q?=E3=81=AE=E8=A8=98=E8=BC=89=E3=82=92=E3=82=B3=E3=83=A1=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=82=A2=E3=82=A6=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index a1a48315dc..fdf19f34b4 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -502,7 +502,7 @@ else end #@# # prints "deconstruct called" # "deconstruct called" が出力されます -"matched: 1" +#=> "matched: 1" case Point.new(1, -2) in x: 0.. => px From 6b99c13daa0451d5ce3b3b570c97783ed7a24b74 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Tue, 3 Jan 2023 02:14:44 +0900 Subject: [PATCH 19/43] =?UTF-8?q?refm/doc/spec=20=E9=85=8D=E4=B8=8B?= =?UTF-8?q?=E3=81=AE=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E3=81=A6=20zpattern=5Fmatc?= =?UTF-8?q?hing.rd=20=E3=81=AB=E7=9B=AE=E6=AC=A1=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refm/doc/spec/pattern_matching.rd | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index fdf19f34b4..1ddeec0b52 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -1,6 +1,15 @@ #@# = Pattern matching = パターンマッチ + * [[ref:patterns]] + * [[ref:variable_binding]] + * [[ref:variable_pinning]] + * [[ref:matching_non_primitive_objects]] + * [[ref:guard_clauses]] + * [[ref:current_feature_status]] + * [[ref:pattern_syntax]] + * [[ref:some_undefined_behavior_examples]] + #@# Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチングを可能にする機能です。 @@ -78,7 +87,7 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true 構文の詳細な例と説明は以下を参照してください。 #@# == Patterns -=== パターン +===[a:patterns] パターン #@# Patterns can be: パターンで利用できるものには次のものがあります。 @@ -252,7 +261,7 @@ end #@end #@# == Variable binding -=== 変数の束縛 +===[a:variable_binding] 変数の束縛 #@# Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying => variable_name after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a rescue ExceptionClass => var clause): 深い構造検査の他のパターンマッチの重要な機能の1つにマッチした部分のローカル変数への束縛があります。束縛の基本的な形はマッチしたパターンの後ろに 『=> 変数名』 と書くことです。(この形は rescue 節で 『rescue ExceptionClass => var』 の形で例外をローカル変数に格納する形に似ています) @@ -379,7 +388,7 @@ end しかし、『_』 で始まる変数の目的は利用しない値を意味するので、束縛された値を再利用することはオススメしません。 #@# == Variable pinning -=== 変数のピン留め +===[a:variable_pinning] 変数のピン留め #@# Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: 変数の束縛の機能では存在しているローカル変数をサブパターンとしてそのまま利用することはできません。 @@ -471,7 +480,7 @@ end #@end #@# == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ -=== プリミティブなオブジェクト以外とのマッチング: deconstruct と deconstruct_keys +===[a:matching_non_primitive_objects] プリミティブなオブジェクト以外とのマッチング: deconstruct と 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). 既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは deconstruct (これは Array/Find パターンで利用されます) か deconstruct_keys (これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 @@ -556,7 +565,7 @@ end #@end #@# == Guard clauses -=== ガード節 +===[a:guard_clauses] ガード節 #@# +if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: もしパターンマッチのときに if を用いて追加の条件(ガード節)を指定した場合、変数への束縛がされた状態で条件の判定が行われます。 @@ -595,7 +604,7 @@ end #@end #@# == Current feature status -=== 機能の現状 +===[a:current_feature_status] 機能の現状 #@# As of Ruby 3.1, 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: Ruby 3.1 の時点では、Find パターンは 「experimental」 と考えられます。Find パターンのシンタックスは将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 @@ -631,7 +640,7 @@ Warning[:experimental] = false # At the time this line is evaluated, the parsing 代わりに、コマンドラインオプションとして 『-W:no-experimental』 を渡すことで "experimental" な機能に対する警告を出力させないようにできます。 #@# == Appendix A. Pattern syntax -=== 付記A: パターンのシンタックス +===[a:pattern_syntax] 付記A: パターンのシンタックス #@# Approximate syntax is: おおよその構文は以下のとおりです。 @@ -671,7 +680,7 @@ Warning[:experimental] = false # At the time this line is evaluated, the parsing | Constant[key: pattern, key:, ..., **variable] #@# == Appendix B. Some undefined behavior examples -=== 付記B: `未定義` の振る舞いの例 +===[a:some_undefined_behavior_examples] 付記B: `未定義` の振る舞いの例 #@# To leave room for optimization in the future, the specification contains some undefined behavior. 将来的な最適化の余地を残すため、仕様には一部 `未定義` の振る舞いが含まれています。 From 2a852c111ebe03850c1553ae89165537f2f775c6 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Fri, 6 Jan 2023 11:02:49 +0900 Subject: [PATCH 20/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE?= =?UTF-8?q?=E8=A1=A8=E7=8F=BE=E3=82=92=E4=BB=96=E3=81=AE=E3=83=9A=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E3=81=9F(FooBarEr?= =?UTF-8?q?ror=E3=81=8Craise=E3=81=95=E3=82=8C=E3=82=8B=20->=20=E4=BE=8B?= =?UTF-8?q?=E5=A4=96FooBarError=E3=81=8C=E7=99=BA=E7=94=9F=E3=81=99?= =?UTF-8?q?=E3=82=8B)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#pullrequestreview-1237193464 --- refm/doc/spec/pattern_matching.rd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 1ddeec0b52..ad6ed5cc2c 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -38,7 +38,7 @@ in 節と when 節は1つの case 式の中に混ぜて書くことはできま in #@# 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. -case/in 式は 「網羅的」 です。もし case 式の値がどの節にもマッチせず else 節がない場合、NoMatchingPatternError が raise されます。 +case/in 式は 「網羅的」 です。もし case 式の値がどの節にもマッチせず else 節がない場合、例外 NoMatchingPatternError が発生します。 #@# Therefore, the +case+ expression might be used for conditional matching and unpacking: そのため、条件付きのマッチングやアンパックに case 式が使われることがあります。 @@ -66,7 +66,7 @@ end config = {db: {user: 'admin', password: 'abc123'}} #@# config => {db: {user:}} # will raise if the config's structure is unexpected -config => {db: {user:}} # config の構造が予期しないものだった場合は例外が raise されます +config => {db: {user:}} # config の構造が予期しないものだった場合は例外が発生します puts "Connect with user '#{user}'" #@# # Prints: "Connect with user 'admin'" From 09fa165cc95ffdba2ea68f59c94854d193a224d6 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Fri, 6 Jan 2023 11:08:56 +0900 Subject: [PATCH 21/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE?= =?UTF-8?q?=E8=A1=A8=E7=8F=BE=E3=82=92=E4=BB=96=E3=81=AE=E3=83=9A=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E3=81=9F(?= =?UTF-8?q?=E3=82=AB=E3=83=83=E3=82=B3=20->=20=E6=8B=AC=E5=BC=A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#pullrequestreview-1237199520 --- refm/doc/spec/pattern_matching.rd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index ad6ed5cc2c..df74e0efa9 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -206,7 +206,7 @@ end #@end #@# Parentheses around both kinds of patterns could be omitted: -Array パターン や Hash パターン は両端の 『[]』 や 『{}』 といったカッコを省略できます。 +Array パターン や Hash パターン は両端の 『[]』 や 『{}』 といった括弧を省略できます。 #@samplecode case [1, 2] @@ -465,7 +465,7 @@ end #@end #@# You can also pin the result of arbitrary expressions using parentheses: -また、カッコを使って任意の式に対してピン演算子を利用できます +また、括弧を使って任意の式に対してピン演算子を利用できます #@samplecode a = 1 @@ -556,7 +556,7 @@ end case SuperPoint.new(1, -2) #@# in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed -in SuperPoint[x: 0.. => px] # [] や () といったカッコは許容されます +in SuperPoint[x: 0.. => px] # [] や () といった括弧は許容されます "matched: #{px}" else "not matched" From 1a446ac53c63ebfb63388b141af6754de1248ac0 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Fri, 6 Jan 2023 11:10:57 +0900 Subject: [PATCH 22/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE?= =?UTF-8?q?=E8=A1=A8=E7=8F=BE=E3=82=92=E4=BB=96=E3=81=AE=E3=83=9A=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E3=81=9F(key=20->?= =?UTF-8?q?=20=E3=82=AD=E3=83=BC(=E3=83=8F=E3=83=83=E3=82=B7=E3=83=A5?= =?UTF-8?q?=E3=81=AE=E6=96=87=E8=84=88=E3=81=A7))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#pullrequestreview-1237202045 --- refm/doc/spec/pattern_matching.rd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index df74e0efa9..d8831e5c65 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -131,7 +131,7 @@ end #@end #@# while the hash matches even if there are other keys besides the specified part: -一方 Hash パターン は一部の key だけ指定している場合(指定している key 以外にも key が存在する場合)でもマッチします。 +一方 Hash パターン は一部のキーだけ指定している場合(指定しているキー以外にもキーが存在する場合)でもマッチします。 #@samplecode case {a: 1, b: 2, c: 3} @@ -172,7 +172,7 @@ end #@samplecode case {a: 1, b: 2} #@# in {a: Integer, **nil} # this will not match the pattern having keys other than a: -in {a: Integer, **nil} # これは a: 以外に key を持つパターンのためマッチしません +in {a: Integer, **nil} # これは a: 以外にキーを持つパターンのためマッチしません "matched a part" in {a: Integer, b: Integer, **nil} "matched a whole" From 84211cae2a7ae7871525a87877afa9e04ad9629d Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Fri, 6 Jan 2023 11:11:48 +0900 Subject: [PATCH 23/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=AE?= =?UTF-8?q?=E8=A1=A8=E7=8F=BE=E3=82=92=E4=BB=96=E3=81=AE=E3=83=9A=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E3=81=9F(?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E3=83=B3=E3=82=B0=20->=20=E3=83=9E?= =?UTF-8?q?=E3=83=83=E3=83=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#pullrequestreview-1237204335 --- refm/doc/spec/pattern_matching.rd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index d8831e5c65..f474ae472b 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -11,7 +11,7 @@ * [[ref:some_undefined_behavior_examples]] #@# Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. -パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチングを可能にする機能です。 +パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチを可能にする機能です。 #@# Pattern matching in Ruby is implemented with the +case+/+in+ expression: Rubyでのパターンマッチは case/in 式を用いて実装されています。 @@ -41,7 +41,7 @@ in 節と when 節は1つの case 式の中に混ぜて書くことはできま case/in 式は 「網羅的」 です。もし case 式の値がどの節にもマッチせず else 節がない場合、例外 NoMatchingPatternError が発生します。 #@# Therefore, the +case+ expression might be used for conditional matching and unpacking: -そのため、条件付きのマッチングやアンパックに case 式が使われることがあります。 +そのため、条件付きのマッチやアンパックに case 式が使われることがあります。 #@samplecode config = {db: {user: 'admin', password: 'abc123'}} @@ -167,7 +167,7 @@ end #@end #@# 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 **nil: -また、パターンで明示的に指定されたキー以外にキーが存在しないケースにマッチングさせたい場合、『**nil』 を指定する方法もあります。 +また、パターンで明示的に指定されたキー以外にキーが存在しないケースにマッチさせたい場合、『**nil』 を指定する方法もあります。 #@samplecode case {a: 1, b: 2} @@ -480,7 +480,7 @@ end #@end #@# == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ -===[a:matching_non_primitive_objects] プリミティブなオブジェクト以外とのマッチング: deconstruct と deconstruct_keys +===[a:matching_non_primitive_objects] プリミティブなオブジェクト以外とのマッチ: deconstruct と 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). 既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは deconstruct (これは Array/Find パターンで利用されます) か deconstruct_keys (これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 From ed29996801e5a5a59442ebd1ef683da17366c068 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Fri, 6 Jan 2023 12:14:35 +0900 Subject: [PATCH 24/43] =?UTF-8?q?sub-pattern=20=E3=81=AE=E7=BF=BB=E8=A8=B3?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cf. https://github.com/rurema/doctree/pull/2773#issuecomment-1370510488 > 原文中で『sub-pattern』としているところは、具体的にArrayパターン、Findパターン、Hashパターンの構文で指定されている``の場所そのものを指していると思われるが、これをどう翻訳するか。カタカナ「サブパターン」は避けたいと感じる > * 具体的には、プルリクファイル「refm/doc/spec/pattern_matching.rd」の312, 393, 506行目らへんなど > * カタカナで『サブパターン』とすると、原文と違い、字面が別物なので「パターン**構文**のあの場所に相当するところかぁ」という気持ちにならない。説明なく現れて消える用語になってしまい、混乱するので、使用を避けたい > * 文脈的に、「構文部分の``のことだね、ウンウン」を意識する必要性自体は薄そう(「まあ、マッチに使うパターンの部分のことやろ」と察せられる) > * 変更案(例) > > * いっそ、全部バッサリ「パターン(部分)」などにしてしまう > * 丁寧に...312, 393行目は本文中で余裕もあるので、「サブパターン(Array/Find/Hashパターン構文の``の部分)」とし、506行目はコードコメントなので「パターン」にする --- refm/doc/spec/pattern_matching.rd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index f474ae472b..afc66145bd 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -391,7 +391,7 @@ end ===[a:variable_pinning] 変数のピン留め #@# Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: -変数の束縛の機能では存在しているローカル変数をサブパターンとしてそのまま利用することはできません。 +変数の束縛の機能では存在しているローカル変数を サブパターン(Array/Find/Hashパターン構文の の部分) としてそのまま利用することはできません。 #@samplecode expectation = 18 @@ -504,7 +504,7 @@ end case Point.new(1, -2) #@# in px, Integer # sub-patterns and variable binding works -in px, Integer # サブパターンと変数への束縛も動きます +in px, Integer # パターンと変数への束縛も動きます "matched: #{px}" else "not matched" From b00f3fc62d938d2ef9bc360fa2dcd09ff2ac0d57 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Fri, 6 Jan 2023 14:09:10 +0900 Subject: [PATCH 25/43] =?UTF-8?q?respond=20to=20=E9=96=A2=E9=80=A3?= =?UTF-8?q?=E3=81=AE=E7=BF=BB=E8=A8=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cf. https://github.com/rurema/doctree/pull/2773#issuecomment-1370510488 > respond to `foobar`のような部分は、「foobar **メソッド**を持つオブジェクト」「オブジェクトに foobar メソッドを定義する」と直接的に表現するのはどうだろうか(そして注釈を削除し、respond toの香りを無くす) > * respond toをあまり大事にする必要がないと思うため: > > * トレイトやインターフェイスのないRubyでは、ダックタイピング的に実装することになるが、そこまでくると、直接的に「メソッドを持つ」でいいと感じる > * ココをうまく使いこなすのに、内部の挙動である`Object#respond_to?`まで踏み込んで理解する必要性は薄く(個人的見解)、却って(初心者寄りの読者は特に)混乱を招きそう --- refm/doc/spec/pattern_matching.rd | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index afc66145bd..976adfca98 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -109,13 +109,10 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true Array/Find/Hash パターンの中に 『』 と書かれている場所では任意のパターンをネストさせることができます。 #@# Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter). -Array パターン と Find パターン は配列か deconstruct を持つオブジェクトにマッチします。(deconstruct については後ほど説明します) +Array パターン と Find パターン は配列か deconstruct メソッドを持つオブジェクトにマッチします。(deconstruct については後ほど説明します) #@# 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. -Hash パターン はハッシュか deconstruct_keys を持つオブジェクトにマッチします。(deconstruct_keys については後ほど説明します) Hash パターン で利用できるキーはシンボルのみです。 - -#@# 原文にないが補足のため追加 -※ deconstruct や deconstruct_keys を扱う際の『〜を持つ』の定義は [[m:Object#respond_to?]] と同様です。 +Hash パターン はハッシュか deconstruct_keys メソッドを持つオブジェクトにマッチします。(deconstruct_keys については後ほど説明します) Hash パターン で利用できるキーはシンボルのみです。 #@# An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: Array パターン と Hash パターン の挙動の重要な違いは Array パターンは配列の 「全ての」 要素がマッチする必要があるということです。 From a4e0eb0f1eda786245dbfc1c74c284efd12f6c10 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Mon, 30 Jan 2023 21:57:53 +0900 Subject: [PATCH 26/43] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=82=B3?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#pullrequestreview-1238960325 - 短さのために、常体(not 丁寧語)に - 能動態を中心に使う - ~が出力されます -> ~と出力 --- refm/doc/spec/pattern_matching.rd | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 976adfca98..f7e450d734 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -48,7 +48,7 @@ config = {db: {user: 'admin', password: 'abc123'}} case config #@# in db: {user:} # matches subhash and puts matched value in variable user -in db: {user:} # ネストしたハッシュにマッチしマッチした値が変数 user に代入されます +in db: {user:} # ネストしてハッシュにマッチして、その値を変数userに代入する puts "Connect with user '#{user}'" in connection: {username: } puts "Connect with user '#{username}'" @@ -56,7 +56,7 @@ else puts "Unrecognized structure of config" end #@# # Prints: "Connect with user 'admin'" -# "Connect with user 'admin'" が出力されます +# "Connect with user 'admin'" と出力 #@end #@# whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: @@ -66,11 +66,11 @@ end config = {db: {user: 'admin', password: 'abc123'}} #@# config => {db: {user:}} # will raise if the config's structure is unexpected -config => {db: {user:}} # config の構造が予期しないものだった場合は例外が発生します +config => {db: {user:}} # もし config の構造が期待したものでなかった場合には、例外が発生する puts "Connect with user '#{user}'" #@# # Prints: "Connect with user 'admin'" -# Connect with user 'admin'" が出力されます +# Connect with user 'admin'" と出力 #@end #@# in is the same as case ; in ; true; else false; end. @@ -169,7 +169,7 @@ end #@samplecode case {a: 1, b: 2} #@# in {a: Integer, **nil} # this will not match the pattern having keys other than a: -in {a: Integer, **nil} # これは a: 以外にキーを持つパターンのためマッチしません +in {a: Integer, **nil} # a: 以外のキーがある場合にはマッチしない "matched a part" in {a: Integer, b: Integer, **nil} "matched a whole" @@ -401,7 +401,7 @@ else end # expected: "not matched. expectation was: 18" #@# # real: "matched. expectation was: 1" -- local variable just rewritten -# real: "matched. expectation was: 1" -- ローカル変数が上書かれている +# 実際の動作:"matched. expectation was: 1" -- ローカル変数が上書きされてしまっている #@end #@# For this case, the pin operator ^ can be used, to tell Ruby "just use this value as part of the pattern": @@ -507,7 +507,7 @@ else "not matched" end #@# # prints "deconstruct called" -# "deconstruct called" が出力されます +# "deconstruct called" と出力 #=> "matched: 1" case Point.new(1, -2) @@ -517,7 +517,7 @@ else "not matched" end #@# # prints: deconstruct_keys called with [:x] -# "deconstruct_keys called with [:x]" が出力されます +# "deconstruct_keys called with [:x]" と出力 #=> "matched: 1" #@end @@ -532,7 +532,7 @@ else "not matched" end #@# # prints: deconstruct_keys called with nil -# "deconstruct_keys called with nil" が出力されます +# "deconstruct_keys called with nil" と出力 #=> "matched: 1" #@end @@ -553,7 +553,7 @@ end case SuperPoint.new(1, -2) #@# in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed -in SuperPoint[x: 0.. => px] # [] や () といった括弧は許容されます +in SuperPoint[x: 0.. => px] # 括弧 [] か () が使える "matched: #{px}" else "not matched" @@ -626,7 +626,8 @@ eval('[0] => [*, 0, *]') パターンマッチの警告はコンパイル時に発生するため、以下のような場合は警告は抑制できません。 #@samplecode -Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted +#@# Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted +Warning[:experimental] = false # この行を評価する段階では、構文解析とそれによる警告の発生は、既に終了している [0] => [*, 0, *] #@end From aeeb5a0ea1b45ce8de0d3dcd433fede07ea801b7 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Fri, 3 Feb 2023 21:20:11 +0900 Subject: [PATCH 27/43] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=82=B3?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=E4=BF=AE=E6=AD=A3(?= =?UTF-8?q?=E7=BF=BB=E8=A8=B3=E6=8A=9C=E3=81=91=20->=20=E5=8E=9F=E6=96=87?= =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E3=82=A2=E3=82=A6=E3=83=88?= =?UTF-8?q?=20+=20=E7=BF=BB=E8=A8=B3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#pullrequestreview-1238960325 ディスカッション中のものを除く --- refm/doc/spec/pattern_matching.rd | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index f7e450d734..1fdd251ee0 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -399,7 +399,8 @@ in expectation, *rest else "not matched. expectation was: #{expectation}" end -# expected: "not matched. expectation was: 18" +#@# # expected: "not matched. expectation was: 18" +# 期待する動作:"not matched. expectation was: 18" #@# # real: "matched. expectation was: 1" -- local variable just rewritten # 実際の動作:"matched. expectation was: 1" -- ローカル変数が上書きされてしまっている #@end @@ -693,8 +694,10 @@ in b in c "not matched" end -a #=> undefined -c #=> undefined +#@# a #=> undefined +a #=> 未定義 +#@# c #=> undefined +c #=> 未定義 #@end #@# Number of +deconstruct+, +deconstruct_keys+ method calls: @@ -711,5 +714,6 @@ in [0, 1] in [0] "matched" end -$i #=> undefined +#@# $i #=> undefined +$i #=> 未定義 #@end From 983f241c9c3411ff1730538b404b320fa544e095 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Sat, 4 Feb 2023 14:45:38 +0900 Subject: [PATCH 28/43] =?UTF-8?q?Value=20=E3=83=91=E3=82=BF=E3=83=BC?= =?UTF-8?q?=E3=83=B3=E3=81=AE=E8=A8=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063574262 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 1fdd251ee0..494473f1e3 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -93,7 +93,7 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true パターンで利用できるものには次のものがあります。 #@# * any Ruby object (matched by the === operator, like in +when+); (Value pattern) - * Ruby のオブジェクト (when での場合のように 『===』 演算子にマッチするもの) (「Value パターン」) + * すべてのRubyオブジェクト (when と同じように、『===』演算子でマッチする) (「Value パターン」) #@# * array pattern: [, , , ...]; (Array pattern) * Array パターン: 『[, , , ...]』 (「Array パターン」) #@# * find pattern: [*variable, , , , ..., *variable]; (Find pattern) From d94ffe7975385a1987127401c8ac841203027adc Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Sat, 4 Feb 2023 14:50:08 +0900 Subject: [PATCH 29/43] =?UTF-8?q?**nil=20=E3=81=AE=E8=AA=AC=E6=98=8E?= =?UTF-8?q?=E3=81=AE=E8=A8=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063584110 > 『**nil』 を指定する方法以外はないので > > 元々の翻訳いただいた文章を活かす場合、 > > > また、パターンで明示的に指定されたキー以外にキーが存在しないケースにマッチングさせたい場合**のために**、『**nil』 を指定する方法もあります。」 > > のようにできると思いますが、ここは原文の文体を維持するよりも、「こういうときは、こうする」という書き方に寄せています。 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 494473f1e3..07f87bd4b5 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -164,7 +164,7 @@ end #@end #@# 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 **nil: -また、パターンで明示的に指定されたキー以外にキーが存在しないケースにマッチさせたい場合、『**nil』 を指定する方法もあります。 +また、パターンで明示的に指定したキー以外のキーが存在しないハッシュにのみ、マッチさせたい場合には、『**nil』 を使います。 #@samplecode case {a: 1, b: 2} From 95db524ed5fed3dd000303855f11279969d86de2 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Sat, 4 Feb 2023 14:52:35 +0900 Subject: [PATCH 30/43] =?UTF-8?q?Hash=20=E3=83=91=E3=82=BF=E3=83=BC?= =?UTF-8?q?=E3=83=B3=E3=81=AB=E3=82=82=E3=82=88=E3=82=8A=E7=B0=A1=E6=BD=94?= =?UTF-8?q?=E3=81=AA=E8=A8=98=E6=B3=95=E3=81=8C=E3=81=82=E3=82=8B=20->=20H?= =?UTF-8?q?ash=20=E3=83=91=E3=82=BF=E3=83=BC=E3=83=B3=E3=81=AB=E3=81=AF?= =?UTF-8?q?=E3=80=81=EF=BC=88=E5=89=8D=E8=BF=B0=E3=81=AE=E7=B0=A1=E6=BD=94?= =?UTF-8?q?=E3=81=AA=E8=A8=98=E6=B3=95=E3=81=AB=E5=8A=A0=E3=81=88=E3=81=A6?= =?UTF-8?q?=EF=BC=89=E6=9B=B4=E3=81=AB=E3=82=88=E3=82=8A=E7=B0=A1=E6=BD=94?= =?UTF-8?q?=E3=81=AA=E8=A8=98=E6=B3=95=E3=81=8C=E3=81=82=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi https://github.com/rurema/doctree/pull/2773#discussion_r1063587560 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 07f87bd4b5..647de79340 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -307,7 +307,7 @@ end #@end #@# 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: -Hash パターンにもより簡潔な記法があります。チェックが不要で変数への束縛のみ行いたい場合、キー名だけを指定することでキー名と同じ変数に値を束縛することができます。 +Hash パターンでは、もっと単純に書くこともできます。キーのみを指定することで、キーと同じ名前のローカル変数に値を束縛できます。 #@samplecode case {a: 1, b: 2, c: 3} From bf2c93c264194d881d9e8e6f21b6ad5e3c01695b Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Sat, 4 Feb 2023 14:56:51 +0900 Subject: [PATCH 31/43] =?UTF-8?q?=E3=82=AB=E3=82=B9=E3=82=BF=E3=83=A0?= =?UTF-8?q?=E3=82=AF=E3=83=A9=E3=82=B9=E3=81=AB=E3=83=9E=E3=83=83=E3=83=81?= =?UTF-8?q?=E3=81=97=E3=81=9F=E5=A0=B4=E5=90=88=E3=81=AE=E8=A8=B3=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063610005 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 647de79340..f5d844d1e7 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -538,7 +538,7 @@ end #@end #@# Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with === -加えて、カスタムクラスにマッチするとき、期待されるクラスはパターンの部品として明記され 『===』 で検査されます +さらに、カスタムクラスに対してマッチする場合には、期待するクラスをパターンの部品として指定することができます。これは 『===』 でチェックされます。 #@samplecode class SuperPoint < Point From b7f8368520d30053ac22459f0afa97166b5b0ea2 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Sat, 4 Feb 2023 14:57:49 +0900 Subject: [PATCH 32/43] =?UTF-8?q?=E3=82=AC=E3=83=BC=E3=83=89=E7=AF=80?= =?UTF-8?q?=E3=81=AE=E8=A8=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063611349 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index f5d844d1e7..d38f3b700e 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -566,7 +566,7 @@ end ===[a:guard_clauses] ガード節 #@# +if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: -もしパターンマッチのときに if を用いて追加の条件(ガード節)を指定した場合、変数への束縛がされた状態で条件の判定が行われます。 +if を使って、パターンにマッチしたときに評価される追加の条件式(ガード節)を加えることができます。この条件式では、マッチした値を束縛した変数を使うこともできます。 #@samplecode case [1, 2] From 3023eb9f629282744e7fd7ef9619c55f5adaeaa2 Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Sat, 4 Feb 2023 14:58:42 +0900 Subject: [PATCH 33/43] =?UTF-8?q?=E3=80=8Cexperimental=E3=80=8D=20?= =?UTF-8?q?=E3=81=A8=E8=80=83=E3=81=88=E3=82=89=E3=82=8C=E3=81=BE=E3=81=99?= =?UTF-8?q?=20->=20=E3=80=8C=E5=AE=9F=E9=A8=93=E7=9A=84=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=80=8D=20=E6=89=B1=E3=81=84=E3=81=A7=E3=81=99,=20=E3=82=B7?= =?UTF-8?q?=E3=83=B3=E3=82=BF=E3=83=83=E3=82=AF=E3=82=B9=20->=20=E6=A7=8B?= =?UTF-8?q?=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063613214 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index d38f3b700e..a8c62736ee 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -605,7 +605,7 @@ end ===[a:current_feature_status] 機能の現状 #@# As of Ruby 3.1, 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: -Ruby 3.1 の時点では、Find パターンは 「experimental」 と考えられます。Find パターンのシンタックスは将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 +Ruby 3.1 の時点では、Find パターンは 「実験的機能」 扱いです。Find パターンの構文は将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 #@samplecode [0] => [*, 0, *] From 878f744b1ae443f60d7c63f7fb686aa391476c8f Mon Sep 17 00:00:00 2001 From: sanfrecce-osaka Date: Sat, 4 Feb 2023 15:01:04 +0900 Subject: [PATCH 34/43] =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=81=E3=81=97?= =?UTF-8?q?=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E3=83=91=E3=82=BF=E3=83=BC?= =?UTF-8?q?=E3=83=B3=E3=81=AE=E4=B8=AD=E3=81=A7=E3=81=AE=E5=A4=89=E6=95=B0?= =?UTF-8?q?=E3=81=AE=E5=88=A9=E7=94=A8=20->=20=E3=83=9E=E3=83=83=E3=83=81?= =?UTF-8?q?=E3=81=97=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E3=83=91=E3=82=BF?= =?UTF-8?q?=E3=83=BC=E3=83=B3=E3=81=AB=E6=8C=87=E5=AE=9A=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=81=9F=E5=A4=89=E6=95=B0=E3=82=92=E4=BD=BF=E3=81=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063614248 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index a8c62736ee..d533722018 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -685,7 +685,7 @@ Warning[:experimental] = false # この行を評価する段階では、構文 将来的な最適化の余地を残すため、仕様には一部 `未定義` の振る舞いが含まれています。 #@# Use of a variable in an unmatched pattern: -#@samplecode マッチしなかったパターンの中での変数の利用 +#@samplecode マッチしなかったパターンに指定していた変数を使う case [0, 1] in [a, 2] "not matched" From c6bc5e0f7492b6dc039083082f839b0648259624 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sat, 4 Feb 2023 15:18:14 +0900 Subject: [PATCH 35/43] =?UTF-8?q?deconstruct=5Fkeys=20=E3=81=A7=E3=81=AE?= =?UTF-8?q?=20keys=20=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6=E3=81=AE?= =?UTF-8?q?=E8=AA=AC=E6=98=8E=E3=81=AE=E8=A8=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063607564 --- refm/doc/spec/pattern_matching.rd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index d533722018..1e65dcb09d 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -523,7 +523,9 @@ end #@end #@# +keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the **rest pattern is used, +nil+ is passed as a +keys+ value: -keys はマッチしたクラスの中で最適化の余地を残して deconstruct_keys へと渡されます。もし全てのハッシュの表現の計算に高い負荷がかかる場合、必要なサブハッシュのみ計算されるかもしれません。『**rest』 パターンが使われている場合、keys の値として nil が渡されます。 +deconstruct_keys メソッドに引数 keys を渡すのは、マッチを行うクラスの実装側に最適化の余地を残すためです。もし、ハッシュのすべての要素を計算するのが重い処理になる場合には、keys で指定された、マッチに必要になる部分のみを計算するように実装しても良いでしょう。 + +『**rest』 パターンが使われた場合には、keys の値として nil が渡されます。 #@samplecode case Point.new(1, -2) From f924b97a51c21023f4b04210036cfe9677f30a24 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sat, 4 Feb 2023 15:43:02 +0900 Subject: [PATCH 36/43] =?UTF-8?q?=E5=A4=89=E6=95=B0=E3=81=AE=E3=83=94?= =?UTF-8?q?=E3=83=B3=E7=95=99=E3=82=81=E3=81=AE=E5=86=92=E9=A0=AD=E3=81=AE?= =?UTF-8?q?=E8=A8=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063607564 > 「変数の束縛の機能」の話ではなく、「変数の束縛の機能の存在のせいで、制限が生まれる」という話だと思われます。 > > そもそも原文(Due to the variable binding feature, ...)に対して、あんまり親切とは言えない・無くなっても困らないレベルの中途半端な言及の仕方だなぁと感じているので、変更案では、ちょっと手厚めにしています。 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 1e65dcb09d..a98abf4fc6 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -388,7 +388,7 @@ end ===[a:variable_pinning] 変数のピン留め #@# Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern: -変数の束縛の機能では存在しているローカル変数を サブパターン(Array/Find/Hashパターン構文の の部分) としてそのまま利用することはできません。 +既に存在しているローカル変数は、サブパターン(Array/Find/Hashパターン構文の の部分) として変数の値をそのまま使うことができません。(これは、変数への束縛の機能を実現するための制限です。) #@samplecode expectation = 18 From 7bffd47f36425fb697ae8a918720c459667b68cb Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sat, 4 Feb 2023 15:54:35 +0900 Subject: [PATCH 37/43] =?UTF-8?q?=E5=BE=8C=E3=81=BB=E3=81=A9=E8=AA=AC?= =?UTF-8?q?=E6=98=8E=E3=81=97=E3=81=BE=E3=81=99=20->=20=E5=BE=8C=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063633163 cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063633460 --- refm/doc/spec/pattern_matching.rd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index a98abf4fc6..a97b1d2dfe 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -109,10 +109,10 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true Array/Find/Hash パターンの中に 『』 と書かれている場所では任意のパターンをネストさせることができます。 #@# Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter). -Array パターン と Find パターン は配列か deconstruct メソッドを持つオブジェクトにマッチします。(deconstruct については後ほど説明します) +Array パターン と Find パターン は配列か deconstruct メソッド(後述)を持つオブジェクトにマッチします。 #@# 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. -Hash パターン はハッシュか deconstruct_keys メソッドを持つオブジェクトにマッチします。(deconstruct_keys については後ほど説明します) Hash パターン で利用できるキーはシンボルのみです。 +Hash パターン はハッシュか deconstruct_keys メソッド(後述)を持つオブジェクトにマッチします。Hash パターン で利用できるキーはシンボルのみです。 #@# An important difference between array and hash pattern behavior is that arrays match only a _whole_ array: Array パターン と Hash パターン の挙動の重要な違いは Array パターンは配列の 「全ての」 要素がマッチする必要があるということです。 From 7a533e0942ad810a577a50a6fd143e5e0a856dd2 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sat, 4 Feb 2023 15:58:20 +0900 Subject: [PATCH 38/43] =?UTF-8?q?=E5=85=A8=E3=81=A6=E3=81=AE=20deconstruct?= =?UTF-8?q?=E3=83=BBdeconstruct=5Fkeys=20=E3=81=AB=E3=80=8C=E3=83=A1?= =?UTF-8?q?=E3=82=BD=E3=83=83=E3=83=89=E3=80=8D=E3=82=92=E4=BB=98=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#pullrequestreview-1239147496 --- refm/doc/spec/pattern_matching.rd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index a97b1d2dfe..b0d5c26829 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -478,10 +478,10 @@ end #@end #@# == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ -===[a:matching_non_primitive_objects] プリミティブなオブジェクト以外とのマッチ: deconstruct と deconstruct_keys +===[a:matching_non_primitive_objects] プリミティブなオブジェクト以外とのマッチ: deconstruct メソッドと 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). -既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは deconstruct (これは Array/Find パターンで利用されます) か deconstruct_keys (これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 +既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは deconstruct メソッド(これは Array/Find パターンで利用されます) か deconstruct_keys メソッド(これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 #@samplecode class Point @@ -703,7 +703,7 @@ c #=> 未定義 #@end #@# Number of +deconstruct+, +deconstruct_keys+ method calls: -#@samplecode deconstruct や deconstruct_keys が呼び出された回数 +#@samplecode deconstruct メソッドや deconstruct_keys メソッドが呼び出された回数 $i = 0 ary = [0] def ary.deconstruct From d04656cc72d62383118a13b59a4fb81b7888174c Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sat, 4 Feb 2023 16:01:35 +0900 Subject: [PATCH 39/43] =?UTF-8?q?=E3=83=97=E3=83=AA=E3=83=9F=E3=83=86?= =?UTF-8?q?=E3=82=A3=E3=83=96=E3=81=AA=E3=82=AA=E3=83=96=E3=82=B8=E3=82=A7?= =?UTF-8?q?=E3=82=AF=E3=83=88=E4=BB=A5=E5=A4=96=E3=81=A8=E3=81=AE=E3=83=9E?= =?UTF-8?q?=E3=83=83=E3=83=81=20->=20=E9=9D=9E=E3=83=97=E3=83=AA=E3=83=9F?= =?UTF-8?q?=E3=83=86=E3=82=A3=E3=83=96=E3=81=AA=E3=82=AA=E3=83=96=E3=82=B8?= =?UTF-8?q?=E3=82=A7=E3=82=AF=E3=83=88=E3=81=AE=E3=83=9E=E3=83=83=E3=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063634607 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index b0d5c26829..8c0397c657 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -478,7 +478,7 @@ end #@end #@# == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ -===[a:matching_non_primitive_objects] プリミティブなオブジェクト以外とのマッチ: deconstruct メソッドと deconstruct_keys メソッド +===[a:matching_non_primitive_objects] 非プリミティブなオブジェクトのマッチ: deconstruct メソッドと 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). 既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは deconstruct メソッド(これは Array/Find パターンで利用されます) か deconstruct_keys メソッド(これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 From 37023788cf93d6e156d7a1e88ac4458645896e50 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Sat, 4 Feb 2023 16:05:22 +0900 Subject: [PATCH 40/43] =?UTF-8?q?deconstruct=20=E3=81=A8=20deconstruct=5Fk?= =?UTF-8?q?eys=20=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6=E3=81=AE=E8=AA=AC?= =?UTF-8?q?=E6=98=8E=E3=81=AE=E8=A8=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#discussion_r1063635255 --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index 8c0397c657..aff10aa470 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -481,7 +481,7 @@ end ===[a:matching_non_primitive_objects] 非プリミティブなオブジェクトのマッチ: deconstruct メソッドと 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). -既に先述されている通り、配列リテラルやハッシュリテラルの他に Array, Find, Hash パターンは deconstruct メソッド(これは Array/Find パターンで利用されます) か deconstruct_keys メソッド(これは Hash パターンで利用されます) が実装されたオブジェクトにマッチします。 +既に述べたように、Array/Find/Hash パターンは、配列やハッシュのリテラルの他に、deconstruct メソッド(Array/Find パターン) あるいは deconstruct_keys メソッド(Hash パターン) を定義しているオブジェクトに対しても、マッチを試みます。 #@samplecode class Point From d2613480c6b564743b019f5c00895be763f382a0 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Fri, 2 Jun 2023 22:16:46 +0900 Subject: [PATCH 41/43] =?UTF-8?q?=E5=86=92=E9=A0=AD=E3=81=AB=E6=9D=9F?= =?UTF-8?q?=E7=B8=9B=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6=E3=81=AE=E6=B3=A8?= =?UTF-8?q?=E8=A8=98=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: shuichi cf. https://github.com/rurema/doctree/pull/2773#issuecomment-1370510488 > 4. 用語『束縛』に対しては、「(Rubyでは)代入と読み替えていいよ」という注釈をつけるか、いっそ『代入』に書き換えるか、をした方が親切に思う > - 個人的には、パターンマッチの文脈で他の言語に触れた際の『束縛』に橋渡しできるので、注釈を一発入れて『束縛』という用語は残していいかも cf. https://github.com/rurema/doctree/pull/2773#issuecomment-1428456003 > ## 4. 用語『束縛』について > > > 「(Rubyでは)代入と読み替えていいよ」 > > > > > > とあるんですがこれは > > > 「(Rubyでは 値の束縛といいつつ再代入ができるので )代入と読み替えていいよ」 > > > > > > という解釈で合っていますか? 👀 > > そう...なのですが、私の大元の意図の記載について言及し忘れておりまして、このパターンマッチのドキュメントは、「特に他のプログラミング言語の知識がないRubyユーザが読んでも理解できるドキュメント」であるべきかなぁと考えておりました。 > > となったときに、「関数型言語のimmutableな変数(らしきもの)に代入(らしきことをする)動作」と詳しく対応させる&そのためにそれらの言語を知る必要性を、前提に置くことなしに、読めてほしいなと思います。 > > また、Rubyに置き換える際には、言語の仕組みが違うので、正確に1対1の用語の射影はできない=いわゆる妥協をする必要があると思っています。 > > ...ということを込めて、 > > > 「『束縛』は、パターンマッチの輸入元である関数型言語なんかの用語で、ここでも使っているんだけども、(Rubyでは)代入と読み替えていいよ」 > > というのは、 > > > 「『束縛』は、パターンマッチの輸入元である関数型言語なんかの用語で、ここでも使っているんだけども、**(ここで『束縛』って初耳です、なぁにそれ、という方々、細かいことは考えなくていい!)**『束縛』は(Rubyでは)代入と読み替えていいよ **(勿論、ホントは関数型言語における『束縛』との比較などの細かい話はあるけれども、だ)** 」 > > みたいな意味合いでした...😅 > > (私の場合、Lispや不慣れなHaskellの知識ぐらいしかないので、ここで言っていることが頓珍漢な可能性があります;Lispは『関数型言語』の文脈で出すべきかはアレですが) --- refm/doc/spec/pattern_matching.rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index aff10aa470..d250dbe2be 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -11,7 +11,7 @@ * [[ref:some_undefined_behavior_examples]] #@# Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. -パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチを可能にする機能です。 +パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチを可能にする機能です。(『束縛』は、パターンマッチの輸入元である関数型言語の用語で、Ruby では代入と読み替えても問題ありません) #@# Pattern matching in Ruby is implemented with the +case+/+in+ expression: Rubyでのパターンマッチは case/in 式を用いて実装されています。 From ea7d92d44520bf4751b71c5a530ea5659f33166f Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Wed, 29 May 2024 20:35:22 +0900 Subject: [PATCH 42/43] =?UTF-8?q?pattern=5Fmatching.rd=20=E3=81=8C=203.0?= =?UTF-8?q?=20=E3=81=AE=20CI=20=E3=81=A7=E8=90=BD=E3=81=A1=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cf. https://github.com/rurema/doctree/pull/2773#discussion_r1089859324 以下のコミットの内容を分岐に取り込んだ cf. [DOC Update pattern matching docs for 3.2](https://github.com/ruby/ruby/commit/ce0f3de032ea0dffbfd20dfbfe33453f65ec5a7c) cf. [Allow omission of parentheses in one line pattern matching](https://github.com/ruby/ruby/commit/ecb6d6a4ef058b5598a7633c3921eeab08ce11c6) cf. [ Add pattern matching pin support for instance/class/global variables](https://github.com/ruby/ruby/commit/fa87f72e1e84e2b55516be188f00434a683b924c) cf. [Pattern matching pin operator against expression](https://github.com/ruby/ruby/commit/21863470d965b8cc299b1f82417c70d5d26f8ab2) cf. [ Update documentation for pattern matching](https://github.com/ruby/ruby/commit/4902f96ee56d0391165b9ba769224c0d88d105fe) cf. [Reintroduce expr in pat](https://github.com/ruby/ruby/commit/88f3ce12d32ffbef983b0950743c20253ea2d0c6) cf. [Pattern matching is no longer experimental](https://github.com/ruby/ruby/commit/b60153241121297c94de976419d421683da4d51b) --- refm/doc/spec/pattern_matching.rd | 112 ++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index d250dbe2be..aa3077005d 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -10,11 +10,26 @@ * [[ref:pattern_syntax]] * [[ref:some_undefined_behavior_examples]] +#@since 3.0 #@# Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチを可能にする機能です。(『束縛』は、パターンマッチの輸入元である関数型言語の用語で、Ruby では代入と読み替えても問題ありません) +#@else +#@# Pattern matching is an experimental feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables. +パターンマッチは、構造化された値に対して、構造をチェックし、マッチした部分をローカル変数に束縛するという、深いマッチを可能にする実験的な機能です。(『束縛』は、パターンマッチの輸入元である関数型言語の用語で、Ruby では代入と読み替えても問題ありません) +#@end +#@since 3.0 #@# Pattern matching in Ruby is implemented with the +case+/+in+ expression: Rubyでのパターンマッチは case/in 式を用いて実装されています。 +#@else +#@# Pattern matching in Ruby is implemented with the +in+ operator, which can be used in a standalone expression: +Rubyでのパターンマッチは in 演算子を用いて実装されており、単体の式や + + in + +#@# or within the +case+ statement: +case 文の中で利用できます。 +#@end case in @@ -30,12 +45,14 @@ Rubyでのパターンマッチは case/in 式を用いて実装されていま #@# (Note that +in+ and +when+ branches can NOT be mixed in one +case+ expression.) in 節と when 節は1つの case 式の中に混ぜて書くことはできません。 +#@since 3.0 #@# Or with the => operator and the +in+ operator, which can be used in a standalone expression: 『=>』 演算子と in 演算子で、単体の式で使用することも可能です。 => in +#@end #@# 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. case/in 式は 「網羅的」 です。もし case 式の値がどの節にもマッチせず else 節がない場合、例外 NoMatchingPatternError が発生します。 @@ -59,14 +76,24 @@ end # "Connect with user 'admin'" と出力 #@end +#@since 3.0 #@# whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: 一方、『=>』 演算子は、期待されるデータ構造があらかじめ分かっている場合に、その一部をアンパックするのに有効です。 +#@else +#@# whilst standalone in statement is most useful when the expected data structure is known beforehand, to just unpack parts of it: +一方、『in』 文は、期待されるデータ構造があらかじめ分かっている場合に、その一部をアンパックするのに有効です。 +#@end #@samplecode config = {db: {user: 'admin', password: 'abc123'}} +#@since 3.0 #@# config => {db: {user:}} # will raise if the config's structure is unexpected config => {db: {user:}} # もし config の構造が期待したものでなかった場合には、例外が発生する +#@else +#@# config in {db: {user:}} # will raise if the config's structure is unexpected +config in {db: {user:}} # もし config の構造が期待したものでなかった場合には、例外が発生する +#@end puts "Connect with user '#{user}'" #@# # Prints: "Connect with user 'admin'" @@ -78,10 +105,12 @@ puts "Connect with user '#{user}'" #@# You can use it when you only want to know if a pattern has been matched or not: パターンにマッチするかどうかだけを知りたいときに使えます。 +#@since 3.0 #@samplecode users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}] users.any? {|user| user in {name: /B/, age: 20..} } #=> true #@end +#@end #@# See below for more examples and explanations of the syntax. 構文の詳細な例と説明は以下を参照してください。 @@ -96,8 +125,10 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true * すべてのRubyオブジェクト (when と同じように、『===』演算子でマッチする) (「Value パターン」) #@# * array pattern: [, , , ...]; (Array pattern) * Array パターン: 『[, , , ...]』 (「Array パターン」) +#@since 3.0 #@# * find pattern: [*variable, , , , ..., *variable]; (Find pattern) * Find パターン: 『[*variable, , , , ..., *variable]』 (「Find パターン」) +#@end #@# * hash pattern: {key: , key: , ...} (Hash pattern) * Hash パターン: 『{key: , key: , ...}』 (「Hash パターン」) #@# * combination of patterns with |; (Alternative pattern) @@ -105,11 +136,21 @@ users.any? {|user| user in {name: /B/, age: 20..} } #=> true #@# * variable capture: => variable or variable; (As pattern, Variable pattern) * 変数のキャプチャ: 『 => variable』 または 『variable』 (「As パターン」, 「Variable パターン」) +#@since 3.0 #@# Any pattern can be nested inside array/find/hash patterns where is specified. Array/Find/Hash パターンの中に 『』 と書かれている場所では任意のパターンをネストさせることができます。 +#@else +#@# Any pattern can be nested inside array/hash patterns where is specified. +Array/Hash パターンの中に 『』 と書かれている場所では任意のパターンをネストさせることができます。 +#@end +#@since 3.0 #@# Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter). Array パターン と Find パターン は配列か deconstruct メソッド(後述)を持つオブジェクトにマッチします。 +#@else +#@# Array patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter). +Array パターン は配列か deconstruct メソッド(後述)を持つオブジェクトにマッチします。 +#@end #@# 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. Hash パターン はハッシュか deconstruct_keys メソッド(後述)を持つオブジェクトにマッチします。Hash パターン で利用できるキーはシンボルのみです。 @@ -202,8 +243,18 @@ end #=> "matched" #@end +#@since 3.1 #@# Parentheses around both kinds of patterns could be omitted: Array パターン や Hash パターン は両端の 『[]』 や 『{}』 といった括弧を省略できます。 +#@else +#@since 3.0 +#@# In +case+ (but not in => and +in+) expressions, parentheses around both kinds of patterns could be omitted: +case 文 (in 文や => ではない) では、パターン の両端の 『[]』 や 『{}』 といった括弧を省略できます。 +#@else +#@# In +case+ (but not in standalone +in+) statement, parentheses around both kinds of patterns could be omitted +case 文 (単体の in 文ではない) では、パターン の両端の 『[]』 や 『{}』 といった括弧を省略できます。 +#@end +#@end #@samplecode case [1, 2] @@ -225,6 +276,7 @@ end #=> "matched" #@end +#@since 3.1 #@samplecode [1, 2] => a, b #@end @@ -236,6 +288,7 @@ end #@samplecode {a: 1, b: 2, c: 3} => a: #@end +#@end #@# このコメントの前後のコードブロックを1つにまとめると #@# {a: 1, b: 2, c: 3} => a: {a: 1, b: 2, c: 3} in a: @@ -444,6 +497,7 @@ end #=> "not matched" #@end +#@since 3.1 #@# In addition to pinning local variables, you can also pin instance, global, and class variables: ローカル変数に加えてインスタンス変数やグローバル変数、クラス変数に対してもピン演算子は利用できます。 @@ -476,12 +530,18 @@ else end #=> "matched" #@end +#@end #@# == Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+ ===[a:matching_non_primitive_objects] 非プリミティブなオブジェクトのマッチ: deconstruct メソッドと deconstruct_keys メソッド +#@since 3.0 #@# 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). 既に述べたように、Array/Find/Hash パターンは、配列やハッシュのリテラルの他に、deconstruct メソッド(Array/Find パターン) あるいは deconstruct_keys メソッド(Hash パターン) を定義しているオブジェクトに対しても、マッチを試みます。 +#@else +#@# As already mentioned above, hash and array patterns besides literal arrays and hashes will try to match any object implementing +deconstruct+ (for array patterns) or +deconstruct_keys+ (for hash patterns). +既に述べたように、Array/Hash パターンは、配列やハッシュのリテラルの他に、deconstruct メソッド(Array パターン) あるいは deconstruct_keys メソッド(Hash パターン) を定義しているオブジェクトに対しても、マッチを試みます。 +#@end #@samplecode class Point @@ -564,6 +624,19 @@ end #=> "matched: 1" #@end +#@since 3.2 +#@# These core and library classes implement deconstruction: +以下のクラスは deconstruct や deconstruct_keys を実装しています。 + +#@# * MatchData#deconstruct and MatchData#deconstruct_keys; +[[m:MatchData#deconstruct]] +[[m:MatchData#deconstruct_keys]] +#@# * Time#deconstruct_keys, Date#deconstruct_keys, DateTime#deconstruct_keys. +[[m:Time#deconstruct_keys]] +[[m:Date#deconstruct_keys]] +[[m:DateTime#deconstruct_keys]] +#@end + #@# == Guard clauses ===[a:guard_clauses] ガード節 @@ -606,6 +679,8 @@ end #@# == Current feature status ===[a:current_feature_status] 機能の現状 +#@until 3.2 +#@since 3.1 #@# As of Ruby 3.1, 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: Ruby 3.1 の時点では、Find パターンは 「実験的機能」 扱いです。Find パターンの構文は将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 @@ -614,13 +689,37 @@ Ruby 3.1 の時点では、Find パターンは 「実験的機能」 扱いで # 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! #@end +#@else +#@since 3.0 +#@# As of Ruby 3.0, one-line pattern matching and find pattern are considered _experimental_: its syntax can change in the future. Every time you use these features in code, the warning will be printed: +Ruby 3.0 の時点では、1行パターンマッチ と Find パターンは 「実験的機能」 扱いです。1行パターンマッチ と Find パターンの構文は将来的に変更の可能性があります。これらの機能を利用する場合は毎回警告が出力されます。 + +#@samplecode +[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! +#@end +#@else +#@# As of Ruby 2.7, feature is considered _experimental_: its syntax can change in the future, and the performance is not optimized yet. Every time you use pattern matching in code, the warning will be printed: +Ruby 2.7 の時点では、パターンマッチは 「実験的機能」 扱いです。パターンマッチの構文は将来的に変更の可能性があり、まだパフォーマンスが最適化されていません。これらの機能を利用する場合は毎回警告が出力されます。 + +#@samplecode +{a: 1, b: 2} in {a:} +# warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby! +#@end +#@end +#@end #@# To suppress this warning, one may use the Warning::[]= method: この警告を抑制したければ、Warning::[]= メソッドが利用できます。 #@samplecode Warning[:experimental] = false +#@since 3.0 eval('[0] => [*, 0, *]') +#@else +eval('{a: 1, b: 2} in {a:}') +#@end #@# # ...no warning printed... # ...警告は出力されない... #@end @@ -631,7 +730,11 @@ eval('[0] => [*, 0, *]') #@samplecode #@# Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted Warning[:experimental] = false # この行を評価する段階では、構文解析とそれによる警告の発生は、既に終了している +#@since 3.0 [0] => [*, 0, *] +#@else +{a: 1, b: 2} in {a:} +#@end #@end #@# So, only subsequently loaded files or `eval`-ed code is affected by switching the flag. @@ -639,6 +742,7 @@ Warning[:experimental] = false # この行を評価する段階では、構文 #@# Alternatively, the command line option -W:no-experimental can be used to turn off "experimental" feature warnings. 代わりに、コマンドラインオプションとして 『-W:no-experimental』 を渡すことで "experimental" な機能に対する警告を出力させないようにできます。 +#@end #@# == Appendix A. Pattern syntax ===[a:pattern_syntax] 付記A: パターンのシンタックス @@ -651,16 +755,22 @@ Warning[:experimental] = false # この行を評価する段階では、構文 | alternative_pattern | as_pattern | array_pattern +#@since 3.0 | find_pattern +#@end | hash_pattern value_pattern: literal | Constant +#@since 3.1 | ^local_variable | ^instance_variable | ^class_variable | ^global_variable | ^(expression) +#@else + | ^variable +#@end variable_pattern: variable @@ -672,9 +782,11 @@ Warning[:experimental] = false # この行を評価する段階では、構文 | Constant(pattern, ..., *variable) | Constant[pattern, ..., *variable] +#@since 3.0 find_pattern: [*variable, pattern, ..., *variable] | Constant(*variable, pattern, ..., *variable) | Constant[*variable, pattern, ..., *variable] +#@end hash_pattern: {key: pattern, key:, ..., **variable} | Constant(key: pattern, key:, ..., **variable) From 497a461bd0102e03349963236d416b0a613ab8b8 Mon Sep 17 00:00:00 2001 From: masatoshi_moritsuka Date: Wed, 29 May 2024 20:56:03 +0900 Subject: [PATCH 43/43] =?UTF-8?q?rest=20=E3=82=92=20=E6=AE=8B=E4=BD=99=20?= =?UTF-8?q?=3D>=20=E6=AE=8B=E3=82=8A,=20unpack=20=E3=82=92=20=E3=82=A2?= =?UTF-8?q?=E3=83=B3=E3=83=91=E3=83=83=E3=82=AF=20=3D>=20=E5=B1=95?= =?UTF-8?q?=E9=96=8B=20=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/rurema/doctree/pull/2773#issuecomment-1573724361 の方針で修正 --- refm/doc/spec/pattern_matching.rd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/refm/doc/spec/pattern_matching.rd b/refm/doc/spec/pattern_matching.rd index aa3077005d..879501bde7 100644 --- a/refm/doc/spec/pattern_matching.rd +++ b/refm/doc/spec/pattern_matching.rd @@ -58,7 +58,7 @@ in 節と when 節は1つの case 式の中に混ぜて書くことはできま case/in 式は 「網羅的」 です。もし case 式の値がどの節にもマッチせず else 節がない場合、例外 NoMatchingPatternError が発生します。 #@# Therefore, the +case+ expression might be used for conditional matching and unpacking: -そのため、条件付きのマッチやアンパックに case 式が使われることがあります。 +そのため、条件付きのマッチや展開に case 式が使われることがあります。 #@samplecode config = {db: {user: 'admin', password: 'abc123'}} @@ -78,10 +78,10 @@ end #@since 3.0 #@# whilst the => operator is most useful when the expected data structure is known beforehand, to just unpack parts of it: -一方、『=>』 演算子は、期待されるデータ構造があらかじめ分かっている場合に、その一部をアンパックするのに有効です。 +一方、『=>』 演算子は、期待されるデータ構造があらかじめ分かっている場合に、その一部を展開するのに有効です。 #@else #@# whilst standalone in statement is most useful when the expected data structure is known beforehand, to just unpack parts of it: -一方、『in』 文は、期待されるデータ構造があらかじめ分かっている場合に、その一部をアンパックするのに有効です。 +一方、『in』 文は、期待されるデータ構造があらかじめ分かっている場合に、その一部を展開するのに有効です。 #@end #@samplecode @@ -221,7 +221,7 @@ end #@end #@# Both array and hash patterns support "rest" specification: -Array パターン と Hash パターン ともに "残余"(rest) の部分にマッチする構文をサポートしています。 +Array パターン と Hash パターン ともに残りの部分にマッチする構文をサポートしています。 #@samplecode case [1, 2, 3] @@ -386,7 +386,7 @@ end #@end #@# The "rest" part of a pattern also can be bound to a variable: -パターンの "残余"(rest) の部分も同様に変数に束縛できます。 +パターンの残りの部分も同様に変数に束縛できます。 #@samplecode case [1, 2, 3]