38

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?

fruchtose
  • 1,270
  • 2
  • 13
  • 16
  • 1
    [This answer](http://stackoverflow.com/a/4294660/646668) looks like what you're looking for. For future reference, [SymbolHound](http://symbolhound.com/) is quite handy for looking up language syntax... – Simon M Oct 01 '13 at 05:45

3 Answers3

49

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”.

Community
  • 1
  • 1
zeantsoi
  • 25,857
  • 7
  • 69
  • 61
  • From [`Proc#call`](http://www.ruby-doc.org/core-2.0.0/Proc.html#method-i-call): *"Note that prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”."* – Stefan Oct 01 '13 at 07:15
  • For the sake of completeness, you can also invoke `call` with square brackets `m[3]` and with the scope resolution operator `m::(3)` – Stefan Oct 01 '13 at 07:32
  • Very right. I've amended my answer for the sake of completeness. – zeantsoi Oct 01 '13 at 07:49
  • 1
    "The dot-parentheses notation is a shorthand way for passing arguments to the implicit `call` method on a Ruby object" – This is wrong. There is no such thing as an "implicit `call` method". Ruby doesn't *have* implicit methods. You may be thinking of Scala, which is (to my knowledge) the only language which has implicits. – Jörg W Mittag Oct 01 '13 at 09:55
  • 1
    "Also note that the following notations are also valid (and equivalent) invocations of the `call` method: `foo['baz']`" – This is wrong: the indexing operator translates into a call to the `[]` method, not to the `call` method. `foo['baz']` is equivalent to `foo.[]('baz')`, not `foo.call('baz')`. – Jörg W Mittag Oct 01 '13 at 09:57
  • @JörgWMittag isn't `a_proc.call(arg)` equivalent to `a_proc[arg]`? – Stefan Oct 01 '13 at 10:32
  • 1
    `a_proc[arg]` is translated to `a_proc.[](arg)` and *not* to `a_proc.call(arg)`. The translation for the `[]` indexing operator doesn't magically change depending on the object, it is *always* translated into a call to the `[]` method and *never* to the `call` method, regardless of whether the object is an `Array`, a `Hash`, a `Proc` or a `FooBarFrobnicatorThingamajingy`. – Jörg W Mittag Oct 01 '13 at 10:39
  • That's right, but for `Proc` and `Method`, `#[]` and `#call` are equivalent. – Stefan Oct 01 '13 at 10:54
  • They are "equivalent" only in that there is a `[]` method which has the same implementation as the `call` method. That's it. – Jörg W Mittag Oct 01 '13 at 11:06
6
foo.(bar, baz)

is interpreted as

foo.call(bar, baz)

just like

foo + bar

is interpreted as

foo.+(bar)

or

foo[bar, baz] = quux

is interpreted as

foo.[]=(bar, baz, quux)

The intention is to make calling function-like objects look similar to calling methods:

foo.(bar, baz) # function
foo(bar, baz)  # method

Despite claims in other answers to this question, it has nothing to do with an "implicit call method" (Ruby doesn't even have implicit methods, only Scala does) or the indexing operator.

The indexing operator is translated into a different method call ([]) and not into a call to call:

o = Object.new

def o.call(*args); "`call` called with #{args.join(', ')}" end

o.(42)
# => "`call` called with 42"

o[42]
# NoMethodError: undefined method `[]' for #<Object:0xdeadbeefc0ffee>

def o.[](*args);   "`[]` called with #{args.join(', ')}"   end

o[42]
# => "`[]` called with 42"
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
5

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.

Konrad Reiche
  • 27,743
  • 15
  • 106
  • 143