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

Perl 5 at 20: Perl v5.20.0

Perl 5 at 20: Perl v5.20.0

Ricardo Signes

July 23, 2014
Tweet

More Decks by Ricardo Signes

Other Decks in Programming

Transcript

  1. Experiments •new features we're trying out •might not stay around

    •or might change how they work •don't build your business on them
  2. sub xyzzy { given (1) { ... } } experimental

    syntax error at -e line 1, near ") {"
  3. use feature 'switch'; sub xyzzy { given (1) { ...

    } } experimental given is experimental at -e line 1.
  4. use feature 'switch'; no warnings "experimental::smartmatch"; sub xyzzy { given

    (1) { ... } } experimental Unknown warnings category 'experimental::smartmatch'
  5. use feature 'switch'; no if $] >= 5.018, warnings =>

    "experimental::feature_name"; sub xyzzy { given (1) { ... } } experimental
  6. $sess # is our session ->{user} # is the logged

    in user ->logins # is an arrayref of logins
  7. $sess # We must record ->{user} # a new login

    ->logins # to this arrayref.
  8. push $sess # We must record ->{user} # a new

    login ->logins # to this arrayref.
  9. push $sess $sess # We must record ->{user} # a

    new login ->logins # to this arrayref.
  10. push $sess->{user} $sess # We must record ->{user} # a

    new login ->logins # to this arrayref.
  11. push @{ $sess->{user}->logins }, $login; $sess # We must record

    ->{user} # a new login ->logins # to this arrayref.
  12. push $sess->{user}->logins , $queue $sess # We must record ->{user}

    # a new login ->logins # to this arrayref.
  13. push $sess->{user}->logins , @{ $queue->{unflushed}->logins }; $sess # We must

    record ->{user} # a new login ->logins # to this arrayref.
  14. push $sess->{user}->logins , @{ $queue->{unflushed}->logins }; ! process(@{ $queue->{unhandled}->jobs });

    ! $sess # We must record ->{user} # a new login ->logins # to this arrayref.
  15. push $sess->{user}->logins , @{ $queue->{unflushed}->logins }; ! process(@{ $queue->{unhandled}->jobs });

    ! map { $_ > $#{$in[0]} } @{$job->input} $sess # We must record ->{user} # a new login ->logins # to this arrayref.
  16. @{ expr } ⇢ ⇢ ⇢ ⇢ expr->@* %{ expr

    } ⇢ ⇢ ⇢ ⇢ expr->%*
  17. @{ expr } ⇢ ⇢ ⇢ ⇢ expr->@* %{ expr

    } ⇢ ⇢ ⇢ ⇢ expr->%* ${ expr } ⇢ ⇢ ⇢ ⇢ expr->$*
  18. @{ expr } ⇢ ⇢ ⇢ ⇢ expr->@* %{ expr

    } ⇢ ⇢ ⇢ ⇢ expr->%* ${ expr } ⇢ ⇢ ⇢ ⇢ expr->$* &{ expr } ⇢ ⇢ ⇢ ⇢ expr->&*
  19. @{ expr } ⇢ ⇢ ⇢ ⇢ expr->@* %{ expr

    } ⇢ ⇢ ⇢ ⇢ expr->%* ${ expr } ⇢ ⇢ ⇢ ⇢ expr->$* &{ expr } ⇢ ⇢ ⇢ ⇢ expr->&* *{ expr } ⇢ ⇢ ⇢ ⇢ expr->**
  20. @{ expr } ⇢ ⇢ ⇢ ⇢ expr->@* %{ expr

    } ⇢ ⇢ ⇢ ⇢ expr->%* ${ expr } ⇢ ⇢ ⇢ ⇢ expr->$* &{ expr } ⇢ ⇢ ⇢ ⇢ expr->&* *{ expr } ⇢ ⇢ ⇢ ⇢ expr->**
  21. @{ expr } ⇢ ⇢ ⇢ ⇢ expr->@* %{ expr

    } ⇢ ⇢ ⇢ ⇢ expr->%* ${ expr } ⇢ ⇢ ⇢ ⇢ expr->$* &{ expr } ⇢ ⇢ ⇢ ⇢ expr->&* *{ expr } ⇢ ⇢ ⇢ ⇢ expr->** $#{ expr } ⇢ ⇢ ⇢ ⇢ expr->$#*
  22. # terastring.perl $x = "x" x 1_000_000; $y = $x

    for 1..1_000_000; ~$ time perl5.18.2 terastring.pl
  23. # terastring.perl $x = "x" x 1_000_000; $y = $x

    for 1..1_000_000; ~$ time perl5.18.2 terastring.pl 53.476 total
  24. # terastring.perl $x = "x" x 1_000_000; $y = $x

    for 1..1_000_000; ~$ time perl5.20.0 terastring.pl ~$ time perl5.18.2 terastring.pl 53.476 total
  25. # terastring.perl $x = "x" x 1_000_000; $y = $x

    for 1..1_000_000; ~$ time perl5.20.0 terastring.pl 0.165 total ~$ time perl5.18.2 terastring.pl 53.476 total
  26. # terastring.perl $x = "x" x 1_000_000; $y = $x

    for 1..1_000_000; ~$ time perl5.20.0 terastring.pl 0.165 total ~$ time perl5.18.2 terastring.pl 53.476 total …sometimes…
  27. warn "The Warning" if $favorite_band =~ /^Queensrÿche/; ! warn "The

    Warning" if $favorite_band =~ /^Queensrÿche/;
  28. ¨

  29. 0028; 0029; o # LEFT PARENTHESIS 0029; 0028; c #

    RIGHT PARENTHESIS 005B; 005D; o # LEFT SQUARE BRACKET 005D; 005B; c # RIGHT SQUARE BRACKET 007B; 007D; o # LEFT CURLY BRACKET 007D; 007B; c # RIGHT CURLY BRACKET ⋮ 300C; 300D; o # LEFT CORNER BRACKET 300D; 300C; c # RIGHT CORNER BRACKET
  30. 0028; 0029; o # LEFT PARENTHESIS 0029; 0028; c #

    RIGHT PARENTHESIS 005B; 005D; o # LEFT SQUARE BRACKET 005D; 005B; c # RIGHT SQUARE BRACKET 007B; 007D; o # LEFT CURLY BRACKET 007D; 007B; c # RIGHT CURLY BRACKET ⋮ 300C; 300D; o # LEFT CORNER BRACKET 300D; 300C; c # RIGHT CORNER BRACKET U+0028 = ( U+0029 = )
  31. 0028; 0029; o # LEFT PARENTHESIS 0029; 0028; c #

    RIGHT PARENTHESIS 005B; 005D; o # LEFT SQUARE BRACKET 005D; 005B; c # RIGHT SQUARE BRACKET 007B; 007D; o # LEFT CURLY BRACKET 007D; 007B; c # RIGHT CURLY BRACKET ⋮ 300C; 300D; o # LEFT CORNER BRACKET 300D; 300C; c # RIGHT CORNER BRACKET U+0028 = ( U+0029 = )
  32. 0028; 0029; o # LEFT PARENTHESIS 0029; 0028; c #

    RIGHT PARENTHESIS 005B; 005D; o # LEFT SQUARE BRACKET 005D; 005B; c # RIGHT SQUARE BRACKET 007B; 007D; o # LEFT CURLY BRACKET 007D; 007B; c # RIGHT CURLY BRACKET ⋮ 300C; 300D; o # LEFT CORNER BRACKET 300D; 300C; c # RIGHT CORNER BRACKET U+0028 = ( U+0029 = ) qw( x y )
  33. 0028; 0029; o # LEFT PARENTHESIS 0029; 0028; c #

    RIGHT PARENTHESIS 005B; 005D; o # LEFT SQUARE BRACKET 005D; 005B; c # RIGHT SQUARE BRACKET 007B; 007D; o # LEFT CURLY BRACKET 007D; 007B; c # RIGHT CURLY BRACKET ⋮ 300C; 300D; o # LEFT CORNER BRACKET 300D; 300C; c # RIGHT CORNER BRACKET U+0028 = ( U+0029 = ) U+300C = ʮ U+300D = ʯ qw( x y )
  34. 0028; 0029; o # LEFT PARENTHESIS 0029; 0028; c #

    RIGHT PARENTHESIS 005B; 005D; o # LEFT SQUARE BRACKET 005D; 005B; c # RIGHT SQUARE BRACKET 007B; 007D; o # LEFT CURLY BRACKET 007D; 007B; c # RIGHT CURLY BRACKET ⋮ 300C; 300D; o # LEFT CORNER BRACKET 300D; 300C; c # RIGHT CORNER BRACKET U+0028 = ( U+0029 = ) U+300C = ʮ U+300D = ʯ qw( x y )
  35. 0028; 0029; o # LEFT PARENTHESIS 0029; 0028; c #

    RIGHT PARENTHESIS 005B; 005D; o # LEFT SQUARE BRACKET 005D; 005B; c # RIGHT SQUARE BRACKET 007B; 007D; o # LEFT CURLY BRACKET 007D; 007B; c # RIGHT CURLY BRACKET ⋮ 300C; 300D; o # LEFT CORNER BRACKET 300D; 300C; c # RIGHT CORNER BRACKET U+0028 = ( U+0029 = ) U+300C = ʮ U+300D = ʯ qw( x y ) qwʮ x y ʯ
  36. sub assert_scored { my ($input) = @_; return score_for($awesome_arg) or

    die("no score for $input!"); } warning: Possible precedence issue with control flow operator
  37. use locale; •UTF-8 locales work •"use locale" works if your

    OS has no locale support (you get LC=C)
  38. use locale; •UTF-8 locales work •"use locale" works if your

    OS has no locale support (you get LC=C) •-DL for tracing locales
  39. use locale; •UTF-8 locales work •"use locale" works if your

    OS has no locale support (you get LC=C) •-DL for tracing locales •radix character doesn't leak
  40. use 5.10.0; use POSIX 'locale_h'; ! my $x = 1.234;

    ! { use locale; setlocale(LC_ALL, 'de_DE'); } ! say $x;
  41. use 5.10.0; use POSIX 'locale_h'; ! my $x = 1.234;

    ! { use locale; setlocale(LC_ALL, 'de_DE'); } ! say $x; 1,234
  42. use 5.10.0; use POSIX 'locale_h'; ! my $x = 1.234;

    ! { # this can be in a distant package! use locale; setlocale(LC_ALL, 'de_DE'); } ! say $x; 1,234
  43. use 5.10.0; use POSIX 'locale_h'; ! my $x = 1.234;

    ! ! ! reticulate_splines; ! ! say $x; 1,234
  44. use 5.10.0; use POSIX 'locale_h'; use JSON; my $x =

    1.234; ! ! ! reticulate_splines; ! ! say JSON->new->encode({value => $x});
  45. use 5.10.0; use POSIX 'locale_h'; use JSON; my $x =

    1.234; ! ! ! reticulate_splines; ! ! say JSON->new->encode({value => $x}); { "value": 1,234 }
  46. use 5.10.0; use POSIX 'locale_h'; use JSON; my $x =

    1.234; ! ! ! reticulate_splines; ! ! say JSON->new->encode([ 1, 234, $x ]);
  47. use 5.10.0; use POSIX 'locale_h'; use JSON; my $x =

    1.234; ! ! ! reticulate_splines; ! ! say JSON->new->encode([ 1, 234, $x ]); [1,234,1,234]
  48. $ host-status | perl -n -F, -le \ 'print "$F[0]

    is $F[1]"' Sample input: myhost,up,angry,80
  49. $ host-status | perl -n -F, -le \ 'print "$F[0]

    is $F[1]"' Sample input: myhost,up,angry,80 Program output:
  50. $ host-status | perl -n -F, -le \ 'print "$F[0]

    is $F[1]"' Sample input: myhost,up,angry,80 Program output: ␠is␠
  51. $ host-status | perl -n -F, -le \ 'print "$F[0]

    is $F[1]"' Sample input: myhost,up,angry,80 Program output: ␠is␠ you forgot the -a
  52. my @array = qw[ foo bar baz quux ]; my

    @slice = @array[ 1, 3 ];
  53. my @array = qw[ foo bar baz quux ]; my

    @slice = @array[ 1, 3 ];
  54. my @array = qw[ foo bar baz quux ]; my

    @slice = @array[ 1, 3 ]; # Now @slice is ("bar", "quux")
  55. my @array = qw[ foo bar baz quux ]; my

    @slice = @array[ 1, 3 ]; # Now @slice is ("bar", "quux")
  56. my %hash = (a => 1, b => 2, c

    => 3); my @slice = @hash{ 'a', 'c' };
  57. my %hash = (a => 1, b => 2, c

    => 3); my @slice = @hash{ 'a', 'c' };
  58. my %hash = (a => 1, b => 2, c

    => 3); my @slice = @hash{ 'a', 'c' }; # Now @slice is (1, 3)
  59. my %hash = (a => 1, b => 2, c

    => 3); my @slice = @hash{ 'a', 'c' }; # Now @slice is (1, 3)
  60. my %hash = (a => 1, b => 2, c

    => 3); my %slice = %hash{ 'a', 'c' };
  61. my %hash = (a => 1, b => 2, c

    => 3); my %slice = %hash{ 'a', 'c' }; # Now %slice is (a => 1, c => 3)
  62. my %hash = (a => 1, b => 2, c

    => 3); my @slice = %hash{ 'a', 'd', 'a' };
  63. my %hash = (a => 1, b => 2, c

    => 3); my @slice = %hash{ 'a', 'd', 'a' }; # Now @slice is # (a => 1, d => undef, a => 1)
  64. my $record = { artist => $album{artist} title => $album{title},

    tracks => $album{tracks}, year => $album{edition}{year},
  65. my $record = { artist => $album{artist} title => $album{title},

    tracks => $album{tracks}, year => $album{edition}{year}, label => $album{edition}{lable},
  66. my $record = { artist => $album{artist} title => $album{title},

    tracks => $album{tracks}, year => $album{edition}{year}, label => $album{edition}{lable}, };
  67. my $record = { artist => $album{artist} title => $album{title},

    tracks => $album{tracks}, ! year => $album{edition}{year}, label => $album{edition}{lable}, };
  68. my $record = { artist => $album{artist} title => $album{title},

    tracks => $album{tracks}, ! year => $album{edition}{year}, label => $album{edition}{label}, };
  69. my $record = { %album{qw( artist title tracks )}, !

    year => $album{edition}{year}, label => $album{edition}{label}, };
  70. # Your mission: get a slice of values # from

    $hashref->{x} my $hashref = { x => { ... } };
  71. # Your mission: get a slice of values # from

    $hashref->{x} my $hashref = { x => { ... } }; $hashref->{x}{ k1, k2 } #1
  72. # Your mission: get a slice of values # from

    $hashref->{x} my $hashref = { x => { ... } }; $hashref->{x}{ k1, k2 } #1
  73. # Your mission: get a slice of values # from

    $hashref->{x} my $hashref = { x => { ... } }; $hashref->{x}{ k1, k2 } #1 @{ $hashref->{x} }->{ k1, k2 } #2
  74. # Your mission: get a slice of values # from

    $hashref->{x} my $hashref = { x => { ... } }; $hashref->{x}{ k1, k2 } #1 @{ $hashref->{x} }->{ k1, k2 } #2
  75. # Your mission: get a slice of values # from

    $hashref->{x} my $hashref = { x => { ... } }; $hashref->{x}{ k1, k2 } #1 @{ $hashref->{x} }->{ k1, k2 } #2 @{ $hashref->{x}{ k1, k2 } } #3
  76. # Your mission: get a slice of values # from

    $hashref->{x} my $hashref = { x => { ... } }; $hashref->{x}{ k1, k2 } #1 @{ $hashref->{x} }->{ k1, k2 } #2 @{ $hashref->{x}{ k1, k2 } } #3
  77. # Your mission: get a slice of values # from

    $hashref->{x} my $hashref = { x => { ... } }; $hashref->{x}{ k1, k2 } #1 @{ $hashref->{x} }->{ k1, k2 } #2 @{ $hashref->{x}{ k1, k2 } } #3 @{ $hashref->{x} }{ k1, k2} #4
  78. my $record = { %album{qw( artist title tracks )}, !

    year => $album{edition}{year}, label => $album{edition}{label}, };
  79. my $record = { %album{qw( artist title tracks )}, !

    $album->{edition}->%{ qw(year label) } );
  80. my @array = qw[ foo bar baz quux ]; my

    @slice = @array[ 1, 3 ];
  81. my @array = qw[ foo bar baz quux ]; my

    @slice = @array[ 1, 3 ];
  82. my @array = qw[ foo bar baz quux ]; my

    @slice = @array[ 1, 3 ]; # @slice is ("bar", "quux")
  83. my @array = qw[ foo bar baz quux ]; my

    @slice = @array[ 1, 3 ]; # @slice is ("bar", "quux")
  84. my @array = qw[ foo bar baz quux ]; my

    @slice = %array[ 1, 3 ];
  85. my @array = qw[ foo bar baz quux ]; my

    @slice = %array[ 1, 3 ];
  86. my @array = qw[ foo bar baz quux ]; my

    @slice = %array[ 1, 3 ]; # @slice is (1 => "bar", 3 => "quux")
  87. my @array = qw[ foo bar baz quux ]; my

    @slice = %array[ 1, 3 ]; # @slice is (1 => "bar", 3 => "quux")
  88. my @array = qw[ foo bar baz quux ]; my

    @slice = %array[ 3, 1 ];
  89. my @array = qw[ foo bar baz quux ]; my

    @slice = %array[ 3, 1 ];
  90. my @array = qw[ foo bar baz quux ]; my

    @slice = %array[ 3, 1 ]; # @slice is (3 => "quuz", 1 => "bar")
  91. my @array = qw[ foo bar baz quux ]; my

    @slice = %array[ 3, 1 ]; # @slice is (3 => "quuz", 1 => "bar")
  92. Compiling a split operator whose third argument is a named

    constant evaluating to 0 … split /,/, $input, SPLIT_FIELDS;
  93. Compiling a split operator whose third argument is a named

    constant evaluating to 0 no longer causes the constant's value to change. split /,/, $input, SPLIT_FIELDS;
  94. sub add { ($x, $y) = @_; ! return $x

    + $y; } add(1,2); &add(1,2);
  95. sub add { ($x, $y) = @_; ! return $x

    + $y; } add(1,2); &add(1,2);
  96. sub add { ($x, $y) = @_; ! return $x

    + $y; } add(1,2); &add(1,2); do add (1,2);
  97. sub add { ($x, $y) = @_; ! return $x

    + $y; } add(1,2); &add(1,2); do add (1,2);
  98. say $^H; # <-- private compile-time hints say ; #

    <-- private compile-time hints
  99. say $^H; # <-- private compile-time hints say ; #

    <-- private compile-time hints say $␈; # <-- private compile-time hints
  100. sub add { my $x = shift // 0; my

    $y = shift // 0; ! return $x + $y; }
  101. add(1,2) ⇢ 3 add() ⇢ runtime error! add(1) ⇢ runtime

    error! sub add ($x, $y) { return $x + $y; }
  102. add(1,2) ⇢ 3 add() ⇢ runtime error! add(1) ⇢ runtime

    error! add(1,2,3) ⇢ runtime error! sub add ($x, $y) { return $x + $y; }
  103. sub add ($x, $y = 0) { return $x +

    $y; } add(1,2) ⇢ 3
  104. sub add ($x, $y = 0) { return $x +

    $y; } add(1,2) ⇢ 3
  105. sub add ($x, $y = 0) { return $x +

    $y; } add(1,2) ⇢ 3 add() ⇢ runtime error!
  106. sub add ($x, $y = 0) { return $x +

    $y; } add(1,2) ⇢ 3 add() ⇢ runtime error! add(1) ⇢ 1
  107. sub add ($x, $y = 0) { return $x +

    $y; } add(1,2) ⇢ 3 add() ⇢ runtime error! add(1) ⇢ 1 add(1,2,3) ⇢ runtime error!
  108. sub add ($x = 0, $y) { return $x +

    $y; } compile time error!!
  109. sub add ($x = 0, $y = 0) { !

    return $x + $y; }
  110. sub add ($x = 0, $y = 0) { !

    return $x + $y; } add(1,2) ⇢ 3
  111. sub add ($x = 0, $y = 0) { !

    return $x + $y; } add(1,2) ⇢ 3
  112. sub add ($x = 0, $y = 0) { !

    return $x + $y; } add(1,2) ⇢ 3 add() ⇢ 0
  113. sub add ($x = 0, $y = 0) { !

    return $x + $y; } add(1,2) ⇢ 3 add() ⇢ 0 add(1) ⇢ 1
  114. sub add ($x = 0, $y = 0) { !

    return $x + $y; } add(1,2) ⇢ 3 add() ⇢ 0 add(1) ⇢ 1 add(1,2,3) ⇢ runtime error!
  115. sub add ($x = 0, $y = 0) { !

    return $x + $y; } add(1,2) ⇢ 3 ! add() ⇢ 0 add(1) ⇢ 1 add(1,2,3) ⇢ runtime error!
  116. sub add ($x = 0, $y = (return $x)) {

    ! return $x + $y; } add(1,2) ⇢ 3 ! add() ⇢ 0 add(1) ⇢ 1 add(1,2,3) ⇢ runtime error!
  117. sub add ($x = (return 0), $y = (return $x))

    { ! return $x + $y; } add(1,2) ⇢ 3 ! add() ⇢ 0 add(1) ⇢ 1 add(1,2,3) ⇢ runtime error!
  118. # adder.pl sub add ($x, $y) { return $x +

    $y; } $ perl -MO=Deparse adder.pl
  119. # adder.pl sub add ($x, $y) { return $x +

    $y; } sub add { die 'Too many arguments for subroutine' unless @_ <= 2; die 'Too few arguments for subroutine' unless @_ >= 2; my $x = $_[0]; my $y = $_[1]; (); return $x + $y; } $ perl -MO=Deparse adder.pl
  120. # adder.pl sub add ($x, $y = (return $x)) {

    return $x + $y; } $ perl -MO=Deparse adder.pl
  121. # adder.pl sub add ($x, $y = (return $x)) {

    return $x + $y; } sub add { die 'Too many arguments for subroutine' unless @_ <= 2; die 'Too few arguments for subroutine' unless @_ >= 1; my $x = $_[0]; my $y = @_ >= 2 ? $_[1] : (return $x); (); return $x + $y; } $ perl -MO=Deparse adder.pl
  122. # adder.pl sub add ($x = (return 0), $y =

    (return $x)) { return $x + $y; }
  123. # adder.pl sub add ($x = (return 0), $y =

    (return $x)) { return $x + $y; } $ perl -MO=Deparse adder.pl
  124. # adder.pl sub add ($x = (return 0), $y =

    (return $x)) { return $x + $y; } sub add { die 'Too many arguments for subroutine' unless @_ <= 2; my $x = @_ >= 1 ? $_[0] : (return 0); my $y = @_ >= 2 ? $_[1] : (return $x); (); return $x + $y; } $ perl -MO=Deparse adder.pl
  125. "Strict Arity" •no fewer than the count of no-default parameters

    •no more than the count of all parameters
  126. "Strict Arity" •no fewer than the count of no-default parameters

    •no more than the count of all parameters •so what about variadic functions?
  127. sub send_spam (@messages, @addrs) { ... } send_spam(@messages, @addr1, @addr2);

    send_spam(@msgs1, @msgs2, @addrs); send_spam($msg1, $msg2, $addr1, $addr2);
  128. sub add ($x = 0, $y = 0) { !

    return $x + $y; }
  129. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6);
  130. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6);
  131. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6); add(@summands) ⇢
  132. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6); ! add(@summands) ⇢ ?????
  133. sub ($x, $y) { return $x + $y; } sub

    ($$) { my ($x, $y) = @_; return $x + $y; }
  134. sub add ($x = 0, $y = 0) { !

    return $x + $y; }
  135. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6);
  136. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6);
  137. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6); add(@summands) ⇢ 14
  138. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6); add(@summands) ⇢ 14 add(@summands) ⇢ 2
  139. sub add ($x = 0, $y = 0) { !

    return $x + $y; } my @summands = (8, 6); ! add(@summands) ⇢ 14 add(@summands) ⇢ 2
  140. sub each { my ($code, @rest) = @_; ! $code->()

    for @rest; } each( sub { say }, 1, 2, 3 );
  141. package Logger { sub log ($self, $message) { $self->syslog->log($message); }

    } package Logger::Null { sub log ($self, $message) { # do nothing! } }
  142. package Logger { sub log ($self, $message) { $self->syslog->log($message); }

    } package Logger::Null { sub log ($self, _) { # do nothing! } }
  143. package Logger { sub log ($self, $message) { $self->syslog->log($message); }

    } package Logger::Null { sub log ($self, $) { # do nothing! } }
  144. package Logger { sub log ($self, $message) { $self->syslog->log($message); }

    } package Logger::Null { sub log ($, $) { # do nothing! } }
  145. package Logger { sub log ($self, $message = '') {

    $self->syslog->log($message); } } package Logger::Null { sub log ($, $) { # do nothing! } }
  146. package Logger { sub log ($self, $message = '') {

    $self->syslog->log($message); } } package Logger::Null { sub log ($, $ = '') { # do nothing! } }
  147. package Logger { sub log ($self, $message = '') {

    $self->syslog->log($message); } } package Logger::Null { sub log ($, $ =) { # do nothing! } }
  148. sub add ($x = 0, $y = 0, @) {

    return $x + $y; }
  149. # adder.pl sub add ($x = 0, $y = 0)

    { return $x + $y; } $ perl -MO=Deparse adder.pl
  150. # adder.pl sub add ($x = 0, $y = 0)

    { return $x + $y; } sub add { die 'Too many arguments for subroutine' unless @_ <= 2; my $x = @_ >= 1 ? $_[0] : 0; my $y = @_ >= 2 ? $_[1] : 0; (); return $x + $y; } $ perl -MO=Deparse adder.pl
  151. # adder.pl sub add ($x = 0, $y = 0,

    @) { return $x + $y; }
  152. # adder.pl sub add ($x = 0, $y = 0,

    @) { return $x + $y; } $ perl -MO=Deparse adder.pl
  153. # adder.pl sub add ($x = 0, $y = 0,

    @) { return $x + $y; } sub add { ! my $x = @_ >= 1 ? $_[0] : 0; my $y = @_ >= 2 ? $_[1] : 0; (); return $x + $y; } $ perl -MO=Deparse adder.pl
  154. Signatures!!! •sub x ($y, $z) •sub y ($y = default_expr)

    •sub z ($x, $y, @z) •sub w ($self, $, @)
  155. Signatures!!! •sub x ($y, $z) •sub y ($y = default_expr)

    •sub z ($x, $y, @z) •sub w ($self, $, @) •sub wtf :prototype($$) ($ugh, $bah)
  156. Signatures sub xyzzy :Attr(foo) ($x, $y)
 not
 sub xyzzy ($x,

    $y) :Attr(foo) lousy errors (from sub, not caller)
  157. Signatures sub xyzzy :Attr(foo) ($x, $y)
 not
 sub xyzzy ($x,

    $y) :Attr(foo) lousy errors (from sub, not caller) a little slower than necessary