Numbered Parameters in Ruby 2.7

A new feature called “numbered parameters” will see the light of day in the Ruby 2.7 release at the end of the year. What caught my attention was not the feature itself but the mixed reception it got from the community.

Block parameters

Whenever you open a block you have the chance to pass a list of numbered parameters

object.method { |parameter_1, parameter_2, ... parameter_n| ... }

For example if you were iterating over a hash to print its keys with matching values you’d do something like this:

my_hash.each { |key, value| puts "#{key}: #{value}" }

Numbered parameters

With the new numbered parameters you are going to be able to save yourself some keystrokes and use @ followed by the number that represents the position of the parameter that you want do use so our previous code would now look like this:

my_hash.each { puts "#{@1}: #{@2}" }

No default variable name

Other languages like Kotlin use it as the default variable name within a block. { println(it) }

This is not the case with this new feature.

object.method { p @1 }

is syntactic sugar for

object.method { |parameter_1,| p parameter } 

and not for

object.method { |parameter| p parameter } 

So pay attention to the dataset you are passing because you might get some unexpected behaviour like this one:

[1, ['a', 'b'], 3, {foo: "bar"}].map { @1 }
=> [1, "a", 3, {:foo=>"bar"}]

As you can see 1 and 3 are taken as the first numbered parameter as expected. Each element of the array becomes one of the numbered parameters so @1 => 'a', @2 => 'b'. And the hash is treated as a single object so it won’t get split either.

This shouldn’t come as a surprise since it’s the expected behaviour of doing

[1, ['a', 'b'], 3, {foo: "bar"}].map { |x,| x }

but in this case we make it clear to the reader when we say |x,|. There is no plan to make it a default variable name which is weird because that’s exactly what was requested in the original issue.

Backwards compatibility is a high priority

As I already mentioned this is what the person who requested the issue wanted to have but it was not accepted in its original form because of backwards compatibility. Introducing new keywords to the Ruby language is a no-go at the moment because Matz is not a fan of breaking developers’ old code with newer versions of Ruby.

I appreciate that Matz takes such a strong stance on this matter, I think it’s important to update your code bases to use the latest version of Ruby but the harder it is to make an update, the less likely it is that you’ll end up doing it. So if I update to Ruby 2.7 and I start seeing breaking changes everywhere in my code base I’m just going to put it on hold for as long as possible. Instead this experience should be a welcoming one.

Pain or gain?

I don’t know how many times you pass a list of parameters to a block versus how many times you pass a single parameter, but I’m pretty sure in every code base you can find many more instances of the latter than the former. So the question is: How valuable is this new feature?

Nobody seems to like the fact that numbered parameters start with @ and some community members are also saying that developers could get confused thinking that the numbered parameters are instance variables.

There is currently an open issue requesting to reconsider numbered parameters because in it’s current state it brings more pain than value. What do you think? Do you like numbered parameters? Do you think they should be implemented in a different way? Would you rather not have them at all? There’s some informal voting happening in case you want to chip in.