229
The Essential Perl Hacker's Toolkit Stephen R. Scaffidi [email protected] YAPC::NA 2012

The Essential Perl Hackers Toolkit

Embed Size (px)

Citation preview

Page 1: The Essential Perl Hackers Toolkit

The Essential Perl Hacker's Toolkit

Stephen R. [email protected]

YAPC::NA 2012

Page 2: The Essential Perl Hackers Toolkit

Thanks for coming!

Page 3: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Contents

Page 4: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 5: The Essential Perl Hackers Toolkit

This is a talk about the essentials

Page 6: The Essential Perl Hackers Toolkit

essential to...

Page 7: The Essential Perl Hackers Toolkit

getting my job done

Page 8: The Essential Perl Hackers Toolkit

getting my job done better

Page 9: The Essential Perl Hackers Toolkit

getting my job done faster

Page 10: The Essential Perl Hackers Toolkit

so I can go out and drink beer

Page 11: The Essential Perl Hackers Toolkit

so I can go out and drink beerspend time posting on reddit

Page 12: The Essential Perl Hackers Toolkit

so I can go out and drink beerspend time posting on reddit

watching youtube

Page 13: The Essential Perl Hackers Toolkit

so I can go out and drink beerspend time posting on reddit

watching youtubeDANCING WITH THE STARS

Page 14: The Essential Perl Hackers Toolkit

the editor of the previous three slides has been sacked

Page 15: The Essential Perl Hackers Toolkit

I <3 Task::Kensho

Page 16: The Essential Perl Hackers Toolkit

This talk != Task::Kensho

Page 17: The Essential Perl Hackers Toolkit

But it is essential

Page 18: The Essential Perl Hackers Toolkit

So look it up:Task::Kensho

Page 19: The Essential Perl Hackers Toolkit

my @essentials

Page 20: The Essential Perl Hackers Toolkit

Modules and tools I depend on

Page 21: The Essential Perl Hackers Toolkit

make my job easier

Page 22: The Essential Perl Hackers Toolkit

make my code better

Page 23: The Essential Perl Hackers Toolkit

easier to write

Page 24: The Essential Perl Hackers Toolkit

easier to read

Page 25: The Essential Perl Hackers Toolkit

easier to maintain

Page 26: The Essential Perl Hackers Toolkit

fewer bugs

Page 27: The Essential Perl Hackers Toolkit

because...

Page 28: The Essential Perl Hackers Toolkit

this is the code I don't write

Page 29: The Essential Perl Hackers Toolkit

I'm not that good.

Page 30: The Essential Perl Hackers Toolkit

Neither are you*

Page 31: The Essential Perl Hackers Toolkit

Neither are you*

*with several exceptions, half of them probablyleaving this room right now...

Page 32: The Essential Perl Hackers Toolkit

Previous iterations of this talk...

Page 33: The Essential Perl Hackers Toolkit

touchy-feely

Page 34: The Essential Perl Hackers Toolkit

waxed poetic about community

Page 35: The Essential Perl Hackers Toolkit

gushed about the CPAN

Page 36: The Essential Perl Hackers Toolkit

but...

Page 37: The Essential Perl Hackers Toolkit

there's simply no time

Page 38: The Essential Perl Hackers Toolkit

too many modules

Page 39: The Essential Perl Hackers Toolkit

too many modules(on the dance floor)

Page 40: The Essential Perl Hackers Toolkit

I prefer Perl because of this variety

Page 41: The Essential Perl Hackers Toolkit

No language is perfect

Page 42: The Essential Perl Hackers Toolkit

but...

Page 43: The Essential Perl Hackers Toolkit

Perl has the CPAN

Page 44: The Essential Perl Hackers Toolkit

And the CPAN gives us many, many ways to improve Perl

Page 45: The Essential Perl Hackers Toolkit

mst once said...

Page 46: The Essential Perl Hackers Toolkit

Perl is my VMCPAN is my language

Page 47: The Essential Perl Hackers Toolkit

so...

Page 48: The Essential Perl Hackers Toolkit

let's learn about some of the best parts of this language we call the

CPAN

Page 49: The Essential Perl Hackers Toolkit

Allow me some hubris...for the next 40 minutes or so.

Page 50: The Essential Perl Hackers Toolkit
Page 51: The Essential Perl Hackers Toolkit

Bring out the modules!

Page 52: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 53: The Essential Perl Hackers Toolkit

strict

warnings

Page 54: The Essential Perl Hackers Toolkit

really?

Page 55: The Essential Perl Hackers Toolkit

experience tells me the answer is yes.

Page 56: The Essential Perl Hackers Toolkit

English

Page 57: The Essential Perl Hackers Toolkit

Get English versions of Perl's “punctuation vars”

Page 58: The Essential Perl Hackers Toolkit

use English qw( -no_match_vars );

Page 59: The Essential Perl Hackers Toolkit

$#@^ English$\ $OUTPUT_RECORD_SEPARATOR

$$ $PID

$^O $OSNAME

$+ $LAST_PAREN_MATCH

$! $OS_ERROR

$? $CHILD_ERROR

$< $REAL_USER_ID

Examples

Page 60: The Essential Perl Hackers Toolkit

perldoc perlvar

Page 61: The Essential Perl Hackers Toolkit

autodie

Page 62: The Essential Perl Hackers Toolkit

Does what it says on the tin...

Page 63: The Essential Perl Hackers Toolkit

# overrides various built-ins...use autodie;

# Now, they all succeed or die!open my $foo, '>', 'file.txt';chdir 'foo/bar';pipe my($baz), my($buh);readline $foo;print “Do you ever check for print errors???”;

Page 64: The Essential Perl Hackers Toolkit

autodie is indispensable.

Why write an “or die” clause after every open() when you no

longer have to???

Page 65: The Essential Perl Hackers Toolkit

Data::Dumper

Page 66: The Essential Perl Hackers Toolkit

Better than print().

Page 67: The Essential Perl Hackers Toolkit

Data::Dump::Streamer

Page 68: The Essential Perl Hackers Toolkit

Better than Data::Dumper!

Page 69: The Essential Perl Hackers Toolkit

List::Util

Page 70: The Essential Perl Hackers Toolkit

List::UtilList::MoreUtils

Page 71: The Essential Perl Hackers Toolkit

List::UtilList::MoreUtils

Scalar::Util

Page 72: The Essential Perl Hackers Toolkit

For those go to Steve Lembark's talk on Util modules tomorrow

morning.

Page 73: The Essential Perl Hackers Toolkit

parent

Page 74: The Essential Perl Hackers Toolkit

Stop messing with @ISA

Page 75: The Essential Perl Hackers Toolkit

# sets up @ISA for youuse parent qw(Some::Base Other::Base);

Page 76: The Essential Perl Hackers Toolkit

Clear and declarative!

Page 77: The Essential Perl Hackers Toolkit

Try::Tiny

Page 78: The Essential Perl Hackers Toolkit

Stop messing with eval {} for exception handling.

Page 79: The Essential Perl Hackers Toolkit

use Try::Tiny;

try { something_that_might_die();}catch { handle_error($_); # note: not $@}finally { clean_up();};

Page 80: The Essential Perl Hackers Toolkit

IO::All

Page 81: The Essential Perl Hackers Toolkit

Maybe not essential

Page 82: The Essential Perl Hackers Toolkit

But damn handy!

Page 83: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 84: The Essential Perl Hackers Toolkit

Not just modules

Page 85: The Essential Perl Hackers Toolkit

App::cpanminus

Page 86: The Essential Perl Hackers Toolkit

A light-weight cpan client that understands local::lib

Page 87: The Essential Perl Hackers Toolkit

App::Ack

Page 88: The Essential Perl Hackers Toolkit

ack is better than grep

Page 89: The Essential Perl Hackers Toolkit

Devel::NYTProf

Page 90: The Essential Perl Hackers Toolkit

Hands-down, the best profiler for Perl

Page 91: The Essential Perl Hackers Toolkit

Devel::Cover

Page 92: The Essential Perl Hackers Toolkit

Tells you how well your tests cover your code

Page 93: The Essential Perl Hackers Toolkit

Speaking of tests...

Page 94: The Essential Perl Hackers Toolkit

prove

Page 95: The Essential Perl Hackers Toolkit

use it to run your tests

Page 96: The Essential Perl Hackers Toolkit

Lots of things under Test::

Page 97: The Essential Perl Hackers Toolkit

Test::Moreand/or

Test::Most

Page 98: The Essential Perl Hackers Toolkit

Many, many others...

Page 99: The Essential Perl Hackers Toolkit

Perl::Critic

Page 100: The Essential Perl Hackers Toolkit

Make sure your code confirms to certain quality standards.

Page 101: The Essential Perl Hackers Toolkit

You do use coding standards, right??

Page 102: The Essential Perl Hackers Toolkit

Mooseand/or

Mouse / Moo / Any::Moose

Page 103: The Essential Perl Hackers Toolkit

Stop writing your own OO layers

Page 104: The Essential Perl Hackers Toolkit

Stop doing it inconsistently

Page 105: The Essential Perl Hackers Toolkit

Stop messing up inheritance, destructors, accessors and all

those little things that you have to write over and over and over

again...

Page 106: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 107: The Essential Perl Hackers Toolkit

File::Spec

Page 108: The Essential Perl Hackers Toolkit

my $path = join '/', qw(foo bar baz)

Page 109: The Essential Perl Hackers Toolkit

What if it runs on Windows?Or VMS?

Or early MacOS?AcornOS?

QNX?

Page 110: The Essential Perl Hackers Toolkit

use File::Spec;

my $correct_path =File::Spec->catdir qw(foo bar

baz);

Page 111: The Essential Perl Hackers Toolkit

use File::Spec::Functions qw(catdir);

my $path = catdir qw(foo bar baz);

Page 112: The Essential Perl Hackers Toolkit

Declarative and correct

Page 113: The Essential Perl Hackers Toolkit

Lots of other functions, too:

● canonpath● catfile● rootdir● updir● devnull● tmpdir● curdir

● splitpath● splitdir● catpath● abs2rel● rel2abs● file_name_is_absolute● case_tolerant

Page 114: The Essential Perl Hackers Toolkit

Path::Class

Page 115: The Essential Perl Hackers Toolkit

use Path::Class qw(dir file); # create dir and file objects...my $dir = dir('foo', 'bar');my $file = file('bob', 'file.txt'); # Stringifies with proper separator on# each supported platformprint "dir: $dir\n";print "file: $file\n";

# methods do what you expect... my $subdir = $dir->subdir('baz');my $parent = $subdir->parent;my $dir2 = $file->dir;

Page 116: The Essential Perl Hackers Toolkit

File::Find

Page 117: The Essential Perl Hackers Toolkit

Traversing directories in a filesystem is tricky.

You're not that good.

Page 118: The Essential Perl Hackers Toolkit

File::Find::Rules

Page 119: The Essential Perl Hackers Toolkit

If you don't like File::Find, File::Find::Rules has some very

nice functionality. Try it.

Page 120: The Essential Perl Hackers Toolkit

File::Touch

Page 121: The Essential Perl Hackers Toolkit

For when you need to touch a file. Simple, and works cross-

platform.

Page 122: The Essential Perl Hackers Toolkit

File::Basename

Page 123: The Essential Perl Hackers Toolkit

same as the system's basename and dirname commands.

Page 124: The Essential Perl Hackers Toolkit

File::Slurp

Page 125: The Essential Perl Hackers Toolkit

Simple thing... but which is more readable?

Page 126: The Essential Perl Hackers Toolkit

my $text =do { local(@ARGV, $/) = "file.txt"; <> };

or

my $text = read_file 'file.txt';

Page 127: The Essential Perl Hackers Toolkit

File::ReadBackwards

Page 128: The Essential Perl Hackers Toolkit

When you need it... you DON'T want to do it yourself!

Page 129: The Essential Perl Hackers Toolkit

File::Temp

Page 130: The Essential Perl Hackers Toolkit

Let this module handle temp files and directories for you and stop

doing it wrong.

Page 131: The Essential Perl Hackers Toolkit

File::HomeDir

Page 132: The Essential Perl Hackers Toolkit

Don't try to find a user's home directory on your own.

Page 133: The Essential Perl Hackers Toolkit

File::Which

Page 134: The Essential Perl Hackers Toolkit

Why are you shelling out to which?

STOP IT!

Page 135: The Essential Perl Hackers Toolkit

File::Copy

Page 136: The Essential Perl Hackers Toolkit

Don't shell out to the system.Don't write your own copy

routine.

Please, PLEASE, just use File::Copy.

Page 137: The Essential Perl Hackers Toolkit

File::LibMagicand/or

File::MimeInfo

Page 138: The Essential Perl Hackers Toolkit

If you need to recognize a common file type...

STOP DOING IT YOURSELF!!!

Page 139: The Essential Perl Hackers Toolkit

If one doesn't work for you, try the other.

Page 140: The Essential Perl Hackers Toolkit

File::Path

Page 141: The Essential Perl Hackers Toolkit

recursively create and remove directories

Page 142: The Essential Perl Hackers Toolkit

File::stat

Page 143: The Essential Perl Hackers Toolkit

Can you remember this?

my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat $file;

Page 144: The Essential Perl Hackers Toolkit

Maybe this?

my $dev = (stat $file)[0];my $ino = (stat $file)[1];my $mode = (stat $file)[2];my $nlink = (stat $file)[3];my $uid = (stat $file)[4];my $gid = (stat $file)[5];my $rdev = (stat $file)[6];my $size = (stat $file)[7];# etc...

Page 145: The Essential Perl Hackers Toolkit

Try this, instead...

use File::stat;

my $s = stat $file;$s->dev;$s->ino;$s->size;

Much nicer, no?

Page 146: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 147: The Essential Perl Hackers Toolkit

Tie::IxHashor

Tie::StoredOrderHash

Page 148: The Essential Perl Hackers Toolkit

Building your own sucks

Page 149: The Essential Perl Hackers Toolkit

Try this:

use Tie::StoredOrderHash qw(ordered);

my $hash = ordered [one => 1, two => 2, three => 3

];

while (my($k, $v) = each %$hash) {print "$k: $v ";

} # one: 1 two: 2 three: 3

Page 150: The Essential Perl Hackers Toolkit

Hash::Merge::Simple

Page 151: The Essential Perl Hackers Toolkit

Recursively merge hash structures

Page 152: The Essential Perl Hackers Toolkit

use Hash::Merge::Simple qw(merge);

my $a = { a => 1, c => 3, d => { i => 2 }, r => {}};

my $b = { b => 2, a => 100, d => { l => 4 }};

my $c = merge $a, $b;

# $c is now {# a => 100, b => 2, c => 3,# d => { i => 2, l => 4 }, r => {} }

Page 153: The Essential Perl Hackers Toolkit

Simple, declarative and correct.

Page 154: The Essential Perl Hackers Toolkit

Params::Util

Page 155: The Essential Perl Hackers Toolkit

use Params::Util qw(_SCALAR _HASH _INSTANCE);

sub foo {my $object = _INSTANCE(shift, 'Foo') or die;my $image = _SCALAR(shift) or die;

my $opts = _HASHLIKE(shift) || {};}

Page 156: The Essential Perl Hackers Toolkit

Sure, it's ugly...

Page 157: The Essential Perl Hackers Toolkit

But focused on correctly doing something common and

(surprisingly) tricky

Page 158: The Essential Perl Hackers Toolkit

Params::Validate

Page 159: The Essential Perl Hackers Toolkit

The de-facto standard in parameter validation.

Page 160: The Essential Perl Hackers Toolkit

Algorithm::Combinatorics

Page 161: The Essential Perl Hackers Toolkit

Don't do combinatorics on your own. Your code will be wrong. It

will be slow. It will suck.

Page 162: The Essential Perl Hackers Toolkit

Set::CrossProductor

Set::CartesianProduct::Lazy

Page 163: The Essential Perl Hackers Toolkit

Just here for shameless self-promotion.

Page 164: The Essential Perl Hackers Toolkit

Data::Compare

Page 165: The Essential Perl Hackers Toolkit

Recursively and correctly compare data structures.

Page 166: The Essential Perl Hackers Toolkit

Test::Deep::NoTest

Page 167: The Essential Perl Hackers Toolkit

More functionality than Data::Compare.

Page 168: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 169: The Essential Perl Hackers Toolkit

DateTime

Page 170: The Essential Perl Hackers Toolkit

The most correct handling of dates and times in Perl. Use it.

Page 171: The Essential Perl Hackers Toolkit

DateTime::Format::Strptimeand/or

DateTime::Format::DateManip

Page 172: The Essential Perl Hackers Toolkit

Use these to transform various time formats from strings into

DateTime objects

Page 173: The Essential Perl Hackers Toolkit

Time::Piece

Page 174: The Essential Perl Hackers Toolkit

Make localtime() and gmtime() return objects...

use Time::Piece; my $t = localtime;print "Time is $t\n";print "Year is ", $t->year, "\n";

Page 175: The Essential Perl Hackers Toolkit

Time::Local

Page 176: The Essential Perl Hackers Toolkit

Gives you inverse functions for localtime() and gmtime()

use Time::Local qw(timelocal timegm);

my $localtime = timelocal($sec, $min, $hour, $mday, $mon, $year);

my $gmtime = timegm($sec, $min, $hour, $mday, $mon, $year);

Page 177: The Essential Perl Hackers Toolkit

DateTime::Tiny(and friends)

Page 178: The Essential Perl Hackers Toolkit

If DateTime is too “heavy” for you, at least use

DateTime::Tiny, or Date::Tiny or Time::Tiny

Page 179: The Essential Perl Hackers Toolkit

Time::ParseDate

Page 180: The Essential Perl Hackers Toolkit

Parsing dates and times is a PITA. Use a module...

use Time::ParseDate qw(parsedate);

$epoch_time =parsedate("12/11/94 2pm", %options)

Page 181: The Essential Perl Hackers Toolkit

Date::Extract

Page 182: The Essential Perl Hackers Toolkit

When you need to extract dates and times from arbitrary blocks of

text...

Page 183: The Essential Perl Hackers Toolkit

But it tries hard to avoid false-positives

Page 184: The Essential Perl Hackers Toolkit

Date::Extract::Surprise

Page 185: The Essential Perl Hackers Toolkit

For when you're willing to be surprised at the dates found!

Page 186: The Essential Perl Hackers Toolkit

Simply works harder to find dates and times in text, at the cost of

possibly false-positives.

Page 187: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 188: The Essential Perl Hackers Toolkit

YAML::Any

Page 189: The Essential Perl Hackers Toolkit

use YAML::Any qw(Dump Load);

$YAML::Indent = 3;

my $yaml = Dump(@objects);

my @objects = Load($yaml);

Page 190: The Essential Perl Hackers Toolkit

JSON

Page 191: The Essential Perl Hackers Toolkit

use JSON qw(to_json from_json);

my $json = to_json($perl_scalar);

my $perl_scalar = from_json($json);

Page 192: The Essential Perl Hackers Toolkit

Text::CSV

Page 193: The Essential Perl Hackers Toolkit

use Text::CSV;

my $csv = Text::CSV->new({ binary => 1 });open my $fh, "<:encoding(utf8)", "test.csv";while ( my $row = $csv->getline( $fh ) ) {

$row->[2] =~ m/pattern/ or next; push @rows, $row;}

Page 194: The Essential Perl Hackers Toolkit

URIURI::Split

URI::Escape

Page 195: The Essential Perl Hackers Toolkit

Spreadsheet::Read

Page 196: The Essential Perl Hackers Toolkit

Parse and read in a bunch of different spreadsheet formats,

including Excel.

Page 197: The Essential Perl Hackers Toolkit

XML::Simple

Page 198: The Essential Perl Hackers Toolkit

For simply reading in and parsing some XML into a data structure.

For non-simple stuff, look at Task::Kensho!

Page 199: The Essential Perl Hackers Toolkit

Check Task::Kensho for more XML essentials.

Page 200: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 201: The Essential Perl Hackers Toolkit

Module::Runtime

Page 202: The Essential Perl Hackers Toolkit

safely and properly load modules at run-time

Page 203: The Essential Perl Hackers Toolkit

IO::Interactive

Page 204: The Essential Perl Hackers Toolkit

Do you know how to properly test for an interactive terminal?

DOUBTFUL

Page 205: The Essential Perl Hackers Toolkit

IPC::Run

Page 206: The Essential Perl Hackers Toolkit

The grand-daddy of running external commands and

controlling the IO

Page 207: The Essential Perl Hackers Toolkit

Capture::Tiny

Page 208: The Essential Perl Hackers Toolkit

Capture stdout and stderr of any code

Page 209: The Essential Perl Hackers Toolkit

It Just Plain Works(tm)

Page 210: The Essential Perl Hackers Toolkit

Net::Serveror

Net::Daemon

Page 211: The Essential Perl Hackers Toolkit

Writing daemons properly is hard

Page 212: The Essential Perl Hackers Toolkit

String::ShellQuote

Page 213: The Essential Perl Hackers Toolkit

(my $unsafe_string =q{string you're passing to system}) =~ s/([\/;()\\])/\\$1/g

Page 214: The Essential Perl Hackers Toolkit

Unsafe, incorrect, and ugly.

Page 215: The Essential Perl Hackers Toolkit

use String::ShellQuote qw(shell_quote);

my $safe_string = shell_quoteq{something you might pass to

system};

Page 216: The Essential Perl Hackers Toolkit

Much safer and more correct

Page 217: The Essential Perl Hackers Toolkit

IPC::System::Simple

Page 218: The Essential Perl Hackers Toolkit

Make using system() and output capturing (a-la backticks) safer

Page 219: The Essential Perl Hackers Toolkit

use IPC::System::Simpleqw(system systemx);

# overrides system() built-in...

# Succeed or die, avoid shell if @argssystem("some_command",@args);

# NEVER invokes the shellsystemx("some_command",@args);

Page 220: The Essential Perl Hackers Toolkit

use IPC::System::Simpleqw(capture capturex);

# Use capture() instead of backticks: (also works in list context)

# Succeeds or dies,# avoids shell if @argsmy $output =

capture("some_command",@args);

# NEVER invokes the shellMy $output =

capturex("some_command",@args);

Page 221: The Essential Perl Hackers Toolkit

Introduction The Little Things Slightly Bigger Things Handling Files and Filesystems Wrangling Data Structures and Types Dealing with Dates and Times Reading and Writing File Formats Potpourri Conclusion

Page 222: The Essential Perl Hackers Toolkit

Don't take my word for it

Page 223: The Essential Perl Hackers Toolkit

Explore the CPAN for yourself

Page 224: The Essential Perl Hackers Toolkit

Create your own toolkit

Page 225: The Essential Perl Hackers Toolkit

Be consistent

Page 226: The Essential Perl Hackers Toolkit

be thoughtful

Page 227: The Essential Perl Hackers Toolkit

Share what you learn

Page 228: The Essential Perl Hackers Toolkit

Contribute and help this language grow!

Page 229: The Essential Perl Hackers Toolkit

Thanks again.I'm hercynium on IRC and

twitter.