Prototyping Perl programs... with bash!

schwern on 2007-09-23T13:18:57

Way back in 1999 I gave my very first conference presentation at the first YAPC in Pittsburgh. The title was "Ineffective Perl Programming" and it drew as its material from the many, many, many awful books on Perl out at the time and the ridiculous example code therein. I spent many days in bookstores trolling through pages and pages of "programming by the pound" tomes.

Sometimes in my investigations I'd discover some gems that would provide me with endless material. PI, a "Package Installer for Perl" is one I've just discovered. It's "a simple manager for Perl binary packages". The docs tout, "it doesn't require any external modules, like XML parser or MakeMaker". Well this will be feat. Ok, let's look at that pi.pl the docs talk about.

Hmm... no pi.pl. But there's pi.sh. What's in there?

#!/bin/bash

# Perl Package Installer - prototype shell implementation


That's right folks, let's prototype Perl programs using bash! Why would you inflict such a thing on the world? Maybe it's like some sort of martial arts training/torture test where the master makes the young pupil do some inane task using broken tools in order to learn some cryptic and vaguely masochistic lesson.

"Today you will learn the Tao by building a doghouse using these poorly crafted and ancient stone tools." "But master, that will take days!" "Ahh, yes it will. Then once your painstaking and inevitably shoddy work is complete you will tear it all down and build a new one with hammer and nails." "But master, we do not have a dog."

Oh, but the fun doesn't stop there.

compare_versions () {
    perl -l -- - "$@" << 'END'

sub compare_versions { my $a = shift || 0; my $b = shift || 0;

...and so on... }

print compare_versions(@ARGV); END


Yes, shell functions which contain Perl functions which are then fed to perl and the result pulled back into the shell function and spat back out. It's like pulling your car with a bicycle and then congratulating yourself for saving gas.

But sometimes there's shell code that shells out to perl!

    newversion=`perl -MFile::Spec -MExtUtils::MM -le '
        my $modfile = $ARGV[0];
        foreach my $dir (@INC) {
            my $p = File::Spec->catfile($dir, $modfile);
            if (-r $p) {
                $version = MM->parse_version($p);
                last;
            }
        }
        print $version;' "$modfile"`


What the hell? Make up your mind!

And what's this, it's using external modules! Wasn't the whole point not to use any modules? There's File::Spec and MakeMaker. And look, it uses XML::Parser and YAML.pm!

Holy crap, look at this:

    # Load Perl configuration
    eval `perl -V:.*`


It sucks in every Perl configuration variable into the main program.

So many wonders to explore in just one program. I'm tempted to write the author and find out WTF is going on here, but I think I'd rather just back away slowly and not make any sudden movements.


Irony

chromatic on 2007-09-23T20:55:54

That's right folks, let's prototype Perl programs using bash! Why would you inflict such a thing on the world? ... Yes, shell functions which contain Perl functions which are then fed to perl and the result pulled back into the shell function and spat back out.... But sometimes there's shell code that shells out to perl!

If you like that, you should see the guts of MakeMaker sometime.

Re:Irony

Aristotle on 2007-09-23T22:15:04

I think it was Schwern himself who said that MakeMaker needs to die.

Re:Irony

chromatic on 2007-09-23T23:51:38

Heh. I was in the room for that, more than once.