152
Perl 6 in Production

Perl6 in-production

Embed Size (px)

Citation preview

Page 1: Perl6 in-production

Perl 6 in Production

Page 2: Perl6 in-production

15 years of development

Page 3: Perl6 in-production

Ready December 2015

Page 4: Perl6 in-production

This December

Page 5: Perl6 in-production

Start using?

Page 6: Perl6 in-production

Perl 6 for Web

Development

Page 7: Perl6 in-production

What’s wrong with Perl 6?

Page 8: Perl6 in-production

What’s wrong with today’s Perl 6?

Page 9: Perl6 in-production

Not that it is too late

Page 10: Perl6 in-production

Rather that it is too mature

Page 11: Perl6 in-production
Page 12: Perl6 in-production

Lots of blog posts

Page 13: Perl6 in-production

Lots of documentation

Page 14: Perl6 in-production

Lots of code examples

Page 15: Perl6 in-production

Lots of errors

Page 16: Perl6 in-production

Everything has been googled

Page 17: Perl6 in-production

Not easy to find how this or that works

Page 18: Perl6 in-production

Most of code examples and modules are outdated

Page 19: Perl6 in-production

Outdated before the release!

Page 20: Perl6 in-production

Nothing works!

Page 21: Perl6 in-production

Even if it used to work

Page 22: Perl6 in-production

===SORRY!===  Error  while  compiling    !

Undeclared  routine:        eval  used  at  line  7.          Did  you  mean  'val'?

Page 23: Perl6 in-production

===SORRY!===  Error  while  compiling    !

Undeclared  routine:        eval  used  at  line  7.          Did  you  mean  'val'?

Page 24: Perl6 in-production

(use EVAL)

Page 25: Perl6 in-production

A bit of history

Page 26: Perl6 in-production

2000 Perl 6 announced

Page 27: Perl6 in-production

First implementations

Page 28: Perl6 in-production

Parrot

Page 29: Perl6 in-production

Parrot with Perl 6 compiler

Page 30: Perl6 in-production

Pugs

Page 31: Perl6 in-production

Pugs, the Perl 6 compiler

Page 32: Perl6 in-production

Rakudo

Page 33: Perl6 in-production

Rakudo Star

Page 34: Perl6 in-production

Past

Page 35: Perl6 in-production

2004 real.perl6.ru

http://web.archive.org/web/*/real.perl6.ru

Page 36: Perl6 in-production
Page 37: Perl6 in-production

Some examples of the code of 2004

Page 38: Perl6 in-production

Reading environment variables

Page 39: Perl6 in-production

my  @keys  =  ('SERVER_NAME',                                                          'REMOTE_ADDR',                            'HTTP_USER_AGENT');  !

my  $key;  foreach  $key  (@keys){      print  "$key=%ENV{$key}<br  />\n";  }

Page 40: Perl6 in-production

Looks almost like Perl 5

Page 41: Perl6 in-production

my  @keys  =  ('SERVER_NAME',                                                          'REMOTE_ADDR',                            'HTTP_USER_AGENT');  !

my  $key;  foreach  $key  (@keys){      print  "$key=%ENV{$key}<br  />\n";  }

Page 42: Perl6 in-production

You could learn Perl 6 in a few hours

Page 43: Perl6 in-production

Setting/getting cookies

Page 44: Perl6 in-production

print  "Content-­‐Type:  text/html\n"  print  'Set-­‐Cookie:  cookie-­‐name=test-­‐value;  path=/;\n\n';  !

print  %ENV{'HTTP_COOKIE'};

Page 45: Perl6 in-production

URL GET parameters

Page 46: Perl6 in-production

read_params  (          %ENV{'QUERY_STRING'},            @params_key,          @params_value  );

Page 47: Perl6 in-production

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;        }  }

Page 48: Perl6 in-production

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;        }  }

Page 49: Perl6 in-production

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);        }  }  

Page 50: Perl6 in-production

URL GET parameters using hashes

Page 51: Perl6 in-production

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);

Page 52: Perl6 in-production

To speed it up

Page 53: Perl6 in-production

Compiling to bytecode

Page 54: Perl6 in-production

.pasm .imc

Page 55: Perl6 in-production

100% compatible

Page 56: Perl6 in-production

2007/2008 november-wiki.org

https://github.com/viklund/november

Page 57: Perl6 in-production
Page 58: Perl6 in-production

November::CGI

Page 59: Perl6 in-production

class  November::CGI  {          has  %.params;          has  %.cookie;          has  @.keywords;          has  November::URI  $.uri;

Page 60: Perl6 in-production

self.parse_params(%*ENV<QUERY_STRING>  //  '');

Page 61: Perl6 in-production

has  $!crlf  =  "\x[0D]\x[0A]";                .  .  .  !print  "Status:  $status$!crlf";  print  "Location:  $uri";  print  "$!crlf$!crlf";

Page 62: Perl6 in-production

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/

Page 63: Perl6 in-production

Smartmatch and junctions

Page 64: Perl6 in-production

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;              }  }  

Page 65: Perl6 in-production

Compiler incompatibilities

Page 66: Perl6 in-production

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;              }  }  

Page 67: Perl6 in-production

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;  }  !

Page 68: Perl6 in-production

(I never managed to install mod_parrot)

Page 69: Perl6 in-production

Grammar for URL parsing

Page 70: Perl6 in-production

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      {  .*  };  }

Page 71: Perl6 in-production

#  Official  regexp  (p5):  #  my($scheme,  $authority,  $path,  $query,  $fragment)  =  #  $uri  =~  m/  #                      (?:([^:/?#]+):)?  #                      (?://([^/?#]*))?  #                      ([^?#]*)  #                      (?:\?([^#]*))?  #                      (?:#(.*))?  #                  /x;

Page 72: Perl6 in-production

Not like Perl 5 any more :-)

Page 73: Perl6 in-production

2011 Plackdo

https://github.com/lopnor/p6-plackdo

Page 74: Perl6 in-production

Plack-like web interface on Perl 6

Page 75: Perl6 in-production

my  $app  =  sub  (%env)  {          return  (                  200,                  [                            Content-­‐Type  =>  'text/plain',                            Content-­‐Length  =>  %env.perl.bytes,                  ],                  [  %env.perl  ]          );  };

HTTP status code

Page 76: Perl6 in-production

my  $app  =  sub  (%env)  {          return  (                  200,                  [                            Content-­‐Type  =>  'text/plain',                            Content-­‐Length  =>  %env.perl.bytes,                  ],                  [  %env.perl  ]          );  };

HTTP headers

Page 77: Perl6 in-production

my  $app  =  sub  (%env)  {          return  (                  200,                  [                            Content-­‐Type  =>  'text/plain',                            Content-­‐Length  =>  %env.perl.bytes,                  ],                  [  %env.perl  ]          );  };

Response body

Page 78: Perl6 in-production

my  $builder  =  Plackdo::Builder.new;  $builder.add_middleware(          Plackdo::Middleware::XFramework.new(                framework  =>  'foobar')  );  $builder.to_app($app);

Page 79: Perl6 in-production

~2014 wee6

https://github.com/vti/wee6

Page 80: Perl6 in-production

Present

Page 81: Perl6 in-production

Rakudo Star

http://rakudo.org

Page 82: Perl6 in-production

+

Page 83: Perl6 in-production

modules.perl6.org

Page 84: Perl6 in-production

Installing Rakudo*

Page 85: Perl6 in-production

perl  Configure.pl    \          -­‐-­‐backend=moar  \          -­‐-­‐gen-­‐moar    !

make  !

make  install

Page 86: Perl6 in-production

MoarVM

http://moarvm.org

Page 87: Perl6 in-production

Managing modules

Page 88: Perl6 in-production

“Ecosystem”

https://github.com/perl6/ecosystem

Page 89: Perl6 in-production
Page 90: Perl6 in-production

Panda !

for installing Perl 6 modules

Page 91: Perl6 in-production

modules/panda/bootstrap.pl

Page 92: Perl6 in-production

panda  install  Module::X

Page 93: Perl6 in-production

Distribution modules live in install/share/perl6/lib

Page 94: Perl6 in-production

Panda puts modules to install/share/perl6/site

Page 95: Perl6 in-production

BTW, Rakudo’s “make install”

compiles modules to .moarvm

Page 96: Perl6 in-production

OK, Perl. Let’s build a web server

Page 97: Perl6 in-production
Page 98: Perl6 in-production

HTTP::Easy

Core’s

Page 99: Perl6 in-production

HTTP::Easy::PSGI

Core’s

Page 100: Perl6 in-production

use  HTTP::Easy::PSGI;  

Page 101: Perl6 in-production

my  $http  =  HTTP::Easy::PSGI.new(                                :port(8080)                        );  

Page 102: Perl6 in-production

my  $app  =  sub  (%env)  {            .  .  .    }  

Page 103: Perl6 in-production

my  $app  =  sub  (%env)  {            .  .  .    }  !

$http.handle($app);

Page 104: Perl6 in-production

my  $app  =  sub  (%env)  {                return  [                  200,                  [                      'Content-­‐Type'  =>                      'text/plain'                  ],                  [                      'Hello,  World!’                  ]          ];  }

Page 105: Perl6 in-production

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"  ]  ];  }  !

$http.handle($app);

Page 106: Perl6 in-production

!

Web::App module set

Explore

Page 107: Perl6 in-production

Bailador

Page 108: Perl6 in-production

Bailador(Dancer)

Page 109: Perl6 in-production

Available in the Rakudo* distribution

Page 110: Perl6 in-production

(Does not instantly work in the 2015.09 distribution)

Page 111: Perl6 in-production

use  Bailador;

Page 112: Perl6 in-production

use  Bailador;  !

get  '/'  =>  sub  {  !

}  

Page 113: Perl6 in-production

use  Bailador;  !

get  '/'  =>  sub  {          return  "Hi\n";  }  !

Page 114: Perl6 in-production

use  Bailador;  !

get  '/'  =>  sub  {          return  "Hi\n";  }  !

baile;

Page 115: Perl6 in-production

use  Bailador;  !

get  '/'  =>  sub  {          "Hi\n"  }  !

baile;

Page 116: Perl6 in-production

$  perl6  test.pl  !

Entering  the  development  dance  floor:  http://0.0.0.0:3000  [2015-­‐11-­‐17T13:41:08Z]  Started  HTTP  server.  

Page 117: Perl6 in-production

Started… !

Then open it in a browser

Page 118: Perl6 in-production

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

Page 119: Perl6 in-production

Update HTTP::Easy using panda

Page 120: Perl6 in-production

git  clone  ...  panda  install  ./Bailador

Page 121: Perl6 in-production

!

-­‐  connection.send($res.Str);  !

+  connection.print($res.Str);  

Page 122: Perl6 in-production

use  Bailador;  !

get  '/'  =>  sub  {          return  "Hi\n";  }  !

get  '/hello/:name'  =>  sub  ($name)  {          return  "Hi,  $name\n";  }  !

baile;

Page 123: Perl6 in-production

use  Bailador;  !

get  '/'  =>  sub  {          return  "Hi\n";  }  !

get  '/hello/:name'  =>  sub  ($name)  {          return  "Hi,  $name\n";  }  !

baile;

Page 124: Perl6 in-production

NB!

Page 125: Perl6 in-production

!

get  '/hello/:name'  =>  sub  ($name)  {  !

vs.!

get  '/hello/:name'  =>  sub($name)  {

Page 126: Perl6 in-production

===SORRY!===    Error  while  compiling  test1.pl  Variable  '$name'  is  not  declared  at  test1.pl:7  !

-­‐-­‐-­‐-­‐-­‐-­‐>    get  '/hello/:name'  =>  sub(⏏$name)    

Page 127: Perl6 in-production

Accessing request data

Page 128: Perl6 in-production

get  '/'  =>  sub  {          return  request.perl;  }

Page 129: Perl6 in-production

Bailador::Request.new(env  =>  {:HTTP_ACCEPT("*/*"),  :HTTP_HOST("0.0.0.0:3000"),  :HTTP_USER_AGENT("curl/7.35.0"),  :PATH_INFO("/"),  :QUERY_STRING(""),  :REQUEST_METHOD("GET"),  :REQUEST_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),  "p6sgi.errors.buffered"  =>  Bool::True,  

Page 130: Perl6 in-production

What is a ‘request’?

Page 131: Perl6 in-production

class  Bailador::App  {          .  .  .          method  request  {                  $.context.request          }          method  response  {                  $.context.response          }          .  .  .  }

Page 132: Perl6 in-production

get  /.*/  =>  sub  {          return                  request.env<REQUEST_URI>                  ~                  "\n";  }  

Page 133: Perl6 in-production

get  /.*/  =>  sub  {          return                  request.env<REQUEST_URI>                  ~                  "\n";  }  

Page 134: Perl6 in-production

Templates

Page 135: Perl6 in-production

get  '/'  =>  sub  {          template                    't.tt',                  {  name  =>  'Name'  }  }

Page 136: Perl6 in-production

get  '/'  =>  sub  {          template                    't.tt',                  {  name  =>  'Name'  }  }

Page 137: Perl6 in-production

%  my  ($h)  =  @_;  <html>  <head>          <title>              Hi,  <%=  $h<name>  %>          </title>  </head>  <body>          <h1>Hello  <%=  $h<name>  %></h1>  </body>  </html>

Page 138: Perl6 in-production

%  my  ($h)  =  @_;  <html>  <head>          <title>              Hi,  <%=  $h<name>  %>          </title>  </head>  <body>          <h1>Hello  <%=  $h<name>  %></h1>  </body>  </html>

Page 139: Perl6 in-production

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  

Page 140: Perl6 in-production

my  $_location;  !

.  .  .  !

$!renderer.render(          slurp(                  "$_location/views/$tmpl"          ),          @params  );

lib/Bailador/App.pm

Page 141: Perl6 in-production

my  $_location;  !

.  .  .  !

$!renderer.render(          slurp(                  "$_location/views/$tmpl"          ),          @params  );

lib/Bailador/App.pm

Page 142: Perl6 in-production

my  $_location  =  '.';  !

.  .  .  !

$!renderer.render(          slurp(                  "$_location/views/$tmpl"          ),          @params  );

lib/Bailador/App.pm

Page 143: Perl6 in-production

OK, Perl. What about databases?

Page 144: Perl6 in-production

DBIish

Page 145: Perl6 in-production

panda  install  DBIish

Page 146: Perl6 in-production

use  DBIish;

Page 147: Perl6 in-production

use  DBIish;  my  $dbh  =  DBIish.connect(      'mysql',      :host<example.com>,      :port(3306),      :database<$dbname>,      :user<$dbuser>,      :password<$dbpassword>);

Page 148: Perl6 in-production

my  $sth  =  $dbh.prepare(            "select  now()"  );  !

$sth.execute();

Page 149: Perl6 in-production

my  $arr  =            $sth.fetchall_arrayref();

Page 150: Perl6 in-production

my  $arr  =            $sth.fetchall_arrayref();  !

for  $arr  -­‐>  $x  {          say  $x;  }

Page 151: Perl6 in-production

It works!

Page 152: Perl6 in-production

__END__

Cluj-Napoka 2015 !

!

Andrew Shitov | [email protected]