http://qs1969.pair.com?node_id=472458

So I've spent a lot of time whipping out perl programs that always get the job done, but I'm haunted by the niggling fact that while my code is effecitve, it's anything but sexy, and often wastes resources.

So I'm thinking to myself, how can I begin to improve my base stock of Perlness? and it comes to me that Modules (a black hole in my Perl education) can go a long way to tightening up both the code and the resources used.

So I ask myself, how do I really start to tackle the plethora of modules out there and what they can do? Now the obvious answer is to simply use the ones you need as you need them. But how to go about starting a tight, useful cluster of Modules on which to build a respectable Module know-how for myself?

So I thought I'd get some viewpoints from the Monk community in the way of the Desert Island Disks theme:

You are stranded on some remote island, programming for some very eccentric concern when a strange virus gets into the perl binary and eats away all possiblity for more than 3 modules. (You have to use your imagination a bit.) You can choose any three modules, but they will be the only ones you can ever use again in your perl programming.

Assuming all other dependancies remain intact, what three modules would you choose and why?

Replies are listed 'Best First'.
Re: Desert Island Modules
by Corion (Patriarch) on Jul 05, 2005 at 14:19 UTC
Re: Desert Island Modules
by rinceWind (Monsignor) on Jul 05, 2005 at 14:38 UTC

    I believe that this thought process is similar to what Mark Fowler went through to arrive at 25 modules for the original Perl Advent Calendar.

    --

    Oh Lord, won’t you burn me a Knoppix CD ?
    My friends all rate Windows, I must disagree.
    Your powers of persuasion will set them all free,
    So oh Lord, won’t you burn me a Knoppix CD ?
    (Missquoting Janis Joplin)

Re: Desert Island Modules
by davidrw (Prior) on Jul 05, 2005 at 14:33 UTC
Re: Desert Island Modules
by Tanktalus (Canon) on Jul 05, 2005 at 14:36 UTC

    Only three? Aw, gee, that's what I have in my standard perl script/module template! strict, warnings, and diagnostics - and this is just to keep me from doing stupid things, nevermind actually accomplishing work.

    Now, assuming that you're going to allow all the pragma modules we want, I've found the most use so far from CGI::Application (even though there are aspects of its design that still bother me, I just haven't had time to go in and take what I like about it and put it in a module that has nothing I dislike), XML::Twig (syntax is a bit heavy, but that also gives me a lot of flexibility), and HTML::Template (the nice thing about HTML::Template is that it is a complex piece of machinery hidden behind a relatively simple API - no need for anyone to write HTML::Template::Simple!).

    Of course, the other issue with the question is that I need to write domain-specific modules, and the way the question is phrased, it sounds like that isn't allowed. I'm going with the spirit of the question with the above three modules, not the letter of the question. :-)

    With the spirit of the question, though, I have to say that there are a lot of other simpler modules (smaller API and smaller scope) which I find useful as well which may be a more reasonable place to start. Text::Wrap is just too cool - and is standard as well. Not difficult stuff, but at least I don't need to think about edge cases ;-) Term::ANSIColor (even though they misspell 'colour' ;->) is a nice, readable way to make things stand out in my output. LWP::Simple allows you to easily download webpages (or any other web resource). Those would be my "simpler" 3 pick.

Re: Desert Island Modules
by Mutant (Priest) on Jul 05, 2005 at 14:42 UTC
    It's pretty tough to limit to 3. I'd have to cheat and say pragmas don't count, and have DBI (not counting drivers either :), HTML::Template, and Data::Dumper.

    By the way, you may also want to look at [id://Favourite modules of 2006|this node] for more lists of popular modules.
Re: Desert Island Modules
by samizdat (Vicar) on Jul 05, 2005 at 17:25 UTC
    Since I'm on a desert island, I guess I won't have Internet, so that leaves out anything related to that. Ditto Microsoft, so I won't need WriteExcel either. ;-D

    I guess the only thing I'll be able to do is make my computer talk to me in some non-boring way, so I'll say Parse::RecDescent, GD, and maybe AI::Fuzzy.
Re: Desert Island Modules
by monarch (Priest) on Jul 05, 2005 at 14:38 UTC
    The worst part is that so many modules have dependencies. But assuming the fantasy is real any *any* three modules, including dependencies, I too would require DBI. I would also like Net::SNMP because that makes communicating with network devices soooo much easier. Finally I might have to throw in DateTime because let's face it, on a desert island I'm going to need to keep track of how long I've been stranded. And I certainly like that module for the swiss army knife of time concerns.
Re: Desert Island Modules
by jhourcle (Prior) on Jul 06, 2005 at 03:00 UTC

    I'm guessing that if I'm trapped on a desert island, I'd have very little reason to be writing computer programs.

    I'd much rather have a copy of the US Army Survival Manual, so I'd need LWP to download it.

    Other than that, I'm hoping there's something in Geo:: that might help me figure out where I am, and then for the third module, some sort of communications (even if it's just Net::Telnet, and I can generate SMTP messages by hand), to get help.

        Another OT must-have is DIY 12 Volt Solar Power. I can. perhaps, be forgiven once one learns that this book teaches you how to use solar to power cordless tools such as grinders and circular saws, and even to weld. Plus loads more (the book has pictures of solar-powered lights, a walkman, an amplifier, a sander, milling machine, hammer drill, turning lathe, drill press, fan, sewing machine, washer, spin dryer, guitar, and etc.).

        HTH,

        planetscape
Re: Desert Island Modules
by ghenry (Vicar) on Jul 05, 2005 at 15:05 UTC

    Me too, just the one, CPAN ;-)

    Walking the road to enlightenment... I found a penguin and a camel on the way.....
    Fancy a yourname@perl.me.uk? Just ask!!!
Re: Desert Island Modules
by greenFox (Vicar) on Jul 06, 2005 at 03:12 UTC

    Given its a desert island I will assume internet access is out leaving a whole range of modules useless. So I would go with Tk-804.027, one of DBM::Deep or DBD-SQLite probably DBD-SQLite (thanks Merlyn) and SDL_Perl for fun... Though I imagine modules for lighting fires, purifying water, producing food, erecting shelter etc would be of more use *grin*

    --
    Murray Barton
    Do not seek to follow in the footsteps of the wise. Seek what they sought. -Basho

Re: Desert Island Modules
by jonadab (Parson) on Jul 06, 2005 at 13:51 UTC

    It's hard to pick three, and there are a lot more than three that I'd like to pick, but I think if I were stuck with a limit of three, it would probably come down to the following:

    • DateTime is hands-down my number-one choice. I don't consider Perl to be properly installed until this module is working. If I had to do all date calculations based on gmtime and localtime and strftime and their ilk, I would have gone insane several years ago and probably switched to Python or Ruby or something. This one really ought to be core, along with it's suite of DateTime::Format::Foo modules for converting to and from every major date/time format.
    • Data::Dumper. This is another one without which I don't consider Perl to be properly installed. Use of this module can save you weeks of debugging time and petalocks of hair.
    • DBI. I've been using it with DBD::myql, but for my rather basic purposes any decent DBD module will do.

    Others worthy of serious consideration include Class::DBI, XML::Twig, Net::Server, WWW::Mechanize, Mail::Sendmail, Archive::Zip, File::Spec::Functions, and HTML::Tree. Each of these becomes invaluable if you find yourself needing to do the thing it's designed to do.

    Also, HTML::Entities is worth knowing about just because it's so simple and easy to learn to use. It would be a much easier wheel to re-invent than the ones above, but then again, there's no need.

    Someone will come along and say CGI, but I disagree and never use it, even though I do quite a lot of CGI stuff. It's bloated and gross and has a truly horrific API that is much more trouble to learn than the problem it solves is worth. (CGI is, after all, *not* a hard thing to implement.) I only recommend it to people who don't know their way around CGI already; otherwise my advice is to give this one a miss.

    I also experimented with CGI::Lite but found that it is buggy, hides information from you that you need, does not handle file uploads correctly all of the time, and in general is not worth your time; you can roll your own replacement in less than half the time it will take you to figure out why it's messing up your data. Avoid.

    P.S., from the node title I thought you were talking about castaway's im2-related modules.

      Can you describe what you do use for CGI programming?
        Can you describe what you do use for CGI programming?

        Sure. As far as writing the HTML output, I have some custom elisp that facilitates writing wellformed XHTML. For instance, if I hit Ctrl-t table <enter> I get the following, with my cursor inside the first tr element:

        <table><thead> <tr> </tr> </thead><tbody> <tr></tr> </tbody></table>

        I have a hook set up to load that stuff whenever cperl-mode starts up. For the other half of CGI, getting data in, I mostly use the following:

        sub getforminput { my %opt = @_; # OPTIONS: # multiples - What to do if there are multiple inputs with t +he # same name. By default, you get an arrayref, b +ut # if you set this to 'first' or 'last', you'll g +et # the first or last value, respectively. 'join' # will "firstval,secondval,thirdval,...,lastval" +. # filename - If true, and if the browser supplies a filenam +e for # a file upload, send it as 'filename'. (Multip +les # are not supported by this, so you can't also h +ave # a form element named 'filename'.) Default is # to ignore any user-supplied filename(s), which # is generally recommended for security anyway. # content_type - If true, and the browser supplies a Content-ty +pe # with a file upload, send it as 'content_type', # with similar caveats as for filename. use Taint; die "Cannot both fold and reject multiples.\n" if $opt{fold_multiple +s} and $opt{reject_multiples}; my ($formdata, %input); { my $num_bytes=$ENV{CONTENT_LENGTH}; if ($num_bytes > 0) { $num_bytes == read (STDIN, $formdata, $num_bytes) or warn "CONTE +NT_LENGTH is full of lies!"; } else { $formdata=$ENV{QUERY_STRING}; } } loginput($formdata) if $formdata; if ($ENV{CONTENT_TYPE}=~/multipart\/form-data.*boundary=(.+?)$/) { my $boundary=$1; Taint::taint($boundary); foreach my $part (split /--$boundary/, $formdata) { my $partname=""; my ($headers, $value, @moreval) = $part =~ /^(.*?)\r?\n\s?\r?\n( +.*?)(?:\r?\n)?$/s; Taint::taint($headers, $value); $value=join("\n\n", ($value, @moreval)) if @moreval; foreach my $h (split (/\r?\n/, $headers)) { if ($h =~ /Content-Disposition: ([^;]+); (.*?)$/) { my ($content_disposition, $t)=($1,$2); Taint::taint($t); foreach (split /; /, $t) { if (/^name=(.*?)$/) { ($partname) = $1 =~ /\"?([^"]*)/; Taint::taint($partname); } elsif (/^filename=(.*?)$/ and $opt{filename}) { my ($filename) = $1 =~ /\"?([^"]*)/; Taint::taint($filename); $input{filename} = $filename; # Note that multiples aren +'t supported for this. } } } else { if ($h =~ /Content-Type:\s+(.*)/ and $opt{content_type}) { ($input{content_type}) = $1 =~ m!([\w]+/[\w]+)!; } } } if ($partname) { if ($opt{multiples} eq 'first') { $input{$partname} = $value unless exists $input{$partname}; +# Take first value only; reject subsequent ones. } elsif ($opt{multiples} eq 'last') { $input{$partname} = $value; +# Take the latest value every time. } elsif ($opt{multiples} eq 'join') { $input{$partname} = (join ",", $input{$partname} , $value); +# Join with commas. } else { # +# Default: construct an arrayref if necessary. if (exists $input{$partname} and ref $input{$partname}) { push @{$input{$partname}}, $value; } elsif (exists $input{$partname}) { $input{$partname} = [$input{$partname}, $value]; } else { $input{$partname} = $value; }} }} } else { foreach (split /&/, $formdata) { s/\+/ /g; # That's how CGI encodes spaces. my ($name, $value) = split(/=/, $_); $name =~ s/%(..)/pack("c",hex($1))/ge; # These lines reverse th +e %nn encodings $value =~ s/%(..)/pack("c",hex($1))/ge; # CGI does for punctuati +on marks and such. Taint::taint($name, $value); $input{$name}=$value; }} if ($formdata) { return \%input; } else { return undef; } }

        I tried to save myself from maintaining that by using modules, but it turned out to be false laziness, because it's not that big and not that hard to maintain, and having the ability to do things like keep a log of all input data for any given script turns out to be a fantastic debugging aid (not just for debugging this function, but especially for debugging the calling code). I have had significantly less trouble with this code than with the module I was using previously (CGI::Lite). I guess some wheels are worth reinventing.