Mini HowTo: How to port Perl 5 modules to Perl 6

  - Other resources:
      http://pugs.kwiki.org/?ConversionGuide
      http://perlmonks.org/index.pl?node_id=442402

  - Before you start porting a module, make sure you understand the class
    hierarchy of that module. It helps if you've actually used that module in
    Perl 5 :)

  - Port a module even if it depends on some other (not yet ported) modules --
    the dependencies can be ported later on.

  - Often, the translation of P5 -> P6 is quite mechanic:
    - $array[idx] -> @array[idx]
    - @array[1,2,3] -> @array[1,2,3]
    - $hash{$key} -> %hash{$key}
    - $hash{word} -> %hash<word>
    - @hash{'a','b','c'} -> %hash<a b c>
    - "@array" -> "@array[]"
    - "%hash" -> "%hash{}"
    - scalar @foo -> +@foo # or @foo.elems
    - a ? b : c -> a ?? b !! c
    - $self->method(...) -> self.method(...) or $.method(...), @.method(...)...
    - sub { my ($self, $a, $b) = @_; ... } ->
      method ($a, $b) { ... }
    - $x =~ s/.../.../g -> $x ~~ s:P5:g/.../.../
    - $self->{foo} -> $.foo
    - $foo = "bar" unless defined $foo ->
      $foo //= "bar" # (//) and (//=) will be in 5.9, too, IIRC
    - if($foo eq "a" or $foo eq "b" or $foo eq "c") {...} ->
      if $foo eq "a"|"b"|"c" {...}
    - foreach my $foo (@baz) {...} ->
      for @baz -> $foo {...}
    - length("foo") -> "foo".chars
    - Regular expressions:
      m/ a * b /x       -> m/ a * b /               # /x now default
      m/ a\  b /x       -> m/ a\  b /
                           m/ a <sp> b /            # also see below
                           m:s/ a b /               # :s == :sigspace
      (space)           -> <sp>                     # or \c[SPACE], \x20, \o40,
                                                    # <' '>

      [abc]             -> <[abc]>
      [^abc]            -> <-[abc]>
      [abc ]            -> <[ abc\ ]>               # ws meta in <[...]> too
      (?:...)           -> [...]
      <  >              -> \<  \>

      \p{prop}          -> <prop>
      \P{prop}          -> <-prop>

      \Qstring\E        -> <{ quotemeta 'string' }> # or <'literal string'>
      \Q$var\E          -> $var                     # always literal
      $var              -> <$var>

      \A                -> ^
      \z                -> $
      \Z                -> \n?$

      \n                -> \c[LF]                   # specifically a linefeed
      \r?\n             -> \n                       # logical newline
      [^\n]             -> \N                       # not a logical newline
                           \C[LF]                   # not a linefeed
      .                 -> \N                       # no /s
      .                 -> .                        # /s

      \G                -> <( .pos == $oldpos )>
                           m:p/pat/

      \a                -> \c[BEL]
      \N{CENT SIGN}     -> \c[CENT SIGN]
      [^\N{CENT SIGN}]  -> \C[CENT SIGN]
      \c[               -> \e
      \cX               -> \c[^X]
      [^\t]             -> \T
      [^\r]             -> \R
      [^\f]             -> \F
      [^\e]             -> \E
      [^\x1B]           -> \X1B
      [^\x{263a}]       -> \X[263a]

      \1                -> $1
      /$1/              -> my $old1 = $1; /$old1/
      //                -> /<null>/ or /<prior>/
      /a|/              -> /a|<null>/

      \C                -> [:bytes .]               # forced byte in UTF-8 (not
                                                    # recommended)
      \X                -> <.>                      # single grapheme
                           [:graphs .]

      x{2}              -> x**{2}
      x{2,}             -> x**{2...}
      x{1,2}            -> x**{1..2}
      x{1,2}?           -> x**{1..2}?

      (?=foo)           -> <?before foo>
      (?!foo)           -> <!before foo>
      (?<=foo)          -> <?after foo>
      (?<!foo)          -> <!after foo>

      (?{...})          -> {...}
      (??{...})         -> <{...}>

      (?>\d*)           \d*:                    # single atom no backtrack
      (?>(\d*))         (\d*):                  # () is still single atom
      (?>...)           [...]:                  # multiple atoms need []

      (?(c)t|f)         [ c :: t | f ]

      s/foo/bar()/e     -> s/foo/{ bar() }/
      m/^foo$/s         -> m/^foo$/
      m/^foo$/m         -> m/^^foo$$/
      m?foo?            -> m:once/foo/

  - split(m/;/, $foo) -> split(/;/, $foo) # notice: no m
    m// now works immediately, so:
        split(m/;/, $foo);
    would use the return value of the match (on the implicit $_) as the
    delimiter.
  - Or, if you don't want to split on a regular expression:
    split(m/;/, $foo) -> split(";", $foo)

  - split(' ', $foo) -> words($foo) or $foo.words or «$foo»

  - Heredocs:
      <<END    -> qq:to/END/
      <<"END"  -> qq:to/END/
      <<'END'  ->  q:to/END/

  - You can normally remove all that Perl 5 argument parsing and simply replace
    it with a nice signature.

  - # Perl 5
    require Exporter;
    our @ISA    = qw< Exporter >;
    our @EXPORT = qw< foo >;
    sub foo { ... }
    
    # -> Perl 6
    sub foo(...) is export { ... }

  - return map {.4.} sort {.3.} grep {.2.} map {.1.} ->
    map {.1.} ==> grep {.2.} ==> sort {.3.} ==> map {.4.} ==> return

  - The Perl 6 translation of Perl 5's getter/setter idiom is especially cool:

    # Perl 5
    sub get_foo {
      my $self = shift;

      my $ret = $self->{foo};
      return lc $ret; # always normalize
    }
    
    sub set_foo {
      my ($self, $to) = @_;

      $to =~ s/\s+$//; # strip whitespace at the end
      $self->{foo} = $to;
    }

    # -> Perl 6 (see L<S06/"Lvalue subroutines"> for information about Proxy)
    has $!foo;
    method foo() is rw {
      return new Proxy:
        FETCH => { lc $!foo },
        STORE => -> $to is copy {
          $to ~~ s/\s+$//;
          $!foo = $to;
        };
    }
    # And then:
    say $obj.foo;
    $obj.foo = "..."; # Notice: Standard assignment syntax!
                      # Assignments should look like assignments, not like
                      # method calls
  
  - If you trust the user to give appropriate data to the accessors, you can
    also use:
    has $.foo is rw;
  - Or:
    subset OddInt of Int where { $^n % 2 == 1 }
    has OddInt $.foo is rw;
    # And then:
    $obj.foo = 12; # will die

  - Arrays in item context become references to themselves, e.g.:
        my @bar = (1, "a", 3, "b")
        my $foo = @bar; # $foo now contains a reference to @bar
        $foo[1]; # == "a"

    Hashes behave in the same way:
        my %bar = (a => 1, b => "baz");
        my $foo = %bar; # $foo now contains a reference to @bar
        $foo<b>; # == "baz"

  - Methods and properties generally belong to the object contained, not the
    container:
        my @bar = (1, 2, 3, 4);
        my $foo = @bar;
        $foo.elems; # == 4 (@bar.elems)
    but
        tied($x)->foo -> variable($x).foo
    also non-scalar container objects are accessed directly:
        @bar.elems

  - When calling a method, parentheses are required on the dot notation if 
    there are any arguments. There may be no space between the method name 
    and the left parenthesis unless you use the dot form of parentheses:
        .doit       # okay, no arguments
        .doit()     # okay, no arguments
        .doit ()    # ILLEGAL (two terms in a row)
        .doit.()    # okay, no arguments, same as .doit()
        .doit .()   # ILLEGAL (two terms in a row)
        .doit\  .() # okay, no arguments, same as .doit()
    But a colon may stand in for a left paren with no corresponding right:
        .doit: 1,2,3 # okay

  - Subroutine/method/array/hash access: whitespace is disallowed
    between the name and the opening brace. The "long dot form" can be used
    to introduce intervening space.

        foo(@args)      # ok
        foo.(@args)     # ok
        foo (@args)     # WRONG
        foo\ .(@args)   # ok
        @a[0]           # ok
        @a.[0]          # ok
        @a [0]          # WRONG
        @a\ .[0]        # ok
        %h{'k'}         # ok
        %h.{'k'}        # ok
        %h {'k'}        # WRONG
        %h\ .{'k'}      # ok
        %h<k>           # ok
        %h.<k>          # ok
        %h  <k>         # WRONG
        %h\ .<k>        # ok

  - open()
       open my $fh, "<", $filename or die $!;    ->   my $fh = open($filename, :r) err die $!;

       "<"   -> :r
       ">"   -> :w
       ">>"  -> :a
       '+<"  -> :rw

       mixing them does not work yet

       open(FH, $filename)     ->  our $fh = open($filename) 
                                    my $fh = open($filename) 
                                and possibly:
                                    sub FH () { $fh }
                                    macro FH () { q:code { $fh } }
                                but $fh generally preferred

   - print to file
       print $fh "Hello\n";    -> print $fh: "Hello\n";   # adding the colon
                                  or
                               -> $fh.print("Hello\n");
                               -> $fh.print: "Hello\n";

   - close the file
     close($fh);               -> the same or $fh.close;

   - <FH>   reading from a file
     $fh.readline
     =$fh
