DarkWiiPlayer
DarkWiiPlayer

Reputation: 7064

Why no `()` operator for objects?

Lambdas (and procs) in Ruby are just objects with a call method, as in any OO language with functional programming glued on as an afterthought. There are also:

as syntactic sugar for lambda.call().

Lua allows for a __call meta method, that lets me call an object, and in the background, the arguments (and the table) are handed to a real function that does the actual magic.

Lambdas don't feel like dealing with real functions since they are called with [] or .() instead of (). Why not add a () operator that can be overloaded? Then object() would be translated to mean object.(), same as with +, || or any other operator.

Wouldn't it make sense to have syntactic sugar that allows calling the lambda directly? Is this more a matter of design philosophy than technical limitations?

Addressing some "problems" (that aren't really problems) that people have brought up:

If a method returns a lambda, what does that method followed by () mean? does it call only the method, or also the returned lambda?

method() means call method. If that expression returns a lambda, method()() would then call said lambda. The opposite would make no sense at all.

If there is a method called foo, and a callable object called foo, what does foo() mean?

Answer: if foo is a method and a variable, what do you expect foo to evaluate to? The variable. Ruby already does deal with this kind of ambiguity by simply choosing the more intuitive of two options. Thus, if there is a method foo, foo() should call that method. If there's a callable method foo in the same scope, that'd be shadowed by the real function.

Upvotes: 0

Views: 109

Answers (1)

Stefan
Stefan

Reputation: 114208

Why not add a () operator that can be overloaded?

It would be ambiguous. If object is both, a method and a local variable, then object refers to the local variable, whereas object() invokes the method:

def object
  123
end
object = :abc

object   #=> :abc
object() #=> 123

Changing this convention would likely break existing code.

That's (presumably) why Ruby has object.() – it is syntactic sugar for object.call:

class MyClass
  def call
    123
  end
end

object = MyClass.new
object.call #=> 123
object.()   #=> 123

Having a separate syntax to call lambdas allows to distinguish between a method call and calling a lambda which is returned by that method: (thanks Amadan for pointing that out)

def object
  -> { 123 }
end

object    #=> #<Proc:0x007fe494110a78@(irb):2 (lambda)>
object()  #=> #<Proc:0x007fe494110a78@(irb):2 (lambda)>

object.()   #=> 123
object().() #=> 123

Upvotes: 5

Related Questions