if baz > 10
func = :foo
else
func = :bar
end
result = self.send(func) if baz > 10
func = :foo
else
func = :bar
end
result = self.send(func) if baz > 10
func = method(:foo)
else
func = method(:bar)
end
result = func.call
Here, we actually deal with the Method objects, rather than just sending a dynamic message. Although the send() approach would be closer to idiomatic Ruby, I wanted to emphasize that dealing with methods as first class objects in Ruby is indeed possible. p = Proc.new {|str| puts "Hello #{str}" }
p["World"] # prints "Hello World"
:)It's fun to contrast this with Lua, by the way.
In Python, you can make anything callable by providing a __call__() method, and the parentheses will work as expected. This makes functions fungible with anything, including any object or anonymous function.
In Ruby, only methods are callable, and everything else must be called with the call() method, which means you can't use one in a place where the other might be expected. They're two concepts with the same verb--call--that require different syntax. It's inconsistent.
In that sense, I see why it's not so bad; the difference between methods and anonymous functions is very explicit, and when you want to pass things around, it's likely that you will have target code which expects a Proc object and source code that generates it. Perhaps it's not so bad because there are few legitimate use cases, if any, for transporting a method when an arbitrary block is expected.
As wycats pointed out in a post earlier this year (http://yehudakatz.com/2010/02/21/ruby-is-not-a-callable-orie...), the reason you don't need to explicitly call #call on methods is that Ruby is designed for the common case of calling methods. In addition, it's uncommon to even explicitly use #call or #[] on Procs since calling them is built into the language via yield.
Also, see wycats post: http://yehudakatz.com/2010/02/21/ruby-is-not-a-callable-orie...
This doesn't really work if you would want to pass several procs into a method, but honestly, that is not very common.
a = lambda { |x| x + 1 }
a(3) #=> 4
But since it doesn't, the alternatives are not too bad (though likely far too numerous for Python tastes) a[3] #=> 4
a.(3) #=> 4 (on Ruby 1.9)
I think that Ruby's ability to call methods without () make for better readability in the case of writing domain specific interfaces, but come at a cost in other places. Personally I think it's a worthwhile tradeoff but I can see the other side of the argument.