Perl, Haskell, stuff
A couple of interesting comments to my Five things I hate about Perl. Quicksilver pointed out that I'd missed the difference between arrays and lists. Yup, that's pretty subtle, and of course it's bitten me a few times (though oddly enough, I don't have that strong a dislike of it). Luqui on the other hand pointed out that Perl is so much more fun if you do take the plunge and use language-mutating modules, irrespective of the fact that they're not standard. I do agree, though it can sometimes be difficult getting to use these modules for work, as everyone else has to buy in to the benefits and (perceived or real) risks (learning curve, stability, speed, etc.).
So here's an example of something that I'd forgotten I hated until I banged my head against it in work's codebase: AUTOLOAD.
AUTOLOAD like other languages' "method-missing" feature, allows you to dynamically respond to a method invocation without having explicitly defined the method. So, for example, someone might call get_name on an object, and the accessor for the 'name' field will be automatically be generated.
Actually, that sounds pretty cool, no? The problems are really in the implementation.
use vars '$AUTOLOAD';
sub AUTOLOAD {
my $sub_name = $AUTOLOAD=~/(\w+)$/;
...
}
Yuck. Of course, someone has already dealt with most of the problem in a module: Ben Tilly's Class::AutoloadCAN. Using this module, you just declare a CAN sub, which may or may not return a coderef (the subroutine that will deal with the problem). Behind the scenes, overriding of the standard 'can' meta-method and an auto-generate AUTOLOAD will automagically do the right thing. Yay!
The syntax isn't that pleasant though. If we want to handle multiple autoloaded subs, we have to stick them all into this CAN routine. I'd much rather do something like:
sub foo :handles(/^foo_(.*)/) {
print "Fooing $1";
}
sub bar :handles(/^bar_(.*)/) {
print "Bar'ing $1";
}
So I thought, let's use Attribute::Handlers, which lets us define these handlers. But I don't really like Perl's
attributes feature, and to be honest, I'm not keen on the redunancy of naming a sub and then the
regex that it handles.
I'd rather have some syntax like:
autosub (get_(.*)) {
...
}
and of course that suggests Matt Trout's beautiful
Devel::Declare.
And it's surprisingly simple* to knock up a prototype AutoSub module which implements this. From the accompanying test.pl:
autosub (^take_(.*)) {
my($what, @args) = @_;
return "Took a $what";
};
autosub (^get_([^_]+)_(.*)) {
my($adj, $noun, @args) = @_;
return "Got a $adj $noun";
};
autosub (^do_the_.*$) {
my ($what, @args) = @_;
return join "," => $what, @args;
};
* Where "surprisingly simple" glosses over a couple of points, noted here briefly for reference:
Osfameron's blog on Haskell, Perl programming, stuff.
CPAN updates - Just another lambdabananacamel,
July 27th, 2008 at 10:24 am