
Python vs. Ruby: A Battle to The Death
1 year ago
This talk was given at Northwest Python Day 2010. The companion blog post is at blog.extracheese.org/2010/02/python-vs-ruby-a-battle-to-the-death.html
MOV
00:27:28
2 Related collections
| Date | Plays | Likes | Comments |
|---|---|---|---|
| Totals | 34.4K | 86 | 18 |
| Feb 14th | 13 | 1 | 0 |
| Feb 13th | 28 | 0 | 0 |
| Feb 12th | 25 | 0 | 0 |
| Feb 11th | 31 | 0 | 0 |
| Feb 10th | 19 | 0 | 0 |
| Feb 9th | 36 | 0 | 0 |
| Feb 8th | 30 | 2 | 0 |
-
Vimeo: About / Blog / Developers / Jobs /
Community Guidelines /
Help Center / Video School / Music Store / Site Map
/ Vimeo
or
-
Legal: TM + ©2012 Vimeo, LLC. All rights reserved. / Terms of Service / Privacy Statement / Copyright

Prev week
my_proc.call makes sense, because Proc is a class, and my_proc is an instance of Proc, not a function. Also you cannot overide () as an operator (probably because () are optional in Ruby), so they used the next best thing.
Note that in Ruby 1.9 you can use the added sugar my_proc.() to invoke a Proc object
with self.assertRaises(TypeError):
MyClass.add(2, "two")
(and of course nose should add the same thing, with a nicer method name...)
I don't think either of these is relevant to my comments in the talk. The Proc issue *does* introduce inconsistency, and the &:symbol issue *does* introduce confusion.
Proc#call makes sense for the compiler, but it does not, in my opinion, make sense for the programmer. It introduces two more syntaxes (#call and #[]) for a concept that already had two to begin with (calls with and without parens)!
Yes, "core syntax" was the wrong term to use. It was late, I'd already given one talk five hours earlier on the same day, and I was tired. I apologize. Even with the poor choice of words, though, the point is the same – the history of &:symbol is confusing and user-hostile. I do not accept your argument that "it's easy to know", because my experience shows that Ruby programmers are widely confused by this issue.
Despite my disagreements, thanks for the comment, and I'm glad that you liked the talk overall. :)
As you acknowledge yourself, a Proc is an object and so is 'invoked' by sending it a msg. In Ruby the `()` operator cannot be overloaded and so the #call message is used instead.
What you are asking for, essentially, is that Ruby allow the '()' operator to be overloaded but _this_ would result in inconsistency as the '()' would then be mandatory when invoking Procs (and other user-defined functors) but not when invoking methods.
It just doesn't make sense to allow overloading of the '()' operator in a language where parentheses are optional.
Further, Common Lisp, a language you mention a few times in your talk, works in a similar way. Anonymous functions in Common Lisp cannot be invoked like 'normal' functions and must be invoked through a similar 'call' mechanism: (funcall my-lambda args ...).
I'll grant you your point on &:symbol (I use it sometimes, but it does still feel like a clever hack)
;)
In Python, this distinction does not exist, even though it, too, has multiple callable types. Python has conceptual consistency here; Ruby does not. One nice benefit of this is that, in Python, you can pass any callable type to a function that expects a callable and it will just work – instancemethod, function, lambda, object with __call__ defined, it doesn't matter.
This is not an absolute value judgement on Ruby. It's simply a *relative* value judgement – if we judge this syntax with respect to the pythonic standards in The Zen, it comes up deficient. That doesn't mean it's in a state of moral disarray, or that I think Ruby is fundamentally wrong in this way; it just means that Ruby doesn't live up to the set of standards the Python community happens to have settled on (not surprising!). That's all. :)
A Method Object is a method wrapped up into an object so it can be passed around.
Method Objects _cannot_ be invoked without using #call, they have an almost identical API to Procs, see:
class HelloClass
def hello; puts "hello"; end
end
m = HelloClass.new.method(:hello)
m() #=> error, no method 'm'
m.call #=> "hello", this actually invokes the Method Object
A 'method' itself is not an object, rather it implements the behaviour OF an object.
A 'method' _cannot_ be said to be an instance of the Method class. It is only when you call the #method(method_name) that the 'method' is wrapped up into a Method Object.
Ruby is entirely consistent here - NO objects support the '()' operator, and methods are _not_ objects. The only way to invoke functors (Procs, Method Objects, and so on) in Ruby therefore is to explicitly send a message. In Ruby 1.8.6 the messages are #call and #[] and in Ruby 1.9 you can use #.().
The only point of difference being that in some languages the '()' operator can be overloaded and so the distinction between 'method' and 'wrapped method object' is harder to perceive.
From the start, I have not been talking about the implementation. I'm talking about my mental model of how software works. My brain contains the concept of "callable object". I want to treat this as a single, unified concept, interacting with all "callable object"s in the same way. Python lets me do this; Ruby does not. I don't care why this is the case – procs, methods, objects – who cares? The point I was trying to make in the talk is that the concept of "callable object" is not unified in Ruby; it's fractured. You're giving me the details of *why* it's fractured. That's fine, but it doesn't change my original statement.
Once again, for good measure: it's not about the details of procs or methods. I'm talking about the concept of "callable object" that is present in the brains of some humans, including me, but is not present in a single canonical form in Ruby.
I will reiterate that this is not an absolute value judgement – I'm not saying "my brain is Right; Ruby is Wrong." It's an almost entirely subjective issue.
This is different to the case in Python where AFAIK methods, functions, and lambdas really are just different kinds of 'functions' and so thinking of them together in this way as 'callable objects' makes more sense.
In Ruby though, there is no unifying idea of a 'function' there are instead 'methods' and Procs (et al).
The distinction between the two is that 'methods' are executable code bound to the state of an object but Procs are _objects_ that wrap 'free' code. These differences (esp. the fact that one is a full-blown Object and one is _not_) are so fundamental IMO that convolving the two ideas into a single notion of 'callable object' and then complaining about lack of 'consistency' is wrongheaded.
Another issue altogether is whether, despite these fundamental differences, you can nonetheless provide them with the same interface. Scala (which also makes a similar distinction between methods and 'function objects') _does_ allow overloading of the '()' operator and so the interfaces are the same. Ruby, on the other hand, does not allow overloading of '()' and so the interfaces are different. This does _not_ mean that Scala is more 'consistent' than Ruby, it just means, on this particular point, that Scala is arguably more aesthetically pleasing.
As I've stated before, it is because parentheses are optional in Ruby that the '()' operator cannot be overloaded. I agree that this results in slightly annoying #call syntax when invoking Procs but I think overall it is a win for Ruby's elegance. Personally I do not mind having to type #call to invoke a functor if what i'm gaining in return is an API with the beauty and elegance of Rake or Sinatra.
Also, as I said before, having to use a call mechanism to invoke an anonymous function is not unique to Ruby, Common Lisp also works like this and I do not recall anyone calling CL 'inconsistent' on this point.
That's my whole argument, man. We've wasted all of this time debating a point made in a few seconds of the most frivolous section of a silly talk filled to the brim with wild-ass statements. This is not worth the effort.
It's OK for Ruby to be unpythonic. Everything is fine. The universe is at peace. Two languages have different design aesthetics; that's all. Nothing is wrong here. I do not want to continue discussing this! :)
However it seems you now hold the more innocuous view of "The two languages have different design aesthetics; that's all. Nothing is wrong here.".
If this is the view you now hold, then we are in complete agreement. :)
I found an old rant regarding closures(Proc, proc, etc)
Please see
innig.net/software/ruby/closures-in-ruby.rb
After that, now you can tell me ruby is consistent...:-)
Nonetheless though that article makes some interesting points (esp. regarding the lack of multiple blocks) I really think the author is a bit hysterical. It is true there are some subtle differences between Procs, lambdas and blocks, but the situation is not nearly as byzantine as the author makes out. In my opinion most of the content in that article could be compressed to about 6 lines of code.
Well put!
Ruby is NOT a Callable Oriented Language' on his blog yehudakatz.com/2010/02/21/ruby-is-not-a-callable-oriented-language/