March 3, 2020
This blog is part of our Ruby 2.7 series.
At some point, all of us have used names like a
, n
, i
etc for block
parameters. Below are few examples where numbered parameters can come in handy.
> (1..10).each { |n| p n * 3 }
> { a: [1, 2, 3], b: [2, 4, 6], c: [3, 6, 9] }.each { |_k, v| p v }
> [10, 100, 1000].each_with_index { |n, i| p n, i }
Ruby 2.7 introduces a new way to access block parameters. Ruby 2.7 onwards, if
block parameters are obvious and we wish to not use absurd names like n
or i
etc, we can use numbered parameters which are available inside a block by
default.
We can use **1_ for first parameter, **2_ for second parameter and so on.
Here's how Ruby 2.7 provides numbered parameters inside a block. Below shown are the examples from above, only this time using numbered parameters.
> (1..10).each { p _1 * 3 }
> { a: [1, 2, 3], b: [2, 4, 6], c: [3, 6, 9] }.each { p _2 }
> [10, 100, 1000].each_with_index { p _1, _2 }
Like mentioned in
News-2.7.0 docs,
Ruby now raises a warning if we try to define local variable in the format _1
.
Local variable will have precedence over numbered parameter inside the block.
> _1 = 0
> => warning: `_1' is reserved for numbered parameter; consider another name
> [10].each { p _1 }
> => 0
Numbered parameters are not accessible inside the block if we define ordinary
parameters. If we try to access _1
when ordinary parameters are defined, then
ruby raises SyntaxError
like shown below.
> ["a", "b", "c"].each_with_index { |alphabet, index| p _1, _2}
=> SyntaxError ((irb):1: ordinary parameter is defined)
This feature was suggested 9 years back and came back in discussion last year.
After many suggestions community agreed to use _1
syntax.
Head to following links to read the discussion behind numbered parameters, Feature #4475 and Discussion #15723.
Here's relevant commit for this feature.
If this blog was helpful, check out our full blog archive.