The Last of the Careless Men blog kindly referred to my Euler blog post from last week.
The blog post brought to my attention the Euler Benchmark Suite. To quote from the Readme:
The Euler Benchmark Suite aims at comparing language speeds for the Euler
So I was curious to see what Euler 4 in Perl5 looked like.
use strict; use warnings;
my $max = 0;
for my $a ( 100..999 ){
for my $b ( $a..999 ){
my $product = $a * $b;
$max = $product if $product > $max
and $product eq reverse $product;
}
}
print "$max\n";
At first glance this doesn’t look as “elegant” as the functional code I posted last week.
However remember this code was optimised for speed! It comes it at 3.5 times faster than even this slightly more optimised version of last weeks functional code (see below, which now comes it at around 0.48s here):
say max
grep { $_ eq reverse $_ }
map {
my $x = $_;
map { $x * $_ } $x .. 1000;
} 100..1000;
Another thing of interest from the blog post was the Perl6 example. Like with Ruby example its definitely easier to grok things going in a chain from left to right, ie. just like how we read english text.
autobox to the rescue!
use autobox::Core;
[1..1000]->map( sub{ my $x = $_; map { $x * $_ } $x..1000 } )->grep( sub{ $_ eq reverse $_ } )->max->say;
Not bad. And comes in at respectabe average of 1.25s. However having that extra map within the map method is not too elegant.
Luckily autobox is extensible! So lets add a Cartesian Product method to autobox:
use autobox::Core;
sub autobox::Core::ARRAY::product {
my $a = shift;
my @c = map { [ $_ ] } @$a;
for my $b (@_) {
@c = map { my $x = $_; map { [ $x, @$_ ] } @c } @$b;
}
return \@c;
}
[1..1000]->product( [1..1000] )->map( sub{ $_->[0] * $_->[1] } )->grep( sub{ $_ eq reverse $_ } )->max->say;
Now thats really nice. Now if future versions of Perl can provide a mechanism to allow for blocks (ie. anonymous subs) to passed more seamlessly, say like
[1..1000]->product( [1..1000] )->map(){ $_->[0] * $_->[1] }->grep(){ $_ eq reverse $_ }->max->say;
# or even
[1..1000]->product( [1..1000] )->map{ $_->[0] * $_->[1] }->grep{ $_ eq reverse $_ }->max->say;
Then we’re really cooking!
/I3az/
This post is in memory of Colin. My Father-in-law and a fellow blogger who suddenly and unexpectedly passed away yesterday. RIP
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/
Well if you hadn’t heard of Stackoverflow when i mentioned about it last month then chances are you’ve definitely not heard of RefactorMyCode either.
Its yet another interesting and engrossing site which I stumbled across in the past year, funnily enough after hearing about it from an answer to a Stackoverflow question.
The premise of the site is if you have some working code that you’re not totally happy with then offer it up for code review with the hope someone can help refactor it.
The Perl section could do with some more input and engagement. But don’t just stop there because seeing how snippets of code in other languages are refactored is also a good learning experience.
/I3az/
Following on from my last post it seems I have also been waiting for a kind of virtual conjunction between Perl 5.10.1, Parrot 1.0 & Padre being a year old.
Perl 5.10.1
Currently I run 5.8.8 in production on all servers that I manage. I do have Perl 5.10.0 running locally on my Mac but only for playing with.
So first step is to load Perl 5.10.1 on my Mac (Tiger) alongside my other Perl’s and then start testing & with the plan to roll it out to replace 5.8.8 in the not too distant future.
These are my steps to load 5.10.1 locally so that it doesn’t conflict with any other Perl I have here:
- Download & unpack Perl source code in my normal user login
- perl Configure -de -Dusethreads -Dprefix=~/local/Perl/perl-5.10.1/
- gmake
- gmake test
- gmake install-all
I now have Perl 5.10.1 running out of my $HOME directory.
This all worked fine except the default location of .cpan directory was in $HOME (~/.cpan). This could clash with other locally installed Perl if nothing is done so I amended everything in cpan shell to use ~/local/Perl/perl-5.10.1/.cpan instead (I did this using “o conf”).
I then quickly blasted my new local Perl 5.10.1 with a few CPAN modules which included:
- Moose
- MooseX::Declare
- autobox::Core
- DateTime
- XML::LibXML
- Devel::REPL
All modules I selected installed without a single hitch. CPAN comes up trumps again!
Devel::REPL was of great interest to me because when I last tried to install this on 5.8.8 & 5.10.0 I did have some problems.
This time it installed & worked wonderfully. Only slight issue was there was no command line history? (ie. readline). This was easily resolved by loading Bundle::CPAN (which also gave cpan shell history as well!)
Padre
Normally I don’t compile Perl with threads. However I needed it for Padre, which is something I forgot about when I last tried installing Padre on my local 5.10.0
I installed the following CPAN modules into my new Perl 5.10.1:
- Alien::wxWidgets
- Wx
- Padre
All compiled & installed seamlessly. On starting Padre I got a nice pretty butterfly splash screen but then unfortunately it crashed
As with most things in life if you not starting off with a clean slate then it may cause problems. I had some residue stuff from previous attempt that was part of the problem.
Two things were needed resolve this stumbling block:
- Remove WxWidget which was installed via MacPorts (
sudo port deactivate wxWidgets) - Make sure new Perl 5.10.1 was first Perl in $PATH env variable. Because even though I was running 5.10.1 CPAN shell the Wx module seemed fixated on picking up Alien::wxWidgets from the first Perl it could get its hands on
After this reinstalling the Wx & Padre modules gave me a fully functional Padre.
Parrot 1.0 / Rakudo / Perl6
I was now using Padre 0.48 to edit & run my Perl 5.10.1 code. Want I wanted now was to add Perl6 into the mix.
For this I just followed the instructions from Rakudo site and installed it in my local user dir with no hitch at all.
Next in Perl 5.10.1 I installed the Padre::Plugin::Perl6 to make Padre Perl6 aware. My first bit of Perl6 code ran from Padre & command line perfectly (don’t forget to add your rakudo path to $PATH env):
use v6;
for 1..10 { .say }
class Dog {
method bark { "woof" }
}
my Dog $rover .= new;
my $spot = Dog.new;
say $rover.bark;
say $spot.bark;
So where do I stand with Padre? Well I do love my Textmate so it is going to be hard to tug me away from it.
But I love the idea of an editor being hosted and extensible in Perl. So come my next round of free time I may find the tugging from Padre just to strong to resist
/I3az/
For about a year I’ve put off replacing my Apple iMac with a Mac Pro until Snow Leopard arrived.
But thats nothing because I’ve been hanging on to my old, tired and very battered Sony Ericsson mobile phone while I’ve been waiting for the iPhone to eventually come to my mobile phone network
Waiting looks to have paid off because the new 27inch iMac with the Nehalem processors certainly look sweet. I even got to play with magic mouse at an Apple store the other day and have to say first impressions were very nice.
So new iMac will be a nice Xmas pressie
The iPhone is a few months off yet but I can hold on a bit longer
The temptation to buy a Google Android phone was strong though. It came close especially when Google announced that Perl was available for it.
Gosh having Perl on a “mobile” device brings back memories. I had Perl running on my Psion Revo PDA back in the day.
Unfortunately no Perl on the iPhone thus far… unless its jail broken!
Still perusing the iTunes App Store does show up a few things Perl. O’Reilly have “ported” quite a few of their books to the store.
Amazingly i am still an app virgin on my iPod Touch! So I thought I’d give it a go and purchase Perl Pocket Reference app.
I can’t say its this e-book is going to set my world alight but for £1.79 I couldn’t really go wrong and you will never know when it will come in handy.
/I3az/
When I started this blog my “ideal” scenario was to post weekly. However my “pragmatic” operand was to at least post every month.
So with a broad grin of achievement I see that yesterday I passed the milestone of posting a blog entry on every single month for a whole year!
Always nice to give one self a little pat on the back from time to time. But I also have to thank Perl Iron Man for providing the required stimulus at the right moment
I’ll try not to rest on my laurels so I will see if I can raise the gears up a few notches over next few months (surely I can become more than a paper man!).
Before I go a couple of recent blogging changes that I can’t take any credit for whatsoever are:
- WordPress syntax highlighting as changed again. Perl code is now is a more subtle nicer looking font
- iPhone / iPod Touch users will now see a tailored rendering of this site. Looks very snazzy.
/I3az/
A couple of weeks ago I was pleasantly surprised by being 10th person to receive a Perl badge on Stackoverflow
Slipping in at number 10 with such other celebrated Perl names if indeed an honour. *blush*
Of course none of this will mean a jot if you’ve never heard of Stackoverflow.com!
Its a programming language question and answer site started by Joel Spolsky (of Joel on Software fame) and Jeff Atwood (of Coding Horror fame).
Its very similar in vein to Perlmonks except its for all programming languages and not just Perl and its also Q&A only. So no mediations, epiphanies or wandering off topic
You will need an OpenID account to start but once past that you will find the site easy to use. Just start asking or answering questions. You get up or down voted depending on the quality of your question/answer.
I do feel the site is more approachable than Perlmonks especially for beginners. Its also a good place to start when looking for a clear answer to a specific question.
So what’s in it for me?
Well you can just view it as a game or challenge. Perhaps even treat it as a ladder to Rock and Roll stardom! Certainly nothing wrong with bit of ego inflating now and then
Or you can view it as a philanthropic pursuit by spreading things you learnt with others.
However the thing I get most from it all is that I’m continuing to learn new things. And in most cases its from my own answers! You can really enhance your Perl foo and improve your Perl memory muscles when trying to answer a question.
Disclaimer: It can get addictive. If you have a procrastinating nature then please avoid during the working day
So what’s in it for all of us?
Stackoverflow continues to grow. More and more programmers are getting sucked into it. Some of these are beginners or language toe dippers so the presence of good Perl questions & answers may benefit the Perl community in many different ways.
Here’s a good place to start: Perl tagged questions.
/I3az/
Well I’ve gone thru and amended all my previous posted code to use the new
Perl syntax highlighting. Yawn
My grandmother always told me I shouldn’t learn a craft or trade which relied on electricity
I think my sage advise to my future grandchildren will be:
Don’t use anything which cannot be easily munged with favourite programming language!
/I3az/
PS. I have just now noticed on CPAN some WordPress modules:
I’ll have to give these a closer look next time round
First the bad news. At some point last week all code previously posted here suddenly had all its comments converted into upper case
Now the good news. While looking into why WordPress syntax highlighter was suddenly doing this I re-tested to see if Perl had been added and lo and behold it had!
This is how a previous code looked using “ruby”:
# sourcecode lang="ruby"
{
package Anonyject;
use MooseX::SingletonMethod;
}
my @dingfirsts;
for my $line ( 1..10 ) {
push @dingfirsts, Anonyject->new->add_singleton_methods(
ding => sub { 'ding' x $line },
dong => sub { 'dong' x $line },
line => sub { $line },
)
}
for (@dingfirsts) {
say "First ", $_->ding, " on line ", $_->line;
}
Now Perl works!:
# sourcecode lang="perl"
{
package Anonyject;
use MooseX::SingletonMethod;
}
my @dingfirsts;
for my $line ( 1..10 ) {
push @dingfirsts, Anonyject->new->add_singleton_methods(
ding => sub { 'ding' x $line },
dong => sub { 'dong' x $line },
line => sub { $line },
)
}
for (@dingfirsts) {
say "First ", $_->ding, " on line ", $_->line;
}
WordPress must have updated this plugin last week. Hopefully they’ll fix the comment issue soon
Anyway the Perl code is so much nicer. The Ruby sigil variables were in bold which wasn’t nice on the eye. I’ll be updating all my previous posts to now use Perl highlighting very shortly.
/I3az/
On use Perl; the other day revdiablo asked whether there were Anonymous objects as easily as hashrefs? any where within Moose or sitting (hiding!) on CPAN.
Well the answers posted gave a yes for both Moose & CPAN.
Here is my twist on things using something already on CPAN which uses Moose and its Class::MOP foundations: MooseX::SingletonMethod.
With this we can easily create anonymous singleton objects like so:
{
package Anonyject;
use MooseX::SingletonMethod;
}
my @dingfirsts;
for my $line ( 1..10 ) {
push @dingfirsts, Anonyject->new->add_singleton_methods(
ding => sub { 'ding' x $line },
dong => sub { 'dong' x $line },
line => sub { $line },
)
}
for (@dingfirsts) {
say "First ", $_->ding, " on line ", $_->line;
}
We can show that each of these objects created have unique anonymous classes using Moose introspection:
for (@dingfirsts) {
say $_->line, ': ', ( $_->meta->class_precedence_list )[0];
}
# outputs
# => 1: Class::MOP::Class::__ANON__::SERIAL::2
# => 2: Class::MOP::Class::__ANON__::SERIAL::3
# => 3: Class::MOP::Class::__ANON__::SERIAL::4
# => 4: Class::MOP::Class::__ANON__::SERIAL::5
# => 5: Class::MOP::Class::__ANON__::SERIAL::6
# => 6: Class::MOP::Class::__ANON__::SERIAL::7
# => 7: Class::MOP::Class::__ANON__::SERIAL::8
# => 8: Class::MOP::Class::__ANON__::SERIAL::9
# => 9: Class::MOP::Class::__ANON__::SERIAL::10
# => 10: Class::MOP::Class::__ANON__::SERIAL::11
The rest of the class chain upwards for each of these objects is:
Anonyject >> Class::MOP::Class::__ANON__::SERIAL::1 >> Moose::Object
So you can add methods or attributes to Anonyject class and they will be available to all the anonymous objects created.
NB. Class::MOP::Class::__ANON__::SERIAL::1 is where the MooseX::Singleton methods live.
So for more proof in the singleton pudding:
my $obj1 = Anonyject->new->add_singleton_methods(
ding => sub { "wing" },
dong => sub { "wong" },
line => sub { 23_939 },
);
my $obj2 = Anonyject->new->add_singleton_methods(
something => sub { "else" },
);
say $obj1->ding; # Says "wing"
say $obj2->something; # Says "else"
say $obj1->something; # Should break and now does
say $obj1->broken; # Breaks properly
say $obj2->dong; # And also breaks properly
And all these objects are easily extensible:
# add dingdong just to $obj2
$obj2->meta->add_method( dingdong => sub { 'dingdong!' } );
say $obj2->dingdong; # "dingdong!"
# add bang to all anonymous Anonyject objects
Anonyject->meta->add_method(
bang => sub { 'bang ' . ( $_[0]->meta->class_precedence_list )[0] }
);
say $obj1->bang; # "bang Class::MOP::Class::__ANON__::SERIAL::12"
say $obj2->bang; # "bang Class::MOP::Class::__ANON__::SERIAL::13"
/I3az/



