Hacker News new | past | comments | ask | show | jobs | submit login
Python vs Ruby, slightly more in-depth (rapd.wordpress.com)
52 points by edw519 on Aug 4, 2009 | hide | past | favorite | 56 comments



He mentions Python's GIL (which makes multi-threading completely useless), but Ruby (even 1.9) has a GIL too [1] that works exactly the same (awful) way. Ruby 2.0 will have it too [2]. A new Python implementation, unladen swallow is developped by Google to adress exactly this issue. Python-stackless avoids this problem, but the paraigm change is huge, 'normal' code has to be largely rewritten for stackless.

Note that, if I correctly understood, python event engine Twisted uses a custom C-implemented event loop to avoid this.

[1] http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ru...

[2] http://groups.google.com/group/comp.lang.ruby/msg/e809a7a720...

Wow, seems like MacRuby uses OS threads and completely abolished the GIL [3].

[3] http://www.infoq.com/news/2009/06/macruby-drops-gil-threadin...


The GIL (in Python, can't speak about Ruby) is a controversial issue because people assume its bad and Python is therefore bad at concurrent programming etc. Without the GIL, the implementation would be drastically more complex and slower because all built in datatypes, dictionary lookups (for method lookups) etc would need to be made atomic, through locking. I think I can live with the GIL in this case - use threads for asynchronous (rather than parallel) code and use processes (and Python 2.6's multiprocessing library makes this easy) for parallel code execution.

Having said that, I welcome Google's unladen swallow and hope they succeed in removing the GIL.


That's not strictly true. Take a look at http://plausible.org/nasal for an example of an interpreter (mine) in the same broad space as Python and Ruby, yet without a global lock for anything but garbage collection (fixable -- there's no reason in principle preventing a concurrent GC from being dropped in). In tests of CPU-bound code without excessive allocation, it scales to 4-way SMP without trouble.


Sorry, I meant in Pythons case. Obviously theres plenty of virtual machines/interpreters/compilers which do not have a GIL and work perfectly fine.

Here are some of the reasons Python uses a GIL: http://www.grouplens.org/node/244#comment-2493

Pasted for convenience:

""" Python has a GIL as opposed to fine-grained locking for several reasons:

--- It is faster in the single-threaded case.

--- It is faster in the multi-threaded case for i/o bound programs.

--- It is faster in the multi-threaded case for cpu bound programs that do their compute-intensive work in C libraries.

--- It makes C extensions easier to write: there will be no switch of Python threads except where you allow it to happen (i.e. between the Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS macros).

--- It makes wrapping C libraries easier. You don't have to worry about thread-safety. If the library is not thread-safe, you simply keep the GIL locked while you call it. """


"Python-stackless avoids this problem"

Not really. Stackless Python still has a GIL, and if you want to make use of multiple threads, the GIL will still bite you.

Stackless allows you to write coroutines and has lots of cool abilities, but avoiding the GIL is simply not one of them as far as making use of multiple cores.


FWIW, JRuby does not have a GIL, plus you get to use java.util.concurrent.* classes in your Ruby code.


Jython doesn't have a GIL either. Nor does IronPython.


Why is everyone so concerned with multi-core concurrency withi languages like Python and Ruby? Adding another processor will get you, best case, a 2x speedup. Rewriting in, say, OCaml or Haskell will get you a 25x speedup.

25 processors buys you a lot of programming time.


Adding another processor to my computer is quick and easy. Rewriting an application in another language is slow and hard.


I quite hoped to be reading an in-depth comparison, but this article merely scratches the surface. What I would like to see from an in-depth article is actual code implementing stuff, showing the features a language has (and comparing them with each other).

I don't think this is a good article nor a useful one.


+1, the article is a 10-minute gloss at best and has virtually no content or analysis.

I mean come on, just look at the 'conclusion': These languages are interchangeable, especially for building web application. Neither are more awesome. They get the job done and they make programmers happy.


Having used both professionally, I think that's a pretty good conclusion, actually.


I'd agree with the conclusion, but I'd also agree with nudded - the article is nearly free of useful content. Listing popular libraries of each language does not a comparison make.


It's a fair (and quite reasonable) conclusion but the article in no way supports it.


In fact, Python and Ruby both are very high level, multiparadigm (oop, procedural, functional, ...) dynamic languages and the difference between them is pretty small. One is a bit more perlish, and one is focussing on a clear, deterministic syntax. Thus, I think the conclusion easily generalizes.

As one wise man once said: Wether you prefer Python or Ruby depends mostly on which one you met first.


It is intended to be a gloss over of functionality that I use frequently. If I want to write much more in-depth comparison then I would have written these (which I may in the future, these kind of blog post takes time to write):

* Beautiful Soup vs Nokogiri/HPricot * Fabric vs Vlad * Paste vs Mongrel performance using proxy pass behind Nginx * (I am not going to write Rails vs Django)


The conclusion isn't wrong, but the content is weak for the evaluation.

At this point in the Ruby VS Python conversation, my expectations for an evaluation are benchmarks of code that is algorithmically identical. If one language provides for a better algorithm than the other, I'd like to see those differences as well.


Also he's rather overlooked that the web is a tiny corner of the Python world. Ruby has nothing that's even close to NumPy/SciPy.


Poster here,

I intentionally downplay what Python has to offer. It is true that Python has greater breath than Ruby in terms of communities, especially outside web world.

If I started to mention those, it will make Ruby looks less capable (or I would naturally skew the article biased towards Python).


Hopefully you recognize that you misrepresented Ruby throughout the post, in some parts quite dramatically and strangely; the "Modules (for Web Apps)" section is a remarkable mess, listing a random handful of libraries, some of which have nothing directly to do with web development, some of which are components of others, and all representing only a fraction of what's available.

I also see that you were apparently unaware that lambda exists in Ruby until someone in the comments told you, which makes me seriously doubt that you've even used the language at all.

Googling around for info on a language with which you have limited or quite possibly no experience is not a basis for purporting to present an "in-depth" comparison, nor does it qualify you to make claims about capability of a language.


If you read both paragraphs in the Web App section, I made almost immediate comparison between the two:

* (Django, Pylons vs Rails, Merb) * (web.py vs sinatra) * (Beautiful Soup vs HPricot) * (Paste vs Mongrel) * (Moneta vs Shove) * (Psyco vs RubyInline)

I would defend myself and say that all these modules are useful for web development. For example:

* You never had to scrape other site's HTML and parse the elements for useful information?

* You never curious about hot-and-shiny key value databases for work?

* You never felt like a certain function could have been optimized and make your web app faster?

Especially in these two paragraphs, I actually use all the ruby modules I mentioned in those paragraphs (minus merb & DataMapper), and I use all the Python modules mentioned as well.

For other non-web related or modules that I haven't use frequent enough, i set it aside and "downplay" it in the article.

Lastly, no amount of blog post could do justice on these two languages. The best way to know about these languages is to use it to hack on something.


"I would ... say that all these modules are useful for web development."

It's very unusual for a web developer to work directly with RubyInline. It's quite a stretch to classify it as a "web development tool" or significantly related to "Web Apps."

"I made almost immediate comparison between the two"

It's not even close, though. The Ruby analogue to WSGI and Paste is Rack, not Mongrel. RubyInline and Psyco are very different things. HPricot is one of multiple options for HTML parsing in Ruby (nokogiri, scrapi, scrubyt). There are multiple JSON options for Ruby (including yajl bindings), and half the paragraph is about simplejson vs python-cjson, which has nothing to do with Ruby. There are also multiple Ruby templating systems available (erb, erubis, haml, markaby, liquid), but you only mention python templating enigines.

And all of these are just a small subset of libraries that you can have in a typical web app, such a small subset that they aren't really representative of anything.

"You never curious about hot-and-shiny key value databases for work?"

There are a whole slew of libraries for "hot-and-shiny" data stores (there are at least 5 Ruby libraries for couchdb alone) and it's not uncommon for people to roll their own. I don't think shove even supports anything "hot-and-shiny" like couchdb, tokyo, cassandra, etc.

"The best way to know about these languages is to use it to hack on something."

This is very true.


Why is this downmodded to -2?

"intentionally downplay" is a bad choice of words, sure, but I think he means "am only comparing web stuff". Most web developers do not care about SciPy. Most research scientists don't care about web frameworks.

(Edit: and this is downmodded too? Did Programming Reddit change their color scheme again?)


Well, I downmodded that comment because I took it as the author saying he'd deliberately left out information so as to support the conclusion he wanted to reach. Which is both dishonest and at odds with the stated goal of an "in-depth" look at the languages.


You seemed to be missing the word slightly in the blog title =)


Thank you for clarifying, I am indeed only comparing web development tools.


The PLEAC codebase was new to me. It reminds me of the idiomatic python reference (http://python.net/~goodger/projects/pycon/2007/idiomatic/han...) I've found very useful, but haven't delved into PLEAC to see if the coding examples are truly idiomatic.

Python > http://pleac.sourceforge.net/pleac_python/index.html

Ruby > http://pleac.sourceforge.net/pleac_ruby/index.html

Coverage varies depending on the language.


"Reflection a.k.a Meta Programming a.k.a Monkey Patching"

Really? These are all the same thing? I think not.

"Python comes with webbrowser, urllib2, smtp, http, SocketServer, HttpServer, and more, while Ruby only has net/HTTP"

Untrue. Seems the author knows Python, and spent a little time with Ruby.

More useful points to make would have been how objects are implemented, how inheritance and mixins are handled, and the key paradigms in the language (e.g., in Python, foo.bar() means invoking the method bar; in Ruby, it means sending foo a bar message.)


Agreed. Reflection != metaprogramming != monkey patching. They are loosely related, but FAR from being the same thing.


That is correct, they are not the same thing. That statement is coming from my use case, where I, have so far, only use them for manipulating objects during run time.

Be it calling function, setting attributes, or adding extra functionality by including modules.


"That is correct, they are not the same thing. That statement is coming from my use case, where I, have so far, only use them for manipulating objects during run time."

So here's my main complaint: If you know that these things are not really the same, why do you present them as if they were? You would have had a much more favorable reaction had you been more upfront on your biases, limited Ruby experience, and narrow focus for comparison.


Because in my eyes, they all serve this purpose: "That means you have access to the inner working of an object."

Whichever technique I choose to use does not matter.

I am using my blog the way blog is intended to be used, as opinion piece, I had no attempt in hiding my biases, but there's no need to purposely be biased as well because I like both and make a living out of both.


RE daemonizing, Ruby 1.9 does have a nice Process.daemon function (this is what the author is hoping for?). I'm also a big fan of the 1.9-introduced spawn() function. Not only does this make it easy to create background processes, but via its :in, :out, and :err options (also now found in system() and exec()) it's pretty easy to pipe one spawned process's output to another.

OTOH, I'm a big fan of the What's New in Python X.X articles. Nice features like spawn() seem to sneak into the Ruby codebase unheralded and practically unnoticed.


"Testing Ruby wins a lot of TDD practitioners. There are plethora of Ruby modules created for making testing experience truly wonderful. See: RSpec, Shoulda, Factory Girl, Selenium."

Yes, testing in Ruby is absolutely wonderful. It makes writing tests an enjoyable experience compared to pretty much any other language I've used. Nowadays I strive for 100% C0 testing coverage and near-100% C1 testing coverage whenever I write software. This can be done very easily in Ruby but is hard to very hard in most other languages.


It's very easy in Perl.

But anyway, "100% code coverage" is very misleading. Sure, every branch might have been executed once, but you don't ensure that every combination of branches executed once. If you have state that can be shared between code paths, then you are not doing an adequate job testing.

(This is why people like functional programming. One input always produces the same output, cutting the number of cases you have to test dramatically.)


Writing tests is only good if people actually run them.

The default configuration for RubyGems doesn't run unit tests. Therefore unit tests provide a sophisticated check for, "Works on my machine" but isn't so helpful for getting good bug reports about what doesn't work on other people's machines. By contrast the default configuration for Perl's CPAN runs unit tests before you install anything, and this has been the default for Perl modules since the last millennium. (Actually unit testing has been part of Perl culture since 1987! Yes, the "make, make test, make install" idiom was in the first release of the Perl core. This was over a decade before Kent Beck began popularizing the idea for a broader audience.)

And it doesn't end there. For instance the Ruby world has no real equivalent to CPAN Testers. That's a distributed group of people who run all of the unit tests on all of the CPAN modules on different platforms and make publicly available reports of success/fail. That project runs nearly a half-million test suites per month. Which makes it possible to do things like dependency analysis on CPAN modules to track down who is causing what other modules problems. See http://ali.as/top100/.

In short I'm glad that you're doing unit testing and like the tools that Ruby offers for it. However if you're open to cross-pollination, there ARE things you can learn about unit testing from other language communities. Some of them might be great additions to Ruby.


> eval()/exec() are simply evil in both languages. They make debugging more difficult.

I stopped reading at this point. More complicated debugging is a reasonable tradeoff for intuitive APIs. To call them evil indicates the OP is quite inexperienced.


This suggests an important difference in the cultures around the language.


That statement comes from personal experience where some functions did not exists in the eye of text editor because they were defined inside a string.

Not that big of a deal, but enough to annoy me.


Not that big a deal != evil.


I'm currently working on a python web project; the lack of a mature, battle-hardened payment library kills me.

Ruby's ActiveMerchant is a well-crafted bit of code. The handful of python contenders I've discovered are (1) immature and often poorly coded, and (2) unable to touch ActiveMerchant in terms of number of supported gateways and features supported per gateway.


> Decorator is Python’s implementation to visitor pattern...

huh?


Visitor patterns add new functionality to existing object structure [http://en.wikipedia.org/wiki/Visitor_pattern].

Python decorator does not do that?


The decorator syntax

  @decorator2
  @decorator1
  def foo(*args):
      pass
is just a shorthand for

  def foo(*args):
      pass
  foo = decorator2(decorator1(foo))
I completely fail to see the visitor pattern here, even with stretching until breaking.


Python decorator can do more than just that.

@decorator1 can be a completely different class which manipulate foo.__class__


Certainly, it is an arbitrary python function, so the resulting foo might be a dictionary or whatever. But this doesn't push it closer to the visitor pattern.

Certainly, you can use decorators as a tool to implement the visitor pattern by implementing some hairy, magical reflecting class-decorator which adds a method visit to an object, which then calls visit_{CLASSNAME} on the parameter, but this is just a way of implementing this and not the visitor pattern in itself.


I think it's pretty clear that one person isn't going to be able to write the article we're all actually looking for. We need to get two experts together, one in each language, and in the spirit of respect and discovery, have both people put their language's best foot forward, to try to "get" the other language but to not descend into endless wankery about the details.

But, honestly, I know how it would turn out: The technical considerations are not all that different. Most people who bitch about one of the two and praise the other seem to not understand the one they are bitching about, and the pattern is strong enough at this point that it should be considered the norm. I'm tired of Ruby advocates who seem unaware that yes, Python can pass functions as first class arguments and yes, that pretty much is a block, and tired of Python advocates who get shredded in the comments for obviously having only gone through a Rails tutorial.

In the end the big difference is community. I think there is a big difference there. I'll skip igniting a flamewar by trying to characterize the communities, since it is impossible to do that neutrally, but there's definitely a difference I can see.


The comparison is slightly tendentious in that the info on ruby isn't always up to date (eg "Modules" and "HTTP and other Internet stuff").


  Python                 Ruby
  map                    collect,map
  lambda                 block
  filter                 select
  ?                      reject
  reduce (functools)     inject (native)
Guido van Rossum on inclusion of 'reduce' in Python 3.0, in 2005:

"This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly" (http://www.artima.com/weblogs/viewpost.jsp?thread=98196)

Ruby lets you do it however you want to. I don't see myself learning Python any time soon.


He neglected to mention Python's lack of anonymous functions. (and no, lambda doesn't count given its restrictions).


Functionality that I do not mention means that I don't have to use them often, both for work or personal projects.

I don't miss anonymous functions that much, yet, because I have inner function and list comprehension in Python.


  Both still needs javascript to make awesome looking web applications.
Not so much "looking", as js would not help with that, but working, yeah.


There's this site where you can compare implementations of several patterns in different languages... If only I could remember where... anyone?


Are you talking about Pleac http://pleac.sourceforge.net/


That's it! Thanks!





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: