Perl6::Perl5::Differences -- Differences between Perl 5 and Perl 6
This document is intended to be used by Perl 5 programmers who are new to Perl 6 and just want a quick overview of the main differences. More detail on everything can be found in the language reference, which have been linked to throughout. In certain cases, you can also just use Perl 5 code in Perl 6 and compiler may say what's wrong. Note that it cannot recognize every difference, as sometimes old syntax actually means something else in Perl 6.
This list is currently known to be incomplete.
Where you used to say:
my @fruits = ("apple", "pear", "banana"); print $fruits[0], "\n";
You would now say:
my @fruits = "apple", "pear", "banana"; say @fruits[0];
Or even use the <>
operator, which replaces qw()
:
my @fruits = <apple pear banana>;
Note that the sigil for fetching a single element has changed from $
to @
; perhaps a better way to think of it is that the sigil of a variable is now a part of its name, so it never changes in subscripting. This also applies to hashes.
For details, see "Names and Variables" in S02.
Hash elements no longer auto-quote:
Was: $days{February} Now: %days{'February'} Or: %days<February> Or: %days<<February>>
The curly-bracket forms still work, but curly-brackets are more distinctly block-related now, so in fact what you've got there is a block that returns the value "February". The <>
and <<>>
forms are in fact just quoting mechanisms being used as subscripts (see below).
Yes, a twigil. It's the second character in the variable name. For globals, it's a *
.
Was: $ENV{FOO} Now: %*ENV<FOO>
For details, see "Names and Variables" in S02.
The command-line arguments are now in @*ARGS
, not @ARGV
. Note the *
twigil because @*ARGS
is a global.
Number of elements in an array:
Was: $#array+1 or scalar(@array) Now: @array.elems
Index of last element in an array:
Was: $#array Now: @array.end
Therefore, last element in an array:
Was: $array[$#array] Now: @array[@array.end] @array[*-1] # beware of the "whatever"-star
For details, see "Built-In Data Types" in S02
Old New --- --- __LINE__ $?LINE __FILE__ $?FILE __PACKAGE__ $?PACKAGE __END__ =begin END __DATA__ =begin DATA
See "double-underscore forms are going away" in S02 for details. The ?
twigil refers to data that is known at compile time.
There are still three main contexts, void, item (formerly scalar) and list. Aditionally there are more specialized contexts, and operators that force that context.
my @array = 1, 2, 3; # generic item context my $a = @array; say $a.WHAT; # prints Array # string context say [email protected]; # "1 2 3" # numeric context say [email protected]; # 3 # boolean context my $is-nonempty = [email protected];
Apostrophes '
and dashes -
are allowed as part of identifiers, as long as the next character is alphabetic. In other words, any two valid identifiers may be joined with a single '
or -
character to form a longer identifier.
A comprehensive list of operator changes is documented at "Changes to Perl 5 operators" in S03 and "New operators" in S03.
Some highlights:
qw()
changes; new interpolating formWas: qw(foo) Now: <foo> Was: split ' ', "foo $bar bat" Now: <<foo $bar bat>>
Quoting operators now have modifiers that can be used with them (much like regexes and substitutions in Perl 5), and you can even define your own quoting operators. See S03 for details.
Note that ()
as a subscript is now a sub call, so instead of qw(a b)
you would write qw<a b>
or qw[a b]
(if you don't like plain <a b>
), that is).
String concatenation is now done with ~
.
Regex match is done with the smart match operator ~~
, the perl 5 match operator =~
is gone.
if "abc" ~~ m/a/ { ... }
|
and &
as infix operators now construct junctions. The binary AND and binary OR operators are split into string and numeric operators, that is ~&
is binary string AND, +&
is binary numeric AND, ~|
is binary string OR etc.
Was: $foo & 1; Now: $foo +& 1;
The bitwise operators are now prefixed with a +, ~ or ? depending if the data type is a number, string or boolean.
Was: $foo << 42; Now: $foo +< 42;
The assignment operators have been changed in a similar vein:
Was: $foo <<= 42; Now: $foo +<= 42;
Parenthesis don't construct lists, they merely group. Lists are constructed with the comma operator. It has tighter precedence than the list assignment operator, which allows you to write lists on the right hand side without parens:
my @list = 1, 2, 3; # @list really has three elements
The arrow operator ->
for dereferencing is gone. Since everything is an object, and derferencing parenthesis are just method calls with syntactic sugar, you can directly use the appropriate pair of parentheses for either indexing or method calls:
my $aoa = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; say $aoa[1][0]; # 4 my $s = sub { say "hi" }; $s(); # or $s.(); $aoa.[1][0]
See S04 for the full specification of blocks and statements in Perl6.
Was: if ($a < $b) { ... } Now: if $a < $b { ... }
Likewise for while
, for
, etc. If you insist on using parens, make sure there's a space after the if
, otherwise it's a sub call.
Using eval
on a block is now replaced with try
.
Was: eval { # ... }; if ([email protected]) { warn "oops: [email protected]"; } Now: try { # ... CATCH { default { warn "oops: $!" } } }
CATCH provides more flexiblity in handling errors. See "Exception_handlers" in S04 for details.
Was: foreach (@whatever) { ... } Now: for @whatever { ... }
Also, the way of assigning to something other than $_
has changed:
Was: foreach my $x (@whatever) { ... } Now: for @whatever -> $x { ... }
This can be extended to take more than one element at a time:
Was: while (my($age, $sex, $location) = splice @whatever, 0, 3) { ... } Now: for @whatever -> $age, $sex, $location { ... }
(Except the for
version does not destroy the array.)
See "The for statement" in S04 and "each" in S29 for details.
Was: for ($i=0; $i<10; $i++) { ... } Now: loop ($i=0; $i<10; $i++) { ... }
loop
can also be used for infinite loops:
Was: while (1) { ... } Now: loop { ... }
Here's a simple translation of a Perl5 regular expression to Perl6:
Was: $str =~ m/^\d{2,5}\s/i Now: $str ~~ m:P5:i/^\d{2,5}\s/
The :P5
modifier is there because the standard Perl6 syntax is rather different, and 'P5' notes a Perl5 compatibility syntax. For a substitution:
Was: $str =~ s/(a)/$1/e; Now: $str ~~ s:P5/(a)/{$0}/;
Notice that $1
starts at $0
now, and /e
is gone in favor of the embedded closure notation.
Anonymous regexpes are now default, unless used in boolean context.
Was: my @regexpes = ( qr/abc/, qr/def/, ); Now: my @regexpes = ( /abc/, /def/, );
Also, if you still want to mark regexp as anonymous, the qr//
operator is now called rx//
(Mnemonic: regex) or regex { }
.
For the full specification, see S05. See also:
The related Apocalypse, which justifies the changes:
http://dev.perl.org/perl6/doc/design/apo/A05.html
And the related Exegesis, which explains it more detail:
http://dev.perl.org/perl6/doc/design/exe/E05.html
Formats will be handled by external libraries.
Perl 6 has an object system built into the language, with key words for classes, roles, methods and attributes. Public attributes have the .
twigil, private ones the !
twigil.
class YourClass { has $!private; has @.public; # and with write accessor has $.stuff is rw; method do_something { if self.can('bark') { say "Something doggy"; } } }
Was: $object->method Now: $object.method
Was: $self->$method() Now: $self.$method() # hard ref Now: $self."$method"() # symbolic ref
Most built-in functions are now methods of built-in classes such as String
, Array
, etc.
Was: my $len = length($string); Now: my $len = $string.chars; Was: print sort(@array); Now: print @array.sort; @array.sort.print;
You can still say sort(@array)
if you prefer the non-OO idiom.
Since both builtin functions and operators are multi subs and methods, changing their behaviour for particular types is as simple as adding the appropriate multi subs and methods. If you want these to be globally available, well, you can't, because everything is lexically scoped in Perl 6. You can, however, export multi definitions to any code that wishes to import it.
class TurkishStr { multi sub uc(TurkishStr $str) is export { ... } # overload the string concatenation: multi sub infix:<~>(TurkishStr $us, TurkishStr $them) is export { ... } }
If you want to offer a type cast to a particular type, just provide a method with the same name as the type you want to cast to.
sub needs_bar(Bar $x) { ... } class Foo { ... # coercion to type Bar: method Bar { ... } } needs_bar(Foo.new.Bar); # coerces to Bar
If you want to write a class whose objects can be assigned to a variable with the @
sigil, you have to implement the Positional
roles. Likewise, for the %
sigil you need to do the Associative
role. The &
sigil implies Callable
.
The roles provides the operators postcircumfix:<[ ]>
(Positional; for array indexing), postcircumfix:<{ }>
(Associative) and postcircumfix:<()>
(Callable). They are technically just functions with a fancy syntax. You can override these to provide the desired semantics.
class OrderedHash does Associative { multi sub postcircumfix:<{ }>(OrderedHash \this, Int $index) is export { # code for accessing single hash elements here } multi sub postcircumfix:<{ }>(OrderedHash \this, **@slice) is export { # code for accessing hash slices here } ... } import OrderedHash; my %orderedHash = OrderedHash.new(); say %orderedHash{'a'};
See S13 for all the gory details.
Was: if (-r $file && -x _) {...} Now: if $file ~~ :r & :x {...}
For details, see "Changes to Perl 5 operators"/"The filetest operators now return a result that is both a boolean" in S03
A number of builtins have been removed. For details, see:
Capture
objects fill the ecological niche of references in Perl 6. You can think of them as "fat" references, that is, references that can capture not only the current identity of a single object, but also the relative identities of several related objects. Conversely, you can think of Perl 5 references as a degenerate form of Capture
when you want to refer only to a single item.
Was: ref $foo eq 'HASH' Now: $foo ~~ Hash Was: @new = (ref $old eq 'ARRAY') ? @$old : ($old); Now: @new = @$old; Was: %h = ( k => \@a ); Now: %h = ( k => @a );
To pass an argument to modify by reference:
Was: sub foo {...}; foo(\$bar) Now: sub foo ($bar is rw); foo($bar)
The "obsolete" reference above has the details. Also, look for Capture under "Names_and_Variables" in S02, or at the Capture FAQ, Perl6::FAQ::Capture.
This is a version of print
that auto-appends a newline:
Was: print "Hello, world!\n"; Now: say "Hello, world!";
Since you want to do that so often anyway, it seemed like a handy thing to make part of the language. This change was backported to Perl 5, so you can use say
after you will use v5.10
or better.
wantarray
is gone. In Perl 6, context flows outwards, which means that a routine does not know which context it is executed in.
Instead you should return objects that do the right thing in every context.
Kirrily "Skud" Robert, <[email protected]>
, Mark Stosberg, Moritz Lenz, Trey Harris, Andy Lester, Larry Wall