

Ruby's not ready - glyphobet
http://glyphobet.net/blog/essay/228

======
tptacek
From an ex-Pythonista a year in to Ruby, point-by-point:

* Ruby's Unicode support is indeed inferior to Python's; unlike Python, you need to explicitly use library calls to work with UTF-16 strings. Python does indeed bake this in to the language.

* I don't use multiline regexps. On the other hand, I do use normal regexps, all the time, and the fact that I don't have to call out to a library to use them, or deal with special "match" objects with their own API, is a plus. Ruby has more natural support for regular expressions than Python, where regular expressions are an afterthought.

* Ruby's documentation sucks. Full stop.

* I have no idea why I'm meant to care about what this guy thinks of Ruby 1.9 or Ruby 2.0. There's a Ruby 2.0?

* Python is way faster than Ruby. Not by a little bit.

* Ruby's scoping rules are a dream compared to Python's; it support real closures, instance variables and methods with encapsulation, and coroutines that were designed for more than just iteration.

* Ruby and Python are equivalent when it comes to internal consistency. Python delegates virtually everything to a sprawling standard library for which there is, most certainly, "more than one way to do it". Calling out the difference between "print" and "puts" is particularly amusing if you know how Python handles the same distinction.

* Ruby has a cleaner object model than Python, where virtually every feature of the language appears to have been built by exposing the raw symbol table to the language. The simplest way to observe the difference is by taking an existing class and wrapping it with an object that catches all method invocations, a la "method_missing".

* Both Ruby and Python support keyword arguments by giving functions a dictionary type of keyword/value pairs; Ruby has the added benefit of a Symbol type, like Lisp and Smalltalk. No Ruby program fails to use them.

* I'm guessing about, oh, zero people on Hacker News give a shit about SAP support.

* I never noticed that Ruby didn't print the actual line of code that threw an exception. It's true! Python does! I never noticed that, either! That's pretty neat.

* Apparently, despite having been largely ported from Rails, Pylons is more mature than Rails. Awesome.

~~~
akkartik
Scoping. I got bitten by a huge bug in ruby's scoping last night:

    
    
        irb> [1,2,3].collect{|n| n+1}
        => [2, 3, 4]
        irb> n
        NameError: undefined local variable or method `n' for main:Object # Expected behavior - n's scope is restricted.
        irb> n = 0
        => 0
        irb> [1,2,3].collect{|n| n+1}
        => [2, 3, 4]
        irb> n
        => 3 # BAD
    

I have ruby 1.8.4. Most recent version is 1.8.6. Gotta go see if it's a known
bug or worse if it's _supposed_ to work this way..

Edit: elided profanity.

~~~
ambition
It is supposed to work this way for some good reasons. But! Enough people have
had the same problem as you that new versions of Ruby behave the way you
expect.

~~~
raganwald
Help me understand: what are the good reasons for the _parameters_ of a block
overwriting variables in an enclosing scope?

That is, we are talking about:

    
    
        i = 100
        x = 0
        [1,2,3].each { |i| x += i }
    

I understand why it is incredibly helpful for x to refer to a variable in the
enclosing scope (even if we could accomplish this same effect with a fold).
What are the use cases for the parameter i referring to a variable in the
enclosing scope?

~~~
brlewis
As someone who's used to Scheme (lexical scoping), I have to say that's pretty
bizarre.

That's my second disappointment with Ruby blocks. The first was learning you
could only have one block argument.

Do they resemble first-class objects at all? Can you assign a variable to a
block? If you were to assign

    
    
      { |i| x += i }
    

to a variable outside that enclosing scope, and then used that variable in
that scope, would i be overwritten in that call to the block?

~~~
raganwald
"you could only have one block argument"

Do you mean one method can only have one block?

~~~
brlewis
Having only read about Ruby and not coded in it, I'm not sure what the correct
terminology is. I'm talking about doing something like this:

    
    
      someObject.someMethod({block1},{block2})

~~~
tptacek
You can't pass more than one block literal to a method. But you can certainly
pass multiple blocks; they're objects, just like anything else. Just add the
token "lambda" to your expression:

    
    
       def foo(x, y); x.call(y.call); end
       foo(lambda {|x| 2+x}, lambda {1})  # => 3
    

It seems to me that in this case, the language degrades to approximately the
same level as Common Lisp.

~~~
brlewis
It's good to see that an upgrade to approximately the power of CL is possible
in this case. Still, I feel a little let down. When I first saw Ruby block
literals, I said to myself, "Hey, that's a great, concise syntax for lambda.
Languages really are getting more lisp-like all the time." But now I know that
Ruby block literals aren't really lambda. It does look like Ruby lambdas
really are lambdas, though.

~~~
mdemare
Blocks are lambda's, they're just not objects (but they can be converted to
objects.)

~~~
brlewis
If you can't pass more than one block literal to a method, then a block
literal is not a real lambda, from the Lisp point of view.

~~~
tptacek
This is confusing, because Lisp doesn't have the literal notation you're
talking about. Since Ruby supports arbitrary lambdas using "lambda" notation
(something Python _does not_ support), it seems like Ruby's syntax can only be
be better than Lisp's in this regard.

~~~
brlewis
Programming languages should be designed not by piling feature on top of
feature, but by removing the weaknesses and restrictions that make additional
features appear necessary. I do not think Ruby is better for having an
additional syntax (block literals) that is just like an existing syntax
(lambda) only more restricted.

~~~
tptacek
The syntax isn't meant to be "a better lambda". The syntax is meant to recast
other language functions, like looping and iteration, in terms of messages and
anonymous functions. Since idiomatic Ruby basically never has "for" loops,
despite their easy availability in the language, I'm going to go ahead and
call the "block" expiriment successful.

~~~
brlewis
If it's meant to recast certain language functionality in terms of anonymous
functions, why didn't they just make block literals return anonymous
functions? It still strikes me as an almost-could-have-been-great syntax.

Idiomatic Scheme basically never has "do" loops, despite their being part of
the core standard, and it's been that way for decades.

~~~
tptacek
I agree that block syntax should semantically result in expression evaluating
to a Proc object. This would be great:

    
    
      y = {|x| x} # => #<Proc>
    

I agree that block syntax could therefore be greater than it is.

I disagree that you can fairly knock Ruby for this, since blocks and implicit
block arguments are still better than what you get in other languages.

------
nickb
I couldn't disagree more. Having tried both platforms, I felt like I was
coding with one hand tied behind my back when I was learning Python, Pylons
and Django. Web tools and the stack is a lot less mature than RoR stack and
the amount of various plugins/gems available for both platforms was not even
close. RoR plugins were so much more mature and multitudinous that after we
started planning our app, we realized that we'd have to spend about 6
months(!!!) just writing the functionality in Django/Pylons that we were
getting for free with Rails. Now this was about one year ago so things might
have changed.

Since I don't have the time to go over each point that the author makes, I'll
concentrate on a couple.

Lack of Unicode in Ruby 1.8.x. OK, so this might have been an issue before RoR
1.2 came out but since 1.2, RoR has introduced Multibyte and has been a
lifesaver. Now, I don't have a clue how many Rails Unicode apps the author has
written in his career but I can tell you for a fact that Unicode is not an
issue in Rails anymore. We have an app in beta that uses Unicode for every
string that we handle and we handle so many strings for so many languages that
your head will spin. We haven't had any huge issues with RoR's Unicode support
at all. So that argument is really a moot point.

As for language performance, who really cares?! Programmer's time is so much
more expensive than servers so the last thing I worry these days is how fast
some specialized benchmark runs. As long as the latency is acceptable and you
can solve the problem by parallelizing it, the performance of an interpreter
is completely irrelevant.

~~~
jmtulloss
I think his point about performance was more that the rails developers were
not taking significant steps to improve it. From what I understand, they are
doing this for Ruby 2.0.

He definitely addresses the programmer time thing a lot, except from the
perspective of code readability instead of keystrokes or whatever other metric
you might use. Python is generally a much more readable language, and might
make for more maintainable large scale systems because of it.

~~~
nickb
>From what I understand, they are doing this for Ruby 2.0.

In less than a year's time, you'll have so many choices to choose from. Ruby
1.9 is just one of the Ruby interpreters that you'll be able to pick from.
There's also Rubinius (which is already outperforming MRI on so many
benchmarks)

Take a look here: [http://programblings.com/2008/04/01/rubinius-for-the-
layman-...](http://programblings.com/2008/04/01/rubinius-for-the-layman-
part-1-rubies-all-the-way-down/)

And you'll also be able to choose from JRuby and IronRuby. The way I see it, I
think there's more work being done on improving Ruby's than Python's
ecosystem.

~~~
tptacek
Ruby people should be more candid about the performance situation, which is a
catastraphuck. It _is_ worth it, it _will probably_ get better, and raw
performance _isn't_ that important for I/O bound apps, but Ruby is noticeably
slower than pretty much all its competitors.

~~~
tonystubblebine
People make this claim all the time but I never hear anyone talk about actual
examples where they were bitten by this.

People especially like to harp on the speed of ruby as a knock on ruby on
rails. However I have not once run into a real life situation where the
performance problem was directly related to the raw performance of Ruby. I
have though run into plenty of performance problems:

* At Odeo (RoR circa 2005) we had plenty of problems with memory leaks in our FCGI (this was 2005!) processes and in feed_tools (well known to be slow)

* At my next company we quickly ran into situations where pages were slow to load due to the sheer number of database calls. When I started doing web apps I can remember never having more than three queries behind any given page. Some of our pages were doing 500 queries. This was easily fixed but Rails definitely tempts you to put up scaffolding which you then have to rework once it starts getting real use. In my experience this is a good thing. I'm twice as likely to throw away the scaffolding than I am to have to rewrite it.

* Twitter, which is the poster child for RoR scaling issues, actually actually has had almost all their problems on the backend, having to rapidly change their database and message queue architectures and deal with flaky service providers (AOL and phone companies). Again nothing to do with the architecture they launched with.

So, in the lab Ruby is a slow language, but in the real world how is this
biting people?

~~~
tptacek
Like I said earlier, our app parses with racc, does cryptography, and a fair
bit of analysis. It is not heavily database dependent. Most of our I/O is
memcached. I assert without evidence that Ruby's performance deficits have in
fact bit us.

------
tptacek
Well, this was interesting. My team just finished a Rails project that used
Racc extensively (with multiple different grammars), made extensive use of
cryptography, and spent several weeks up on blocks being tuned with ruby-prof.

Obviously, it also used ranges, keyword arguments (like _every other Ruby
program ever written_ ), strings and string conversions, blocks, private
methods, and yes, even Unicode.

I did notice that the documentation for these features was lacking. What I
didn't realize was how much Ruby sucked, compared to Python.

I am now steeling myself to begin typing "self" in front of every instance
variable, write ten lines of code every time I need a "method_missing", fish
the gettimeofday equivalent out of 19 different libraries that return and
manage time, re-learn whether I want to call popen, popen2, popenN, or create
a Popen class, wrap my data types up in a list when I need code to close over
them, condense all my anonymous functions to single expressions to work around
Python's accidental support for lambdas (which, according to GvR, are evil),
write my oh-so-thread-safe-code for an interpreter that serializes around a
global interpreter lock, pretend that my classes have private methods by
naming them differently, just like I do in my object-oriented C code, marvel
over the amazing things I can accomplish with "generators", continue to format
strings using "printf" semantics the way Kernighan and Richie want me to, and
track down bugs that are literally invisible due to semantic whitespace.

Can't. Wait. You know what I miss most? Twisted.

~~~
fuzzyman
"method_missing" - do you know about '__getattr__' for Python? (can be a one
liner if you want...)

"oh-so-thread-safe-code for an interpreter that serializes around a global
interpreter lock" - so Ruby's threading is better??

------
SwellJoe
I haven't found the argument about backwards compatibility to be true of
Python, but it has been true of Perl. Code that I wrote 5-6 years ago in
Python has needed at least three updates to run in newer versions of Python
(1.5->2.0 and 2.0->2.2 and 2.2->2.4--I no longer work in Python, so I don't
know if they'd need an update to run on newer versions). On the other hand,
code that I wrote ten years ago in Perl still runs unmodified on Perl 5.10.
The only major upgrade problem I've seen has been the introduction of native
Unicode in Perl, which caused anything that assumed scalars to be made up of
8-bit bytes to break, but that's a pretty broken assumption, anyway.

So, in short, I don't think Python is exactly a paragon of backward
compatibility. It may be better than Ruby, but it isn't a solved problem.

I also disagree with the assessment that TIMTOWTDI is a bug. But, me being a
Perl coder may have warped my judgment. I find Ruby very intuitive--moreso
than Python, even though I've written more Python code than Ruby.

That said, there are some serious deal-breakers in Ruby. Lack of Unicode is
one of them. I wasn't among the folks criticizing Arc when it didn't have
Unicode at first release...but if it had gone more than a year without
Unicode, I would have joined the bandwagon of critics. And, once again, I
think Perl has solved Unicode better than Python.

------
benreesman
While I agree that Ruby (in the form of MRI) is pretty limited in the kinds of
production applications it's ready to support, I feel just as strongly that
Python is an evolutionary dead end.

Personally I predict that JRuby (which addresses most of the issues listed in
TFA) will become the mainline production Ruby. It runs adequately fast, and
has JVM threading, meaning that ceteris paribus it is 'fast enough' for the
largely IO-bound tasks that make up web-programming. And when you program in
JRuby you find yourself leaning on the Java libraries for most of the heavy-
duty stuff (say what you like about Java, I certainly do, but the libraries
are abundant and abundantly production-worthy). Ultimately, when you've got
lambda and reasonably low-impedance hash tables then you can make everything
else, so there's a future for Ruby.

Python on the other hand is a lost cause. Objects are a valid and important
ingredient in a balanced diet of programming abstractions, but 'object-
oriented programming' is for idiots or assholes or worse. Objects as a first-
class language feature are nice-but-optional, I've worked on large C systems
written in an object oriented style (one was a simulation, another was a
widget toolkit, both had 'object' as a meaningful native domain concept).
First-class functions OTOH are not optional, without them you've designed a
language for infants. If you are designing a modern high-level programming
language and you choose to cripple lambda (either because you've made
regrettable decisions about your syntax that prevents their expression, or
because you want to put training-wheels on the language itself, or LOL both)
then you're an asshole, full stop. Python's scoping is tragic, at least Larry
and Brendan had the humility to admit they fucked up and add reasonable
scoping. GVR isn't wrong, 30 years of hard-won experience with correct lexical
scoping is. If you think Scheme is wrong then I've got news for you: you are.
Funny, now that I think about it it's not even about right and wrong anymore,
it's about 'Pythonicity', which basically means that not only is GVR never
wrong, if you don't agree then you're some kind of barbaric programming-
language outsider. God I can't wait for a good example of Python (and more
importantly the frigid, self-righteous, under-endowed Python community, I'm
looking at you Paul Prescodd) to come into direct competition (- lisp epsilon)
in a measurable, documented way.

At least Ruby and Javascript know that (- lisp epsilon) is the place to be,
and they're both in the process of trying to add enough curly-braces to make
themselves palatable to Java-refugees and no more.

Just remember: Python's not wrong, you are.

[http://www.python.org/doc/faq/general/#why-must-self-be-
used...](http://www.python.org/doc/faq/general/#why-must-self-be-used-
explicitly-in-method-definitions-and-calls)

------
tx
I'm going the opposite direction: after having done two non-trivial RoR apps I
have a Pylons project on my hands right now. What can I say? Pylons is a baby
Rails and Python is a baby Ruby. Language issues aside, Pylons' architecture
seem to be a little cleaner than Rails, but even that advantage largely goes
away with all these cleanups done in Rails 2.0.

Pylons/Python are more ugly and less complete than Rails/Ruby:

a) Ugliness: passing "self" to each method, deriving from Object all the time
and having __foo__() method names is ugly, ugly, ugly.

b) Incompleteness: URL generation/routing and SQLAlchemy are too primitive and
require more coding comparing to Rails. Stuff like form_for(Model.new) isn't
possible as far as I can tell. Moreover, Pylons application requires a lot of
bootstrapping to get going, setting up DB access is especially tedious
comparing to ActiveRecrod's magic. Ralis' soft inforcement and helpers'
assistance with RESTful controllers can't be seen anywhere in Pylons as far as
I can tell. The list goes on: Pylons is more like a very very old Rails
version distorted by ugly Python's object system.

Pylons probably looks pretty sweet to someone who's starting on it with a
fresh head, but after two years on Rails I am less than thrilled to work with
it. I may not be Pylons expert by now, but man... it's been two months and it
still doesn't show me any love :-)

I love Python though. I like CPython implementation and quality of the
libraries. Right now it's my language of choice for any stand-alone piece of
software, but I try as hard as I can to avoid Python's object system.

~~~
ardit33
The beauty of Python, is that there is a lot of choices when it comes to
frameworks. Actually, probably Python is one of the those langues which makes
using a framework strictly optional. And there are so many options if you do
things that are not your average web app. With Ruby, you are stuck with one,
good framework, but not much if you want to do things very differently.

Django, Pylons, Cherry.py, web.py, Turbogears, and countless of other
frameworks.

And I completely agree, on the fact that object oriented programming in Python
is not pretty at all, but as a language it wasn't necessary ment to be used
that way.

~~~
pius
In Ruby you've also got a bunch of Web frameworks/libraries (Rails, Merb,
Camping, Rack, Ramaze, Sinatra, and Nitro, to name a few).

------
chaostheory
He has some valid points, but I think a more accurate title is: "Why I don't
like Ruby"

"Migration to Ruby 1.9/2.0"

Won't python dev's have the same problem with Python 3000?

"Performance (or lack of)"

JRuby and Ruby 1.9/2.0 already address this issue

"Scoping" "There’s more than one way to do it"

I don't see this as a weakness. This is more about style and preference,
though I admit I like Python's philosophy better (Ruby code just looks more
beautiful to me)

overall I still think it's well written criticism (at times I cringe looking
at the horrible stuff people in the ruby community write)

~~~
glyphobet
> Won't python dev's have the same problem with Python 3000?

Read that section. It outlines why Python won't have the same problem.

~~~
chaostheory
that's assuming the conversion program works well... It may work well for
snippets, but I have to see it work well with larger/mature python code bases
to believe it.

~~~
glyphobet
Ok, that's fair enough. Who knows how well the conversion program will work.
Still, for Python 3, there's a clear plan... and there's no clear plan for
Ruby 2 (yet).

~~~
chaostheory
good point

------
ambition
I've noticed a bias in favour of "What I learned first is better." It applies
whether the topic of discussion is programming languages and operating systems
or politics and religious values.

(Pre-emption: "bias", not "law".)

Psychologists have lots of fancy words for describing why this is.

~~~
raganwald
<http://en.wikipedia.org/wiki/Baby_Duck_Syndrome>

------
ken
These, of course, are not problems with Ruby -- so fellow Rubyists, don't get
bent out of shape over this. It's a list of his priorities, which don't happen
to align with the current state of Ruby. It's not hard to come up with a
different set of criteria that make Ruby look perfect and Python look
unusable, and I'm sure other people here will do just that.

But interestingly, all three of his main arguments in favor of Python (more
mature, more consistent, and more complete documentation) also sound like
great reasons to use Common Lisp over Python.

------
sc
Everything appears to be a matter of taste:

Ruby has two range operators, .. and .... Why? The only difference is that the
shorter one, with two periods, returns a longer range, and the longer one
returns a shorter range, not including the endpoint. Can this possibly get any
more confusing? 2 The language should have one, not two. It is not hard to add
or subtract one when you want a range with, or without, its endpoints.

I like the shortcut. Then again, I like the English language. I like the fact
that you can express things in a myriad of (yes, you can say "myriad of")
different ways depending on how you want to express them.

A Pythonista friend of mine once complained over the simple fact that Ruby had
so many ways to express a conditional but none as elegant as what was used in
Python.

Python:

\- if foo: bar()

Ruby:

\- if foo then bar end

\- if foo; bar end

\- if foo: bar end # deprecated

\- foo if bar

\- foo && bar

\- foo unless !bar

I love the diversity, however. Really, the first thing that sticks out to me
with Python are those superfluous parentheses. Taste, taste, taste.

~~~
mikeryan
Its funny someone once wrote that Rails should have been written in Python -
his main argument was that Ruby gives you so many ways to do things but Python
tends to pick "a" way. The Rails framework tends to follow this Python like
mentality of Picking a particular way.

------
justindz
Imagine how much good code in either language is currently _not_ getting
written ;-)

------
sah
As someone who spends most of his time working in Python, the section called
_One nice thing about Ruby’s scoping_ made me a little bit jealous. I hate the
way Python handles default parameters.

Also, I think glyphobet is a little hard on Ruby's range objects. He says:

 _Python’s xrange() can also be passed around like a variable, but you test
for membership with value in myrange instead of ===._

An important difference there is that "value in xrange(10000)" iterates to
find the value, while "(1..10000) === value" does something O(1), like 1 <=
value < 10000\. Range objects are handy, and different from list constructors
like range() and generators like xrange(). But I agree that the ".." and "..."
syntax is weird.

~~~
glyphobet
Ah... You're right. I thought value in xrange(10000) just checked the
endpoints, but it appears to iterate. Someone should write a PEP. :)

------
sant0sk1
He brings up a good point w/ documentation. Ruby's has left me wanting in more
than a few situations.

~~~
nickb
If you're working professionally with RoR buy few commercial books on Ruby and
Rails. The cost is negligible when you consider the savings in time that you
will get when learn from a good Rails/Ruby book. Sure, Django has a free book
on the basics of it and there is Dive into Python series but the number of
books on Rails is much greater and they are professionally edited and are of
better quality.

The lack of free books is an issue but you get what you pay for.

~~~
tptacek
"You can buy a good book" is not a valid response to "Ruby's documentation
sucks". I have all those books, and I don't feel compensated for Ruby's crappy
documentation.

------
astine
I think that the real teller on Ruby is it's own website. not the main page,
but most of the surrounding infrastructure linked community is really slow.
That is, it is painful to browse. I don't use Ruby or Python very much, but
when I do I usually go through the main site for language to find reference
and documentation and Ruby is definitely more difficult on that count because
of this. I can only assume that it is because they build their websites in
Ruby.

On the other hand, Ruby is Japanese. I suppose that the websites may be hosted
on on Japanese servers all that way across the and that may account for the
lag. It's still annoying though.

------
anr
The author has ceirtainly touched a nerve.

I wonder if Perl 6 will be a better Ruby... I do hope we can start to use it
by this year's end.

------
yawl
I like ruby as a language, but not the implementation. And as a matter of
fact, matz knows and acknowledged he is not a good implementator.

------
theoutlander
Ruby works for me. I like the language semantics. What I miss are the email
libraries/parsers that are available in other languages. Don't you think Ruby
will catch up with the missing features in a couple of years? The
documentation isn't that bad either.

------
jrsims
Serious question:

Doesn't the fact that Twitter has been running a highly trafficked Ruby
website for a while now nullify all arguments that "Ruby's not ready"?

Sure, we all know that Ruby could be _better_. But isn't it ready now?

------
Kwaziko
Blah Bah Blah Bah Blah Blah.

Too much time is wasted on this planet due to people trying to convince
themselves they are "doing the right thing".

I don't know (or care) what the results are for others. For me, Ruby on Rails
saves me tremendous time when developing projects and makes me enjoy coding
web apps again. So I use it.

If you get that same feeling, use it too. If you don't, try something else.

Anyone who sees anything more to this needs a vacation.

------
davidmathers
Shorter glyphobet: Ruby's not Python.

------
sabat
"The language is inconsistent and needlessly complex."

Huh? This is Ruby he's talking about? I don't find it to be inconsistent or
complex.

~~~
tx
Ruby's syntax is by far more complex than Python's. By "complex" I mean it
from a parser's grammar point of view.

~~~
tptacek
Won't somebody _please_ think of the parsers?!

~~~
sabat
Leave Britney's parser alone!!!

------
pius
Isn't it a little late for April Fools' jokes?

------
russ
Ruby pwns Python. word.

