What's TOTALLY COMPELLING about Ruby over Python?

John Roth newsgroups at jhrothjr.com
Tue Aug 19 02:42:17 CEST 2003

"Andrew Dalke" <adalke at mindspring.com> wrote in message
news:bhrmk0$hi7$1 at slb0.atl.mindspring.net...
> John Roth
> > All of the Ruby collections implement a .each method, which is
> > a version of the Visitor pattern. If I want to do something to every
> element
> > in a list or a dict (or any kind of collection,) all I have to do is say
> > something like (using Python syntax):
> >
> > collectObj.each(<method name>)
> Does that mean 'apply the method to each element of my
> collection?'?  Does it return a new container or modify things
> in-place?  Is it applied recursively?

I think that's something that each object which implements .each
needs to specify.

> > And you
> > have to worry about distinctions between functions and methods. In other
> > words, it's a mess compared to Ruby.
> Where does that distinction come into play?  A method is a bound
> function, kinda like a curried function with self.

Ruby doesn't have functions in the sense that Python does. Since
a module is treated as a class without instances, module level
functions are class methods: they have the module itself as the instance.

I find this to be a conceptually cleaner way of handling the

> I find C++ methods more confusing, because a reference to a
> class method is unbound, when I almost always want it bound.

Well, in C++, there is no class object to bind it to. I think that's
a difficulty in C++, but then, I don't use the language.

> > Now, you can say: "We've got that with map()." Well, we've got it when
> > your inputs are either lists (or implement the correct protocol) but the
> > result is a list, it's not an internal modification to the object's
> Ahh.  Are strings in Ruby mutable or immutable? ...  Yup,
> looks like it's mutable.  From the FAQ
>   def downer(string)
>     string.downcase!
>   end
>   a = "HELLO"
>   downer(a)
>   puts a        #=> "hello"
> In which case it makes more sense for this in Ruby than in
> Python, since
> "ABCDEFG".each(f)
> can't do that much unless f modifies state, either as a bound
> method or tweaking global variable.
> Given that rather fundamental difference, an each method
> in Python + code blocks wouldn't be any more powerful
> than a for statement.  The following is possible
> def each(container, f):
>     for i, x in enumerate(container):
>         container[i] = f(container[i])
> but then it requires the container be indexable, which
> is stronger than just being iterable.

The major difference is in program expressiveness.
As I said, a For statement is a statement, while .each
is an expression, even when followed by a code block.
There's a considerable difference in the way the program
is laid out, which makes a difference in how easy it is to
determine what is being done.

> How do Ruby's associative arrays work when the string used
> as the key is mutated in-place?  Is it copy-on-write?

I believe that's true for strings: they're used enough that there's
a special provision for them. For other objects, it's up to the
object type to maintain its hash value properly, or to the
application to rehash the dictionary.

I don't really consider this to be the best policy, though.
I like the Python solution better, though: solve the problem
by not allowing mutable values as keys.

> > To continue on this vein, Ruby directly implements Visitor, Observer,
> > Delegate and Singleton. I don't particularly like the way it does some
> > of them, but Python can't claim any one of the four!

> The Python approach to a Singleton is called a 'Borg' class.

I knew I should have said: "And don't tell me about Borg.
It's a bloody hack that never should have been invented,
and should be quietly buried at the crossroads with a stake
through its heart now that it's possible to do it properly."
And I have said it before, on this newsgroup, in fact.

> The other way  to get singletons is with a factory function,
> which under Python wouldn't look different than a normal
> constructor.  I looked at some Java code recently and
> wanted to suggest a factory implementation only to realized
> that would require a lot of 'new' removals.

Well, yes. You've always been able to do that, and
the Ruby mechanism is basically a class function. The
thing that the __new__() method (and Borg, to give it
its due) does that neither the factory function nor the
alternate constructor does is use the proper convention
for creating the instance: that is, the class's name.

That means that if you want to convert it from a singleton,
you've got a greater chance of having code you don't have
to touch.

> Despite my best attempts, I find it almost impossible to slag someone
> without including information to back up my view.  Eg, I thought my
> numbers and trends of mentions of other programming languages was
> pretty interesting, but I guess it was of no value to you.  :(

I found it interesting, but not to the point. If there is one,
it's simply a question of whether any of the differences are
significant enough so someone who knows one language would
consider switching to another one. Google searches won't tell
you that, only looking for people who've made that switch
will tell you.

And I doubt if you'll find them on this newsgroup. That's the
one problem I have with Brandon's questions. If I wanted
to find out whether someone considered Ruby to be sufficiently
better than Python to switch, I'd look on the Ruby newsgroup,
not this one.

I'm basically taking it from the viewpoint of whether there's
anything in Ruby that I think would be good in Python, which
is a question that might interest people on this NG.

John Roth
>                     Andrew
>                     dalke at dalkescientific.com

More information about the Python-list mailing list