Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Perl6 in-production

1,156 views

Published on

A brief historical overview of how Perl 6 was used to make web sites in the past, and how you can use it today to run the Plack/PSGI-based site.

Published in: Technology
  • Be the first to comment

Perl6 in-production

  1. 1. Perl 6 in Production
  2. 2. 15 years of development
  3. 3. Ready December 2015
  4. 4. This December
  5. 5. Start using?
  6. 6. Perl 6 for Web Development
  7. 7. What’s wrong with Perl 6?
  8. 8. What’s wrong with today’s Perl 6?
  9. 9. Not that it is too late
  10. 10. Rather that it is too mature
  11. 11. Lots of blog posts
  12. 12. Lots of documentation
  13. 13. Lots of code examples
  14. 14. Lots of errors
  15. 15. Everything has been googled
  16. 16. Not easy to find how this or that works
  17. 17. Most of code examples and modules are outdated
  18. 18. Outdated before the release!
  19. 19. Nothing works!
  20. 20. Even if it used to work
  21. 21. ===SORRY!===   Error  while  compiling     ! Undeclared  routine:        eval  used  at  line  7.        Did  you  mean  'val'?
  22. 22. ===SORRY!===   Error  while  compiling     ! Undeclared  routine:        eval  used  at  line  7.        Did  you  mean  'val'?
  23. 23. (useEVAL)
  24. 24. A bit of history
  25. 25. 2000 Perl 6 announced
  26. 26. First implementations
  27. 27. Parrot
  28. 28. Parrot with Perl 6 compiler
  29. 29. Pugs
  30. 30. Pugs, the Perl 6 compiler
  31. 31. Rakudo
  32. 32. Rakudo Star
  33. 33. Past
  34. 34. 2004 real.perl6.ru http://web.archive.org/web/*/real.perl6.ru
  35. 35. Some examples of the code of 2004
  36. 36. Reading environment variables
  37. 37. my  @keys  =  ('SERVER_NAME',                                            'REMOTE_ADDR',                            'HTTP_USER_AGENT');   ! my  $key;   foreach  $key  (@keys){      print  "$key=%ENV{$key}<br  />n";   }
  38. 38. Looks almost like Perl 5
  39. 39. my  @keys  =  ('SERVER_NAME',                                            'REMOTE_ADDR',                            'HTTP_USER_AGENT');   ! my  $key;   foreach  $key  (@keys){      print  "$key=%ENV{$key}<br  />n";   }
  40. 40. You could learn Perl 6 in a few hours
  41. 41. Setting/getting cookies
  42. 42. print  "Content-­‐Type:  text/htmln"   print  'Set-­‐Cookie:  cookie-­‐ name=test-­‐value;  path=/;nn';   ! print  %ENV{'HTTP_COOKIE'};
  43. 43. URL GET parameters
  44. 44. read_params  (          %ENV{'QUERY_STRING'},            @params_key,          @params_value   );
  45. 45. sub  read_params  ($query,  @params_key,   @params_value){        my  $pos  =  0;        loop  (my  $c  =  0;  1;  $c++)  {              my  $newpos  =  index  ($query,  '&',  $pos);              my  @keyvalue;              my  $pair  =  substr  ($query,  $pos,  $newpos   ==  -­‐1  ??  length  ($query)  ::  $newpos  -­‐  $pos);              split_pair  ($pair,  @keyvalue);              @params_key[$c]  =  @keyvalue[0];              @params_value[$c]  =  @keyvalue[1];              last  if  $newpos  ==  -­‐1;              $pos  =  $newpos  +  1;        }   }
  46. 46. sub  read_params  ($query,  @params_key,   @params_value){        my  $pos  =  0;        loop  (my  $c  =  0;  1;  $c++)  {              my  $newpos  =  index  ($query,  '&',  $pos);              my  @keyvalue;              my  $pair  =  substr  ($query,  $pos,  $newpos   ==  -­‐1  ??  length  ($query)  ::  $newpos  -­‐  $pos);              split_pair  ($pair,  @keyvalue);              @params_key[$c]  =  @keyvalue[0];              @params_value[$c]  =  @keyvalue[1];              last  if  $newpos  ==  -­‐1;              $pos  =  $newpos  +  1;        }   }
  47. 47. sub  split_pair  ($pair,  @keyvalue){        my  $pos  =  index  ($pair,  '=');        if  ($pos  ==  -­‐1){              @keyvalue[0]  =  $pair;              @keyvalue[1]  =  '';        }        else{              @keyvalue[0]  =  substr  ($pair,  0,  $pos);              @keyvalue[1]  =  substr  ($pair,  $pos  +  1);        }   }  
  48. 48. URL GET parameters using hashes
  49. 49. sub  params2hash  (%params,  @params_key,   @params_value){        for  0  ..  @params_key  -­‐>  $c{              %params{@params_key[$c]}  =              @params_value[$c];        }   }   ! read_params  (%ENV{'QUERY_STRING'},  @params_key,   @params_value);   my  %params;   params2hash  (%params,  @params_key,   @params_value);
  50. 50. To speed it up
  51. 51. Compiling to bytecode
  52. 52. .pasm .imc
  53. 53. 100% compatible
  54. 54. 2007/2008 november-wiki.org https://github.com/viklund/november
  55. 55. November::CGI
  56. 56. class  November::CGI  {          has  %.params;          has  %.cookie;          has  @.keywords;          has  November::URI  $.uri;
  57. 57. self.parse_params(%*ENV<QUERY_STRING>  //  '');
  58. 58. has  $!crlf  =  "x[0D]x[0A]";                .  .  .   ! print  "Status:  $status$!crlf";   print  "Location:  $uri";   print  "$!crlf$!crlf";
  59. 59. has  $!crlf  =  "x[0D]x[0A]";                .  .  .   ! print  "Status:  $status$!crlf";   print  "Location:  $uri";   print  "$!crlf$!crlf"; Compare https://p6weekly.wordpress.com/2015/11/09/2015-46- production-today/
  60. 60. Smartmatch and junctions
  61. 61. method  add_param  (  Str  $key,  $value  )  {              if  %.params{$key}  :exists  {              #  RAKUDO:  ~~  Scalar              if  %.params{$key}  ~~  Str  |  Int  {                          my  $old_param  =  %.params{$key};                          %!params{$key}  =                                    [  $old_param,  $value  ];              }              elsif  %.params{$key}  ~~  Array  {                          %!params{$key}.push(  $value  );              }              }              else  {              %!params{$key}  =  $value;              }   }  
  62. 62. Compiler incompatibilities
  63. 63. method  add_param  (  Str  $key,  $value  )  {              if  %.params{$key}  :exists  {              #  RAKUDO:  ~~  Scalar              if  %.params{$key}  ~~  Str  |  Int  {                          my  $old_param  =  %.params{$key};                          %!params{$key}  =                                    [  $old_param,  $value  ];              }              elsif  %.params{$key}  ~~  Array  {                          %!params{$key}.push(  $value  );              }              }              else  {              %!params{$key}  =  $value;              }   }  
  64. 64. if  %*ENV<MODPERL6>  {            my  $r  =  Apache::RequestRec.new();            my  $len  =  $r.read($input,                                  %*ENV<CONTENT_LENGTH>);   }   else  {              #  Maybe  check  content_length  here                #  and  only  take  that  many  bytes?              $input  =  $*IN.slurp;   }   !
  65. 65. (I never managed to install mod_parrot)
  66. 66. Grammar for URL parsing
  67. 67. grammar  November::URI::Grammar  {          token  TOP                {  ^  [<scheme>  ':']?                  [  '//'  <authority>]?                  <path>  ['?'  <query>]?  ['#'  <fragment>]?  $  };          token  scheme          {  <-­‐[:/&?#]>+  };          token  authority    {  <host>  [':'  <port>]?  };          token  host              {  <-­‐[/&?#:]>*  };          token  port              {  (d**1..5)                                                    <?{  $0  <  2  **  16  }>                                                <!before  d>  };          token  path              {  <slash>?  [  <chunk>  '/'?]*  };          token  slash            {  '/'  };          token  chunk            {  <-­‐[/?#]>+  };          token  query            {  <-­‐[#]>*  };          token  fragment      {  .*  };   }
  68. 68. #  Official  regexp  (p5):   #  my($scheme,  $authority,  $path,  $query,  $fragment)  =   #  $uri  =~  m/   #                      (?:([^:/?#]+):)?   #                      (?://([^/?#]*))?   #                      ([^?#]*)   #                      (?:?([^#]*))?   #                      (?:#(.*))?   #                  /x;
  69. 69. Not like Perl 5 any more :-)
  70. 70. 2011 Plackdo https://github.com/lopnor/p6-plackdo
  71. 71. Plack-like web interface on Perl 6
  72. 72. my  $app  =  sub  (%env)  {          return  (                  200,                  [                            Content-­‐Type  =>  'text/plain',                            Content-­‐Length  =>  %env.perl.bytes,                  ],                  [  %env.perl  ]          );   }; HTTP status code
  73. 73. my  $app  =  sub  (%env)  {          return  (                  200,                  [                            Content-­‐Type  =>  'text/plain',                            Content-­‐Length  =>  %env.perl.bytes,                  ],                  [  %env.perl  ]          );   }; HTTP headers
  74. 74. my  $app  =  sub  (%env)  {          return  (                  200,                  [                            Content-­‐Type  =>  'text/plain',                            Content-­‐Length  =>  %env.perl.bytes,                  ],                  [  %env.perl  ]          );   }; Response body
  75. 75. my  $builder  =  Plackdo::Builder.new;   $builder.add_middleware(          Plackdo::Middleware::XFramework.new(                framework  =>  'foobar')   );   $builder.to_app($app);
  76. 76. ~2014 wee6 https://github.com/vti/wee6
  77. 77. Present
  78. 78. Rakudo Star http://rakudo.org
  79. 79. +
  80. 80. modules.perl6.org
  81. 81. Installing Rakudo*
  82. 82. perl  Configure.pl              -­‐-­‐backend=moar            -­‐-­‐gen-­‐moar     ! make   ! make  install
  83. 83. MoarVM http://moarvm.org
  84. 84. Managing modules
  85. 85. “Ecosystem” https://github.com/perl6/ecosystem
  86. 86. Panda ! for installing Perl 6 modules
  87. 87. modules/panda/bootstrap.pl
  88. 88. panda  install  Module::X
  89. 89. Distribution modules live in install/share/perl6/lib
  90. 90. Panda puts modules to install/share/perl6/site
  91. 91. BTW, Rakudo’s “make install” compiles modules to .moarvm
  92. 92. OK, Perl. Let’s build a web server
  93. 93. HTTP::Easy Core’s
  94. 94. HTTP::Easy::PSGI Core’s
  95. 95. use  HTTP::Easy::PSGI;  
  96. 96. my  $http  =  HTTP::Easy::PSGI.new(                                :port(8080)                        );  
  97. 97. my  $app  =  sub  (%env)  {            .  .  .     }  
  98. 98. my  $app  =  sub  (%env)  {            .  .  .     }   ! $http.handle($app);
  99. 99. my  $app  =  sub  (%env)  {                return  [                  200,                  [                      'Content-­‐Type'  =>                      'text/plain'                  ],                  [                      'Hello,  World!’                  ]          ];   }
  100. 100. use  HTTP::Easy::PSGI;   my  $http  =   HTTP::Easy::PSGI.new(:port(8080));   ! my  $app  =  sub  (%env)  {          my  $name  =  %env<QUERY_STRING>   ||  "World";          return  [  200,  [  'Content-­‐Type'   =>  'text/plain'  ],  [  "Hello   $name"  ]  ];   }   !
  101. 101. ! Web::App module set Explore
  102. 102. Bailador
  103. 103. Bailador (Dancer)
  104. 104. Available in the Rakudo* distribution
  105. 105. (Does not instantly work in the 2015.09 distribution)
  106. 106. use  Bailador;
  107. 107. use  Bailador;   ! get  '/'  =>  sub  {   ! }  
  108. 108. use  Bailador;   ! get  '/'  =>  sub  {          return  "Hin";   }   !
  109. 109. use  Bailador;   ! get  '/'  =>  sub  {          return  "Hin";   }   ! baile;
  110. 110. use  Bailador;   ! get  '/'  =>  sub  {          "Hin"   }   ! baile;
  111. 111. $  perl6  test.pl   ! Entering  the  development  dance   floor:  http://0.0.0.0:3000   [2015-­‐11-­‐17T13:41:08Z]  Started  HTTP server.  
  112. 112. Started… ! Then open it in a browser
  113. 113. Method  'send'  not  found  for   invocant  of  class   'IO::Socket::INET'      in  method  run  at  /home/ash/p/ rakudo-­‐star-­‐2015.09/install/share/ perl6/lib/HTTP/Easy.pm6:193      in  sub  baile  at  /home/ash/p/ rakudo-­‐star-­‐2015.09/install/share/ perl6/lib/Bailador.pm:153      in  block  <unit>  at  test.pl:8
  114. 114. Update HTTP::Easy using panda
  115. 115. git  clone  ...   panda  install  ./Bailador
  116. 116. ! -­‐  connection.send($res.Str);   ! +  connection.print($res.Str);  
  117. 117. use  Bailador;   ! get  '/'  =>  sub  {          return  "Hin";   }   ! get  '/hello/:name'  =>  sub  ($name)  {        return  "Hi,  $namen";   }   ! baile;
  118. 118. use  Bailador;   ! get  '/'  =>  sub  {          return  "Hin";   }   ! get  '/hello/:name'  =>  sub  ($name)  {        return  "Hi,  $namen";   }   ! baile;
  119. 119. NB!
  120. 120. ! get  '/hello/:name'  =>  sub  ($name)  { ! vs. ! get  '/hello/:name'  =>  sub($name)  {
  121. 121. ===SORRY!===     Error  while  compiling  test1.pl   Variable  '$name'  is  not  declared   at  test1.pl:7   ! -­‐-­‐-­‐-­‐-­‐-­‐>     get  '/hello/:name'  =>  sub(⏏$name)    
  122. 122. Accessing request data
  123. 123. get  '/'  =>  sub  {          return  request.perl;   }
  124. 124. Bailador::Request.new(env  =>   {:HTTP_ACCEPT("*/ *"),  :HTTP_HOST("0.0.0.0:3000"),  :HTTP _USER_AGENT("curl/ 7.35.0"),  :PATH_INFO("/"),  :QUERY_STRI NG(""),  :REQUEST_METHOD("GET"),  :REQUE ST_URI("/"),  :SERVER_NAME("0.0.0.0"),   :SERVER_PORT(3000),  :SERVER_PROTOCOL(" HTTP/1.1"),  "p6sgi.encoding"  =>   "UTF-­‐8",  "p6sgi.errors"  =>   IO::Handle.new(path  =>   IO::Special.new(what  =>  "<STDERR>"),   ins  =>  0,  chomp  =>  Bool::True),  
  125. 125. What is a ‘request’?
  126. 126. class  Bailador::App  {          .  .  .          method  request  {                  $.context.request          }          method  response  {                  $.context.response          }          .  .  .   }
  127. 127. get  /.*/  =>  sub  {          return                  request.env<REQUEST_URI>                  ~                  "n";   }  
  128. 128. get  /.*/  =>  sub  {          return                  request.env<REQUEST_URI>                  ~                  "n";   }  
  129. 129. Templates
  130. 130. get  '/'  =>  sub  {          template                    't.tt',                  {  name  =>  'Name'  }   }
  131. 131. get  '/'  =>  sub  {          template                    't.tt',                  {  name  =>  'Name'  }   }
  132. 132. %  my  ($h)  =  @_;   <html>   <head>          <title>              Hi,  <%=  $h<name>  %>          </title>   </head>   <body>          <h1>Hello  <%=  $h<name>  %></h1>   </body>   </html>
  133. 133. %  my  ($h)  =  @_;   <html>   <head>          <title>              Hi,  <%=  $h<name>  %>          </title>   </head>   <body>          <h1>Hello  <%=  $h<name>  %></h1>   </body>   </html>
  134. 134. Use  of  uninitialized  value   $_location  of  type  Any  in  string   context   Any  of  .^name,  .perl,  .gist,   or  .say  can  stringify  undefined   things,  if  needed.    in  method   template  at  /home/ash/p/rakudo-­‐ star-­‐2015.09/install/share/perl6/ site/lib/Bailador/App.pm:14   Failed  to  open  file  /views/t.tt:  no such  file  or  directory      in  method  template  at  
  135. 135. my  $_location;   ! .  .  .   ! $!renderer.render(          slurp(                  "$_location/views/$tmpl"          ),          @params   ); lib/Bailador/App.pm
  136. 136. my  $_location;   ! .  .  .   ! $!renderer.render(          slurp(                  "$_location/views/$tmpl"          ),          @params   ); lib/Bailador/App.pm
  137. 137. my  $_location  =  '.';   ! .  .  .   ! $!renderer.render(          slurp(                  "$_location/views/$tmpl"          ),          @params   ); lib/Bailador/App.pm
  138. 138. OK, Perl. What about databases?
  139. 139. DBIish
  140. 140. panda  install  DBIish
  141. 141. use  DBIish;
  142. 142. use  DBIish;   my  $dbh  =  DBIish.connect(      'mysql',      :host<example.com>,      :port(3306),      :database<$dbname>,      :user<$dbuser>,      :password<$dbpassword>);
  143. 143. my  $sth  =  $dbh.prepare(            "select  now()"   );   ! $sth.execute();
  144. 144. my  $arr  =            $sth.fetchall_arrayref();
  145. 145. my  $arr  =            $sth.fetchall_arrayref();   ! for  $arr  -­‐>  $x  {          say  $x;   }
  146. 146. It works!
  147. 147. __END__ Cluj-Napoka 2015 ! ! Andrew Shitov | andy@shitov.ru

×