
What's better about Ruby than Python? - comp.lang.python - pbjorklund
http://groups.google.com/group/comp.lang.python/msg/28422d707512283
======
telemachos
The title made me nervous that this would be run-of-the-mill fanboy garbage.
But I trust the author (Alex Martelli), so I read it, and I'm glad I did. It's
reasonable and sane.

My two big take-away points:

1) It's very nearly a wash. Ruby and Python are so close together (beneath any
superficial differences) that distinguishing is _almost_ an exercise in
futility.

2) The key thing about Ruby he doesn't like is its "TOTAL, unbridled
"dynamicity", including the ability to "reopen" any existing class, including
all built-in ones, and change its behavior at run-time." To M's way of
thinking, this makes Ruby less "suited for use in large production
applications" and more suited for "tinkering."

I don't buy the argument myself, but I will admit that when I first started
learning about Ruby, everything I read went on and on about how cool it was
that you could open everything up and play. But as I read more, I discovered
that the community seems pretty heavily tilted against monkey-patching now. (I
may be wrong about this, but it's my impression.) I don't think that means
Ruby is for tinkering only, but it does suggest that Martelli's concern is
legitimate.

He also offers some nice pasta recipes along the way. (So much so, that now
I'm hungry.)

~~~
xal
We run probably one of the largest Ruby production systems that has ever been
made and the dynamism and "monkey patching" are used daily to skillfully make
the language better and better over time for the tasks that we solve.

It's absolutely crucial to teams that internalize it's power and pitfalls.

~~~
techiferous
"one of the largest Ruby production systems that has ever been made"

As an aside, I worked on a very large Ruby app (built by about a dozen
developers over the course of years) and then later worked on another very
large Ruby app of similar size. One of the employees there remarked that it
was the largest Rails app built. I think the people who write very large Ruby
apps tend to be very quiet about it (no blogs, no open-source, less community
participation, etc.) so that if you're one of the ones writing a very large
Ruby app you think yours is the largest. :)

~~~
nkassis
I can fully agree about the quietness of developers working on large ruby app
considering I work on such an app but were not big on advertising it yet.

------
petercooper
My biggest beef when I've done a little Python has been inconsistency, such as
that over functions versus methods. Ruby has a simpler mental model to me. I
hear this has improved in Python 3.0, but it felt bleurgh to use functions
like _len(str)_ some of the time and methods at other times (though
_str.__len__()_ is a poor workaround here). That said, the reasons have been
discussed and defended numerous times, so it's definitely just my opinion
rather than a critique of the language:
[http://mail.python.org/pipermail/python-
dev/2008-January/076...](http://mail.python.org/pipermail/python-
dev/2008-January/076612.html)

~~~
j_baker
The main reason why I like having functions instead of methods is that it
removes the possibility for inconsistency. In some languages, you have some
objects with methods named size, some with length, etc. With python, you just
have one global len method to remember.

~~~
equark
I am often frustrated by this as well, but I'm not sure it's specific to
Python or Ruby. Why is it Math.log(1) rather than 1.log()? And given whatever
reason it's Math.log, why is it a.inverse() when a is a Matrix not
MatrixMath.inverse(a)?

Is there a good guideline for static method vs. instance method distinction?

~~~
ominous_prime
In python the convention tends to be:

    
    
      a.inverse() -> mutates 'a' to its inverse
      MatrixMath.inverse(a) -> returns the inverse of 'a', leaving 'a' unchanged

~~~
xtho
1 isn't a matrix. Integers/floating point numbers are in many languages
treated differently than other types for reasons of performance and memory
management etc. Ruby isn't different in this respect (IIRC they call it
immediate objects). A matrix is a "normal" object in ruby.

BTW the ruby equivalent for the above convention would be (maybe inspired by
scheme?)

    
    
        a.inverse!() -> mutate a
        a.inverse() -> return the inverse
    

Which one is more consistent?

~~~
rikthevik
I am a python user, but I _really_ like that .inverse!() notation indicating
that the object itself is being mutated. It's concise and consistent.
Sometimes punctuation in names is exactly what you need. Same with ? for
predicates. I'll take even? over evenp any day of the week.

------
po
The biggest difference between Python and Ruby is in the mindset of the
developers that choose them.

I think of Ruby and Python as two languages standing back-to-back in the same
spot, mostly unaware of each other, greeting developers who come from
different directions.

~~~
bmelton
I know it's early yet, so take this with all appropriate grains of salt, but
that is easily the most insightful comment I've read today, and really drives
home a point I've been trying to make for awhile (and probably failed to).

I started out with Ruby, because of Rails, and just never seemed to quite make
it jive with me mentally. When I found Python (because of Django), everything
clicked more. I'm not even sure it was the language differences that clicked
more for me, or whether it was the documentation, or the code samples, or some
other intangible that made it all work.

~~~
edanm
Possibly, your greater experience was the difference. I don't know what
experience you had before, but if you came to Ruby with no experience in a
"dynamic" language, everything seemed new and hard-to-understand. Later,
coming to Python, you probably understood everything better as you were
learning it, having had experience with Ruby.

Just a guess, of course.

~~~
bmelton
I'd had some experience with Perl and quite a bit of experience (had built a
couple large-ish apps) in PHP.

The reason I referenced Rails and Django as motivators in finding those
languages is because after having built and then forced to maintain an
enterprise-class application in PHP, I REALLY liked the notion of an MVC
framework, and things like Cake and Symfony weren't out (or at least I didn't
know about them) yet.

So, yeah, I wasn't a programming newbie altogether, but I wasn't as
comfortable in just picking up new languages either.

------
wrs
This is good stuff, except that he seems to misunderstand the ()-less method
call in Ruby. There's no "function" or "object" being "called" with that
syntax, as in Pascal or Visual Basic (his chosen analogies). There are no
functions in Ruby in that sense, and callable objects are explicitly called
(with a "call" method). The expression "foo" in Ruby evaluates to the value of
the local variable "foo" if any, or else sends the message "foo" to self and
evaluates to the result. So yes, the parentheses are optional, but the
ambiguity is with local variables, not with any other form of function call--
so the ambiguity is hardly noticeable.

Also, the parentheses are _always_ optional, not just for zero-argument calls,
so he also missed the opportunity to discuss "poetry mode Ruby": a bunch of
method calls with no parentheses. Stylistically, "poetry mode" enables the
pseudo-DSL style that Ruby frameworks use frequently, but can't really be done
in Python.

~~~
cameldrv
Yes, there is a semantic difference here. In Python, you can do things like
this:

    
    
      if baz>10:
          func = self.foo
      else:
          func = self.bar
      result = func()
    

Here func gets assigned something called a "bound method", which has a
reference to the object and the method, which you can then apply the ()
operator and call. I am not a rubyist, but my understanding is that you would
use a symbol to do a similar thing.

~~~
rlivsey
Yep, the equivalent would probably be something along the lines of:

    
    
        if baz > 10
          func = :foo
        else
          func = :bar
        end
    
        result = self.send(func)

~~~
sandal
That may accomplish the same thing, but the direct translation would be:

    
    
        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.

~~~
mcantor
I HATE dealing with first class functions in Ruby. I understand that it was a
design choice, but man, in Python you can pass a function or a lambda and you
just don't have to worry about which one you're calling. In Ruby, () will
explode on a Proc object. What is with that?!!?

~~~
Twisol
Because () doesn't call a method, it's simply used where a method call occurs.
To call a callable object, you use #call or (as mentioned by epochwolf) #[],
the latter of which I personally detest.

It's fun to contrast this with Lua, by the way.

~~~
mcantor
It's the inconsistency that bothers me.

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.

~~~
Confusion
You can also make anything callable in Ruby: just provide a call method. The
parenthesis will still work as may be expected in Ruby, but, as several folks
said before: in Ruby parenthesis are not used to call anything. A method is
called simply be mentioning it. Anything that follows is an argument and
sometimes parameters are needed for disambiguation of the parameters. This is
counterintuitive, only because it differs from most other languages. If you
want to postpone evaluation, you have to wrap the method call in a closure
that you .call later: in Ruby a method is not a closure and not a function
pointer. It's different than in many other languages, but that alone doesn't
make it inconsistent.

~~~
mcantor
Thank you--this is a good explanation of why the parentheses don't work on
anonymous functions: Ruby's immediate calling essentially forces you to choose
between "objects that you can call like methods" and "objects that you can
easily pass around." This hearkens back to carbon8's comment
(<http://news.ycombinator.com/item?id=1141245>); viewing Ruby's handling of
first-class functions as "inconsistent" definitely betrays a Python-centric
view of things.

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.

------
statictype
What struck me the most was when he spoke about Java possibly borrowing string
immutability from Python and then the realization that Python is an older
language than Java.

------
weavejester
There are two things that Ruby has that Python doesn't have a good syntax for.
One is blocks; in Ruby, I can write:

    
    
        foo { |x| puts x }
    

Whilst in Python, I need to write:

    
    
        def tmp(x): print x
        foo(tmp)
    

It's not really very nice.

The other thing is that Python has no concept of context. In Ruby, I can type:

    
    
        foo(x)
    

And it will execute foo(x) for the containing object. In Python, the closest
equivalent would be:

    
    
        self.foo(x)
    

This syntax difference may seem trivial, but it allows you to do some very
interesting things to classes. For instance:

    
    
        class Foo
          def self.property(name)
            define_method(name) do
              instance_variable_get(name)
            end
          end
        end
    
        class Bar < Foo
          property :x
        end
    

Now the class Bar has a method called "x", without us needing to explicitly
define it.

Ruby's instance_eval method extends this further, allowing you to execute a
block of code in the context of any object you wish.

~~~
llimllib
> The other thing is that Python has no concept of context

Rather, I'd say that part of the zen of python is: _implicit is better than
explicit_ , and I prefer python's behavior in this instance.

~~~
nuclear_eclipse
You've got that backwards for Python: Explicit is better than implicit.

~~~
llimllib
doh!

------
Goladus
This is a fairly superficial difference, but Python's syntax grammar is very
conventional, Ruby's isn't. Compare the grammars of Python, Ruby, and ANSI C.

Python: <http://docs.python.org/release/2.5.2/ref/grammar.txt>

Ruby:
[http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/yacc...](http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/yacc.html)

ANSI C: <http://www.lysator.liu.se/c/ANSI-C-grammar-y.html>

Python and ANSI C both have a similar organization of productions and names
for statements and expressions. It's pretty easy to follow the grammar to
obvious points where the language differs. What are valid unary expressions in
Python and ANSI C? There's a production in each grammar that makes a
convenient starting point and comparison is easy. What is a valid unary
expression in Ruby? It's much less clear.

The Ruby grammar isn't large, so I'm sure some people prefer the way it's
organized. Once you've absorbed the whole thing questions like "what's a valid
unary expression?" don't matter anymore. But I think it's an interesting
distinction to someone trying to decide which language to learn.

------
NyxWulf
I cringed when I saw this link, because I was a regular on comp.lang.python at
the time. I remember very clearly this discussion and the ensuing flame war.
This was when it dawned on me that these types of discussions live _forever_
on the internet. It pays to tone down your rhetoric, especially if you use
your real name in the discussion. <sigh>, at least the link was not to the
flame war in general.

------
cschneid
It's to be noted that while Ruby CAN change builtin functions, the
metaprogramming ability is much more often used in cases like ActiveRecord,
where you can say `acts_as_list`, and it reopens the AR class and inserts new
list-related functionality. It's more powerful than simply using modules,
since it can make decisions as it's being included.

Working with Ruby on a day-to-day-basis, I have never reopened core classes
and changed anything. Rails comes with some common extensions which simply add
new methods, which are less error prone (although I avoid Rails &
ActiveSupport whenever possible).

------
pkulak
I think he's totally right about how to call methods. They just don't feel as
first class as they do in JS or Lisp. I don't agree with his criticism of
dynamic strings, however. The only time you want immutable strings is when
you're not using them as strings. Ruby has symbols for when you need a hash
key.

------
derefr
Ruby and Python are so similar, in fact, that I'm really surprised that there
is no ongoing effort to merge them together. They could really use one
another's libraries and various VM implementations, for example; even the
parsers are almost identical.

The only things that are really "different" between Python and Ruby are
topical features of the grammars of each, that mostly disappear once the code
has been AST-transformed. These could likely be expressed more succinctly in
terms of a simple common base grammar, and two small, modular sets of reader
macros.

~~~
malkarouri
As somebody who used Python a lot and being unable to learn Ruby, I have to
say that I don't feel they can be merged.

I have been successful at learning a variety of languages. Ruby was difficult
for me because it is so similar to Python and yet so different. You have
almost the same syntax getting very different results. So if you come from
Python you get the exact opposite experience to the principle of least
surprise. On the other hand, if you move from OCaml or Erlang there are no
surprises because the syntax is different enough that there are no pre-
expectations.

Also, metaprogramming in Python and Ruby are quite distinct. The way Python
went about it using metaclasses and decorators is very different to the
monkeypatching you get in Ruby, so I don't expect the AST results to be that
similar for idiomatic code in both languages.

------
blacksmythe
Basically Ruby and Python fill the same niche.

When two species fill a different niche in nature, they can co-exists. When
they fill the same niche, it is a bitter fight for survival.

~~~
mkramlich
more evidence: vi vs The Unholy, er, I mean, Emacs

~~~
graywh
One of those is an editor. The other is a lisp environment with editing
functions.

------
mcantor
There are many small-to-medium differences between Python and Ruby, but in my
experiences, no one _actually_ chooses one language over the other because of
these differences. When you ask someone, "Why do you prefer Ruby over Python?"
or vice-versa, everyone has their favorite differences to talk about, but
often, the choice is actually made before enough familiarity with both
languages is established to be _aware_ of those differences. Most people
choose between the two based on _je ne sais quoi_ , rather than an objective
comparison of the differences.

More succinctly: "Ugh! Python? I hate the idea of syntactic whitespace," and
"Ugh! Ruby? I have the idea of using @ for instance variables," are both
cursory judgments that mask deeper preferential foundations therein.

------
hartror
I love the cooking analogy in the middle I use them often when talking about
programming!

------
d0m
For me, the biggest difference between Ruby and Python is that Ruby is more
perlish (i.e. more hacker, one liners, clever stuff) while Python is cleaner
but a bit more verbose and less clever. So in that sens, when I want to hack
something, I usually go with Ruby.. but for a big project, I'd prefer Python.

(But these days, I'm mostly hacking with Arc :p)

------
blowmage
Why was a seven year old post resurrected for discussion here? Does anyone
still believe that Ruby, even with its unbridled dynamicity, is just for
tinkerers and won't work for large teams or production quality applications?

------
albertzeyer
Very interesting to read. And it raised the question in my head about
immutable types. I like functional languages a lot and I like it if just
everything is immutable. Also, I like C++ where I just have everything
mutable. But to have both immutable types and mutables types in one language
always felt very inconsistent to me. Are there good reasons for this?

I put this question also on Stackoverflow:
[http://stackoverflow.com/questions/3584945/non-technical-
ben...](http://stackoverflow.com/questions/3584945/non-technical-benefits-of-
having-string-type-immutable)

------
RiderOfGiraffes
I just get a login screen.

\+ Newspapers require me to register and login - I go somewhere else.

\+ Commercial sites require me to register and login - I go somewhere else.

\+ Google requires me to register and login, guess what happens.

I can't be bothered. I've got stuff to write, products to ship, and a life to
live. It's just another article. I've saved time by not reading it, and the
chances it was useful are small. Besides, skimming the comments has given me
enough of the flavor that I don't really think I'm missing much that I didn't
get from the comments themselves.

Score another one for the HN community. Thank you.

~~~
gxti
This seems to be a bug in Google Groups -- if you have an expired session, it
forces you to log in. But you were never signed in (or if you signed out) it
doesn't ask and goes straight to the article.

------
16s
That's an easy one... In Ruby, I can do string.reverse(). Python makes me type
string[::-1] to reverse a string. In a nutshell, that is why Ruby is better
than Python.

I must admit that I use Python more than Ruby. I like both, but know Python
better. I feel Ruby is more consistent though. Either is a good language!

~~~
koenigdavidmj
You can actually say `reversed(iterable)`, which returns another iterable
yielding everything backwards. Now, this is not returning a string, which
leads to some warts:

* list(reversed(a_list)) * "".join(reversed(a_str))

and the like.

------
nkassis
One thing that bothered me in Python is lambda expression being limited to one
line (as far as I know). Procs/lambdas in ruby can be very complex which often
need.

But if I wrong about this, please let me know.

------
ojbyrne
"Other syntax differences such as '@foo' versus 'self.foo', or the higher
significance of case in Ruby vs Python"

...suddenly wonders if there's a language where both case and indentation are
significant.

~~~
eipipuz
I think he was talking about the "case" control structure. Or maybe I should
just go to sleep... In any case, "case" returns a value, doesn't need breaks
and doesn't need to be the same type. That's awesome.

~~~
regularfry
Given that the switch-case construct doesn't exist _at all_ in Python, I'm
pretty sure he was talking about character case.

------
aphyr
Surprised nobody has mentioned this: Python's generator expressions and list
comprehensions are delicious. I'm primarily a Ruby guy, but I think Python
could teach us a thing or two. :)

------
c4urself
make sure to use the zoom button on that... (not only the page itself but the
differences too)

~~~
nailer
Try Readability (<http://lab.arc90.com/experiments/readability>) - it will fix
the monospace and excess whitepace (as well as the size) in a single click.

------
chewbranca
Fun comparison of Ruby and Python. The pasta analogy was especially
entertaining.

------
sabat
One good reason: programming style (AKA personal preference). Python is a fine
language. Ruby works better for me -- but that's just me.

------
mkramlich
This is one of those articles where any discussion thread about it will lead
to the sharp knives coming out between the Pythonistas and the Rubyists. The
languages are so close in so many ways, and yet so different, that it is bound
to happen.

