<?xml version="1.0" encoding="UTF-8" ?>
<presentation>
  <title>Introducing Perl - Version VI: A New Hope</title>
<!--
  <subtitle>Subtitle If Needed</subtitle>
-->
  <author>Grant McLean^H^H^H^HSam Vilain</author>
  <email>grantm^H^H^Hsamv@cpan.org</email>

<!--
  Who needs a DTD when you have an example?!? ...

  <slide>
    <title>Title Here</title>
    <image src="images/filename.jpg" />         // will be floated right
    <screenshot>filename.png</screenshot>       // will be inlined with bullets
    <bullet></bullet>
    <code><![CDATA[
    ]]></code>
    <notes>                                     // go into notes.txt for speaker
    </notes>
  </slide>

-->

  <slide>
    <title>What is Perl 6?</title>
    <image src="images/p6_cover_medium.png" />
    <bullet>A new high level programming language</bullet>
    <bullet>Designed by @Larry</bullet>
    <bullet>Bears a striking resemblance to this other language called
       Perl 5, in much of its syntax and feel</bullet>
    <bullet>Also Open Source</bullet>
    <notes>
      - programming vs scripting - offline
      - compiled vs interpreted - offline
      - procedural/object oriented/functional? - Yes
      - Larry also wrote 'patch' (and 'rn')
      - one of the original Open Source projects
      - Perl 1 released in 1987 (4 years before Linux)
      - Perl 5 released in 1994
      - Uncle Sam wants lazy programmers image?
    </notes>
  </slide>

  <slide>
    <title>Cool things about Perl 6</title>
    <image src="images/phd.png" />
    <bullet>'Clean' re-write - Lots of Broken As Designed(TM) things fixed</bullet>
    <bullet>Optional Strict Typing</bullet>
    <bullet>Objects in core</bullet>
    <bullet>Rules-based programming</bullet>
    <bullet>Higher Order functions</bullet>
    <bullet>Interpreter independance</bullet>
    <bullet>Grammar mutation, macros</bullet>
    <bullet>Continuations and Coroutines</bullet>
    <notes>
      - Second System by people fully aware of SSD
      - Objects system is Roles-based, like Smalltalk traits or Haskell classes
    </notes>
  </slide>

  <slide>
    <title>What can Perl 6 be used for?</title>
    <image src="images/swiss-army-lightsabre.jpg" />
    <bullet>Everything Perl 5 could</bullet>

    <bullet>Writing compiled programs</bullet>

    <bullet>Writing BIG programs</bullet>

    <bullet>Writing compilers and parsers via rules and types
      system(s)</bullet>

    <bullet>Simpler Application Servers via continuations</bullet>
    <bullet>...</bullet>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Our first Perl program</title>
    <code><![CDATA[
      print "Hello World!\n";
    ]]></code>
    <notes>
      - \n = newline (in double quotes)
      - semicolon is a statement separator - not strictly needed in this case
    </notes>
  </slide>

  <slide>
    <title>Our first Perl 6 program</title>
    <code><![CDATA[
      say "Hello World!";
    ]]></code>
    <notes>
      - say makes automatic newline
      - Still basically the same
    </notes>
  </slide>

  <slide>
    <title>Running our first program</title>
    <code><![CDATA[
      pugs hello.p6
    ]]></code>
    <bullet>Or, add a 'shebang' line and chmod</bullet>
    <code><![CDATA[
      #!/usr/local/bin/pugs
    ]]></code>
    <notes>
      - Windows: associate .p6 with your editor
    </notes>
  </slide>

  <slide>
    <title>good_greeting.pl</title>
    <code><![CDATA[
      ($sec,$min,$hour,$day,$mon,$year) = localtime();

      if($hour < 12) {
          $greeting = "Good morning";
      }
      elsif($hour < 17) {
          $greeting = "Good afternoon";
      }
      else {
          $greeting = "Good evening";
      }

      print "$greeting World!  (The time is $hr:$min)\n";
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>good_greeting.p6</title>
    <code><![CDATA[
      ($sec,$min,$hour,$day,$mon,$year) = localtime();

      if $hour < 12 {
          $greeting = "Good morning";
      }
      elsif $hour < 17 {
          $greeting = "Good afternoon";
      }
      else {
          $greeting = "Good evening";
      }

      say "$greeting World!  (The time is $hr:$min)";
    ]]></code>
    <notes>
      - don't need parantheses around if conditionals
    </notes>
  </slide>

  <slide>
    <title>good_greeting.p6</title>
    <code><![CDATA[
      ($sec,$min,$hour,$day,$mon,$year) = localtime();

      given $hour {
         when $hour < 12 {
            $greeting = "Good morning";
         }
         when $hour < 17 {
            $greeting = "Good afternoon";
         }
         default {
            $greeting = "Good evening";
         }
      }

      say "$greeting World!  (The time is $hr:$min)";
    ]]></code>
    <notes>
      - switch statement
    </notes>
  </slide>

  <slide>
    <title>good_practice.p6</title>
    <code><![CDATA[
      #!/usr/local/bin/pugs

      my($sec,$min,$hour,$day,$mon,$year) = localtime();

      my $greeting = {
          given $hour {
             when $hour < 12 { "Good morning"   }
             when $hour < 17 { "Good afternoon" }
             default         { "Good evening"   }
          }
      };

      say "$greeting World!  (The time is { sprintf("%02u:%02u",
                                                    $hour, $min) })";
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>good_practice.p6 output</title>
    <code><![CDATA[
samv:~/utsl/pm/perl-intro$ pugs ./good_practice.p6
*** No compatible subroutine found: "&localtime"
    at good_practice.p6 line 3, column 39-50
samv:~/utsl/pm/perl-intro$
    ]]></code>
    <notes>
    </notes>
  </slide>

    <slide>
    <title>No worries!  TIMTOWTDI</title>
    <code><![CDATA[
      my $secs  = time() % 86400;
      my $mins  = int($secs / 60);
      my $hours = int($mins / 60);
      ($mins, $secs) »%= 60;
      my $time = sprintf("%02u:%02u:%02u", $hour, $min, $secs);
    ]]></code>
    <notes>
      - hyper operator
    </notes>
  </slide>

  <slide>
    <title>No worries!  TIMTOWTDI</title>
    <code><![CDATA[
      my $secs  = time() % 86400;
      my $mins  = int($secs / 60);
      my $hours = int($mins / 60);
      ($mins, $secs) »%= 60;
      my $time = sprintf("%02u:%02u:%02u", $hour, $min, $secs);
    ]]></code>
    <bullet>Or:</bullet>
    <code><![CDATA[
      my @time = eval_perl5("localtime()");
      say @time.join(":");
    ]]></code>
    <bullet>Or:</bullet>
    <code><![CDATA[
      my $time = eval_perl5("[localtime()]");
      say @$time.join(":");
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>good_practice.p6</title>
    <code><![CDATA[
#!/usr/bin/pugs

my $list = eval_perl5 "[localtime()]";

my ($sec,$min,$hour,$day,$mon,$year) = (0..6).map:{$list[$_]};

my $greeting = {
    given $hour {
        when $hour < 12 { "Good morning"   }
        when $hour < 17 { "Good afternoon" }
        default         { "Good afternoon" }
    }
};

say "$greeting World!  (The time is { sprintf("%02u:%02u",
                                              $hour, $min) })";
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>good_practice.p6 - output</title>
    <code><![CDATA[
samv:~/utsl/pm/perl-intro$ pugs ./good_practice.p6
<SubBlock(<anon>)> World!  (The time is 16:03)
samv:~/utsl/pm/perl-intro$     ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>good_practice.p6</title>
    <code><![CDATA[
#!/usr/bin/pugs

my $list = eval_perl5 "[localtime()]";

my ($sec,$min,$hour,$day,$mon,$year) = (0..6).map:{$list[$_]};

my $greeting = {
    given $hour {
        when $hour < 12 { "Good morning"   }
        when $hour < 17 { "Good afternoon" }
        default         { "Good afternoon" }
    }
};

say "$greeting() World!  (The time is { sprintf("%02u:%02u",
                                              $hour, $min) })";
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>good_practice.p6 - output</title>
    <code><![CDATA[
samv:~/utsl/pm/perl-intro$ pugs ./good_practice.p6
Good afternoonWorld!  (The time is 16:05)
samv:~/utsl/pm/perl-intro$     ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Data Types: core</title>
    <code><![CDATA[
      my Str $name   = 'Buffy';
      my Int $age    = 12;

      my int8 $age   = 256;  # bad!  Becomes 0 or overflow

      my bool $foo   = 1;    # becomes bool::true

      my Num $pi     = 3.14159;
      my Any $radius = 6.378e3;

      my CGI $cgi    = CGI.new();

      say "Hello my name is $name and I am $age years old";

      say "Earth's circumference: ", ($pi * $radius ** 2).int, "km";

      print $cgi.header('text/plain');
    ]]></code>
    <notes>
      - rich scalar types
      - still "Any" type
      - can annotate object types, but still have to use constructor
      - object syntax uses . now
    </notes>
  </slide>

  <slide>
    <title>Perl 5 Data Types: arrays</title>
    <code><![CDATA[
      my @names = ('Tom', 'Dick', 'Larry');

      print $names[0], "\n";

      push @names, 'Moe';

      print join(', ', @names), "\n";

      print join(', ', @names[1,3]), "\n";

      my $count = @names;

      print "The list contains $count names\n";

      print "The last name is number $#names\n";
    ]]></code>
    <notes>
      - zero based indexes
      - don't use plurals for naming arrays
      - array size adjust dynamically
      - array slices (what will this print?)
      - array in scalar context - DWIM
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Data Types: arrays</title>
    <code><![CDATA[
      my @names = ('Tom', 'Dick', 'Larry');

      say @names[0];

      push @names, 'Moe';

      say join(', ', @names);

      say join(', ', @names[1,3]);
 


      say "The list contains { @names.elems } names";

      say "The last name is number { @names.end }";
    ]]></code>
    <notes>
      - don't change sigil
      - can't just use array in scalar context to get elems any more
      - no $# syntax
    </notes>
  </slide>

  <slide>
    <title>Perl 5 Data Types: hashes</title>
    <code><![CDATA[
      my %roman = ('I' => 1, 'II' => 2, 'III' => 3, 'IV' => 4);

      print $roman{'III'}, "\n";

      print join(', ', keys(%roman)), "\n";

      while(my($key, $value) = each(%roman)) {
        print "$key = $roman{$key}\n";
      }

      delete($roman{IV});

      print join(', ', @roman{'I', 'II', 'III'}), "\n";
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Data Types: hashes</title>
    <code><![CDATA[
      my Int %roman = ('I' => 1, 'II' => 2, 'III' => 3, 'IV' => 4);

      say %roman{'III'};

      say %roman.keys.join(", ");

      for %roman.kv -> $key, $value {
        say "$key = $value";
      }

      %roman.delete<IV>;

      say %roman<I II III>.join(', ');
    ]]></code>
    <notes>
      - again, sigil stays the same
      - list results can be chained
      - pointy subs
      - angle lookups
    </notes>
  </slide>

  <slide>
    <title>Perl 5 Syntax: while loop</title>
    <code><![CDATA[
      $count = 1;
      while($count < 10) {
        print "$count\n";
        $count = $count + 1;
      }
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Syntax: while loop</title>
    <code><![CDATA[
      loop $count = 1; $count < 10; $count++ {
        print "$count\n";
      }
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>A Perl 5 implementation of 'grep'</title>
    <code><![CDATA[
      #!/usr/bin/perl -w

      use strict;

      my $pattern = shift;

      while(<>) {
        print if(/$pattern/);
      }
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>A Perl 6 implementation of 'grep'</title>
    <code><![CDATA[
      #!/usr/local/bin/pugs

      my $foo;

      while ($foo = =<>) {
        print $foo if $foo ~~ m:perl5/$pattern/;
      }
    ]]></code>
    <notes>
      - =$foo syntax for iterators
      - m:perl5: for pcre
    </notes>
  </slide>

  <slide>
    <title>Perl 5 Syntax: for loop</title>
    <code><![CDATA[
      for($count = 1; $count < 10; $count++) {
        print "$count\n";
      }
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Syntax: for loop</title>
    <code><![CDATA[
      $count = 1;
      while $count < 10 {
        say $count;
        $count++;
      }
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Perl 5 Syntax: foreach loop</title>
    <code><![CDATA[
      foreach my $count (1..9) {
        print "$count\n";
      }
    ]]></code>
    <bullet>Or:</bullet>
    <code><![CDATA[
      foreach (1..9) {
        print "$_\n";
      }
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Syntax: for loop</title>
    <code><![CDATA[
      for 1..9 -> $count {
        say $count;
      }
    ]]></code>
    <bullet>Or:</bullet>
    <code><![CDATA[
      for 1..9 {
         say;
      }
    ]]></code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Perl Syntax: subroutines</title>
    <code><![CDATA[
      my $pi = 3.14159;

      print circumference(6.378e3);

      sub circumference {
        my($radius) = @_;

        return($pi * $radius ** 2);
      }
    ]]></code>
    <notes>
      - variable scoping: file scoped global vs local to subroutine
      - arguments passed in via @_
      - can return multiple values
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Syntax: subroutines</title>
    <code><![CDATA[
      my $pi = 3.14159;

      print circumference(6.378e3);

      sub circumference(Num $radius) {
        return($pi * $radius ** 2);
      }
    ]]></code>
    <notes>
      - named arguments
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Syntax: subroutines</title>
    <code><![CDATA[
      print circumference(:radius(6.378e3));

      sub circumference(Num $radius, Num ?$pi = 3.14159) {
        return($pi * $radius ** 2);
      }
    ]]></code>
    <notes>
      - named arguments
    </notes>
  </slide>

  <slide>
    <title>A data munging example</title>
    <bullet>Input:</bullet>
    <code>
      Auckland:
      Graeme Barker        grabar@xtra.co.nz        027 555 1234
      Martin Fenwick       m.fenwick@clear.net.nz   021 555 5432

      Waikato:
      Fiona Winters        fiwi@mooloo.net.nz       021 555 8113
      Justin Hiraka        justinh@xtra.co.nz       027 555 289

      Hawkes Bay:
      Michael Teller       mike.teller@bay.net.nz   027 555 9753
    </code>
    <bullet>Output:</bullet>
    <code>
      INSERT INTO dealer VALUES (
        'Graeme', 'Barker', 'grabar@xtra.co.nz',
        '027 555 1234', 'Auckland'
      );
    </code>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>Data munging continued</title>
    <code><![CDATA[
      #!/usr/bin/perl -w

      use strict;

      my $input_file = 'dealers.txt';

      open my $in, '<', $input_file or die "open($input_file): $!";

      my $region = '';

      while(<$in>) {
        if(/^([a-zA-Z ]+):\s*$/) {
          $region = $1;
          next;
        }
        if(/^(\w+)\s+(\w+)\s+(\S*?@\S+)\s+(\d+(?:\s+\d+)*)/) {
          print "INSERT INTO dealer VALUES (",
                "'$1', '$2', '$3', '$4', '$region');\n";
        }
      }
    ]]></code>
    <notes>
      - earlier 'grep' example opened files implicitly, explicit here
      - regular expressions for pattern matching
      - if it looks like a region, store it in global (next to short-circuit)
      - if it looks like a record, print out in appropriate form
      - naive regex doesn't handle apostrophes, hyphens, 3 names etc
    </notes>
  </slide>

  <slide>
    <title>Data munging continued</title>
    <code><![CDATA[
      #!/usr/local/bin/pugs



      my $input_file = 'dealers.txt';

      my $in = open $input_file or die "open($input_file): $!";

      my $region = '';

      for =$in {
        if m:perl5/^([a-zA-Z ]+):\s*$/ {
          $region = $0;
          next;
        }
        if m:perl5/^(\w+)\s+(\w+)\s+(\S*?@\S+)\s+(\d+(?:\s+\d+)*)/ {
          print "INSERT INTO dealer VALUES (",
                "{ $/.map:{"'$_'"}.join(', ') }, '$region');\n";
        }
      }
    ]]></code>
    <notes>
      - open now returns its result
      - matches now based at $0
      - $/ match object
    </notes>
  </slide>

  <slide>
    <title>Perl 6 Documentation</title>
    <image src="images/Books-Of-perl6.png" />
    <bullet>Perl6::Bible - AES</bullet>
    <bullet>pugs examples/</bullet>
    <bullet>pugs test suite</bullet>
    <bullet>(Outdated) books</bullet>
    <notes>
      - this slide was left until last because it's the most important
      - demo ActiveState HTML if poss
      - demo perldoc -f localtime
      - perlop - describes regex options (eg: i = case insensitive)
      - don't forget the books
    </notes>
  </slide>

  <slide>
    <title>Perl6 resources on the net</title>
    <bullet>dev.perl.org/perl6</bullet>
    <bullet>www.pugscode.org</bullet>
    <bullet>www.perlmonks.org</bullet>
    <notes>
    </notes>
  </slide>

  <slide>
    <title>The End</title>
    <bullet>Questions?</bullet>
  </slide>

  <slide>
    <title>Not enough!</title>
    <bullet>Port slide generator to Perl 6</bullet>
    <bullet>much faster than Spork</bullet>
  </slide>

  <slide>
    <title>Grant's XML slide generator</title>
    <code><![CDATA[
      #!/usr/bin/perl -w

      use strict;

      use XML::LibXML;
      use Data::Dumper;

      my %template = (
        index => Template::MasonLite->new_from_file('./_index.html'),
        toc   => Template::MasonLite->new_from_file('./_toc.html'),
        slide => Template::MasonLite->new_from_file('./_slide.html'),
        notes => Template::MasonLite->new_from_file('./_notes.txt'),
      );

      my $file = 'talk.xml';

      my $parser = XML::LibXML->new;
      my $doc    = $parser->parse_file($file);
      my $root   = $doc->getDocumentElement;

      gen_title_page($root);
      gen_contents_page($root);
      gen_slides($root);
      gen_notes($root);

      exit;


      sub gen_title_page {
        my($doc) = @_;
      
        ...
      ]]></code></slide>

  <slide>
    <title>Grant's XML slide generator - module</title>
    <code><![CDATA[
      #  -*- perl -*-

      package mkpres;

      use strict;

      use XML::LibXML;
      use Data::Dumper;

      my %template = (
        index => Template::MasonLite->new_from_file('./_index.html'),
        toc   => Template::MasonLite->new_from_file('./_toc.html'),
        slide => Template::MasonLite->new_from_file('./_slide.html'),
        notes => Template::MasonLite->new_from_file('./_notes.txt'),
      );

      sub new {
          bless {}, shift;
      }

      sub get_xmldoc {
          shift;
          my $file = shift;
      
          my $parser = XML::LibXML->new;
          my $doc    = $parser->parse_file($file);
          my $root   = $doc->getDocumentElement;
      
          return $root;
      }


      sub gen_title_page {
          shift;
        ...
      ]]></code></slide>

  <slide>
    <title>mkpres.p6</title>
    <code><![CDATA[
      #!/usr/local/bin/pugs

      use mkpres--Perl5;

      my $file = 'talk.xml';

      my $mkpres = mkpres.new();

      say "Getting XML from $file";
      my $root = $mkpres.get_xmldoc($file);

      say "Got $root?";

      say "Generating Title Page";
      $mkpres.gen_title_page($root);
      say "Generating Contents Page";
      $mkpres.gen_contents_page($root);
      say "Generating Slides";
      $mkpres.gen_slides($root);
      say "Generating Notes";
      $mkpres.gen_notes($root);

      exit;
    ]]></code>
  </slide>

  <slide>
    <title>mkpres.p6 output</title>
    <code><![CDATA[
samv:~/utsl/pm/perl-intro$ pugs mkpres.p6
Getting XML from talk.xml
Got XML::LibXML::Element=SCALAR(0x862aca8)?
Generating Title Page
Generating Contents Page
Generating Slides
Generating Notes
samv:~/utsl/pm/perl-intro$ 
    ]]></code>
  </slide>

</presentation>
