Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Stabby McDamage
Dec 11, 2005

Doctor Rope
I'm a big fan of Perl, using it at home, at work, and sometimes in the bathroom, so I thought I'd christen the Cavern with a Perl thread before those whitespace-delimited python bastards get here.

Perl is a compact, occasionally cryptic scripting language born of the brain of Larry Wall (see fig. 1).


Fig 1: Larry Wall. If you find something weird about Perl, this is the cause.

To sum up the language, Perl is a higher level language than C and Java, and is in the same camp as Python and Ruby. It's great for small to medium-size programs, especially for data munging, database access, job control, etc. It's a mix of C, shell script, sed/awk, and even a bit of LISP. Despite being higher level, it doesn't lose it's UNIX roots, so if you like forks and pipes but not pointers, Perl is for you.

Features
- Automatic data typing and memory management.
- Flexible arrays that grow and shrink as needed.
- Hashes, which allow arbitrary key-value pairs (AKA "associative arrays" in PHP or "dictionaries" in Python).
- Hashes and arrays can contain references to other hashes or arrays, making complex data structures easy to implement. (I once wrote an web-based game that stored the entire state of the universe in a single hash).
- Core functions include sorting, list grepping, mapping functions onto lists, and other labor-savers.
- Many low-level C system calls are included, so you can fork(), alarm(), umask(), setpgrp(), ioctl(), etc. You can even set interrupt handlers!
- Subroutines can be passed as variables ("higher-order programming").
- Regular expressions are built into the syntax of the language.
- Object oriented programming is supported through packages.
- A super-gigantic ton of existing libraries can be instantly installed via the Comprehensive Perl Archive Network (CPAN).

Getting Perl
- If you're on Linux or OSX, you have it.
- If you're on Windows, get ActiveState Perl or the Cygwin suite, which includes Perl.

For new users
If you want to go the book route, I'd pick up Learning Perl, then Programming Perl, then study the Perl Cookbook (all linked below). But that's me. You could also go through some of these tutorials and documents:
- Picking Up Perl is a free online book that introduces Perl.
- About.com's Perl section has several tutorials.
- Perl Lessons is a brief introductory course.

Web resources and references
- Perldoc, the web-based version of the perldoc manpages.
- The single-page built-in function reference "perlfunc" is quite handy.
- All the extra modules live on the Comprehensive Perl Archive Network (CPAN), and can be installed with the "cpan" command-line tool.
- The Perl Monks like helping folks learn Perl, and have a huge blog of examples and help.
- Perl Regular Expression Quick Reference - Print out and stick on wall.
- A ton of Perl examples, projects, and documentation can be found at Perl.com and About.com's Perl section.
- Perl Design Patterns. A wiki applying the principles of design patterns (common code configurations to solve a certain kind of problem) to Perl. The problem index is useful.

Books
- Learning Perl, 3rd ed. The O'Reilly book for learning the language. Google Books.
- Programming Perl, 3rd ed. Called the "camel book", this is the definitive reference, also from O'Reilly. Google Books.
- The Perl Cookbook, from O'Reilly, is a collection of techniques and examples ranging from the simple to the complex. It's the only printed reference book I frequently use. Google Books.
- Perl Best Practices. Style and design tips to make your code maintainable and good. If you use this from the start, then you won't have to resort to...
- Perl Medic. It's about keeping up legacy ("poo poo") code, and transforming it into something that doesn't give you the tetanus. Glowing reviews at TechBookReport.

Stabby McDamage fucked around with this message at 15:19 on Oct 26, 2007

Adbot
ADBOT LOVES YOU

Stabby McDamage
Dec 11, 2005

Doctor Rope

syphon^2 posted:

So, Perl gurus, where do I go next?

As much as I like Perl, anyone who programmer should be largely language-agnostic. Pick up more languages, learn their strengths and weaknesses, and add them to your toolbox. Moving from low level languages to higher ones is generally easy, as you're just adding to your feature set; C->Perl and Perl->Python are examples of this. Moving the other direction is harder: you have to learn new skills and ways of thinking. Perl->C will be painful, but you'll grow a lot as a programmer.

That said, leveling up in Perl is also a virtue, as it's good to have a "home" language where you can knock out language-neutral problems quickly. Pick up the "camel book" (linked in OP), as it covers all the interesting stuff (and some of the less interesting).

Also, it may sound weird, but I read the Perl Cookbook cover to cover, even though is supposed to be a reference. That's where you learn neat ways to turn the bucket of knowledge that regular texts give you into real programming horsepower.

OOP in Perl is good if you want to make a few modules interact and have a clean namespace. However, doing a lot of heavy lifting using OOP principles can get very hairy very fast if you're not experienced and disciplined. It pains me to say, but if you find yourself thinking how to "architect" or "refactor" a Perl program, it may be time to move to another language.

Stabby McDamage
Dec 11, 2005

Doctor Rope

floWenoL posted:

... It's a double-edged sword, and frankly, the negative edge is bigger...
I like Perl, but let's not turn this thread into a wankfest.

Then we can just agree that it's an excellent language for stabbing things until they die, and that children should be kept away from it.

Stabby McDamage
Dec 11, 2005

Doctor Rope

Subotai posted:

How do I get info about filesystems in Perl? There is a statfs call but no statvfs call, etc.

Filesys::Df.

Stabby McDamage
Dec 11, 2005

Doctor Rope
If I understand Ubuntu right, perl 5.10 will never be in the current Ubuntu distribution, since each distribution doesn't advance major package versions, just minor updates. So I believe you'll see it if you install Ubuntu 8.04 in 3 months.

It may become available through the backports repository, which is disabled by default.

If you really need Perl 5.10, you probably need it for something specific, so install it to /opt or your home directory and start your scripts with #!/opt/perl/bin/perl or somesuch. When the upgrade comes, just change the header lines.

Stabby McDamage
Dec 11, 2005

Doctor Rope
I have a large file (>4GB), and when I do a tell() on it, I get negative values since I'm on a 32-bit Linux. Is there a way to use 64-bit file offsets in Perl without installing a 64-bit OS or recompiling the binary?

Stabby McDamage fucked around with this message at 15:40 on May 22, 2008

Stabby McDamage
Dec 11, 2005

Doctor Rope

magimix posted:

I might be flying off in totally the wrong direction, but can MySQL actually handle multiple active statements on a single database handle?

I've always found I couldn't execute a second statement on a DB handle without first fetching or discarding the result-set of the previously executed statement.

Yes and no. MySQL itself doesn't seem to support this, but library trickery makes it seem like it works.

By default, the entire result set is streamed to the DBI library at execute time. This is "mysql_store_result" mode. Because the whole result set is cached at the client before any fetches occur, MySQL never sees more than one query going on at a time.

This isn't a good solution when you want to iterate very large data sets that don't fit in RAM, as I had to do recently. For that, you need to use "mysql_use_result", which transfers records as you fetch them. The problem with this is that you can't do other queries inside of that loop, since the outer query is still in progress.

I couldn't find an elegant solution to this, so I just read my outer query out to disk first, then iterated from disk for my small inner queries, which worked fine in mysql_store_result mode.

Basically, if you can't do this for lack of memory:

code:
my $sth_giant_query = $dbh->prepare("SELECT * FROM bigtable") or die();
my $sth_inner_query = $dbh->prepare("UPDATE othertable SET thing=? WHERE id=?") or die();
$sth_giant_query->execute();
while ($row = $sth_giant_query->fetchrow_hashref()) {
  $sth_inner_query->execute(function($row),$row->{id});
}
Then you might try to change that first line so as to not cache the giant query results:

code:
my $sth_giant_query = $dbh->prepare("SELECT * FROM bigtable",{ "mysql_use_result" => 1}) or die();
But this will fail on the $sth_inner_query execute because multiple queries can't run at the same time on the MySQL side, so you might end up having to do something like this:

code:
my $sth_giant_query = $dbh->prepare("SELECT * FROM bigtable",{ "mysql_use_result" => 1}) or die();
my $sth_inner_query = $dbh->prepare("UPDATE othertable SET thing=? WHERE id=?") or die();
$sth_giant_query->execute();
while ($row = $sth_giant_query->fetchrow_hashref()) {
  write $row to disk
}

while ($row = read from disk) {
  $sth_inner_query->execute(function($row),$row->{id});
}
This kind of crap is what made me give up MySQL for any kind of data analysis. MySQL will do for powering a dopey blog or something, but nothing serious.

Stabby McDamage
Dec 11, 2005

Doctor Rope
On *nix, how can I determine which mountpoint owns a particular file?

If I can't find a programmatic way, I'll have to parse `mount`, which seems ugly.

Stabby McDamage
Dec 11, 2005

Doctor Rope

Pooball posted:

CPAN? :)

Thanks. I searched CPAN for "mountpoint", "filesys", etc., but I didn't find that. It's perfect.

EDIT: Wait, it doesn't have a way to look up a mountpoint from a file. I ended up using the output of 'df', since you can say "df /any/file" and it will just report the mount that provides that file. I'd still prefer a pure Perl method, if one exists.

Stabby McDamage fucked around with this message at 18:10 on Sep 22, 2008

Stabby McDamage
Dec 11, 2005

Doctor Rope

ShoulderDaemon posted:

Here's some quick and dirty code to walk up an absolute path until we find a directory that's part of a different filesystem.


That's a cool idea. I might use that.

Adbot
ADBOT LOVES YOU

Stabby McDamage
Dec 11, 2005

Doctor Rope

Erasmus Darwin posted:

I ran a quick test, and it looks like that doesn't work for SIGTERM:

code:
$ perl -e 'END { print "Dying!\n"; } kill("TERM", $$); sleep(120);'
Terminated
$
So he'd still need to worry about catching the signal somehow. For a general purpose module, I suspect that any solution will be slightly messy and have some suboptimal side-effects.

You can save the original handler coderef, then call it from your handler, thus preserving whatever the user had set up:
code:
#!/usr/bin/perl

###### user code: ######
use strict;
$SIG{INT} = sub { print "original handler\n"; };

####### your module: #######

my $oldhandler = $SIG{INT};
$SIG{INT} = sub { $oldhandler->(@_); print "new handler\n"; };

####### user workload: #######
sleep 5;
$ perl x.pl
<Ctrl-C>
original handler
new handler

  • Locked thread