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

Perl's Syntactic Legacy

Perl's Syntactic Legacy

This is a talk I gave at YAPC::NA 2015 in Salt Lake City (http://www.yapcna.org/yn2015/talk/6085). The video can be found here: https://www.youtube.com/watch?v=sJC725e8ysM

78244476bb128a3a10522fc215bd2e83?s=128

Stevan Little

June 10, 2015
Tweet

Transcript

  1. Perl's Syntactic Legacy Using the future to improve the past

  2. None
  3. None
  4. None
  5. None
  6. #eatfirst

  7. None
  8. None
  9. $785.00!!!!

  10. None
  11. #dammitcancer

  12. Perl's Syntactic Legacy Using the future to improve the past

  13. Legacy /ˈlɛɡəsɪ/ ! adjective ! of or relating to old

    or outdated computer hardware, software, or data that, while still functional, does not work well with up-to-date systems.
  14. /ˈlɛɡəsɪ/ ! noun ! something handed down or received from

    an ancestor or predecessor Legacy
  15. /ˈlɛɡəsɪ/ ! noun ! something handed down or received from

    an ancestor or predecessor Legacy descendant or successor
  16. This talk is about

  17. This talk is about ‣ the evolution of a design

  18. This talk is about ‣ the evolution of a design

    ‣ the slow breakdown of my own stubbornness
  19. Learning

  20. Learning The act of present $you realizing how stupid past

    $you was being
  21. meta(data)

  22. STEVAN stevan@cpan.org stevan @stevanlittle cpan: email: github: twitter:

  23. 1998

  24. 2002

  25. 2004

  26. 2005

  27. 2006

  28. 2011

  29. mop?

  30. Classes, Methods, Attributes & Instances

  31. ... an abstraction of a system of abstractions that is

    used to build abstractions.
  32. ... an abstraction of a system of abstractions that is

    used to build abstractions.
  33. ... an abstraction of a system of abstractions that is

    used to build abstractions.
  34. ... an abstraction of a system of abstractions that is

    used to build abstractions.
  35. *{$pkg . '::foo'} = \&bar;

  36. p5-mop

  37. Goals

  38. Goals 1. class attributes (slots)

  39. Goals 1. class attributes (slots) 2. class/method vs. package/sub

  40. Goals 1. class attributes (slots) 2. class/method vs. package/sub 3.

    role composition
  41. Goals 1. class attributes (slots) 2. class/method vs. package/sub 3.

    role composition 4. introspection API
  42. Goals 1. class attributes (slots) 2. class/method vs. package/sub 3.

    role composition 4. introspection API 5. improve OO syntax
  43. package Point; ! sub new { my $class = shift;

    bless { x => 0, y => 0 }, $class; } ! sub clear { my $self = shift; $self->{x} = 0; $self->{y} = 0; }
  44. class Point { ! has $x = 0; has $y

    = 0; ! method clear { ($x, $y) = (0, 0); } }
  45. package Point; ! sub new { my $class = shift;

    bless { x => 0, y => 0 }, $class; } ! sub clear { my $self = shift; $self->{x} = 0; $self->{y} = 0; }
  46. class Point { ! has $x = 0; has $y

    = 0; ! method clear { ($x, $y) = (0, 0); } }
  47. package Point; ! sub new { my $class = shift;

    bless { x => 0, y => 0 }, $class; } ! sub clear { my $self = shift; $self->{x} = 0; $self->{y} = 0; }
  48. package Point; ! sub new :method { my $class =

    shift; bless { x => 0, y => 0 }, $class; } ! sub clear :method { my $self = shift; $self->{x} = 0; $self->{y} = 0; }
  49. class Point { ! has $x = 0; has $y

    = 0; ! method clear { ($x, $y) = (0, 0); } }
  50. package Point; ! sub new { my $class = shift;

    bless { x => 0, y => 0 }, $class; } ! sub clear { my $self = shift; $self->{x} = 0; $self->{y} = 0; }
  51. package Point; ! sub new { my $class = shift;

    bless { x => 0, y => 0 }, $class; } ! sub clear { my $self = shift; $self->{x} = 0; $self->{y} = 0; }
  52. class Point { ! has $x = 0; has $y

    = 0; ! method clear { ($x, $y) = (0, 0); } }
  53. class Point { ! has $x = 0; has $y

    = 0; ! method clear { ($x, $y) = (0, 0); } }
  54. package Point; ! sub new { my $class = shift;

    bless { x => 0, y => 0 }, $class; } ! sub clear { my $self = shift; $self->{x} = 0; $self->{y} = 0; }
  55. class Point { ! has $x = 0; has $y

    = 0; ! method clear { ($x, $y) = (0, 0); } }
  56. Moose

  57. Perl 5 Core Class::MOP Moose

  58. Perl 5 Core Class::MOP Moose

  59. p5-mop

  60. Perl 5 Core mop.pm

  61. Perl 5 Core mop.pm

  62. None
  63. None
  64. None
  65. None
  66. Throw the first one away!

  67. PadWalker.pm

  68. PadWalker.pm

  69. None
  70. Who is going to maintain this?!!!?!?!

  71. moe

  72. None
  73. -Ofun

  74. ಠ_ಠ

  75. My Moe Wishlist • A more consistent syntax and sane

    grammar • with a real AST • and better tooling support • A less insane runtime • proper MOP (everything is an object) • slimmer core • easy (non-XS) extension mechanism • On a modern VM platform • JVM / CLR / LLVM / V8 • cross language sharing
  76. CPAN

  77. None
  78. None
  79. None
  80. None
  81. None
  82. None
  83. None
  84. p5-mop-redux

  85. Perl 5 Core mop.pm

  86. Perl 5 Core mop.pm

  87. package Foo; use strict; use warnings; ! use Variable::Magic qw[

    wizard cast ]; use Hash::Util::FieldHash qw[ fieldhash ]; ! fieldhash my %foo; ! my $wiz = wizard( data => sub { $_[1] }, set => sub { $_[1]->[0]->{ $_[1]->[1] } = $_[0] }, ); ! sub foo { my $self = shift; my $foo = $foo{$self}; cast $foo, $wiz, [ \%foo, $self ]; ! $foo = shift if @_; $foo; }
  88. package Foo; use strict; use warnings; ! use Variable::Magic qw[

    wizard cast ]; use Hash::Util::FieldHash qw[ fieldhash ]; ! fieldhash my %foo; ! my $wiz = wizard( data => sub { $_[1] }, set => sub { $_[1]->[0]->{ $_[1]->[1] } = $_[0] }, ); ! sub foo { my $self = shift; my $foo = $foo{$self}; cast $foo, $wiz, [ \%foo, $self ]; ! $foo = shift if @_; $foo; }
  89. package Foo; use strict; use warnings; ! use Variable::Magic qw[

    wizard cast ]; use Hash::Util::FieldHash qw[ fieldhash ]; ! fieldhash my %foo; ! my $wiz = wizard( data => sub { $_[1] }, set => sub { $_[1]->[0]->{ $_[1]->[1] } = $_[0] }, ); ! sub foo { my $self = shift; my $foo = $foo{$self}; cast $foo, $wiz, [ \%foo, $self ]; ! $foo = shift if @_; $foo; }
  90. package Foo; use strict; use warnings; ! use Variable::Magic qw[

    wizard cast ]; use Hash::Util::FieldHash qw[ fieldhash ]; ! fieldhash my %foo; ! my $wiz = wizard( data => sub { $_[1] }, set => sub { $_[1]->[0]->{ $_[1]->[1] } = $_[0] }, ); ! sub foo { my $self = shift; my $foo = $foo{$self}; cast $foo, $wiz, [ \%foo, $self ]; ! $foo = shift if @_; $foo; }
  91. package Foo; use strict; use warnings; ! use Variable::Magic qw[

    wizard cast ]; use Hash::Util::FieldHash qw[ fieldhash ]; ! fieldhash my %foo; ! my $wiz = wizard( data => sub { $_[1] }, set => sub { $_[1]->[0]->{ $_[1]->[1] } = $_[0] }, ); ! sub foo { my $self = shift; my $foo = $foo{$self}; cast $foo, $wiz, [ \%foo, $self ]; ! $foo = shift if @_; $foo; }
  92. package Foo; use strict; use warnings; ! use Variable::Magic qw[

    wizard cast ]; use Hash::Util::FieldHash qw[ fieldhash ]; ! fieldhash my %foo; ! my $wiz = wizard( data => sub { $_[1] }, set => sub { $_[1]->[0]->{ $_[1]->[1] } = $_[0] }, ); ! sub foo { my $self = shift; my $foo = $foo{$self}; cast $foo, $wiz, [ \%foo, $self ]; ! $foo = shift if @_; $foo; }
  93. None
  94. package Foo; use strict; use warnings; ! has ‘foo’; !

    method foo { $foo = shift if @_; $foo; }
  95. Devel::(every day i’m segfaultin)::Declare

  96. None
  97. Everything should be as simple as it can be, but

    not simpler. – Albert Einstein
  98. It can scarcely be denied that the supreme goal of

    all theory is to make the irreducible basic elements as simple and as few as possible without having to surrender the adequate representation of a single datum of experience.
  99. None
  100. • Plack

  101. • Plack • HTTP::Headers::ActionPack

  102. • Plack • HTTP::Headers::ActionPack • Promises

  103. • Plack • HTTP::Headers::ActionPack • Promises • Bread::Board

  104. • Plack • HTTP::Headers::ActionPack • Promises • Bread::Board • Reply

  105. • Plack • HTTP::Headers::ActionPack • Promises • Bread::Board • Reply

    • Forward::Routes
  106. • Plack • HTTP::Headers::ActionPack • Promises • Bread::Board • Reply

    • Forward::Routes • Action::Retry
  107. • Plack • HTTP::Headers::ActionPack • Promises • Bread::Board • Reply

    • Forward::Routes • Action::Retry • Hashids
  108. • Plack • HTTP::Headers::ActionPack • Promises • Bread::Board • Reply

    • Forward::Routes • Action::Retry • Hashids • Net::IPAddress::Util
  109. None
  110. 200 OK

  111. Perl 5 Core mop.pm

  112. Perl 5 Core mop.pm

  113. Perl 5 Core mop.pm

  114. Perl 5 Core mop.pm

  115. Perl 5 Core mop.pm XS

  116. None
  117. p5-mop-XS

  118. None
  119. None
  120. Perl 5 Core

  121. mop.xs Perl 5 Core

  122. p5-mop-again-seriously-wtf

  123. None
  124. None
  125. sub foo; # required method

  126. $ perl -MDevel::Peek -e 'sub foo; Dump \&foo;' SV =

    IV(0x7fa3b3003428) at 0x7fa3b3003438 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x7fa3b3028978 SV = PVCV(0x7fa3b30271b8) at 0x7fa3b3028978 REFCNT = 2 FLAGS = () COMP_STASH = 0x7fa3b30032b8 "main" ROOT = 0x0 GVGV::GV = 0x7fa3b3028960 "main" :: "foo" FILE = "-e" DEPTH = 0 FLAGS = 0x0 OUTSIDE_SEQ = 0 PADLIST = 0x0 OUTSIDE = 0x0 (null)
  127. # marking sub as method sub foo :method { …

    }
  128. perl -MDevel::Peek -e 'sub foo :method { 1 } Dump

    \&foo;' SV = IV(0x7fec82003428) at 0x7fec82003438 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x7fec82029318 SV = PVCV(0x7fec82027bb8) at 0x7fec82029318 REFCNT = 2 FLAGS = (METHOD) COMP_STASH = 0x7fec820032b8 "main" START = 0x7fec81c0dae8 ===> 1 ROOT = 0x7fec81c0da60 GVGV::GV = 0x7fec82029348 "main" :: "foo" FILE = "-e" DEPTH = 0 FLAGS = 0x1 OUTSIDE_SEQ = 95 PADLIST = 0x7fec81c0cac0 PADNAME = 0x7fec82029378(0x7fec81c0cf90) PAD = 0x7fec820293c0(0x7fec81c051e0) OUTSIDE = 0x7fec82003648 (MAIN)
  129. # signatures sub foo ($self) { … }

  130. + use v5.20; + use experimental ‘signatures’ + - SV*

    - parse_signature (code, …) - # A WHOLE LOAD OF CRAZY XS - # PARSING CODE THAT MADE YOUR - # EYES BLEED AND YOUR HEART - # SINK IN DEEP DESPAIR - # *sigh*
  131. sub foo; ! sub bar :method { … } !

    sub baz ($gorch) { … }
  132. package Foo; use v5.20; use warnings; ! our @DOES =

    (‘BarRole’); ! 1;
  133. package Foo; use v5.20; use warnings; ! our %HAS =

    ( bar => sub { “BAR” }, baz => sub { “BAZ” }, ); ! 1;
  134. our @DOES = (‘BarRole’); ! our %HAS = ( bar

    => sub { “BAR” }, baz => sub { “BAZ” }, );
  135. #include “mop.h”

  136. p5-mop

  137. Conclusion

  138. Respect the Legacy!

  139. Legacy is the remnants of solved problems.

  140. Many of the OO conventions that we take for granted

    are largely inherited from Java, ! … which barely existed when Larry designed the OO features of Perl 5.
  141. Object Orientation in Ada is a Design Pattern

  142. What makes a good “Perl” programmer? • Laziness • Impatience

    • Hubris
  143. What makes a good “perl” programmer? • Do the hard

    work • Patience • Humility
  144. The End (or is it…)