This blog is part of our Ruby 2.7 series. Ruby 2.7.0 was released on Dec 25, 2019.

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.