Perl 5.10 for People Who Aren't Totally Insane

Post on 11-Jun-2015

84.311 views 1 download

Tags:

description

All the hype about perl 5.10 can sound a little intimidating. User-level pragmata! Overloadable smartmatching operator! Thread-safe refkey hashes! For Pete's sake, have you heard about lexically scoped pluggable regexp engines? It's enough to make you think that 5.10's changes are just for the hard-core perl hackers, but it couldn't be further from the truth! The new version of Perl is full of changes that are easy to use and pack lots of useful benefits for doing plain old every day Perl programming. We'll look at the new features, small and large, and see why you, too, will love 5.10.

Transcript of Perl 5.10 for People Who Aren't Totally Insane

Perl 5.10insanefor people who are not

Perl 5.10insanetotallyfor people who are not

perl5100delta

5.10 isn’t like 5.8.x

perl5100delta

5.10 isn’t like 5.8.x

- features only get added in new 5.x releases

perl5100delta

5.10 isn’t like 5.8.x

- features only get added in new 5.x releases

- it’s been 5 years since the last release (5.8)

perl51000delta

5.10 is Way Cool

perl51000delta

5.10 is Way Cool

- no significant new features in Perl since 2002

perl51000delta

5.10 is Way Cool

- no significant new features in Perl since 2002

- remember how bad you wanted to see Star Wars: Episode 1?

perl51000delta

5.10 is Way Cool

- no significant new features in Perl since 2002

- remember how bad you wanted to see Star Wars: Episode 1?

- that’s how excited you should be for 5.10

perl51000delta

5.10 is Way Cool

- no significant new features in Perl since 2002

- remember how bad you wanted to see Star Wars: Episode 1?

- that’s how excited you should be for 5.10

- but it won’t suck (no POD race scene)

perl51000delta

Lexicascopasmartwhat?

perl51000delta

Lexicascopasmartwhat?

- lexically scoped user pragmata!

perl51000delta

Lexicascopasmartwhat?

- lexically scoped user pragmata!

- pluggable regex compilation engines!

perl51000delta

Lexicascopasmartwhat?

- lexically scoped user pragmata!

- pluggable regex compilation engines!

- trie-based non-recursive pattern matching!

perl51000delta

Lexicascopasmartwhat?

- lexically scoped user pragmata!

- pluggable regex compilation engines!

- trie-based non-recursive pattern matching!

- thread-safe weak refkey hashes!

perl51000delta

Yes, You Care

perl51000delta

Yes, You Care

- Not everything in 5.10 is esoteric.

perl51000delta

Yes, You Care

- Not everything in 5.10 is esoteric.

- Not everything in 5.10 is for gurus.

perl51000delta

Yes, You Care

- Not everything in 5.10 is esoteric.

- Not everything in 5.10 is for gurus.

- Not everything in 5.10 is for C programmers.

perl51000delta

Yes, You Care

- Not everything in 5.10 is esoteric.

- Not everything in 5.10 is for gurus.

- Not everything in 5.10 is for C programmers.

- Not everything in 5.10 is super advanced.

feature

First: A Warning

feature

First: A Warning

- 5.10 is backwards compatible

feature

First: A Warning

- 5.10 is backwards compatible

- but adds new keywords and operators

feature

First: A Warning

- 5.10 is backwards compatible

- but adds new keywords and operators

- they’re not enabled by default

feature

First: A Warning

- 5.10 is backwards compatible

- but adds new keywords and operators

- they’re not enabled by default

- use feature ‘mtfnpy’;

feature

First: A Warning

- 5.10 is backwards compatible

- but adds new keywords and operators

- they’re not enabled by default

- use feature ‘mtfnpy’;

- use 5.010;

feature

First: A Warning

- 5.10 is backwards compatible

- but adds new keywords and operators

- they’re not enabled by default

- use feature ‘mtfnpy’;

- use 5.010;

- read the perldoc

feature

First: A Warning

- 5.10 is backwards compatible

- but adds new keywords and operators

- they’re not enabled by default

- use feature ‘mtfnpy’;

- use 5.010;

- read the perldoc I’m a perldoc ref!

feature

First: A Warning

- 5.10 is backwards compatible

- but adds new keywords and operators

- they’re not enabled by default

- use feature ‘mtfnpy’;

- use 5.010;

- read the perldoc

say what

perlfunc

- new built-in, say

- it’s like print

- but it adds a newline for you

say $what

perlfunc

say $what

perlfunc

say $what

print “Hello, world!\n”;

perlfunc

say $what

print “Hello, world!\n”;

print “$message\n”;

perlfunc

say $what

print “Hello, world!\n”;

print “$message\n”;

print “$_\n” for @lines;

perlfunc

say $what

print “Hello, world!\n”;

print “$message\n”;

print “$_\n” for @lines;

say “Hello, world!”;

perlfunc

say $what

print “Hello, world!\n”;

print “$message\n”;

print “$_\n” for @lines;

say “Hello, world!”;

say $message;

perlfunc

say $what

print “Hello, world!\n”;

print “$message\n”;

print “$_\n” for @lines;

say “Hello, world!”;

say $message;

say for @lines;

truth and definedness

perlop

truth and definedness

perlop

truth and definedness

sub record_sale {

perlop

truth and definedness

sub record_sale { my ($product, $amount) = @_;

perlop

truth and definedness

sub record_sale { my ($product, $amount) = @_;

$amount ||= $product->cost;

perlop

truth and definedness

sub record_sale { my ($product, $amount) = @_;

$amount ||= $product->cost;

...

perlop

truth and definedness

sub record_sale { my ($product, $amount) = @_;

$amount ||= $product->cost;

...}

perlop

truth and definednesssub record_sale { my ($product, $amount) = @_;

$amount = defined $amount ? $amount : $product->cost;

...}

perlop

truth and definedness

sub record_sale { my ($product, $amount) = @_;

$amount ||= $product->cost;

...}

perlop

truth and definedness

sub record_sale { my ($product, $amount) = @_;

$amount ||= $product->cost;

...}

perlop

the new OR operator

sub record_sale { my ($product, $amount) = @_;

$amount //= $product->cost;

...}

perlop

the new OR operator

$setting = defined $given ? $given : $default;

perlop

the new OR operator

$setting = $given;unless (defined $setting) { $setting = $default;}

perlop

the new OR operator

$setting = $given || $default;

perlop

the new OR operator

$setting = $given // $default;

keeping state

perlsub

$lines_left = 100;

sub read_line { die “trial period expired” unless $lines_left-- > 0; ...}

State Variables

perlsub

my $lines_left = 100;

sub read_line { die “trial period expired” unless $lines_left-- > 0; ...}

State Variables

perlsub

{ my $lines_left = 100;

sub read_line { die “trial period expired” unless $lines_left-- > 0; ... }}

State Variables

perlsub

package Trial::Period;sub new { my ($class, $arg) = @_; my $guts = { lines_left => $arg->{lines}, error_msg => $arg->{error}, }; return bless $guts => $class;}

sub consume_line { my ($self) = @_; $self->{lines_left}--;}

sub lines_left { my ($self) = @_; return $self->{lines_left};}

sub assert_lines_left { my ($self) = @_; unless ($self->lines_left) { die $self->{error_msg}; }}1;

State Variables

my $LINES = 100;my $ERROR = “sorry, trial period over”;my $TRIAL = Trial::Period->new({ lines => $LINES, error => $ERROR,});

sub read_line { $TRIAL->assert_lines_left; ...}

perlsub

{ my $lines_left = 100;

sub read_line { die “trial period expired” unless $lines_left-- > 0; ... }}

State Variables

perlsub

sub read_line { state $lines_left = 100; die “trial period expired” unless $lines_left-- > 0; ...}

State Variables

-x stacking

perlfunc

if ( -f $fileand -w $fileand -z $file

) {unlink $file;

}

Stackable File Tests

perlfunc

if ( -f $file and -w _ and -z _) {unlink $file;

}

Stackable File Tests

perlfunc

if (-f -w -z $file) {unlink $file;

}

Stackable File Tests

smart matching

perlsyn

Smart Matching

perlsyn

Smart Matching

- a new kind of comparison operator

perlsyn

Smart Matching

- a new kind of comparison operator

- its behavior depends on its inputs

perlsyn

Smart Matching

- a new kind of comparison operator

- its behavior depends on its inputs

- “if these two things match...”

perlsyn

Smart Matching

- a new kind of comparison operator

- its behavior depends on its inputs

- “if these two things match...”

- hard to tell, easy to show...

perlsyn

Smart Matching

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }elsif ($foo ~~ @array) { ... }

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }elsif ($foo ~~ @array) { ... }elsif ($foo ~~ $code) { ... }

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }elsif ($foo ~~ @array) { ... }elsif ($foo ~~ $code) { ... }elsif ($foo ~~ %hash) { ... }

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }elsif ($foo ~~ @array) { ... }elsif ($foo ~~ $code) { ... }elsif ($foo ~~ %hash) { ... }elsif ($foo ~~ qr/re/) { ... }

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }elsif ($foo ~~ @array) { ... }elsif ($foo ~~ $code) { ... }elsif ($foo ~~ %hash) { ... }elsif ($foo ~~ qr/re/) { ... }elsif ($foo ~~ $bar) { ... }

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }elsif ($foo ~~ @array) { ... }elsif ($foo ~~ $code) { ... }elsif ($foo ~~ %hash) { ... }elsif ($foo ~~ qr/re/) { ... }elsif ($foo ~~ $bar) { ... }else { ... }

perlsyn

Smart Matchinggiven ($foo) { when (undef) { ... } when (@array) { ... } when ($code) { ... } when (%hash) { ... } when (qr/re/) { ... } when ($bar) { ... } default { ... }}

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }elsif ($foo ~~ @array) { ... }elsif ($foo ~~ $code) { ... }elsif ($foo ~~ %hash) { ... }elsif ($foo ~~ qr/re/) { ... }elsif ($foo ~~ $bar) { ... }else { ... }

perlsyn

Smart Matching

if ($foo ~~ undef) { ... }elsif ($foo ~~ $array) { ... }elsif ($foo ~~ $code) { ... }elsif ($foo ~~ $hash) { ... }elsif ($foo ~~ qr/re/) { ... }elsif ($foo ~~ $bar) { ... }else { ... }

perlsyn

Smart Matching

my $test;

perlsyn

Smart Matchinggiven ($foo) { when (undef) { ... } when ($aref) { ... } when ($code) { ... } when ($href) { ... } when ($regex) { ... } when ($object) { ... } default { ... }}

perlsyn

Smart Matchinggiven ($foo) { when ($test_1) { ... } when ($test_2) { ... } when ($test_3) { ... } when ($test_4) { ... } when ($test_5) { ... } when ($test_6) { ... } default { ... }}

perlsyn

Smart Matching

perlsyn

Smart Matching

@want = @have->where($test)

perlsyn

Smart Matching

@want = @have->where($test)

@want = @have->where(sub{ …… })

perlsyn

Smart Matching

@want = @have->where($test)

@want = @have->where(sub{ …… })

@want = @have->where(qr/.../sm)

perlsyn

Smart Matching

@want = @have->where($test)

@want = @have->where(sub{ …… })

@want = @have->where(qr/.../sm)

@want = @have->where([ 1,2,3 ])

perlsyn

Smart Matching

perlsyn

Smart Matchingsub where {

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) {

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test;

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array;

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; }

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) {

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) { return grep { $_ =~ $test } @$array;

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) { return grep { $_ =~ $test } @$array; }

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) { return grep { $_ =~ $test } @$array; } if (ref $test eq ‘CODE’) {

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) { return grep { $_ =~ $test } @$array; } if (ref $test eq ‘CODE’) { return grep { $test->($_) } @$array;

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) { return grep { $_ =~ $test } @$array; } if (ref $test eq ‘CODE’) { return grep { $test->($_) } @$array; }

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) { return grep { $_ =~ $test } @$array; } if (ref $test eq ‘CODE’) { return grep { $test->($_) } @$array; }

die “invalid test”

perlsyn

Smart Matchingsub where { my ($array, $test) = @_;

if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) { return grep { $_ =~ $test } @$array; } if (ref $test eq ‘CODE’) { return grep { $test->($_) } @$array; }

die “invalid test”}

perlsyn

Smart Matching

sub where { my ($array, $test) = @_; grep { $_ ~~ $test } @$array;}

perlsyn

Smart Matching

SmartMatch::Sugar

perlsyn

Smart Matching

@want = @have->where( hash )

SmartMatch::Sugar

perlsyn

Smart Matching

@want = @have->where( hash )

@want = @have->where( class )

SmartMatch::Sugar

perlsyn

Smart Matching

@want = @have->where( hash )

@want = @have->where( class )

@want = @have->where(isa(‘Foo’))

SmartMatch::Sugar

unknown undefined

perldiag

$str = “Greetings, $name. Your last login was $last. It is now $time.”;

Better Error Message(s)

perldiag

$str = “Greetings, $name. Your last login was $last. It is now $time.”;

Better Error Message(s)

Use of uninitialized value in concatenation (.) or string at hello.plx line 9.

perldiag

Better Error Message(s)

Use of uninitialized value $time in concatenation (.) or string at hello.plx line 9.

$str = “Greetings, $name. Your last login was $last. It is now $time.”;

inside-out objects

Hash::Util::FieldHash

Inside-Out Objects

Hash::Util::FieldHash

Inside-Out Objects

- traditional objects are a hashref

Hash::Util::FieldHash

Inside-Out Objects

- traditional objects are a hashref

- look up attrs in the obj itself by attr name

Hash::Util::FieldHash

Inside-Out Objects

- traditional objects are a hashref

- look up attrs in the obj itself by attr name

- inside-out objects are content-free refs

Hash::Util::FieldHash

Inside-Out Objects

- traditional objects are a hashref

- look up attrs in the obj itself by attr name

- inside-out objects are content-free refs

- look up attrs in an external hash by obj id

Hash::Util::FieldHash

Inside-Out Objects

- traditional objects are a hashref

- look up attrs in the obj itself by attr name

- inside-out objects are content-free refs

- look up attrs in an external hash by obj id

- there are complications for inside-out objects

Hash::Util::FieldHash

Inside-Out Objects

sub size { my $self = shift;

if (@_) { return $self->{size} = shift; } else { return $self->{size}; }}

Hash::Util::FieldHash

Inside-Out Objectsmy %size;sub size { my $self = shift;

if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; }}

Hash::Util::FieldHash

Inside-Out Objectsmy %size;sub size { my $self = shift; my $id = refaddr $self;

if (@_) { return $size{ $id } = shift; } else { return $size{ $id }; }}

Hash::Util::FieldHash

Inside-Out Objectsmy %size;sub size { my $self = shift; my $id = refaddr $self;

if (@_) { return $size{ $id } = shift; } else { return $size{ $id }; }}

sub DESTROY { my $id = refaddr $_[0]; delete $size{ $id };}

Hash::Util::FieldHash

Inside-Out Objectsmy %size;sub size { my $self = shift; my $id = refaddr $self;

if (@_) { return $size{ $id } = shift; } else { return $size{ $id }; }}

sub DESTROY { my $id = refaddr $_[0]; delete $size{ $id };}

sub CLONE { my $class = shift;

my @properties = map { values %$_ } values %PROP_DATA_FOR;

for my $old_id ( keys %OBJ ) {

my $object = $OBJ{ $old_id }; my $new_id = refaddr $object;

for my $prop ( @properties ) { next unless exists $prop->{ $old }; $prop->{ $new } = $prop->{ $old }; delete $prop->{ $old }; }

weaken ( $OBJ{ $new } = $object ); delete $OBJ{ $old }; }}

Hash::Util::FieldHash

Inside-Out Objectsmy %OBJECT_REGISTRY;my %size;sub size { my $self = shift; my $id = refaddr $self;

$self->register_object;

if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; }}

sub DESTROY { my $id = refaddr $_[0]; delete $size{ $id }; delete $OBJECT_REGISTRY{ $id };}

sub register_object { my ($self) = @_; my $id = refaddr $self; $OBJECT_REGISTRY{ $id } = $self;}

sub CLONE { my $class = shift;

my @properties = map { values %$_ } values %PROP_DATA_FOR;

for my $old_id ( keys %OBJECT_REGISTRY ) {

my $object = $OBJECT_REGISTRY{ $old_id }; my $new_id = refaddr $object;

for my $prop ( @properties ) { next unless exists $prop->{ $old_id }; $prop->{ $new_id } = $prop->{ $old_id }; delete $prop->{ $old_id }; }

weaken ( $OBJECT_REGISTRY{ $new_id } = $object ); delete $OBJECT_REGISTRY{ $old_id }; }}

Hash::Util::FieldHash

Field Hashes

Hash::Util::FieldHash

Field Hashes

- they’re just like hashes

Hash::Util::FieldHash

Field Hashes

- they’re just like hashes

- objects as keys become object ids

Hash::Util::FieldHash

Field Hashes

- they’re just like hashes

- objects as keys become object ids

- but get destroyed and cloned

Hash::Util::FieldHash

Field Hashesmy %size;sub size { my $self = shift;

if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; }}

Hash::Util::FieldHash

Field Hashesfieldhash my %size;sub size { my $self = shift;

if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; }}

Hash::Util::FieldHash

Field Hashes{ fieldhash my %size; sub size { my $self = shift; if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; } }}

Hash::Util::FieldHash

Field Hashessub size { my $self = shift; fieldhash state %size;

if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; }}

lexical topic

(topic is how you say $_)

perlvar

for (@lines) { chomp; next if /^#/; next unless length; s/a/b/; sanity_check; say;}

Lexical Topic

perlvar

Lexical Topic

for my $line (@lines) { chomp $line; next if $line ~~ /^#/; next unless length $line; $line =~ s/a/b/; sanity_check($line); say $line;}

perlvar

for my $_ (@lines) { chomp; next if /^#/; next unless length; s/a/b/; sanity_check; say;}

Lexical Topic

Regex

named captures

perlre

Regex: Named Captures

perlre

Regex: Named Captures

- find matches by name, not position

perlre

Regex: Named Captures

- find matches by name, not position

- avoid the dreaded $1

perlre

Regex: Named Captures

- find matches by name, not position

- avoid the dreaded $1

- no longer second to Python or .Net!

perlre

# our hypothetical format

section:property = value

Regex: Named Captures

perlre

$line ~~ /(\w+):(\w+) = (\w+)/;

$name = $2;$value = $3;

Regex: Named Captures

perlre

$lhs_re = qr/(\w+):(\w+)/;$rhs_re = qr/(\w+)/;

$line ~~ /$lhs_re = $rhs_re/;

$name = $2;$value = $3;

Regex: Named Captures

perlre

$line ~~ /$lhs_re = $rhs_re/;

$name = $2;$value = $3;

Regex: Named Captures

perlre

$line ~~ /$lhs_re = $rhs_re/;

$name = $+{ name }; $value = $+{ value };

Regex: Named Captures

perlre

$lhs_re = qr/(\w+):(\w+)/;$rhs_re = qr/(\w+)/;

Regex: Named Captures

perlre

$lhs_re = qr/(\w+):(?<name>\w+)/;$rhs_re = qr/(?<value>\w+)/;

Regex: Named Captures

better backrefs

perlre

Regex: Backreference

m{< (\w+) > .+ < /\1 > }x

perlre

Regex: Backreference

m{< (\w+) > .+ < /\1 > }x

perlre

Regex: Backreference

\10

perlre

Regex: Backreference

qr{(\d)\10}

perlre

Regex: Backreference

qr{ (\d) \1 0}x

perlre

Regex: Backreference

m{< (\w+) > .+ < /\1 > }x

perlre

Regex: Backreference

m{< (\w+) > .+ < /\g{1} > }x

perlre

Regex: Backreference

\10

perlre

Regex: Backreference

\g{10}

perlre

Regex: Backreference

qr{(\d)\10}

perlre

Regex: Backreference

qr{(\d)\g{1}0}

perlre

Regex: Backreference

qr{(\d)\g{-1}0}

perlre

Regex: Backreference

qr{ (?<digit>\d) \g{digit} 0}x

wtf

Regex: Exit Strategymy $wtf_re = qr{xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:”.\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:”.\\\[\]\000-\037\x80-\xff])|”[^\\\x80-\xff\n\015“]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015”]*)*”)[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:”.\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:”.\\\[\]\000-\037\x80-\xff])|”[^\\\x80-\xff\n\015”]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015”]*)*”)[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:”.\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:”.\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\04};

perlop

Regex: Backreference

if ($str =~ $wtf_re) { ...}

perlop

Regex: Backreference

if ($str ~~ $wtf_re) { ...}

lexically scoped alternate trie-based reentrant user-defined regex pragmata

flexible regex

perlreapi

Alternate Regex Engines

perlreapi

Alternate Regex Engines

- lets you change how regex work

perlreapi

Alternate Regex Engines

- lets you change how regex work

- but not how you use them (=~, s///, etc)

re::engine::POSIX

Alternate Regex Engines

re::engine::POSIX

Alternate Regex Engines

egrep -r -l PATTERN DIR

re::engine::POSIX

Alternate Regex Engines

my $regex = qr{ ... };

my @files = $find->file->in( $root );

say for grep { slurp ~~ $re } @files;

re::engine::POSIX

Alternate Regex Engines

re::engine::POSIX

Alternate Regex Engines

egrep -r -l ‘.+?’ DIR

re::engine::POSIX

Alternate Regex Engines

my $regex = qr{ ... };

my @files = $find->file->in( $root );

say for grep { slurp ~~ $re } @files;

re::engine::POSIX

Alternate Regex Engines

use re::engine::POSIX;

my $regex = qr{ ... };

my @files = $find->file->in( $root );

say for grep { slurp ~~ $re } @files;

re::engine::POSIX

Alternate Regex Engines

use re::engine::POSIX;

my $regex = qr{ ... }x;

my @files = $find->file->in( $root );

say for grep { slurp ~~ $re } @files;

http://www.perl.org/get.html

Any questions?