Upload
ricardo-signes
View
3.055
Download
4
Embed Size (px)
DESCRIPTION
This talk describes the most likely-to-be-used features added to Perl 5 between v5.10 and v5.16, inclusive.
Citation preview
Perl 5what's new?
Perl 5.10for people who are not totally insane
Perl 5.12for everyday use
Perl 5.14for pragmatists
Perl 5.16for the working programmer
Lexical Semantics!
use feature ‘say’;say “This is a test!”;
{ no feature ‘say’; say “This is fatal!”;}
use 5.16.0;say “This is a test!”;
{ no feature ‘say’; say “This is fatal!”;}
#!/usr/bin/perluse strict;use warnings;use 5.16.0; # use feature ‘:5.16’;
my $x = Reticulator->new;
$x->reticulate(@splines);
#!/usr/bin/perluse strict;use warnings; # no feature;
my $x = Reticulator->new;
$x->reticulate(@splines);
#!/usr/bin/perluse strict;use warnings; # use feature ‘:default’
my $x = Reticulator->new;
$x->reticulate(@splines);
array_base: $[
Cool New Features!
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.”;
perlsub
my $LINES_READ = 0;
sub read_line { $LINES_READ++;
...}
State Variables
perlsub
{ my $LINES_READ = 0;
sub read_line { $LINES_READ++;
... }}
State Variables
perlsub
sub read_line { state $LINES_READ = 0;
$LINES_READ++; ...}
State Variables
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) = @_;
my $price = $amount
perlop
truth and definedness
sub record_sale { my ($product, $amount) = @_;
my $price = $amount || $product->price;
perlop
truth and definedness
sub record_sale { my ($product, $amount) = @_;
my $price = $amount || $product->price;
...
perlop
truth and definedness
sub record_sale { my ($product, $amount) = @_;
my $price = $amount || $product->price;
...}
perlop
truth and definednesssub record_sale { my ($product, $amount) = @_;
$price = defined $amount ? $amount : $product->price;
...}
perlop
truth and definedness
sub record_sale { my ($product, $amount) = @_;
my $price = $amount || $product->price;
...}
perlop
truth and definedness
sub record_sale { my ($product, $amount) = @_;
my $price = $amount // $product->price;
...}
perlop
the new OR operator
sub record_sale { my ($product, $amount) = @_;
$amount //= $product->cost;
...}
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;
$ perl -e ‘print “Foo\n”’
$ perl -e ‘print “Foo\n”’
$ perl -E ‘say “Foo”’
sub fact { my ($x) = @_; # must be +int return $x if $x == 1; return $x * fact($x - 1);}
Recursion!
sub fact { my ($x) = @_; # must be +int return $x if $x == 1; return $x * fact($x - 1);}
Recursion!
my $fact = sub { my ($x) = @_; # must be +int return $x if $x == 1; return $x * $fact->($x - 1);};
Recursion!
my $fact = sub { my ($x) = @_; # must be +int return $x if $x == 1; return $x * $fact->($x - 1);};
Recursion!
my $fact;$fact = sub { my ($x) = @_; # must be +int return $x if $x == 1; return $x * $fact->($x - 1);};
Recursion!
my $fact;$fact = sub { my ($x) = @_; # must be +int return $x if $x == 1; return $x * $fact->($x - 1);};
Recursion!
use Scalar::Util qw(weaken);my $fact = do { my $f1; my $f2 = $f1 = sub { my ($x) = @_; return $x if $x == 1; return $x * $f1->($x - 1); }; weaken($f1); $f1;};
Recursion!
use 5.16.0; # current_sub
my $fact = sub { my ($x) = @_; # must be +int return $x if $x == 1; return $x * __SUB__->($x - 1);};
Recursion!
Filehandles!
autodie
autodie
open my $fh, ‘<‘, $filename;
while (<$fh>) { ...}
close $fh;
autodie
autodie
open my $fh, ‘<‘, $filename or die “couldn’t open $filename: $!”;
while (<$fh>) { ...}
close $fh or die “couldn’t close $filename: $!”;
autodie
autodie
use autodie;
open my $fh, ‘<‘, $filename;
while (<$fh>) { ...}
close $fh;
autodie
autodie
use autodie;
open my $fh, ‘<‘, $filename;
while (<$fh>) { no autodie; rmdir or warn “couldn’t remove $_: $!”;}
close $fh;
autodie
autodie
use autodie;
sub foo { my $filename = shift; open my $fh, ‘<‘, $filename;
while (<$fh>) { ... }} # this implicit close DID NOT AUTODIE
perlopentut
IO::Filesub stream_to_fh { my ($self, $fh) = @_;
fileno $fh or die “can’t stream to closed fh”;
while (my $hunk = $self->next_hunk) { print {$fh} $hunk; }
close $fh or die “error closing: $!”;}
perlopentut
IO::Filesub stream_to_fh { my ($self, $fh) = @_;
$fh->fileno or die “can’t stream to closed fh”;
while (my $hunk = $self->next_hunk) { $fh->print($hunk); }
$fh->close or die “error closing: $!”;}
perlopentut
IO::File
sub stream_to_fh { ... $fh->print($hunk); ... $fh->close or die “error closing: $!”;}
open my $target, ‘>’, ‘/dev/null’ or die “can’t open bit bucket: $!”;
stream_to_fh($target);
perlopentut
IO::Fileuse IO::File;
sub stream_to_fh { ... $fh->print($hunk); ... $fh->close or die “error closing: $!”;}
open my $target, ‘>’, ‘/dev/null’ or die “can’t open bit bucket: $!”;
stream_to_fh($target);
perlopentut
IO::Fileuse 5.14.0;
sub stream_to_fh { ... $fh->print($hunk); ... $fh->close or die “error closing: $!”;}
open my $target, ‘>’, ‘/dev/null’ or die “can’t open bit bucket: $!”;
stream_to_fh($target);
perlopentut
IO::Fileuse 5.14.0;use autodie;sub stream_to_fh { ... $fh->print($hunk); ... $fh->close or die “error closing: $!”;}
open my $target, ‘>’, ‘/dev/null’ or die “can’t open bit bucket: $!”;
stream_to_fh($target);
perlfunc
Package Blocks
package Library::Awesome;our $VERSION = 1.234;
sub foo { ... }
1;
perlfunc
Package Blocks
use 5.12.0;
package Library::Awesome 1.234;
sub foo { ... }
1;
perlfunc
Package Blocks
use 5.12.0;
package Library::Awesome 1.234-alpha;
sub foo { ... }
1;
perlfunc
Package Blocks
package Library::Awesome 1.234 {
sub foo { ... }
}
1;
perldoc
overloading
- the -x overload
- the qr overload
- "no overloading"
- unknown overload warns
Other New Features!
smrt match
if ($x ~~ $y) { ...}
smrt match
perldoc
smrt match
perldoc
smrt match
- if $x and $y are unknown, there are 23 possible dispatch paths
perldoc
smrt match
- if $x and $y are unknown, there are 23 possible dispatch paths
- and some of them redispatch recursively
perldoc
smrt match
- if $x and $y are unknown, there are 23 possible dispatch paths
- and some of them redispatch recursively
- no, you won't remember them all
perldoc
smrt match
- if $x and $y are unknown, there are 23 possible dispatch paths
- and some of them redispatch recursively
- no, you won't remember them all
- ...and they can't be intuited
Matching
if ($x ~~ $y) {...}
Matching
if ($x ~~ $y) {...}if ($str ~~ %hash) {...}
Matching
if ($x ~~ $y) {...}if ($str ~~ %hash) {...}if ($str ~~ @arr) {...}
Matching
if ($x ~~ $y) {...}if ($str ~~ %hash) {...}if ($str ~~ @arr) {...}if ($str ~~ [ \%h, ...]) {...}
Matching
if ($x ~~ $y) {...}if ($str ~~ %hash) {...}if ($str ~~ @arr) {...}if ($str ~~ [ \%h, ...]) {...}if (%hash ~~ %h) {...}
Matching
if ($x ~~ $y) {...}if ($str ~~ %hash) {...}if ($str ~~ @arr) {...}if ($str ~~ [ \%h, ...]) {...}if (%hash ~~ %h) {...}if (%hash ~~ @arr) {...}
Matching
if ($x ~~ $y) {...}if ($str ~~ %hash) {...}if ($str ~~ @arr) {...}if ($str ~~ [ \%h, ...]) {...}if (%hash ~~ %h) {...}if (%hash ~~ @arr) {...}if (%hash ~~ [ \%h,...]) {...}
Matching
given ($x) { when ($y) { ... } when ($z) { ... }}
given ($x) { when ($y) { try { ... } catch { warn “error: $_”; return undef; } }}
each @array
while (my ($i, $v) = each @array) { say “$i: $v”;}
each @array
push $aref, @etc;
Now With Fewer Bugs!
y2038
~$ perl5.10.0 -E ‘say scalar localtime 2**31-1’
~$ perl5.10.0 -E ‘say scalar localtime 2**31-1’Mon Jan 18 22:14:07 2038
~$ perl5.10.0 -E ‘say scalar localtime 2**31-1’Mon Jan 18 22:14:07 2038
~$ perl5.10.0 -E ‘say scalar localtime 2**31’
~$ perl5.10.0 -E ‘say scalar localtime 2**31-1’Mon Jan 18 22:14:07 2038
~$ perl5.10.0 -E ‘say scalar localtime 2**31’Fri Dec 13 15:45:52 1901
~$ perl5.12.0 -E ‘say scalar localtime 2**31-1’
~$ perl5.12.0 -E ‘say scalar localtime 2**31-1’Mon Jan 18 22:14:07 2038
~$ perl5.12.0 -E ‘say scalar localtime 2**31-1’Mon Jan 18 22:14:07 2038
~$ perl5.12.0 -E ‘say scalar localtime 2**31’
~$ perl5.12.0 -E ‘say scalar localtime 2**31-1’Mon Jan 18 22:14:07 2038
~$ perl5.12.0 -E ‘say scalar localtime 2**31’Mon Jan 18 22:14:08 2038
perlvar
$@
Try::Tiny
$@
Try::Tiny
$@
- Well, actually, you use Try::Tiny, right?
Try::Tiny
$@
- Well, actually, you use Try::Tiny, right?
- But this makes Try::Tiny more reliable, too!
Try::Tiny
$@
- Well, actually, you use Try::Tiny, right?
- But this makes Try::Tiny more reliable, too!
- You see, eval and $@ are totally awful
perlfunc
use 5.12.0;
{ package X; sub DESTROY { eval { } }}
eval { my $x = bless {} => ‘X’; die “DEATH!!”;};
warn “ERROR: $@”;
perlfunc
use 5.12.0;
{ package X; sub DESTROY { eval { } }}
eval { my $x = bless {} => ‘X’; die “DEATH!!”;};
warn “ERROR: $@”;
$ perl5.12.4 test.plERROR:
perlfunc
use 5.14.0;
{ package X; sub DESTROY { eval { } }}
eval { my $x = bless {} => ‘X’; die “DEATH!!”;};
warn “ERROR: $@”;
perlfunc
use 5.14.0;
{ package X; sub DESTROY { eval { } }}
eval { my $x = bless {} => ‘X’; die “DEATH!!”;};
warn “ERROR: $@”;
$ perl5.14.1 test.plERROR: DEATH!!
perl -le ‘print $^X’
perl -le ‘print $^X’
10.0: perl
perl -le ‘print $^X’
10.0: perl10.1: perl
perl -le ‘print $^X’
10.0: perl10.1: perl12.0: perl
perl -le ‘print $^X’
10.0: perl10.1: perl12.0: perl14.0: perl
perl -le ‘print $^X’
10.0: perl10.1: perl12.0: perl14.0: perl16.0: /Users/rjbs/perl5/perlbrew/perls/16.0/bin/perl
Simpler Strings
perlunicode
Perl is Good at Unicode
perlunicode
Perl 5.16 is Better
perlunicode
Perl 5.16 is Better
- Unicode 6.1
perlunicode
Perl 5.16 is Better
- Unicode 6.1
- every character property is available
perlunicode
Perl 5.16 is Better
- Unicode 6.1
- every character property is available
- \X in regex is more sensible
perlunicode
“The Unicode Bug”
perlunicode
“The Unicode Bug”
- strings aren’t always treated as Unicode
perlunicode
“The Unicode Bug”
- strings aren’t always treated as Unicode
- this causes weird bugs that take ages to find
perlunicode
“The Unicode Bug”
- strings aren’t always treated as Unicode
- this causes weird bugs that take ages to find
- use feature ‘unicode_strings’;
perlunicode
“The Unicode Bug”
- strings aren’t always treated as Unicode
- this causes weird bugs that take ages to find
- use feature ‘unicode_strings’;
- or use 5.12.0
perldoc
Unicode eval
- eval $str- is that octets or chars?
- what if it includes "use utf8"
- or you're under "use utf8"?
perldoc
Unicode eval
- evalbytes $str- unicode_eval
perldiag
My Favorite 5.12-ism?
if (length $input->{new_email}) { $user->update_email(...);}
perldiag
My Favorite 5.12-ism?
Use of uninitialized value in length at - line 3120.
if (length $input->{new_email}) { $user->update_email(...);}
perldiag
My Favorite 5.12-ism?
if (length $input->{new_email}) { $user->update_email(...);}
perlsyn
say “I \o{23145} Perl 5.14!”;
perlsyn
say “I \o{23145} Perl 5.14!”;
I ♥ Perl 5.14!
perlsyn
say “I \23145 Perl 5.14!”;
I ?45 Perl 5.14!
perlsyn
say “I \023145 Perl 5.14!”;
I 145 Perl 5.14!
perlre
qr{ (1) (2) (3) (4) \7 \10 (5) (6) (7) (8) (9) \7 \10 (10) \7 \10}x;
perlre
qr{ (1) (2) (3) (4) \o{7} \o{10} (5) (6) (7) (8) (9) \o{7} \o{10} (10) \g{7} \g{10}}x;
charnames
Unicode 6.1
charnames
Unicode 6.1
charnames
Unicode 6
charnames
Unicode 6
charnames
Unicode 6
charnames
Unicode 6
charnames
Unicode 6
charnames
Unicode 6
charnames
Unicode 6
charnames
Unicode 6
charnames
Unicode 6
use 5.16.0;
say “I \N{HEAVY BLACK HEART} Queensr” . “\N{LATIN SMALL LETTER Y WITH DIAERESIS}” . “che!”;
\N{...}
case folding
if (lc $foo eq lc $bar) { ...}
Case Folding
if (fc $foo eq fc $bar) { ...}
Case Folding
Case Folding
lc ‘ς‘ ➔ ‘ς‘
Case Folding
lc ‘ς‘ ➔ ‘ς‘uc ‘ς‘ ➔ ‘Σ‘
Case Folding
lc ‘ς‘ ➔ ‘ς‘uc ‘ς‘ ➔ ‘Σ‘fc ‘ς‘ ➔ ‘σ‘
Case Folding
lc ‘ς‘ ➔ ‘ς‘uc ‘ς‘ ➔ ‘Σ‘fc ‘ς‘ ➔ ‘σ‘
lc ‘ß’ ➔ ‘ß’
Case Folding
lc ‘ς‘ ➔ ‘ς‘uc ‘ς‘ ➔ ‘Σ‘fc ‘ς‘ ➔ ‘σ‘
lc ‘ß’ ➔ ‘ß’uc ‘ß’ ➔ ‘SS’
Case Folding
lc ‘ς‘ ➔ ‘ς‘uc ‘ς‘ ➔ ‘Σ‘fc ‘ς‘ ➔ ‘σ‘
lc ‘ß’ ➔ ‘ß’uc ‘ß’ ➔ ‘SS’fc ‘ß’ ➔ ‘ss’
Case Folding
Case Folding
“file under: \L$name”
Case Folding
“file under: \L$name”
“file under: \F$name”
Case Folding
Better 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+)/;
$section = $1$name = $2;$value = $3;
Regex: Named Captures
perlre
Regex: Named Captures$line =~ / (?<section> \w+): (?<name> \w+) \s* = \s* (?<value> \w+)/x;
$section = $+{section};$name = $+{name};$value = $+{value};
perlre
New Regex Modifiers
my $hostname = get_hostname;
$hostname =~ s/\..*//;
perlre
New Regex Modifiers
my $hostname = get_hostname =~ s/\..*//;
perlre
New Regex Modifiers
(my $hostname = get_hostname) =~ s/\..*//;
perlre
New Regex Modifiers
my $hostname = get_hostname =~ s/\..*//r;
perlre
New Regex Modifiers
my @short_names = map { s/\..*//; } @long_names;
perlre
New Regex Modifiers
my @short_names = map { s/\..*//; $_ } @long_names;
perlre
New Regex Modifiers
my @short_names = map { my $x = $_; $x =~ s/\..*//; $x } @long_names;
perlre
New Regex Modifiers
my @short_names = map { s/\..*//r } @long_names;
perlre
New Regex Modifiers
my @short_names = map s/\..*//r, @long_names;
perldoc
New Regex Modifiers
perldoc
/u /a /aa /d /l
"൮" =~ /\d/ ✓ ! ! ¿? ¿?
"ð" =~ /\w/ ✓ ! ! ¿? ¿?
"ff" =~ /ff/i ✓ ✓ ! ¿? ¿?
"ff" =~ /pL/i ✓ ✓ ✓ ¿? ¿?
New Regex Modifiers
perldoc
/u /a /aa /d /l
"൮" =~ /\d/ ✓ ! ! ¿? ¿?
"ð" =~ /\w/ ✓ ! ! ¿? ¿?
"ff" =~ /ff/i ✓ ✓ ! ¿? ¿?
"ff" =~ /pL/i ✓ ✓ ✓ ¿? ¿?
New Regex Modifiers
perldoc
/u /a /aa /d /l
"൮" =~ /\d/ ✓ ! ! ¿? ¿?
"ð" =~ /\w/ ✓ ! ! ¿? ¿?
"ff" =~ /ff/i ✓ ✓ ! ¿? ¿?
"ff" =~ /pL/i ✓ ✓ ✓ ¿? ¿?
New Regex Modifiers
perldoc
/u /a /aa /d /l
"൮" =~ /\d/ ✓ ! ! ¿? ¿?
"ð" =~ /\w/ ✓ ! ! ¿? ¿?
"ff" =~ /ff/i ✓ ✓ ! ¿? ¿?
"ff" =~ /pL/i ✓ ✓ ✓ ¿? ¿?
New Regex Modifiers
perldoc
/u /a /aa /d /l
"൮" =~ /\d/ ✓ ! ! ¿? ¿?
"ð" =~ /\w/ ✓ ! ! ¿? ¿?
"ff" =~ /ff/i ✓ ✓ ! ¿? ¿?
"ff" =~ /pL/i ✓ ✓ ✓ ¿? ¿?
New Regex Modifiers
perldoc
/u /a /aa /d /l
"൮" =~ /\d/ ✓ ! ! ¿? ¿?
"ð" =~ /\w/ ✓ ! ! ¿? ¿?
"ff" =~ /ff/i ✓ ✓ ! ¿? ¿?
"ff" =~ /pL/i ✓ ✓ ✓ ¿? ¿?
New Regex Modifiers
perlre
New Regex Modifiers
# To be really ASCII-only:
die “funny un-American characters” if $str =~ /\P{ASCII}/;
$str =~ /...actual pattern.../;
study
my $re = qr{...complex...};
study
my $re = qr{...complex...};my $str = q{...long complex...};
study
my $re = qr{...complex...};my $str = q{...long complex...};
$str =~ $re; # slow!!
study
my $re = qr{...complex...};my $str = q{...long complex...};
$str =~ $re; # slow!!
study $str; # does stuff
study
my $re = qr{...complex...};my $str = q{...long complex...};
$str =~ $re; # slow!!
study $str; # does stuff
$str =~ $re; # fast!!
study
my $re = qr{...complex...};my $str = q{...long complex...};
$str =~ $re; # slow but right!!
study $str; # does stuff
$str =~ $re; # who knows!!
study
my $re = qr{...complex...};my $str = q{...long complex...};
$str =~ $re; # slow but right!!
study $str; # does nothing
$str =~ $re; # slow but right!!
study
Modder Modlib
perlmodlib
Newly Cored Librarys
- JSON
- HTTP::Tiny
- Module::Metadata
- CPAN::Meta
perlmodlib
Newly Ejected Librarys
- Devel::DProf
- Switch
- the perl4 core
- ...and more
Old Stuff Removed
perlop
qw()
for my $show qw(Smallville Lost V) { $tivo->cancel_pass( $show );}
perlop
qw()
for my $show (qw(Smallville Lost V)) { $tivo->cancel_pass( $show );}
$[
perlvar
$[ - first index of array
perlvar
$[ - first index of array
- so you can make $array[1] mean first
perlvar
$[ - first index of array
- so you can make $array[1] mean first
- isn’t that awesome???
perlvar
$[ - first index of array
- so you can make $array[1] mean first
- isn’t that awesome???
- yeah, about as awesome as Comic Sans
perlvar
$[
$[ = 1;
for (1 .. $#array) { ...}
perlvar
$[
for ($[ .. $#array) { ...}
perlvar
$[
Assigned to $[. Are you some kind of idiot or something? at -e line 123.
perlvar
$[
Use of assignment to $[ is deprecated at -e line 123.
defined @arr
Any questions?
Thank you!