Between thought and expression

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 say max 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!

/I3az/