Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Ruby require .call for Proc invocation?

Tags:

syntax

ruby

I just wondered whether there is any good reason for or even an advantage in having to invoke Procs using proc.call(args) in Ruby, which makes higher-order function syntax much more verbose and less intuitive.

Why not just proc(args)? Why draw a distinction between functions, lambdas and blocks? Basically, it's all the same thing so why this confusing syntax? Or is there any point for it I don't realize?

like image 718
Dario Avatar asked Dec 25 '09 20:12

Dario


3 Answers

You need some way to distinguish between calling the Proc and passing it around.

In Python and ECMAScript, it's simple: with parentheses it's a call, without it's not. In Ruby, leaving off the parentheses is also a call, therefore, there must be some other way to distinguish.

In Ruby 1.8, Proc#call and its alias Proc#[] serve that distinction. As of Ruby 1.9, obj.(arg) is syntactic sugar for obj.call(arg) and Proc#() is also an alias for Proc#call.

So, you can call a Proc like this:

  • foo.call(1, 2, 3)
  • foo[1, 2, 3]
  • foo.(1, 2, 3)

And you can even also define () for your own classes.

BTW: the same problem is also why you have to use the method method to get a hold of a method object.

like image 135
Jörg W Mittag Avatar answered Nov 03 '22 14:11

Jörg W Mittag


In ruby you can have a local variable and a method that are both named foo. Assuming the method is private, the only way to call it would be foo(args) (self.foo(args) would not work for private methods which can't have an explicit receiver). If ruby would allow to overload the () operator, so that the foo in foo(bar) can be a variable, there would be no way to call the private method foo, when there is also a local variable named foo.

Note that with features like define_method and method_missing, it is not always possible to avoid situations where you have methods and local variables of the same name.

like image 6
sepp2k Avatar answered Nov 03 '22 14:11

sepp2k


You want to be able to pass it around without calling it, right? Requiring that it be explicitly called allows that. Otherwise, every time you tried to use the proc as a parameter, you would end up calling it.

like image 2
Telemachus Avatar answered Nov 03 '22 15:11

Telemachus