

Python vs Ruby, slightly more in-depth - edw519
http://rapd.wordpress.com/2009/07/13/python-vs-ruby-slightly-more-in-depth/

======
ovi256
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...](http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/)

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

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...](http://www.infoq.com/news/2009/06/macruby-drops-gil-threading)

~~~
dkersten
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.

~~~
ajross
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.

~~~
dkersten
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. """

------
nudded
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.

~~~
Torn
+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._

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

~~~
Xichekolas
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.

------
jamesbritt
"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.)

~~~
didip
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.

~~~
jamesbritt
"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.

~~~
didip
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.

------
trop
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.

------
FooBarWidget
"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.

~~~
jrockway
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.)

------
chriseppstein
> 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.

~~~
didip
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.

~~~
bmelton
Not that big a deal != evil.

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

huh?

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

Python decorator does not do that?

~~~
tetha
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.

~~~
didip
Python decorator can do more than just that.

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

~~~
tetha
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.

------
davepeck
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.

------
jerf
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.

------
wooby

      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.

------
xtho
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").

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

~~~
didip
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.

------
ovi256

      Both still needs javascript to make awesome looking web applications.
    

Not so much "looking", as js would not help with that, but working, yeah.

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

~~~
projecktzero
Are you talking about Pleac <http://pleac.sourceforge.net/>

~~~
ivanyv
That's it! Thanks!

