Skip to content

Between thought and expression

November 21, 2009

Comparing computer languages can usually be interesting, sometimes informative, often amusing and in lots of cases just damn annoying!

Still this recent Hacker News post about Python vs Clojure did catch my eye.

Despite the fact the author of the blog post had pulled the Python code from answers to Project Euler the pythonista’s quite correctly cried foul because it wasn’t well written idiomatic python example and so was an unfair comparison.

There’s a lot of code out there posted on those intertubes over the years. However languages and practises evolve but unfortunately intertube posts can remain set in stone! Perl is often weighed down by its past history on the intertubes. One good way forward is just to produce more Modern Perl posts.

Anyway i digress, so moving on lets take a look at the Euler 4 – Finding Palindroms. This was the Clojure example that was put forward in the blog post:

(reduce max
    (filter #(let [s (str %)]
               (= (seq s) (reverse s)))
            (for [x (range 100 1000)
                  y (range 100 1000)]
              (* x y))))

Now in reply to this a much more idiomatic python example was provided:

print max(s for s in (x * y 
    for x in range(111, 1000) 
    for y in range(x, 1000))
    if list(str(s)) == list(reversed(str(s))))

This uses Python’s list comprehension. Definitely a very powerful construct. However i do find i get lost very quickly when trying to follow long nested comprehension’s 😦

In this same Python post there is also mention of a twitter post by Yukihiro Matz, the creator of Ruby. Matz provided the following Ruby example:

p [*100..1000].product([*100..1000]).map{|x,y| x*y}.select{|s|s=s.to_s; s==s.reverse}.max

Despite being formatted for twitter (ie. one line) i found it easy to follow through the logic.

Ruby & Python are not the only languages that can produce an elegant solution! So not to be out done here is a Perl example. In fact its the exact same code repeated three times but formatted differently:

use Modern::Perl;
use List::Util q(max);

# twitter one liner
say max grep { $_ eq reverse $_ } map { my $x = $_; map { $x * $_ } 100..1000 } 100..1000;

# again in lispy style format
    grep { $_ eq reverse $_ } 
      map {
        my $x = $_;
        map { $x * $_ } 100..1000;
      } 100..1000;

# and finally in my preferred more perlish alignment
say max 
    grep { $_ eq reverse $_ } 
    map {
        my $x = $_;
        map { $x * $_ } 100..1000;
    } 100..1000;

The perl code speaks for itself.. its wonderfully clear and succinct. Also its fast, each version runs in under a second on my machine!


6 Comments leave one →
  1. Michael Peters permalink
    November 23, 2009 2:37 pm

    Just to confirm your findings, the python example took about 2.5 seconds to run on my machine (python 2.6) and then Perl example took less than .5 seconds (perl 5.8.9). And I couldn’t get the ruby example to run (I’m guessing it didn’t work on 1.8.6).

    • November 23, 2009 2:53 pm

      Hi Michael,

      I didn’t bother testing it with Python from here because the Python that ships with Mac OSX Tiger is notoriously slow for some reason and it wouldn’t have been fair to compare it to the Perl times (which comes in on average at 0.85 secs using my own compiled 5.10.1 here).

      The Ruby example requires 1.9.1. Don’t have that or Clojure loaded here but based on times given in the blog posts it doesn’t look likely that they will beat the Perl times.


    • December 1, 2009 9:52 am

      I have Ruby 1.9.1 installed now and the code comes in at 1.2s here. Thats identical to the autobox example I gave in my other post, so not bad at all! (for both autobox and Ruby 1.9.1 !!)


    • February 11, 2012 2:28 am

      Yes, you’re right. But I psaoenrlly consider arrays and hashes to be data structures, not primitive data types.


  1. Tweets that mention Between thought and expression « transfixed but not dead! --
  2. Euler, Euler, Euler, Oi, Oi, Oi! « transfixed but not dead!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: