Tuesday, April 8, 2008

Why I want to use Python, but don't...(yet)

Hello. I appreciate you stopping by. Let me tell you why this blog is here.

I'm a long-time developer. I have roughly 8 years of professional developer experience. I still read things daily by others that leave me in awe, but I think I hold my own pretty well. In other words, I'm good, but I haven't become so arrogant and obnoxious that the rest of the world look like idiots.

The road to here for me has been:

ksh -> C -> Perl -> C++ -> Java -> Php -> Java -> Ruby

I spent around three months doing Python in between Php and the second Java stint. I liked it...it was ok. But, the profession had other ideas for me.

It's been a fun ride. I've really appreciated things about each language I've used. But I finally found something in Ruby that really clicked. The language was intuitive; it could easily be held in your head, and what couldn't could be found quickly by exploring its very solid (though not perfect) introspection capabilities. There was a bit of a curve regarding rails, but that wasn't Ruby's fault...Ruby was just pretty ('cept for those damned dangling ends).

I really like Ruby the language...Ruby the experience...not as much. The docs are really bad right now in general across the Ruby space (I presume this will improve). The implementation is slow, but I honestly haven't done anything popular enough to feel threatened by it. Many of the libraries I need (eventmachine) are immature at this stage.

So many things lately have been pushing me towards Python. First, twisted has all the features I need for the network programming I'm working on. Second, I've read some really good things about Django and Pylons, and am preparing to work on a new web app. Third, Google's release of app engine today provides what I would consider some very strong validation for the Python community and for Python as a web programming language. Woohoo.

I actually started re-learning python a few months ago when I needed what Twisted had, but God help me I choked on the language itself. So many inconsistencies (__builtins__, two object models, .join, etc) that just didn't add up to a language with the beauty of Ruby.

I read the tutorial, bought Python in a Nutshell, read many of those chapters. But wow....I mean, really...Python seems so much more complex than Ruby. The chapter on OOP alone in Python in a Nutshell really twisted my head. And I've been doing OOP for years! Instead of a language like Ruby that you can entirely keep present in brain "ram", Python seems like a language that causes a significant amount of "swapping". In fact, I wonder if most Python programmers keep (or even understand) a very small subset of the language and operate in that space only. (which, if true, is complimentary to the language).

Listen, I want to explore Python. I want to want to use it. Right now I'm only driven by the fact that its libraries are solid and well documented, its implementation is fast, and it is widely used by two things I love (Linux and Google). If Ruby were in the same boat, there'd be no motivation to move. If Ruby had well-documented libraries (some day?), a good VM (soon) and was proven in big environments, I wouldn't be writing this.

So, here's my arm...please twist it. Help me to understand why Python is the way it is. Help me grok why people like it and use it so much. Help me understand why .join is where it is (nope...no chance in that). Help me feel good about investing the effort in to master Python. I want to join the community, but can't help but feel hesitant.

32 comments:

LeonB said...

I had the same problem: ruby's really nice. Buth Python has these awesome libraries. What I did was to use jruby. The power of ruby and the libraries of java!

Paddy3118 said...

You seem to be doing the right thing already. Ruby seems a good language that you have a lot invested in, but you are keeping abreast of what is happening elsewhere.

It can be very difficult learning Python when you already know another scripting language as it is difficult to give yourself the time and space to learn the Python idioms that are different from the Ruby ones, and its fluency in those idioms that would make you more comfortable in Python.

Good look in your quest,

- Paddy.

Anonymous said...

Benefits of Python over Ruby:
* less arrogance & obnoxiousness
* great documentation & libraries
* list comprehensions
* sane and powerful operator overloading (feh to Ruby's 'coerce')
* sane and powerful regex handling
* cannot monkey patch built-in classes (wise over the long haul for big projects and big teams)
* built-in powerful control over imports & names
* bona fide first-class functions (don't need Python's wimpy lambda anyway)
* built-in Unicode, plus a zillion codecs
* dir() and help() (no need to fight with Ruby's ri)
* keyword arguments
* complex numbers are incomparable (Ruby's Complex#<=> is dead wrong)
* deeper recursion in Python than in Ruby

Benefits of Ruby over Python:
* multiline anonymous functions (Python's lambda limited to single expression)
* built-in regex handling (but not as powerful and sane as Python's re library)
* Symbols
* JRuby is farther along than Jython (I, too, use JRuby when I'm desperate for Java libraries)

Python is my true love, but for reasons outside my control I haven't used it in a couple years.

I use Ruby, I enjoy Ruby. But because of crummy documentation and the Pickaxe being no great shakes, I find myself banging my head a lot against Ruby. And its API, even without the standard library, is awfully big and inconsistent. Switching from CRuby to JRuby last year was a plus. At least Java is wonderfully documented.

Now I shall be arrogant. :-) Right off the bat, I can tell from list comprehensions and the complex class that Pythonistas really know something about math. Rubyists are very clever when it comes to metaprogramming and attempts to invent DSL-du-jour, but the knowledge of math that shines through Python tells me Pythonistas are better educated. How's that for arrogant?

The upshot is, I definitely prefer Python, but Ruby/JRuby is mostly fine.

BTW, I fell in love with Python in 2004 from Python in a Nutshell, Dive into Python, and How To Think Like a Computer Scientist: Learning with Python, in that order. Then the Python Cookbook served to strengthen the love.

I think your brain RAM feels overwhelmed by Python because the Nutshell is so thorough. You're right, though, about Python programmers being able to operate just fine with a subset of that knowledge. A lot of Python fits very nicely in my head, and aside from looking up library stuff, I only need to review a couple things in the online docs: the Built-in Functions page of the Library Reference and the Data Model chapter of the Language Reference.

Anonymous said...

If you can't figure it out you should stick to Visual Basic or Logo.

Jake said...

@leonb: but how does JRuby's footprint compare to that of CRuby and CPython? I imagine having the JVM involved would make it huge.

@paddy3118: it's not knowing other scripting languages that make it difficult...I've done loads of Perl, Tcl, Ruby and PHP at this point (not to mention a few shells).

@elizabeth wiethoff: thanks for your thoughtful answer. However, you think Rubyists are more arrogant than Pythonista? Have you spent *any* time on #python ;) ?

@anonymous: um...yeah...

Anonymous said...

I'm the exact opposite. I'm a guy with no programming experience. And I want to use only python, but i don't really have a good method for learning. I'd like to think that I could just pick up Django, but one, it's not that easy, and two the most common and affordable hosting, like shared hosting doesn't offer it, or it's an expensive add on. Seems like there would be a ton of forms processors for python but when you search for them, it's actually not that easy to find, or they aren't really documented.

Norman J. Harman Jr. said...

huh, One reason I like Python is it's so simple and mostly consistent. (lots of warts in std lib, a few in lang core which are going away real soon now py3k) that I can keep it in my head. The language is getting larger and sadly adding unpython things such as ternary operator.

There is definitely a subset thing. I've never, ever, ever had reason to use __builtins__.

I can't imagine what you don't like about join? Oh, mabee the string cat idiom? That ain't join's fault, join is great.

Python grows on you.

Peter Cooper said...

One reason I like Python is it's so simple and mostly consistent.

See, that's why I've had trouble bothering with Python when I've given it a go. Having two entire types of classes doesn't seem consistent for a start (though this is fixed in 3.0). And why len(something) instead of something.len? There seems to be a real arbitrary (dare I say it, PHPesque) choice in how some things are functions and some things are methods in Python. Not very consistent to me. In Ruby you ALWAYS use the method.

Jake said...

@peter: exactly...this is where I have a hard time. In Ruby, you learn a simple set of Rules that define the language. In Python, you learn a simple set of Rules and a larger set of exceptions to those Rules...it makes it very difficult to grok, especially when you're used the the consistency ruby represents.

Still, I stand here wanting to grok it. I only wonder if you can appreciate python *if and only if* you haven't already appreciated (and been spoiled) by ruby?

Me said...

You nailed it perfectly. I've been trying to convince myself to learn python (exactly for the reasons mentioned.) Yet, I find it hard to pull myself away from such a beautiful language to one that's very similar and is not clearly better in any real way (the language, not the documentation/implementation.)

Michael Easter said...

The premise is flawed: we can't explain Python anymore than we can explain good Thai food or the thrill of playing a musical instrument.

You gotta try it. Give it an earnest try and see how it goes.

That said, some thoughts:

(a) I cursed Python early on but soon loved it. It just stays out of the way. And as Bruce Eckel says "life is better without braces".

(b) There are inconsistencies with Python but Python 3000 is on the way.

(c) Both Ruby and Python are excellent and very similar. I have blogged in the past that any disputes between the 2 camps are like people debating Porsches versus Ferraris. It is true hair-splitting.

(d) It may well be true that the "first one wins" in one's heart. I respect Ruby but find it hard to find motivation to learn it. I'm much more interested in Groovy (which has these ephemeral Python fingerprints).

(e) As someone wrote, your impression that Python is more than a headful is due to the book. That said, it is this wonderful, shape-shifting 'goo' that can be functional, OO, etc.

(f) Google is certainly the trump card, but Yahoo and YouTube use it as well. It has a fantastic community and even has a spirit of coding called Pythonic. Essentially, this spirit acknowledges there is 'more than one way to do it' but there are some ways that 'ring true' more than others. They are said to be Pythonic.

Peter Cooper said...

Jake: Exactly! Like you (I'm guessing) I rather want to learn Python, because there are clearly quite a lot of advantages. It's just some of the inconsistencies gave me "ugh points" when I tried.

That said, I've been looking at some C++ lately and that's made me realize that anything Python can throw at us is easily surmountable! Perhaps the trick to learning Python is as procrastination while trying to learn Haskell, Erlang or the intricacies of the STL ;-)

Jake said...

@michael: interesting you mention groovy...as someone who's done a fair bit of groovy, I'd say it's much closer to Ruby than Python... ;)

Michael Easter said...

@Jake. Re: Groovy, This is a very early post on Groovy...

Note this quote:

Python/Jython's a pretty good base - add the nice stuff from Ruby and maybe sprinkle on some AOP features and we could have a really Groovy new language for scripting Java objects

True, they mention Ruby. And as I said there isn't much space between any of these languages. But Python (and Jython) have more influence than many realize.

casey said...

In my experience, poorly documented things do not tend to improve over time. SF development pace tends to outstrip the doc dev pace. Python has been blessed with some really good and dedicated folks who take the time to keep the docs up with the rest of the language.

Worrying about the overall complexity of python when trying to learn it misses the point that you can be amazingly productive with just basic knowledge. I'd wager most Python developers don't care that there are two types of classes, and frankly you can avoid metaclasses and other headfucks indefinitely unless you are penning the next meta-framework (please god, don't!). You can bite off pieces to learn in easy to digest chunks and put them to use immediately.

Python may have warts, but you'll rarely rub against them in practice, and there is a refreshing balance of elegance and pragmatism throughout. Just dive in and don't look back!

Anonymous said...

Jake, I see you've already concluded that it's hopeless to understand why Python's join method is where it is. :-) Nevertheless, here's my take on why join is a str/unicode method.

From the current docs: "join(seq) Return a string which is the concatenation of the strings in the sequence seq. The separator between elements is the string providing this method."

What is a Python "sequence"? A sequence is a str, unicode, list, tuple, buffer, or xrange. A sequence can also be any type which supports __len__, __getitem__, and __iter__ and whose items are indexed by integers or slices. (See here and here).

So, a Python sequence is any iterable of finite length that can be indexed by integers or slices. If desired, a sequence can be immutable (e.g., tuple is an immutable sequence). And if desired, one could define a sequence such that its elements are generated lazily (e.g., xrange is a lazy, immutable sequence). The fact that a sequence can be lazy means a generator expression can be a sequence.

By defining join as a str/unicode method, it's easy to join the elements of various types of sequences:

', '.join('abc')
', '.join(u'abc')
', '.join(['a','b','c'])
', '.join(('a','b','c'))
', '.join(char for char in 'abc')
', '.join(MySequenceTypeDerivedFromList(('a','b','c')))
', '.join(MyHandCraftedSequenceType('a','b','c'))
', '.join(MyHandCraftedLazySequenceType('a','c')) # perhaps akin to Ruby 'a'..'c'

Ruby's join is an Array method. Therefore, you can call it on an Array or something derived from Array. It's also a File method, Pathname method, URI method, and you can define your own join for your own type. But if you want a Plain Jane join "for free," you have to derive from Array. Or you need to define your own to_a method and have clients call to_a.join.

Disadvantages to Ruby's Array#join:
* You might not want to inherit from (mutable, non-lazy) Array.
* You cannot singly inherit from Array if you want to inherit from something else.
* Calling to_a.join on just about any non-Array type creates a temporary Array which requires garbage collection. This is especially wasteful for lazy types.

So Python's join makes good sense even though string.join(sequence) looks weirder than array.join(string).

Aside: My only small gripe about Python's join is that the arg cannot be a sequence of just anything. I wish str.join(seq) would convert each element of seq to a str as it joins so that ', '.join(xrange(1, 11)) would Just Work. Python 3.0 to the rescue! :-)

Some years ago, Alex Martelli wrote a long-winded defense of separator.join(sequence). His MixedJoiner toward the end there is way cool.

So, you can add these to the benefits I listed earlier:

Another benefit of Python over Ruby:
* str/unicode join for any sequence type

Another benefit of Ruby over Python:
* versatile Range type (Python xrange limited to integers)

If Ruby's join were Enumerable#join instead of Array#join, it might be at least as versatile as Python's str/unicode join. But Ruby is AFAIK stuck with Array#join. Hence, I get the impression that Guido et al. thought through joining more thoroughly than Matz et al. did. (I shall now duck the poo getting thrown at me.)

Charles said...

Hmmm, interesting point Elizabeth.

This is, of course, easy to fix :)

module Enumerable
def join sep=$,
str = ''
sep = sep.to_s
first = true
each do |element|
if first
first = false
else
str << sep.to_s
end
str << element.to_s
end
str
end
end

Now:

p (1..10).join(',')
# => "1,2,3,4,5,6,7,8,9,10"

Complete with coercion to string.

Eat_My_Shortz said...

OK I have only used Ruby for a couple of hours - so this is not a stab at Ruby.

I love Python and I use it for just about all my personal and (at the moment) professional work.

I think one big ticket is this nice "special method" system (google Python Special Method), where you can make objects behave just like builtin objects with just a few methods.

Want your object to behave like a number? Well give it a __add__ and a __mul__ and a few other methods, and now you can treat it like a number.

Want to be able to chuck your object in a for loop OR a .join (hehe) - well give it an __iter__ and a __length__ method, and now you can! That means you can put any functionality you like, and now it can be iterated over!

Want to be able to use it as a key in a dictionary? Well give it a __hash__ method.

And of course something every class should have, a __repr__ method, making it easily printable (the interpreter automatically calls repr so it makes it very easy to play with your code's values).

This stuff is very powerful. It's all documented on the page you'll find when you google python special method. As I said, I don't know what Ruby has for this - I think Ruby lets you give something a "+" method and a "tostring" method, but not all these other things like __iter__.

Also the 2 object models (yes, that sucks) are going away in Python 3000.

Anonymous said...

Ruby's __iter__ is called "each" and "include Enumerable". I could be sarcastic and say RTFM, Mr. Shortz, but one of Ruby's biggest problems is its "manual."

Anonymous said...

Yep, aquasync, one great thing about Ruby is it's so easy to fix. :-) You can fix it when the fancy strikes you. I can fix it when the fancy strikes me. We can stick this with a bunch of other fixes into a gem and post it at RubyForge or the RAA, alongside the Extensions library, the Facets gem, Rails's ActiveSupport, and dozens of other HeresHowILikeToFixRuby add-ons. Nutshells and Pickaxes and other definitive guides be damned. We can all run our favorite flavors of Ruby with our favorite fixes and run giant RDoc jobs on our flavors and hope other people can wade through them. I think I'll take down my Ruby API Guide & JRuby Cheat Sheet now that Enumerable#join renders it useless. :-)

So the nice thing about Ruby is, it's so easy to fix. And it's a good thing, too, because I very often get the urge to fix Ruby. And I do fix it. But the nice thing about Python is, I almost never get the desire to fix it in the first place.

With Ruby being so fixable and the community being so inclined to fix it at the drop of a hat, it might be better off, like Smalltalk or Scheme, in an image-based environment--with an entirely different mode of documentation (and style of book authoring). But Matz wants Ruby as a script-file-based language, such as Perl or Python, and RDoc is inadequate with everything being so fixable. C'est la vie chez Ruby.

Anonymous said...

Sorry. I meant Smalltalk and Squeak, not Smalltalk and Scheme.

Dave Kirby said...

A problem I have with Ruby is that it has been infected with the same "everything must be in a class" nonsense that Java has. OOP is great, but sometimes having free-standing functions are more useful, especially functions that can be be applied to unrelated classes. "len" is a good example of this - because len is a function and not a method you can do things like this:

>>> x = ['abc', [1,2], () ]
>>> map(len, x)
[3, 2, 0]

and

>>> sorted(x, key=len)
[(), [1, 2], 'abc']

If 'len' was a method you would only be able to do this if all the objects that you want to take the length of inherited the 'len' method from a common base class (or mixin, in Ruby). This goes against the whole idea of duck typing.

Allen Short said...

Ruby doesn't have Twisted.

Anonymous said...

This is, of course, easy to almost fix. :-)

>> def len(o); o.length; end
>> y = ['abc', 1..2, {}]
>> y.map &method(:len)
=> [3, 2, 0]
>> y.sort_by &method(:len)
=> [{}, 1..2, "abc"]

Just as Python's built-in len function calls an object's __len__ method behind the scenes, my quick 'n' dirty Ruby len calls an object's length method. In both languages, Python and Ruby, any object can have a __len__ or length method no matter what its ancestry. i.e., any duck can have a length.

The big difference is, Python's len function is readily passed as a first-class object to map and sorted, but here in Ruby I muck around (for interesting syntax) constructing a block out of a :len Symbol.

But all is not roses. The Ruby &method trick doesn't work when the object in question is an Array. The Array's members get "splatted" and become multiple arguments to the block:

>> z = ['abc', [1,2,3,4,5], {}]
>> z.map &method(:len)
ArgumentError: wrong number of arguments(5 for 1)
>> z.sort_by &method(:len)
ArgumentError: wrong number of arguments(5 for 1)

(There's something different about block arg splatting in Ruby 1.9, and I don't know how this &method trick behaves beyond 1.8.6.)

Anonymous said...

Dave wrote: "A problem I have with Ruby is that it has been infected with the same 'everything must be in a class' nonsense that Java has."

Agreed. This is especially awkward when you want to do operator overloading. Do you want Money + Money to produce Money? Do you want Numeric + Money and Money + Numeric to be disallowed? Do you want Money * Numeric and Numeric * Money to produce Money? Do you want Money * Money to be disallowed? Do you want Money / Money to produce Numeric? Do you want Money / Numeric to produce Money? Do you want Numeric / Money to be disallowed?

This is the kind of thing you want C++ functions for, but C++ is such a bear in other respects. So, our thoughts turn to Ruby and Python.

In Ruby, you have to stuff way too much of this logic into one overwrought Money#coerce method plus some classes (or object singleton methods) that do nothing but raise errors. And good luck finding a decent lesson on this in a Ruby tutorial or book. (Note to self: Write this up, Elizabeth!)

Even though Python math methods __add__, __mul__, etc. are plain ol' instance methods like Ruby's +, *, etc., Python brings peace and sanity by letting you also define "right associated" math methods __radd__, __rmul__, etc. Maybe one reason why Python is popular among scientists and engineers is, you can define your special math such that It Just Works.

Appendix B of How To Think Like a Computer Scientist: Learning with Python gives a good introduction to the issues one needs to think through when defining a mathematical type. See also "Emulating numeric types" in the Python docs.

Barbie says, "Operator overloading is hard. Let's go shopping... for Python."

Dave Kirby said...

Elizabeth wrote:
"(There's something different about block arg splatting in Ruby 1.9, and I don't know how this &method trick behaves beyond 1.8.6.)."

I get the impression that Ruby is very unstable as a language - both the language and libraries can change in arbitrary ways between releases in ways that may break existing code.

Python is much more stable - most 1.5.2 code from ten years ago will run unchanged on the latest version, and language changes that may not be backwards compatible are introduced gradually using "from __future__ import ...". Libraries are deprecated for a LONG time before being removed.


A recent blog post by PragDave (http://pragdave.blogs.pragprog.com/pragdave/2008/04/ruby-19-standar.html) lists changes to the Ruby libraries for 1.9. There are an awful lot of libraries that have been removed - what happens to any code that uses them?

Python is saving any changes that introduce major incompatibilities for 3.0 (aka Python 3000). This has been planned for years and there is a clear upgrade path, including tools to do automated conversions.

Anonymous said...

Dave wrote: "I get the impression that Ruby is very unstable as a language - both the language and libraries can change in arbitrary ways between releases in ways that may break existing code."

Here's a choice bit from PragDave on March 18, 2008: "Just when I thought I'd finished documenting the standard library for the new PickAxe, I did one last svn up of the Ruby interpreter source and discovered that the Complex and Rational classes are now builtins--no need to require the library to get the basic functionality. [...] Unfortunately it's back to the drawing board on my plans to release a new beta [of the Pickaxe] today..."

It appears that even Prag Dave, author of Ruby's English Bible, I mean the Pickaxe, gets no warning of the changes. He has to stumble upon them by studying svn diffs every few days.

I seriously wonder about the wisdom of writing a Pickaxe for Ruby 1.9 anyway. By Ruby convention, a version whose second number is odd is an "experimental" version not intended for production use. Add to this the fact that Ruby 2.0 is rather akin to Python 3000 in that Ruby 2.0 is Matz's "wild" and "fun" idea of breaking backward compatibility. Ruby 1.9 is just sort of practice along the way.

So I think of 1.9 as a fluid, specless spec of what 2.0 will be. I have no idea whether the Japanese community has clear goals for 2.0 spelled out somewhere. (I kinda doubt it.) In any case, the English community seems to be stuck wandering the blogosphere and diffing 1.9 code to get a clue what 2.0 will be.

Yeah, migration to Ruby 2.0 is mighty ad hoc compared with migration to Python 3.0.

Jake said...

@dave and @elizabeth:

How exactly is Dave's example of:

>>> x = ['abc', [1,2], () ]
>>> map(len, x)
[3, 2, 0]

better than:

irb> x = ['abc', [1,2], [] ]
irb> x.map {|one| one.length rescue nil}
=> [3, 2, 0]

Dave Kirby said...

Carrying on from Elizabeth's last post about not knowing what changes are going on in Ruby...
One of the things I like about Python is the Whats new in Python x.x section of the docs - I can find out in one place what has changed between versions of the language, and what will change in the next version (since it is updated frequently during development). There are also the PEPs where proposed changes are posted up for discussion and refinement (or rejection), so I can read the rationale for each change and even the changes that were proposed and rejected.

I first tried Ruby years ago when the first edition Pickaxe book came out. I though it was a nice language, but did not have any strong advantage over Python and was still immature. I have gone back and looked at it occasionally since then, and tried to find out what has changed in the later versions. I searched for a definitive doc that would tell me - the equivalent of Python's "What's new", but with no success. I guess that if even the leading Ruby author does not know what changes are going on in the language, then such a doc is unlikely to exist.

It feels to me that it is not just the language that is less mature, but also the development process.

Anonymous said...

Jake:

I'd say map(len, x) is no better, in principle, than x.map {|one| one.length}. It's just different. :-) But your question of April 14 highlights few "features" of Ruby in my mind: TIMTOWTDI, the differences between Ruby blocks/procs/lambdas, the lack of a language spec, and a phenomenon I call "Look-it! Look-it!"

Many Ruby built-in classes have both length and size methods, which are synonyms. You and I might be accustomed to calling x.map {|one| one.length}, and Joe Blow might be accustomed to calling x.map {|one| one.size}. That's okay until you and I define a class and give it a length method but not a size method. Meanwhile, Joe Blow defines a class and gives it a size method but not a length method. Now x.map {|one| one.length} and x.map {|one| one.size} potentially bomb depending people's TIMTOWTDI habits and expectations.

If you and I and Joe Blow were programming Python we'd all be on the same page because of the One Way To Do It, namely len with __len__(). An ancillary point, I know, but something to think about. (And I see Woodie in the next article discussion approaches this point from a different direction, encouraging the use of something like a Java interface to force the class implementer to provide a specific method so that everyone knows what to expect.)

As for my block/proc/lambda, spec, & Look-it thoughts, I need to do more thinking and research (and get some uninterrupted time) before writing about them so that I'm not just a cranky, old nincompoop spreading misinformation and FUD. :-)

AkitaOnRails said...

Again, a bunch of non-sense.

Let's sort it out. First of all, yes, Ruby's documentation is lacking at best. Ruby was mostly unknown until Rails appeared in 2005. So Ruby is speeding up very fast ever since and the community is doing what it can to fill in the gaps - instead of moaning like little babies.

So, instead of doing exactly what you all are doing (complaining), lots of people are doing what they can to improve things.

Case in hand: JRuby, IronRuby, Rubinius, MacRuby, and others. One big thing that came out from Rubinius: the RSpec-based Ruby (VM and Standard Lib) test suite, that not only serve as the test bed for all other implementations but will also be useful as an starting point for better and more organized documentation. This week, all of them asked for it to be blessed by Matz and they are in discussion as to how to do this transition.

Performance, threads, garbage collector, etc etc are all being attacked by the alternative implementators and MRI itself. They are relentless. JRuby opened the way for Jython to finally come back. IronRuby was really useful for the DLR team to clean up the mess after IronPython. Lot's of people think that following Python is the same as following any dynamic language. Then they try to implement something really dynamic like Ruby and the foundation starts to feel shaky. Not anymore.

People want something more 'pure'? Turtles all the way? Rubinius is quickly becoming the smalltalkers dream come true. It is not far fetched.

Libraries. Yes, all of those that are really used are being maintained, cleaned up and so forth. We do have very good libraries. Not nearly as comprehensive as Perl's CPAN, that's for sure. But we have enough to keep us busy. We are pushing new stuff like Git. We are pushing Agile, BDD. Martin Fowler is following. Tim Bray is following. Sam Ruby is following.

Then. Odd version number scheme is not an exclusivity of Ruby. Most open source projects do just that, Linux included. So kernel 2.7 will be experimental, 2.8 will be stable.

All that said. I wouldn't pick a fight against Python right now. It is faster. It has better documentation. It is robust. Is has Google supporting it. It is more widely used, and it is also clever in many ways.

Both Python and Ruby are moving targets. There is no point in comparing them. This is an open sourced world. You want to complain to a supplier? Go use C# and complain to Microsoft. Here we have the law of Quid pro Quo, remember?

Ruby and Python are brothers. They are our sons. They are different in their own regard but we should love them both for what they are. No need to bring Python stuff forcefully to Ruby and vice-versa. You don't think like that? You don't belong to the open source community.

I would pick the best tool for the job and that's it. Even PHP and Perl are still widely used and evolving. They both have lots of merit. It is just too easy to pinpoint perceived flaws. It is another thing entirely to do something useful.

Brian said...

I really think it's quite surprising that no-one has mentioned the whitespace thing.
I, for one, loved it when I first used python. But over the course of a coupe of years of usage, I found that it was a horrible drawback - it's brittle as all hell. Sending code in an email, pasting it over IM, using the wrong pasting service, pasting in IRC, loading someone else's code who uses tabs instead of spaces, or vice versa, or someone that uses a different tab-stop, etc, etc. It dawned on me, that it's one of these things that must have seemed like a great idea at the time, but the rest of the world is incompatible, and so it often becomes a major pain in the ass.
I know there are conventions to prevent these things, but you can't get around the fact that python code is a lot more sensitive to what channels and people it passes through because of the whitespace thing.

After having used python for all the small-tool needs I had for a couple of years, I started using ruby - it took me two weeks to get more proficient in ruby than I was with python. I was shocked.
It's like the language just behaved like I expected - I hardly ever have to look anything up, because it just works like I expect from previous experience with other languages and the unix command line.

I still like and respect python, but for most anything I do, ruby gets it done quicker with less doc-lookups for me.