perl 5.10 for people who aren't totally insane
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
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?