Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proc.arity in ruby-3.0.2 vs ruby-2.X.X

Tags:

ruby

Please take a look on the below deviation when executing exactly the same code:

Ruby-3.0.2:

3.0.2 :001 > id = :id
3.0.2 :002 > puts id.to_proc.arity.abs
2

Ruby-2.7.4:

2.7.4 :001 > id = :id
 => :id
2.7.4 :002 > puts id.to_proc.arity.abs
1

Screenshot for execution evidence: 2.7.4 vs 3.0.2

I used 2.7.4. However, any 2.X.X returns “1”.

Is this some kind of BWD compatability issue or a documented change? Thank you

like image 642
Sammy171 Avatar asked Sep 18 '25 17:09

Sammy171


1 Answers

The arity of a method or proc can be either a positive or a negative value. If it's positive, the method/proc accepts a static number of arguments with the number representing the number of required arguments.

If the arity is negative (as is the case for those procs), the method/proc accepts a variable number of arguments. The returned the number gives you the number of required arguments as -1 - n with n being the number of required arguments.

Now for the result of Symbol#to_proc, the more correct arity is -2 as you have to pass an argument (i.e. the receiver where the method representing the Symbol will be called on) plus any number of additional arguments (which will be passed along as method arguments).

In previous Ruby versions, the returned proc was defined to accept any number of arguments, similar to lambda { |*args| ... }. The "body" of the proc then checked the number of arguments and raised if there were too few arguments.

In Ruby 3.0 however, the returned proc is defined similar to lambda { |receiver, *args| ... } Here, the interface of the proc makes it more clear that there is a single required argument and any number of optional arguments.

The behavior of the proc itself was not changed much (but see below). As in both cases, the internal implementation was heavily optimized, both versions check the number of arguments in C code in the implementation of the proc and handle arguments on its own.

With Ruby 3.0 however, the returned Proc is a lambda as it ​actually behaves like a lambda rather than a proc with regards to argument handling (and always has). This was changed in https://bugs.ruby-lang.org/issues/16260.

As such, the behavior itself has not changed, only the announced interface was updated in Ruby 3.0 to better reflect the actual behavior of the proc.

like image 192
Holger Just Avatar answered Sep 20 '25 07:09

Holger Just