name: title class: center, middle, inverse # perldelta ## The Good Parts ### v5.8 - v5.20 .footnote.right[Chicago.PM] --- class: center, middle Perl 5.8 was released July 18, 2002 ![Perl 5.8 was released July 18, 2002](images/perl-5.8-announcement.png) Facebook was launched in 2004 --- class: center, middle Perl 5.8.8 was released January 31, 2006 ![Perl 5.8.8 was released January 31, 2006](images/perl-5.8.8-announcement.png) Twitter was launched in July 2006 --- class: middle # Perl Releases * 5.10 - 2007-12-18 * 5.12 - 2010-04-12 * 5.14 - 2011-05-14 * 5.16 - 2012-05-20 * 5.18 - 2013-05-18 * 5.20 - 2014 --- class: middle # OS Perl versions: * Debian Squeeze (6.0 - 2011-02-06): 5.10.1 * Debian Wheezy (7.0 - 2013-05-04): 5.14.2 * Debian Jessie (8.0 - Developing): 5.18.2 * Ubuntu Lucid (10.04LTS - 2010-04): 5.10.1 * Ubuntu Precise (12.04LTS - 2012-04): 5.14.2 * Ubuntu Saucy (13.10 - 2013-10): 5.14.2 * RHEL 6 (2010-11-10): 5.10? 5.12? * RHEL 7 (Fedora 19 - 2013-07-02): 5.16.3 --- class: center, middle, inverse # Perl 5.10 ## 2007-12-18 --- class: middle, center # `use feature` ## Import new features --- class: middle # Import a single feature ```perl use feature qw( say ); say "Hello, World!"; ``` --- class: middle # Import a bundle of features ```perl use feature qw( :5.10 ); given ( $^V ) { when ( $_ lt v5.14 ) { say "Hello, history!"; } when ( $_ gt v5.14 ) { say "Hello, future!"; } } ``` --- class: middle, center # `say` ## Print with newline `use feature qw( say )` `use feature qw( :5.10 )` --- class: middle # Say ```perl print "Hello, World!\n"; ``` ```perl use feature qw( say ); say "Hello, World!"; ``` --- class: middle, center # `state` variables ## Keep a value between calls to a sub `use feature qw( state )` `use feature qw( :5.10 )` --- class: middle # State .code-half[ .center[Before] ```perl my $i = 0; sub plus_i { print "$i\n"; $i++; } plus_i() for 1..5; ``` ] .code-half[ .center[After] ```perl use feature qw( state say ); sub plus_x { state $x = 0; say $x; $x++; } plus_x() for 1..5; ``` ] --- class: middle, center # `//` ## Defined-or No use required --- # Defined-or ```perl use feature qw( say ); sub false_default { say shift || "Default"; } sub defined_default { say shift // "Default"; } false_default( 1 ); false_default( 0 ); false_default( ); defined_default( 1 ); defined_default( 0 ); defined_default( ); ``` .center[Fun fact: This syntax highlighter doesn't understand defined-or!] --- class: middle, center # `given/when` ## Switch `use feature qw( switch )` `use feature qw( :5.10 )` --- class: middle .code-half[ # If ```perl sub condition { my ( $foo ) = @_; if ( $foo =~ /^FX/ ) { say "Foreign Exchange!"; } elsif ( $foo =~ /^UST/ ) { say "US Treasuries"; } else { say "Unknown!"; } } ``` ] .code-half[ # Given ```perl use feature qw( switch ); sub given_when { my ( $foo ) = @_; given ( $foo ) { when ( /^FX/ ) { say "Foreign Exchange"; } when ( /^UST/ ) { say "US Treasuries"; } default { say "Unknown!"; } } } ``` ] --- class: middle # For/When ```perl use feature qw( switch ); sub for_when { for ( @_ ) { when ( /^FX/ ) { say "Foreign Exchange"; } when ( /^UST/ ) { say "US Treasuries"; } default { say "Unknown!"; } } } ``` --- class: middle, center # Regex Named Groups ## Less magic, more descriptive `(?<name>...)` `\g{name}` `$+{name}` --- class: middle # Regex Named Groups .code-half[ ```perl use feature qw( say ); my $in = "foo: bar\nbaz: biz"; my $old_parse = qr{ ([^:\s]+) : \s* ([^\n]+) }x; while ( $in =~ /$old_parse/g ) { say "Key: $1"; say "Value: $2"; } ``` ] .code-half[ ```perl use feature qw( say ); my $in = "foo: bar\nbaz: biz"; my $new_parse = qr{ (?<key>[^:\s]+) : \s* (?<value>[^\n]+) }x; while ( $in =~ /$new_parse/g ) { say "Key: $+{key}"; say "Value: $+{value}"; } ``` ] --- class: middle, center # Recursive Regex ## Turn regex into parsers `(?1)` `(?-1)` `(?&name)` --- class: middle # Recursive Regex .code-half[ ```perl use feature qw( say ); my $in = "[ [ 1 2 ] 3 [ 4 5 ] ]"; # INT -> \d+ # LIST -> "[" (LIST|INT)* "]" my $parse = qr( (?<LIST> \s* \[ \s* (?: (?&LIST) | (?<INT>\d+) \s* )* \s* \] \s* )* )x; ``` ] .code-half[ ```perl $in =~ $parse; use Data::Dumper; say Dumper \%+; ``` ] --- class: middle, center # Module::CoreList ## Perl core modules, features, and releases `corelist` --- class: middle # corelist * `corelist Module` - Which Perl first had Module? * `corelist -f X` - Which feature bundle is X in? * `corelist -r` - Perl releases --- class: center, middle, inverse # Perl 5.12 ## 2010-04-12 --- class: center, middle # `...` ## Yada-yada-yada No `use feature` needed --- class: middle # Yada-yada-yada ```perl use feature qw( say ); sub foo { die "Unimplemented" } eval { foo(); }; say "foo(): $@"; sub bar { ... } eval { bar(); }; say "bar(): $@"; ``` --- class: center, middle # `each @array; keys @array; values @array;` No `use feature` needed --- class: middle # Arrays are Key/Value Pairs ```perl use feature qw( say ); my @array = qw( foo bar baz ); say 'C-style for loop'; for ( my $i = 0; $i < @array; $i++ ) { say "$i: $array[$i]"; } say 'List of indicies'; for my $i ( 0..$#array ) { say "$i: $array[$i]"; } say 'each @array'; while ( my ( $k, $v ) = each @array ) { say "$k: $v"; } say 'keys @array'; say join ", ", keys @array; say 'values @array'; say join ", ", values @array; ``` --- class: center, middle # `autodie` ## Never forget to check errors again! `use autodie` --- class: middle # autodie ```perl sub old { open my $fh, '<', 'DOESNOTEXIST' or die "Can't open 'DOESNOTEXIST' for reading: '$!'"; } sub new { use autodie; open my $fh, '<', 'DOESNOTEXIST'; } use feature qw( say ); eval { old(); }; say "old(): $@"; eval { new(); }; say "new(): $@"; ``` --- class: center, middle, inverse # Perl 5.14 ## 2011-05-14 --- class: center, middle # `s///r` ## Non-destructive substitution No `use feature` required --- class: middle # Non-destructive substitution ```perl use feature qw( say ); sub old_change { my ( $to_change ) = @_; my $changed = $to_change; $changed =~ s/foo/bar/; say "$to_change -> $changed"; } sub new_change { my ( $to_change ) = @_; my $changed = $to_change =~ s/foo/bar/r; say "$to_change -> $changed"; } old_change( "foo" ); new_change( "foo" ); ``` --- class: middle # Best used in map() ```perl use feature qw( say ); my @array = qw( fooo baro bazo ); sub old { say for map { my $x = $_; $x =~ s/o/0/; $x } @_; } sub new { say for map { s/o/0/r } @_; } say "old()"; old( @array ); say "new()"; new( @array ); ``` --- class: center, middle # More reliable exception throwing ## `DESTROY` can't change `$@` --- class: center, middle ``` Ceci n'est pas un exemple ``` --- class: center, middle # `HTTP::Tiny` ## Simple core HTTP client `use HTTP::Tiny` --- class: middle # No more LWP::Simple ```perl use feature qw( say ); use HTTP::Tiny; my $resp = HTTP::Tiny->new->get( 'http://example.com' ); say $resp->{content}; ``` --- class: center, middle # `JSON::PP` ## Simple core JSON parser `use JSON::PP` --- class: middle # JSON ```perl use feature qw( say ); use JSON::PP; my $json = '{ "foo": "bar", "baz": "fuzz" }'; my $hash = JSON::PP->new->decode( $json ); say "foo: " . $hash->{foo}; ``` --- class: center, middle, inverse # Perl 5.16 ## 2012-05-26 --- class: center, middle # `__SUB__` ## Reference to the current running sub No `use feature` needed --- class: middle # Recurse Without Names ```perl use feature qw( say ); my $old; $old = sub { my ( $i ) = @_; return $i if $i <= 1; return $old->( $i - 1 ) + $old->( $i - 2 ); }; # Hello memory leak! my $new = sub { my ( $i ) = @_; return $i if $i <= 1; return __SUB__->( $i - 1 ) + __SUB__->( $i - 2 ); }; say $old->( 3 ); say $new->( 3 ); ``` --- class: center, middle, inverse # Perl 5.18 ## 2013-05-18 --- class: center, middle # `my sub`, `our sub`, `state sub` ## Lexical subroutines `use feature qw( lexical_subs )` --- class: middle # My subs, Your subs ```perl use feature qw( say lexical_subs ); sub old { say "old()"; my $inner = sub { say "inner()"; }; $inner->(); } sub new { say "new()"; my sub inner { say "inner()"; } inner(); } old(); new(); ``` --- class: middle # Hide your subs ```perl use feature qw( say lexical_subs ); sub new { say "new()"; my sub inner { say "inner()"; } inner(); } sub hide { my sub new { say "hidden new()"; } new(); } new(); hide(); ``` --- class: center, middle, inverse # Perl 5.20 ## Coming in 2014 --- class: center, middle # `%hash{...}`, `%array[...]` ## Hash-based slices No `use feature` needed --- class: middle # Hash/Array in, Hash out ```perl use feature qw( say ); my %hash = ( foo => 0, bar => 1 ); my @array = qw( foo bar ); my %old_part_hash = map { $_ => $hash{$_} } grep { $_ eq 'foo' } keys %hash; my %part_hash = %hash{"foo"}; say "part_hash{foo} -> $part_hash{foo}"; my %part_array = %array[0]; say "part_array{0} -> $part_array{0}"; ``` --- class: center, middle # `$hash_ref->%*`, `$ary_ref->@*` ## Postfix dereference operators --- class: middle # Read From Left to Right ```perl my $href = { foo => "bar", }; my $aref = [ "foo", "bar" ]; say %{ $href }; say $href->%*; say @{ $aref }; say $aref->@*; ``` --- class: middle # Deep Diving Dereference ```perl say %{ $data->{results}[0]{symbols} }; ``` ```perl say $data->{results}[0]{symbols}->%* ``` --- class: center, middle # `sub foo( $bar, @baz );` ## Subroutine signatures `use feature qw( signatures );` --- class: middle # Unpack @_ automatically ```perl use feature qw( say signatures ); sub old { my ( $bar, @baz ) = @_; die "First argument missing" unless $bar; say "$bar -> @baz"; } sub new( $bar, @baz ) { say "$bar -> @baz"; } old( "foo" ); eval { old() }; say "old(): $@"; new( "foo" ); eval { new() }; say "new(): $@"; ``` --- class: center, middle, inverse # Questions!