Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Ruby's .() operator work?

I recently came across some code using a method call consisting of the format object.(arg1, arg2) without seeing a good explanation of how it works. See this sample code:

class TestServiceObject   def call     'method'   end end  TestServiceObject.new.() # => 'method' 

What's the term for this kind of shorthand?

like image 495
fruchtose Avatar asked Oct 01 '13 05:10

fruchtose


People also ask

What is << operator in Ruby?

As a general convention, << in Ruby means "append", i.e. it appends its argument to its receiver and then returns the receiver. So, for Array it appends the argument to the array, for String it performs string concatenation, for Set it adds the argument to the set, for IO it writes to the file descriptor, and so on.

What does === mean in Ruby?

In Ruby, the === operator is used to test equality within a when clause of a case statement. In other languages, the above is true. To my knowledge, Ruby doesn't have true operators, they are all methods which are invoked on the LHS of the expression, passing in the RHS of the expression.

Does Ruby have +=?

<< and + are methods (in Ruby, santa << ' Nick' is the same as santa. <<(' Nick') ), while += is a shortcut combining assignment and the concatenation method.


2 Answers

The dot-parentheses notation is a shorthand way for passing arguments to the implicit call method on a Ruby object:

foo = lambda {|bar| puts bar}  foo.call('baz') #=> baz foo.('baz')  foo.call('baz') === foo.('baz') #=> true 

Also note that the following notations are also valid (and equivalent) invocations of the call method:

foo['baz'] #=> baz foo::('baz') #=> baz 

In your example, you're explicitly overriding the call method on the TestServiceObject class such that it returns the string 'method' when called. Accordingly, you can explicitly override the the call method to accept arguments:

class TestServiceObject   def call(foo=nil)     foo || 'method'   end end  TestServiceObject.new.() #=> method TestServicesObject.new.('bar') #=> bar 

UPDATE:

As commenter @LoganSerman duly notes, the shorthand operator appears to work on anything that responds to call, which is validated in part by the following example:

m = 12.method("+")  m.call(3) #=> 15 m.(3) #=> 15 

UPDATE 2:

As commenter @Stefan also points out from the documentation on Proc#call:

prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”.

like image 176
zeantsoi Avatar answered Sep 18 '22 06:09

zeantsoi


obj.(args) is just a feature provided through the parser. Not technically an alias, but it simply has the same effect as invoking obj.call(args) on an object that defines the call method.

like image 24
Konrad Reiche Avatar answered Sep 19 '22 06:09

Konrad Reiche