From: Florian Gross Date: 2004-10-21T09:54:18+09:00 Subject: Re: Python vs. Ruby (Re: A concise description of Ruby?) Nikolai Weibull wrote: I'm a passionate Ruby user myself and I find Python quite limiting in some aspects (I agree with Francis Hwang's response to your posting), but as a Ruby user I still have to disagree with / add to some of the responses you give. >>- functions should be objects and __call__ is cool (the function >>aplication operator, () ) > > This is a joke, no? I'll assume it is and will stop here. It isn't and it can make for quite some elegant code if you can call functions directly, though this doesn't fit at all into the Ruby model. (Because we have no public fields and use accessors that look like field access all over the place.) The elegance of having a () operator IMHO is that you can do things like this directly: [1, 2, 3].each(output) Where output can either be a built-in method (or a variable referring to one) or a custom one. (Lambda in Ruby.) It's also interesting how this lets you assign functions to fields and get methods automatically: var obj = [1, 2, 3] obj.each = function(block) { this.reverse().each(block) } This model has downsides of course, a big one being that you can't have accessors (I think properties are commonly used, which is just a set of callbacks for assignment/accessing a field.) and the other one being that you want to omit parentheses. Python solves the latter one by making core functions like print no real functions, but rather a piece of built-in syntax. I have to say that I prefer Ruby's model here, though I can see some of the elegance of the other one, too. >>- multiple inheritance is a good thing > > Multiple inheritance has its merits, but generally it makes class > hierarchies both harder for the compiler and for the programmer to > understand. Very few objects one may want to model require multiple > inheritance (mostly geometrics). You can do fine without it. I think Mix-Ins are generally seen as a more limited (and thus easier to understand and maintain) form of Multiple Inheritance. I personally have not needed more than what Mix-Ins provide yet, but Evil Ruby has support for Multiple Inheritance via Module#inherit in case anybody wants to try this out in practice. (It works by converting the given class to a Module and calling include() with it as the argument.) >>- __nonzero__ is sometimes useful (#to_bool for rubyists ) > > Why? In Ruby, everything but false and nil is true, so why would you > want this? If you would want a #to_bool, then use that instead. Using > pseudo-truthvalues on objects is both bad style and confuses the > intention of the code. Because you might want to have Objects that act like other Objects. In current Ruby there is no way of having a WeakRef or some other kind of Proxy act like nil or false. This is a limitation. I would also find this useful for implementing Perl6-style Junctions, but that might not be a big point. > >>- blocks are useless > > Also, if they are useless, why does Python have them? Python has blocks? As far as I know it only has some crippled form of lambdas that are only allowed to have one statement inside. The non-crippled form are nested defs, but those don't have closures by default. (There is a way of emulating closures via default arguments, but it is quite cumbersome.) >>- list comprehensions are far better than map() and the likes > > Yes, that's why Ruby doesn't have map(); that's why we have .map. Why > do you find that > > l = [1, 2, 3] > [i * 2 for i in l] > > is far better than > > l = [1, 2, 3] > l.map{ |i| i * 2 } > > ? It's not like one version is longer than the other, or one is easier > to follow than the other? In fact, the Python version requires the use > of two keywords and an additional feature of list creation. There is one benefit of list comprehensions that I can think of right now -- they don't need to construct immediate lists which makes them act like Shell pipes. I can think of various ways to emulate this in Ruby, but still -- it is simpler to do it in Python. Other than that I think that Ruby's list iteration capabilities feel generally more powerful. Being able to directly use blocks instead of using a nested def with some odd default argument hack contributes a lot of it, but the bigger point is that Ruby has a lot of this already built-in via the Enumerable module. >>- callcc is the devil > > Yes, certainly, and look how easy it is to simulate in Python: > > http://www.ps.uni-sb.de/~duchier/python/continuations.html But note that this is just a way of emulating them. This won't give you the power you have with built-in continuations. I'm not sure if you're really implying here that Continuations are evil, but they can certainly be useful in more esoteric contexts. (Note that Continuations allowed me to implement Binding.of_caller in pure Ruby with a quite reasonable interface.) >>- TIMTOWTDI is a wrong concept > > That's why Ruby isn't Perl. I can't really tell what you are getting at > with this point. I disagree with both these opinions. Python's view is that there is only one truly right way of doing things. But of course this isn't true and not even consistently applied in Python -- requirements vary all the time and solutions to problems ought to vary with them. >>- docstrings are cool > > Yes, they are. Finally, an argument that actually stands up against > simple critique. Ironic that it should be your last choice ;-). Also note that we are getting close with RDoc. What is currently missing is a nice way of accessing RDoc documentation from irb. I would like to see support for that included in a further irb version. Regards, Florian Gross