diff options
author | Victor Shepelev <[email protected]> | 2024-12-18 21:38:40 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2024-12-18 21:38:40 +0200 |
commit | 173ae93e56c62e5cf178d403ae8abcc1b125306d (patch) | |
tree | 5291fd16768d7de1e0edc5e1f093bebf78e72aba | |
parent | 477c505ac0d4d23a860ffafbb487f7598aa89ca3 (diff) |
Document 'it' and update numbered parameters docs (#12375)
Notes
Notes:
Merged-By: zverok <[email protected]>
-rw-r--r-- | proc.c | 89 |
1 files changed, 80 insertions, 9 deletions
@@ -4252,19 +4252,86 @@ proc_ruby2_keywords(VALUE procval) * Since +return+ and +break+ exits the block itself in lambdas, * lambdas cannot be orphaned. * - * == Numbered parameters + * == Anonymous block parameters * - * Numbered parameters are implicitly defined block parameters intended to - * simplify writing short blocks: + * To simplify writing short blocks, Ruby provides two different types of + * anonymous parameters: +it+ (single parameter) and numbered ones: <tt>_1</tt>, + * <tt>_2</tt> and so on. * * # Explicit parameter: * %w[test me please].each { |str| puts str.upcase } # prints TEST, ME, PLEASE * (1..5).map { |i| i**2 } # => [1, 4, 9, 16, 25] * - * # Implicit parameter: + * # it: + * %w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE + * (1..5).map { it**2 } # => [1, 4, 9, 16, 25] + * + * # Numbered parameter: * %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE * (1..5).map { _1**2 } # => [1, 4, 9, 16, 25] * + * === +it+ + * + * +it+ is a name that is available inside a block when no explicit parameters + * defined, as shown above. + * + * %w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE + * (1..5).map { it**2 } # => [1, 4, 9, 16, 25] + * + * +it+ is a "soft keyword": it is not a reserved name, and can be used as + * a name for methods and local variables: + * + * it = 5 # no warnings + * def it(&block) # RSpec-like API, no warnings + * # ... + * end + * + * +it+ can be used as a local variable even in blocks that use it as an + * implicit parameter (though this style is obviously confusing): + * + * [1, 2, 3].each { + * # takes a value of implicit parameter "it" and uses it to + * # define a local variable with the same name + * it = it**2 + * p it + * } + * + * In a block with explicit parameters defined +it+ usage raises an exception: + * + * [1, 2, 3].each { |x| p it } + * # syntax error found (SyntaxError) + * # [1, 2, 3].each { |x| p it } + * # ^~ `it` is not allowed when an ordinary parameter is defined + * + * But if a local name (variable or method) is available, it would be used: + * + * it = 5 + * [1, 2, 3].each { |x| p it } + * # Prints 5, 5, 5 + * + * Blocks using +it+ can be nested: + * + * %w[test me].each { it.each_char { p it } } + * # Prints "t", "e", "s", "t", "m", "e" + * + * Blocks using +it+ are considered to have one parameter: + * + * p = proc { it**2 } + * l = lambda { it**2 } + * p.parameters # => [[:opt, nil]] + * p.arity # => 1 + * l.parameters # => [[:req]] + * l.arity # => 1 + * + * === Numbered parameters + * + * Numbered parameters are another way to name block parameters implicitly. + * Unlike +it+, numbered parameters allow to refer to several parameters + * in one block. + * + * %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE + * {a: 100, b: 200}.map { "#{_1} = #{_2}" } # => "a = 100", "b = 200" + * * Parameter names from +_1+ to +_9+ are supported: * * [10, 20, 30].zip([40, 50, 60], [70, 80, 90]).map { _1 + _2 + _3 } @@ -4279,11 +4346,16 @@ proc_ruby2_keywords(VALUE procval) * [10, 20, 30].map { |x| _1**2 } * # SyntaxError (ordinary parameter is defined) * + * Numbered parameters can't be mixed with +it+ either: + * + * [10, 20, 30].map { _1 + it } + * # SyntaxError: `it` is not allowed when a numbered parameter is already used + * * To avoid conflicts, naming local variables or method - * arguments +_1+, +_2+ and so on, causes a warning. + * arguments +_1+, +_2+ and so on, causes an error. * - * _1 = 'test' - * # warning: `_1' is reserved as numbered parameter + * _1 = 'test' + * # ^~ _1 is reserved for numbered parameters (SyntaxError) * * Using implicit numbered parameters affects block's arity: * @@ -4297,11 +4369,10 @@ proc_ruby2_keywords(VALUE procval) * Blocks with numbered parameters can't be nested: * * %w[test me].each { _1.each_char { p _1 } } - * # SyntaxError (numbered parameter is already used in outer block here) + * # numbered parameter is already used in outer block (SyntaxError) * # %w[test me].each { _1.each_char { p _1 } } * # ^~ * - * Numbered parameters were introduced in Ruby 2.7. */ |