Reputation: 7064
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:
lambda.(<args>)
lambda[<args>]
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?
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
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