Upload
daoswald
View
71
Download
1
Embed Size (px)
Citation preview
Perl’s Modern Features
Dave Oswald
● Conferences Committee Chairman
● Software Engineer
● Platform & Infrastructure Engineering Manager
A brief history of time...
Perl 1: December 1987Perl 2: June 1988Perl 3: October 1989Perl 4: March 1991Perl 5: October 1994
Perl 5 vs Perl 6
Perl 5 and Perl 6 are different languages with similar design philosophies.
Perl 5 development and innovation will continue as Perl 5.x for the foreseeable future.
Perl 5 Versions
● Ancient History– 5.001 (1995)
– 5.002 (1996)
– 5.003 (1996)
– 5.004 (1997)
– 5.005 (1998)
● Middle History– 5.6 (2000)
– 5.8 (2002)
Stagnation in the Perl 5.8 era
Perl 5 Versions
● Modern Perl– 5.10 (2007)
● 2008● 2009
– 5.12 (2010)
– 5.14 (2011)
– 5.16 (2012)
– 5.18 (2013)
● Middle (Dark) Ages– 5.6 (2000)
– 5.8 (2002)● 2003
● 2004
● 2005
● 2006
● 2007
Annual Release Cycles Since 2010(Perl 5.12)
Perl 5.26(2017)
Filling in of the core ecosystem
Core comparison
● Perl 5.000
– Core: 1MB (53 files)
– Libs: 250KB (76 files)
– Exts: 216KB (38 files)
– Tests: 154KB (92 files)
– Docs: 536KB (62 files)
– Total: 2.2MB (321 files)
● Perl 5.26.0
– Core: 9MB (121 files)
– Libs: 24MB (1200 files)
– Exts: 40MB (3017 files)
– Tests: 10MB (2614 files)
– Docs: 8MB (211 files)
– Total: 91MB (7163 files)
corelist
Perl 5.6.x (2000)
open FH, ‘>foo.txt’;
open my $fh, ‘>’, ‘foo.txt’
{ open my $fh, ‘<’, ‘foo.txt’; my @input = <$fh>;}
# $fh falls out of scope, filehandle closed.
Lexical Filehandles
Three arg open
● Two-argument open exposes the shell.
open my $fh, “>$foo”
$foo = “/tmp/foo; rm -rf /”
● Three-argument open does not expose the shell.
open my $fh, ‘>’, $foo
5.8.x (2002-2007)
PerlIO
open my $fh, ‘>:utf8’, $file;
open my $fh, ‘<+’, \$memory;
5.8.7(The minimum version anyone should ever use)
sitecustomize.pl
Set up a sitecustomize.pl for all of your perlbrew, plenv, and
containers.
6 years
5.10 (2007)
The Renaissance of Perl
This is the stuff you might have missed
New Operators:
Defined
$foo = $bar if ! $foo;
$foo ||= $bar
$foo = $bar if ! $foo;
$foo = $bar if ! defined $foo;
$foo //= $bar;
$foo = $bar if ! defined $foo;
$foo = ($bar) ? $bar : $baz;
$foo = $bar || $baz;
$foo = ($bar) ? $bar : $baz;
$foo = (defined $bar) ? $bar : $baz;
$foo = $bar // $baz;
$foo = (defined $bar) ? $bar : $baz;
Smartmatch
~~
(Too) Smartmatch
~~
print “Yes!” if 42 ~~ @array;
print “Yes” if grep {m/^42$/} @array
Nearly all Perl operators are monomorphic, while data-types are polymorphic.
Smartmatch is polymorphic.
Combining polymorphic operators with polymorphic data is madness.
23 Rules
Smartmatch is deprecated in its current form.
given / when
given ($foo) {when (/^abc/) { $abc = 1; }when (/^def/) { $def = 1; }when (/^xyz/) { $xyz = 1; }default { $nothing = 1; }
}
Perl’s version of a switch statement
given / when uses smartmatch semantics
We just said that smartmatch is madness.
...and that it’s deprecated.
Perl doesn’t really need a switch statement
given / when are deprecated in their current form
say
print “Hello world\n”;
say “Hello world”;
use feature ‘say’;
say “Hello world”;
perl -e ‘print “Hello world\n”’
perl -E ‘say “Hello world”;’
use feature qw(say state);
feature Pragma
feature Pragma
● say● state● switch● unicode_strings● unicode_eval● current_sub● array_base
● lexical_subs● postderef● postderef_qq● signatures● refaliasing● bitwise● declared_refs
state
state
{
my $foo = 1;
sub count {
return $foo++;
}
}
say count(); # 1
say count(); # 2
say count(); # 3
sub count {
state $foo = 1;
return $foo++;
}
say count(); # 1
say count(); # 2
say count(); # 3
Named Capture Buffers
$string =~ m/a(b)c/;
say $1; # “b” if $string matched.
$string =~ m/a(?<foo>b)c/;
say $+{foo}; # “b” if $string matched.
Perl 5.12.x (2010)
delete local
our $foo = 10;{ local $foo = 20; say $foo; # 20}say $foo; # 10
my %hash = (foo => 1, bar => 2);
{ local $hash{foo} = 4; say $hash{foo}; # 4}
say $hash{foo}; # 1
my %hash = (foo => 1, bar => 2);
{ my $bar = delete local $hash{foo}; say $bar; # 1; say $hash{foo}; # undef}
say $hash{foo}; # 1
package NAME VERSION
● package Foo::Bar;
our $VERSION = 1.23;
● package Foo::Bar 1.23;
Perl 5.14 (2011)
/d, /l, /u, /a regexp flags
● Modifiers to alter regex Unicode vs ASCII semantics.
– enough said.
Perl 5.16.x (2012)
__SUB__
sub factorial { my ($x) = @_; return 1 if $x == 1; return($x * factorial($x - 1));};
say factorial(5);
my $factorial = sub { my ($x) = @_; return 1 if $x == 1; return($x * __SUB__->($x - 1));};
say $factorial->(5);
Perl 5.18.x (2013)
Extended Bracketed Character Classes
(Set operations on character classes)
/(?[ \p{Thai} & \p{Digit} ])/
Lexical Subroutines
sub foo { say “Goodbye world!” }
{ my sub foo { say “Hello world!” } foo(); # Hello world!}
foo(); # Goodbye world!
perl 5.20.x (2014)
**** Subroutine Signatures ****
sub add { die "Too many arguments for subroutine" unless @_ <= 2; die "Too few arguments for subroutine" unless @_ >= 2;
my ($x, $y) = @_;
return $x + $y;}
sub add ($x, $y) { return $x + $y;}
sub greet ($name = ‘World’) { say “Hello $name!”;}
hello(); # Hello World!
hello(‘Dave’); # Hello Dave!
sub greet { die "Too many arguments for subroutine" unless @_ <= 1; my $name = $_[0] // ‘World’;
say “Hello $name!”;}
greet(); # Hello World!
greet(‘Dave’); # Hello Dave!
postfix dereferencing
my @values = @{$args->{foo}->[0]}
my @values = @{$args->{foo}->[0]}
my @values = $args->{foo}->[0]->@*
my @values = $args->{foo}->[0]->@*
my @values = $args->{foo}[0]->@*
/r
(Non-destructive substitution)
my $string = “Hello world!”;my $copy = $string;$copy =~ s/world/David/;
my $string = “Hello world!”;
(my $copy = $string) =~ s/world/David/;
my $string = “Hello world!”;
my $copy = $string =~ s/world/David/r;
my $translaterated = $string =~ tr/a-f/A-F/r
Perl 5.22 (2015)
Double Diamond Operator
while(<>) { chomp; say $_ * 2;}
while(<<>>) { chomp; say $_ * 2;}
Why?
./myscript ‘|rm -rf’
Diamond operator implicitly opens files named in @ARGV.
<> is like 2-arg open: Exposes the shell.
<<>> is like 3-arg open. Doesn’t expose the shell.
perl 5.24.x (2016)
BORING
perl 5.26.x (2017)
Indented HERE docs
sub foo { print <<’HERE’;Hello world.This is pretty ugly code formatting.HERE}
sub foo { print <<~’HERE’; Hello world. This is much nicer formatting. HERE}
/xx
m/([+-])([\da-f]+)/
m/ ([+-]) ([\da-f]+)/x
m/ ([+-]) ([ \d a-f ]+)/xx
. removed from @INC
.
cwd
@INC
What’s the problem?
● Different versions of a module can load based on where a script is run from.
● The script’s behavior changes based on where we run it from.– From ~/ it may skip an optional dependency.
– From ~/scripts may find an optional dependency in @INC and load it.
● User-writable directories such as /tmp were unsafe as a working directory for running any script.
As long as . is in @INC you cannot ever be sure when you run a script from a path that is writable
by anyone aside from yourself.
You cannot ever be sure modules you are using don’t have optional dependencies.
Steps to protect yourself
● Use Perl 5.26
Perl 5.26 is the minimum Perl version anyone should ever use
Impractical advice.
Steps to protect yourself
● Use Perl 5.26● Set up a sitecustomize.pl
– System, perlbrew, plenv, containers
Steps to protect yourself
● Use Perl 5.26● Set up a sitecustomize.pl
– System, perlbrew, plenv, containers
– Perl must be built with -Dusesitecustomize
– Check state usingperl -MConfig -E ‘say $Config{usesitecustomize}’
Set up sitecustomize.pl if your distribution doesn’t have one
already.
That’s all that has happened since Perl 5.6 in 2000?
Hundreds... thousands of bug fixes, performance improvements, documentation enhancements,
and other features we don’t have time to discuss.
Thousands of...
● Security Patches / Enhancements● Bug fixes● Performance Enhancements● Documentation Enhancements● New features● Unicode improvements● Etc.
Examples
● Improved integer performance● Better hash key order randomization to inhibit
DOS attacks.● Many Unicode upgrades and improvements● fc (fold case)
● More module improvements than you can shake a stick at.
● Thousands of pages of added documentation.
How do I know when feature X was added to Perl?
How do I know when feature X was added to Perl?
How do I know when feature X was added to Perl?
grep -rin 'signatures' $(find $(perl -E 'say for @INC') -name '*delta.pod')
Encourage upgrades to modern Perl versions.
Rather than upgrading “system Perl” use perlbrew or plenv.
Object Orientation
package Foo
sub new {
my $class = shift;
return bless {@_}, $class;
}
sub name {
return $_[0]->{‘name’};
}
use Moo;
has name => (is => ro);
Many wonderful Modules
● Try::Tiny
● Capture::Tiny
● List::MoreUtils
● Mojolicious
● Moose or Moo
● CPAN has over 20000 distributions.
A concept is only valid in Perl if it can be expressed as a one-liner
$ perl -Mojo -E 'say g("mojolicious.org")->dom("h1")->map("text")->join("\n")'
Perl development is alive and well.
(Rumors to the contrary are grossly exaggerated)
Modern Perl
modernperlbooks.com
perldoc perldelta
perldoc perlhist
corelist