Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Perl 5.10 for People Who Are Not (Totally) Insane

Perl 5.10 for People Who Are Not (Totally) Insane

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.

Ricardo Signes

July 23, 2007
Tweet

More Decks by Ricardo Signes

Other Decks in Programming

Transcript

  1. 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)
  2. 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?
  3. 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
  4. 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)
  5. perl51000delta Lexicascopasmartwhat? - lexically scoped user pragmata! - pluggable regex

    compilation engines! - trie-based non-recursive pattern matching!
  6. perl51000delta Lexicascopasmartwhat? - lexically scoped user pragmata! - pluggable regex

    compilation engines! - trie-based non-recursive pattern matching! - thread-safe weak refkey hashes!
  7. perl51000delta Yes, You Care - Not everything in 5.10 is

    esoteric. - Not everything in 5.10 is for gurus.
  8. 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.
  9. 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.
  10. feature First: A Warning - 5.10 is backwards compatible -

    but adds new keywords and operators
  11. feature First: A Warning - 5.10 is backwards compatible -

    but adds new keywords and operators - they’re not enabled by default
  12. feature First: A Warning - 5.10 is backwards compatible -

    but adds new keywords and operators - they’re not enabled by default - use feature ‘mtfnpy’;
  13. 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;
  14. 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
  15. 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!
  16. 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
  17. perlfunc - new built-in, say - it’s like print -

    but it adds a newline for you say $what
  18. perlfunc say $what print “Hello, world!\n”; print “$message\n”; print “$_\n”

    for @lines; say “Hello, world!”; say $message; say for @lines;
  19. perlop truth and definedness sub record_sale { my ($product, $amount)

    = @_; $amount = defined $amount ? $amount : $product->cost; ... }
  20. perlop the new OR operator sub record_sale { my ($product,

    $amount) = @_; $amount //= $product->cost; ... }
  21. perlsub $lines_left = 100; sub read_line { die “trial period

    expired” unless $lines_left-- > 0; ... } State Variables
  22. perlsub my $lines_left = 100; sub read_line { die “trial

    period expired” unless $lines_left-- > 0; ... } State Variables
  23. perlsub { my $lines_left = 100; sub read_line { die

    “trial period expired” unless $lines_left-- > 0; ... } } State Variables
  24. 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; ... }
  25. perlsub { my $lines_left = 100; sub read_line { die

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

    period expired” unless $lines_left-- > 0; ... } State Variables
  27. perlfunc if ( -f $file and -w $file and -z

    $file ) { unlink $file; } Stackable File Tests
  28. perlfunc if ( -f $file and -w _ and -z

    _ ) { unlink $file; } Stackable File Tests
  29. perlsyn Smart Matching - a new kind of comparison operator

    - its behavior depends on its inputs
  30. perlsyn Smart Matching - a new kind of comparison operator

    - its behavior depends on its inputs - “if these two things match...”
  31. 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...
  32. perlsyn Smart Matching if ($foo ~~ undef) { ... }

    elsif ($foo ~~ @array) { ... }
  33. perlsyn Smart Matching if ($foo ~~ undef) { ... }

    elsif ($foo ~~ @array) { ... } elsif ($foo ~~ $code) { ... }
  34. perlsyn Smart Matching if ($foo ~~ undef) { ... }

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

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

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

    elsif ($foo ~~ @array) { ... } elsif ($foo ~~ $code) { ... } elsif ($foo ~~ %hash) { ... } elsif ($foo ~~ qr/re/) { ... } elsif ($foo ~~ $bar) { ... } else { ... }
  38. perlsyn Smart Matching given ($foo) { when (undef) { ...

    } when (@array) { ... } when ($code) { ... } when (%hash) { ... } when (qr/re/) { ... } when ($bar) { ... } default { ... } }
  39. perlsyn Smart Matching if ($foo ~~ undef) { ... }

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

    elsif ($foo ~~ $array) { ... } elsif ($foo ~~ $code) { ... } elsif ($foo ~~ $hash) { ... } elsif ($foo ~~ qr/re/) { ... } elsif ($foo ~~ $bar) { ... } else { ... }
  41. perlsyn Smart Matching given ($foo) { when (undef) { ...

    } when ($aref) { ... } when ($code) { ... } when ($href) { ... } when ($regex) { ... } when ($object) { ... } default { ... } }
  42. perlsyn Smart Matching given ($foo) { when ($test_1) { ...

    } when ($test_2) { ... } when ($test_3) { ... } when ($test_4) { ... } when ($test_5) { ... } when ($test_6) { ... } default { ... } }
  43. perlsyn Smart Matching @want = @have->where($test) @want = @have->where(sub{ ……

    }) @want = @have->where(qr/.../sm) @want = @have->where([ 1,2,3 ])
  44. perlsyn Smart Matching sub where { my ($array, $test) =

    @_; if (ref $test eq ‘ARRAY’) {
  45. perlsyn Smart Matching sub where { my ($array, $test) =

    @_; if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test;
  46. perlsyn Smart Matching sub where { my ($array, $test) =

    @_; if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array;
  47. perlsyn Smart Matching sub where { my ($array, $test) =

    @_; if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; }
  48. perlsyn Smart Matching sub where { my ($array, $test) =

    @_; if (ref $test eq ‘ARRAY’) { my %known = map {$_=>1} @$test; return grep { $known{$_} } @$array; } if (ref $test eq ‘Regexp’) {
  49. perlsyn Smart Matching sub 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;
  50. perlsyn Smart Matching sub 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; }
  51. perlsyn Smart Matching sub 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’) {
  52. perlsyn Smart Matching sub 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;
  53. perlsyn Smart Matching sub 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; }
  54. perlsyn Smart Matching sub 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”
  55. perlsyn Smart Matching sub 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” }
  56. perlsyn Smart Matching sub where { my ($array, $test) =

    @_; grep { $_ ~~ $test } @$array; }
  57. perlsyn Smart Matching @want = @have->where( hash ) @want =

    @have->where( class ) SmartMatch::Sugar
  58. perlsyn Smart Matching @want = @have->where( hash ) @want =

    @have->where( class ) @want = @have->where(isa(‘Foo’)) SmartMatch::Sugar
  59. perldiag $str = “Greetings, $name. Your last login was $last.

    It is now $time.”; Better Error Message(s)
  60. 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.
  61. 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.”;
  62. 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
  63. 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
  64. 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
  65. Hash::Util::FieldHash Inside-Out Objects sub size { my $self = shift;

    if (@_) { return $self->{size} = shift; } else { return $self->{size}; } }
  66. Hash::Util::FieldHash Inside-Out Objects my %size; sub size { my $self

    = shift; if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; } }
  67. Hash::Util::FieldHash Inside-Out Objects my %size; sub size { my $self

    = shift; my $id = refaddr $self; if (@_) { return $size{ $id } = shift; } else { return $size{ $id }; } }
  68. Hash::Util::FieldHash Inside-Out Objects my %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 }; }
  69. Hash::Util::FieldHash Inside-Out Objects my %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 }; } }
  70. Hash::Util::FieldHash Inside-Out Objects my %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 }; } }
  71. Hash::Util::FieldHash Field Hashes - they’re just like hashes - objects

    as keys become object ids - but get destroyed and cloned
  72. Hash::Util::FieldHash Field Hashes my %size; sub size { my $self

    = shift; if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; } }
  73. Hash::Util::FieldHash Field Hashes fieldhash my %size; sub size { my

    $self = shift; if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; } }
  74. Hash::Util::FieldHash Field Hashes { fieldhash my %size; sub size {

    my $self = shift; if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; } } }
  75. Hash::Util::FieldHash Field Hashes sub size { my $self = shift;

    fieldhash state %size; if (@_) { return $size{ $self } = shift; } else { return $size{ $self }; } }
  76. perlvar for (@lines) { chomp; next if /^#/; next unless

    length; s/a/b/; sanity_check; say; } Lexical Topic
  77. 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; }
  78. perlvar for my $_ (@lines) { chomp; next if /^#/;

    next unless length; s/a/b/; sanity_check; say; } Lexical Topic
  79. perlre Regex: Named Captures - find matches by name, not

    position - avoid the dreaded $1 - no longer second to Python or .Net!
  80. perlre $lhs_re = qr/(\w+):(\w+)/; $rhs_re = qr/(\w+)/; $line ~~ /$lhs_re

    = $rhs_re/; $name = $2; $value = $3; Regex: Named Captures
  81. perlre $line ~~ /$lhs_re = $rhs_re/; $name = $+{ name

    }; $value = $+{ value }; Regex: Named Captures
  82. wtf Regex: Exit Strategy my $wtf_re = qr{ xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xf f\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:”.\\\[\]\000-\037\x80-\x

    ff]+(?![^(\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\x8 0-\xff]+(?![^(\040)<>@,;:”.\\\[\]\000-\037\x80-\xff])|”[^\\\x80-\xff\n \015”]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015”]*)*”)[\040\t]*(?:\([^\\\x 80-\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 };
  83. perlreapi Alternate Regex Engines - lets you change how regex

    work - but not how you use them (=~, s///, etc)
  84. re::engine::POSIX Alternate Regex Engines my $regex = qr{ ... };

    my @files = $find->file->in( $root ); say for grep { slurp ~~ $re } @files;
  85. re::engine::POSIX Alternate Regex Engines my $regex = qr{ ... };

    my @files = $find->file->in( $root ); say for grep { slurp ~~ $re } @files;
  86. 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;
  87. 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;