Skip to content

Commit 173ae93

Browse files
authored
Document 'it' and update numbered parameters docs (ruby#12375)
1 parent 477c505 commit 173ae93

File tree

1 file changed

+80
-9
lines changed

1 file changed

+80
-9
lines changed

proc.c

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4252,19 +4252,86 @@ proc_ruby2_keywords(VALUE procval)
42524252
* Since +return+ and +break+ exits the block itself in lambdas,
42534253
* lambdas cannot be orphaned.
42544254
*
4255-
* == Numbered parameters
4255+
* == Anonymous block parameters
42564256
*
4257-
* Numbered parameters are implicitly defined block parameters intended to
4258-
* simplify writing short blocks:
4257+
* To simplify writing short blocks, Ruby provides two different types of
4258+
* anonymous parameters: +it+ (single parameter) and numbered ones: <tt>_1</tt>,
4259+
* <tt>_2</tt> and so on.
42594260
*
42604261
* # Explicit parameter:
42614262
* %w[test me please].each { |str| puts str.upcase } # prints TEST, ME, PLEASE
42624263
* (1..5).map { |i| i**2 } # => [1, 4, 9, 16, 25]
42634264
*
4264-
* # Implicit parameter:
4265+
* # it:
4266+
* %w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE
4267+
* (1..5).map { it**2 } # => [1, 4, 9, 16, 25]
4268+
*
4269+
* # Numbered parameter:
42654270
* %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
42664271
* (1..5).map { _1**2 } # => [1, 4, 9, 16, 25]
42674272
*
4273+
* === +it+
4274+
*
4275+
* +it+ is a name that is available inside a block when no explicit parameters
4276+
* defined, as shown above.
4277+
*
4278+
* %w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE
4279+
* (1..5).map { it**2 } # => [1, 4, 9, 16, 25]
4280+
*
4281+
* +it+ is a "soft keyword": it is not a reserved name, and can be used as
4282+
* a name for methods and local variables:
4283+
*
4284+
* it = 5 # no warnings
4285+
* def it(&block) # RSpec-like API, no warnings
4286+
* # ...
4287+
* end
4288+
*
4289+
* +it+ can be used as a local variable even in blocks that use it as an
4290+
* implicit parameter (though this style is obviously confusing):
4291+
*
4292+
* [1, 2, 3].each {
4293+
* # takes a value of implicit parameter "it" and uses it to
4294+
* # define a local variable with the same name
4295+
* it = it**2
4296+
* p it
4297+
* }
4298+
*
4299+
* In a block with explicit parameters defined +it+ usage raises an exception:
4300+
*
4301+
* [1, 2, 3].each { |x| p it }
4302+
* # syntax error found (SyntaxError)
4303+
* # [1, 2, 3].each { |x| p it }
4304+
* # ^~ `it` is not allowed when an ordinary parameter is defined
4305+
*
4306+
* But if a local name (variable or method) is available, it would be used:
4307+
*
4308+
* it = 5
4309+
* [1, 2, 3].each { |x| p it }
4310+
* # Prints 5, 5, 5
4311+
*
4312+
* Blocks using +it+ can be nested:
4313+
*
4314+
* %w[test me].each { it.each_char { p it } }
4315+
* # Prints "t", "e", "s", "t", "m", "e"
4316+
*
4317+
* Blocks using +it+ are considered to have one parameter:
4318+
*
4319+
* p = proc { it**2 }
4320+
* l = lambda { it**2 }
4321+
* p.parameters # => [[:opt, nil]]
4322+
* p.arity # => 1
4323+
* l.parameters # => [[:req]]
4324+
* l.arity # => 1
4325+
*
4326+
* === Numbered parameters
4327+
*
4328+
* Numbered parameters are another way to name block parameters implicitly.
4329+
* Unlike +it+, numbered parameters allow to refer to several parameters
4330+
* in one block.
4331+
*
4332+
* %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
4333+
* {a: 100, b: 200}.map { "#{_1} = #{_2}" } # => "a = 100", "b = 200"
4334+
*
42684335
* Parameter names from +_1+ to +_9+ are supported:
42694336
*
42704337
* [10, 20, 30].zip([40, 50, 60], [70, 80, 90]).map { _1 + _2 + _3 }
@@ -4279,11 +4346,16 @@ proc_ruby2_keywords(VALUE procval)
42794346
* [10, 20, 30].map { |x| _1**2 }
42804347
* # SyntaxError (ordinary parameter is defined)
42814348
*
4349+
* Numbered parameters can't be mixed with +it+ either:
4350+
*
4351+
* [10, 20, 30].map { _1 + it }
4352+
* # SyntaxError: `it` is not allowed when a numbered parameter is already used
4353+
*
42824354
* To avoid conflicts, naming local variables or method
4283-
* arguments +_1+, +_2+ and so on, causes a warning.
4355+
* arguments +_1+, +_2+ and so on, causes an error.
42844356
*
4285-
* _1 = 'test'
4286-
* # warning: `_1' is reserved as numbered parameter
4357+
* _1 = 'test'
4358+
* # ^~ _1 is reserved for numbered parameters (SyntaxError)
42874359
*
42884360
* Using implicit numbered parameters affects block's arity:
42894361
*
@@ -4297,11 +4369,10 @@ proc_ruby2_keywords(VALUE procval)
42974369
* Blocks with numbered parameters can't be nested:
42984370
*
42994371
* %w[test me].each { _1.each_char { p _1 } }
4300-
* # SyntaxError (numbered parameter is already used in outer block here)
4372+
* # numbered parameter is already used in outer block (SyntaxError)
43014373
* # %w[test me].each { _1.each_char { p _1 } }
43024374
* # ^~
43034375
*
4304-
* Numbered parameters were introduced in Ruby 2.7.
43054376
*/
43064377

43074378

0 commit comments

Comments
 (0)