Help-Site Computer Manuals
Software
Hardware
Programming
Networking
  Algorithms & Data Structures   Programming Languages   Revision Control
  Protocols
  Cameras   Computers   Displays   Keyboards & Mice   Motherboards   Networking   Printers & Scanners   Storage
  Windows   Linux & Unix   Mac

TITLE

TITLE



TITLE

Synopsis_03 - Summary of Perl 6 Operators


AUTHOR

Luke Palmer <luke@luqui.org>


VERSION


  Maintainer: Larry Wall <larry@wall.org>

  Date: 8 Mar 2004

  Last Modified: 25 Feb 2006

  Number: 3

  Version: 13


Operator renaming

Several operators have been given new names to increase clarity and better Huffman-code the language:


New operators


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")».chars;   # (1,2,3)

Note that method calls are really postfix operators, not infix, so you shouldn't put a « after the dot.

Hyper operators are defined recursively on array references, so:


    -« [[1, 2], 3]               #    [-«[1, 2], -«3]

                                 # == [[-1, -2], -3]

    [[1, 2], 3] »+« [4, [5, 6]]  #    [[1,2] »+« 4, 3 »+« [5, 6]]

                                 # == [[5, 6], [8, 9]]


Reduction operators

The other metaoperator in Perl 6 is the reduction operator. Any binary operator can be surrounded by square brackets in term position to create a list operator that reduces using that operation:


    [+] 1, 2, 3;      # 1 + 2 + 3 = 6

    my @a = (5,6);

    [*] @a;           # 5 * 6 = 30

The reduction associates the same way as the operator used:


    [-] 4, 3, 2;      # 4-3-2 = (4-3)-2 = -1

    [**] 4, 3, 2;     # 4**3**2 = 4**(3**2) = 262144

For list-associating operators (like <), all arguments are taken together, just as if you had written it out explicitly:


    [<] 1, 3, 5;      # 1 < 3 < 5

If no arguments are given, the operator calls fail (returning undef, or throwing an exception if use fatal is in effect). If exactly one argument is given, it is returned by default. However, this default doesn't make sense for an operator like < that doesn't return the same type as it takes, so these kinds of operators overload the single-argument case to return something more meaningful. All the comparison operators return truth in this case.

This metaoperator can also be used on the semicolon second-dimension separator:


    [[;] 1,2,3]   # equivalent to [1;2;3]


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 (or List) into the List being constructed for the current call, 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;

as is this:


    my $args = \(@foo, @bar);    # construct List object

    push *$args;

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 it 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';

A colon may also be used on an ordinary method call to indicate that it should be parsed as a list operator:


    $hacker.feed: 'Pizza and cola';


zip

In order to support parallel iteration over multiple arrays, Perl 6 has a zip function that builds tuples of 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 ¥.

To read arrays in parallel like zip but just sequence the values rather than generating tuples, use each instead of zip.


    for each(@names; @codes) -> $name, $zip {

        print "Name: $name;   Zip code: $zip\n";

    }

The each function reads to the end of the longest list, not counting lists that are known to be infinite such as 0..Inf. Missing values are replaced with undef. In contrast, use roundrobin if you just wish to skip missing entries:


    for roundrobin(@queue1; @queue2; @queue3) -> $next {

        ...

    }

To read arrays serially rather than in parallel, use cat(@x;@y).


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 (which is 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 <=> .. ^.. ..^ ^..^ ff ^ff ff^ ^ff^ fff ^fff etc.

    chaining binary     != == < <= > >= ~~ !~ eq ne lt le gt ge =:= ===

    tight and           &&

    tight or            || ^^ //

    ternary             ?? !!

    assignment          = := ::= += -= **= xx= etc. (and also =>)

    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
Programminig
Wy
Wy
yW
Wy
Programming
Wy
Wy
Wy
Wy