TITLE
Synopsis 3: Summary of Perl 6 Operators
AUTHOR
Luke Palmer <luke@luqui.org>
VERSION
Maintainer: Larry Wall <larry@wall.org>
Date: 8 Mar 2004
Last Modified: 22 Feb 2005
Number: 3
Version: 5
Operator renaming
Several operators have been given new names to increase clarity and better Huffman-code the language:
->
becomes.
, like the rest of the world uses.The string concatenation
.
becomes~
. Think of it as "stitching" the two ends of its arguments together.Unary
~
now imposes a string context on its argument, and+
imposes a numeric context (as opposed to being a no-op in Perl 5). Along the same lines,?
imposes a boolean context, and*
imposes a list context.Bitwise operators get a data type prefix:
+
,~
, or?
. For example,|
becomes either+|
or~|
or?|
, depending on whether the operands are to be treated as numbers, strings, or boolean values. Left shift<<
becomes+<
, and correspondingly with right shift. Unary~
becomes either+^
or~^
or?^
, since a bitwise NOT is like an exclusive-or against solid ones. Note that?^
is functionally identical to!
.?|
differs from||
in that?|
always returns a standard boolean value (either 1 or 0), whereas||
return the actual value of the first of its arguments that is true.x
splits into two operators:x
(which concatenates repetitions of a string to produce a single string), andxx
(which creates a list of repetitions of a list or scalar).Trinary
? :
becomes?? ::
.qw{ ... }
gets a synonym:< ...
>, and an interpolating variant,«...»
. For those still living without the blessings of Unicode, that can also be written:<< ... >>
.The scalar comma
,
now constructs a list reference of its operands. You have to use a[-1]
subscript to get the last one.
New operators
Binary
//
is just like||
, except that it tests its left side for definedness instead of truth. There is a low-precedence form, too:err
.Binary
=>
is no longer just a "fancy comma." It now constructs aPair
object that can, among other things, be used to pass named arguments to functions. It provides scalar context to both sides.^^
is the high-precedence version ofxor
.=~
becomes the "smart match" operator~~
, with a whole new set of semantics. Anywhere you used=~
before you now use~~
, but~~
is much more general now. See "Synopsis 4" for details.Unary
.
calls its single argument (which must be a method, or an dereferencer for a hash or array) on$_
.The
..
binary range operator has variants with^
on either end to indicate exclusion of that endpoint from the range....
is a unary postfix operator that constructs a semi-infinite (and lazily evaluated) list, starting at the value of its single argument.However,
...
as a term is the "yada, yada, yada" operator, which is used as the body in function prototypes. It complains bitterly if it is ever executed.In addition, to the ordinary
.
method invocation, there are variants.*
,.?
, and.+
to control how multiple parent methods of the same name are handled. The.=
operator does inplace modification of the object on the left.Unary
=
reads lines from a filehandle or filename, or in general iterates an iterator.
Hyper operators
The Unicode characters »
(\x[BB]
) and «
(\x[AB]
) and their ASCII digraphs >>
and <<
are used to denote "list operations", which operate on each element of two lists (or arrays) and return a list (or array) of the results. Spaces are not allowed on the "pointy" end of each "hyper", but are allowed on the blunt end. For example:
(1,1,2,3,5) »+« (1,2,3,5,8); # (2,3,5,8,13)
If one argument is insufficiently dimensioned, Perl "upgrades" it:
(3,8,2,9,3,8) >>-<< 1; # (2,7,1,8,2,7)
When using a unary operator, only put it on the operand's side:
@negatives = -« @positives;
@positions »++; # Increment all positions
@objects ».run();
("f","oo","bar")».length; # (1,2,3)
Note that method calls are really postfix operators, not infix, so you shouldn't put a «
after the dot.
Junctive operators
|
, &
, and ^
are no longer bitwise operators (see "Operator Renaming") but now serve a much higher cause: they are now the junction constructors.
A junction is a single value that is equivalent to multiple values. They thread through operations, returning another junction representing the result:
(1|2|3) + 4; # 5|6|7
(1|2) + (3&4); # (4|5) & (5|6)
Note how when two junctions are applied through an operator, the result is a junction representing the operator applied to each combination of values.
Junctions come with the functional variants any
, all
, one
, and none
.
This opens doors for constructions like:
unless $roll == any(1..6) { print "Invalid roll" }
if $roll == 1|2|3 { print "Low roll" }
Junctions work through subscripting:
print if @foo[any(1,2,3)]
Junctions are specifically unordered. So if you say
for all(@foo) {...}
it indicates to the compiler that there is no coupling between loop iterations and they can be run in any order or even in parallel.
Chained comparisons
Perl 6 supports the natural extension to the comparison operators, allowing multiple operands.
if 3 < $roll <= 6 { print "High roll" }
if 1 <= $roll1 == $roll2 <= 6 { print "Doubles!" }
Note: any operator beginning with <
must have whitespace in front of it, or it will be interpreted as a hash subscript instead.
Binding
A new form of assignment is present in Perl 6, called "binding," used in place of typeglob assignment. It is performed with the :=
operator. Instead of replacing the value in a container like normal assignment, it replaces the container itself. For instance:
my $x = 'Just Another';
my $y := $x;
$y = 'Perl Hacker';
After this, both $x
and $y
contain the string "Perl Hacker," since they are really just two different names for the same variable.
There is another variant, spelled ::=
, that does the same thing at compile time.
There is also an identity test, =:=
, which tests whether two names are bound to the same underlying variable. $x =:= $y
would return true in the above example.
List flattening
Since typeglobs are being removed, unary *
may now serve as a lazy list flattening operator. It is used to "flatten" an array into a list, usually to allow the array's contents to be used as the arguments of a subroutine call. Note that those arguments still must comply with the subroutine's signature, but the presence of *
defers that test until run time for that argument (and for any subsequent arguments):
my @args = (\@foo, @bar);
push *@args;
is equivalent to:
push @foo, @bar;
In list context, a scalar reference to an array does not flatten. Hence
$bar = @bar;
push @foo, $bar;
merely pushes a single scalar reference onto @foo
. You can explicitly flatten it in any of these ways:
push @foo, *$bar;
push @foo, @$bar;
push @foo, $bar[];
(The *
in list context doesn't change the call semantics as is does in scalar context.) Note that these three forms also allow you to specify list context on assignment:
*$bar = (1,2,3);
@$bar = (1,2,3);
$bar[] = (1,2,3);
The last is particularly useful at the end of a long name naming an array attribute:
$foo.bar.baz.bletch.whatever.attr[] = (1,2,3)
The empty []
and .[]
postfix operators are interpreted as zero-dimensional slices returning the entire array, not null slices returning no elements. Likewise for {}
and .{}
on hashes, not to mention the <>
, .<>
, «»
, and .«»
constant and interpolating slice subscripting forms.
The *
operator flattens lazily. To get an immediate flattening like Perl 5 does, use unary **
instead. You may use either of them on a scalar iterator to force it to iterate.
Piping operators
The new operators ==>
and <==
are akin to UNIX pipes, but work with functions that accept and return lists. For example,
@result = map { floor($^x / 2) }
grep { /^ \d+ $/ }
@data;
Can also now be written:
@data ==> grep { /^ \d+ $/ }
==> map { floor($^x / 2) }
==> @result;
or:
@result <== map { floor($^x / 2) }
<== grep { /^ \d+ $/ }
<== @data;
Either form more clearly indicates the flow of data. See "Synopsis 6" for more of the (less-than-obvious) details on these two operators.
Invocant marker
An appended :
marks the invocant when using the indirect-object syntax for Perl 6 method calls. The following two statements are equivalent:
$hacker.feed('Pizza and cola');
feed $hacker: 'Pizza and cola';
zip
In order to support parallel iteration over multiple arrays, Perl 6 has a zip
function that interleaves the elements of two or more arrays.
for zip(@names, @codes) -> $name, $zip {
print "Name: $name; Zip code: $zip\n";
}
zip
has an infix synonym, the Unicode operator ¥
.
Minimal whitespace DWIMmery
Whitespace is no longer allowed before the opening bracket of an array or hash accessor. That is:
%monsters{'cookie'} = Monster.new; # Valid Perl 6
%people {'john'} = Person.new; # Not valid Perl 6
One of the several useful side-effects of this restriction is that parentheses are no longer required around the condition of control constructs:
if $value eq $target {
print "Bullseye!";
}
while 0 < $i { $i++ }
It is, however, still possible to align accessors by explicitly using the .
operator:
%monsters.{'cookie'} = Monster.new;
%people .{'john'} = Person .new;
%cats .{'fluffy'} = Cat .new;
Precedence
Perl 6 has 22 precedence levels (fewer than Perl 5):
terms 42 "eek" $x /abc/ (1+2) a(1) :by(2) .meth listop
method postfix . .+ .? .* .+ .() .[] .{} .«» .=
autoincrement ++ --
exponentiation **
symbolic unary ! + - ~ ? * ** +^ ~^ ?^ \
multiplicative * / % x xx +& +< +> ~& ~< ~>
additive + - ~ +| +^ ~| ~^
junctive and (all) &
junctive or (any) | ^
named unary rand sleep abs etc.
nonchaining binary => but does cmp <=> .. ^.. ..^ ^..^
chaining binary != == < <= > >= ~~ !~ eq ne lt le gt ge =:=
tight and &&
tight or || ^^ //
ternary ?? ::
assignment = := ::= += -= **= xx= etc.
list item separator , ¥
list op (rightward) <== print push any all true not etc.
pipe forward ==>
loose and and
loose or or xor err
expr terminator ; {} as control block, statement modifiers
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 54:
Non-ASCII character seen before =encoding in 'C<«...»>.'. Assuming UTF-8