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]
    - scalar @foo -> +@foo # or @foo.elems
    - a ? b : c -> a ?? b :: c
    - $self->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:w/ a b /               # :w == :words
      (space)           -> <sp>                     # or \c[SPACE], \x20, \040,
                                                    # <' '>
      
      [abc]             -> <[abc]>
      [^abc]            -> <-[abc]>
      (?:...)           -> [...]
      
      \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
      
      \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/
      
      \C                -> [:bytes .]               # forced byte in UTF-8 (not
                                                    # recommended)
      \X                -> <.>                      # single grapheme
                           [:graphs .]
      
      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>
      
      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.
  
  - Heredocs:
      <<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:
    subtype OddInt of Int where { $^n % 2 == 1 }
    has OddInt $.foo is rw;
    # And then:
    $obj.foo = 12; # will die
  
  - Arrays in scalar 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)

  - 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 .()   # okay, no arguments, same as .doit()

  - Subroutine/method/array/hash access: whitespace is disallowed
    between the name and the opening brace. The "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
