Categories
Posts in this category
- Introduction
- Strings, Arrays, Hashes;
- Types
- Basic Control Structures
- Subroutines and Signatures
- Objects and Classes
- Contexts
- Regexes (also called "rules")
- Junctions
- Comparing and Matching
- Containers and Values
- Where we are now - an update
- Changes to Perl 5 Operators
- Laziness
- Custom Operators
- The MAIN sub
- Twigils
- Enums
- Unicode
- Scoping
- Regexes strike back
- A grammar for (pseudo) XML
- Subset Types
- The State of the implementations
- Quoting and Parsing
- The Reduction Meta Operator
- The Cross Meta Operator
- Exceptions and control exceptions
- Common Perl 6 data processing idioms
- Currying
Sun, 19 Oct 2008
Custom Operators
Permanent link
NAME
"Perl 5 to 6" Lesson 13 - Custom Operators
LAST UPDATED
2015-02-26
SYNOPSIS
multi sub postfix:<!>(Int $x) { my $factorial = 1; $factorial *= $_ for 2..$x; return $factorial; } say 5!; # 120
DESCRIPTION
Operators are functions with unusual names, and a few additional properties like precedence and associativity. Perl 6 usually follows the pattern term infix term
, where term
can be optionally preceded by prefix operators and followed by postfix or postcircumfix operators.
1 + 1 infix +1 prefix $x++ postfix <a b c> circumfix @a[1] postcircumfix
Operator names are not limited to "special" characters, they can contain anything except whitespace.
The long name of an operator is its type, followed by a colon and a string literal or list of the symbol or symbols, for example infix:<+>
is the the operator in 1+2
. Another example is postcircumfix:<[ ]>
, which is the operator in @a[0]
.
With this knowledge you can already define new operators:
multi sub prefix:<€> (Str $x) { 2 * $x; } say €4; # 8
Precedence
In an expression like $a + $b * $c
the infix:<*>
operator has tighter precedence than infix:<+>
, which is why the expression is evaluated as $a + ($b * $c)
.
The precedence of a new operator can be specified in comparison to to existing operators:
multi sub infix:<foo> is equiv(&infix:<+>) { ... } mutli sub infix:<bar> is tighter(&infix:<+>) { ... } mutli sub infix:<baz> is looser(&infix:<+>) { ... }
Associativity
Most infix operators take only two arguments. In an expression like 1 / 2 / 4
the associativity of the operator decides the order of evaluation. The infix:</>
operator is left associative, so this expression is parsed as (1 / 2) / 4
. for a right associative operator like infix:<**>
(exponentiation) 2 ** 2 ** 4
is parsed as 2 ** (2 ** 4)
.
Perl 6 has more associativities: none
forbids chaining of operators of the same precedence (for example 2 <=> 3 <=> 4
is forbidden), and infix:<,>
has list
associativity. 1, 2, 3
is translated to infix:<,>(1; 2; 3)
. Finally there's the chain
associativity: $a < $b < $c
translates to ($a < $b) && ($b < $c)
.
multi sub infix:<foo> is tighter(&infix:<+>) is assoc('left') ($a, $b) { ... }
"Overload" existing operators
Most (if not all) existing operators are multi subs, and can therefore be customized for new types. Adding a multi sub is the way of "overloading" operators.
class MyStr { ... } multi sub infix:<~>(MyStr $this, Str $other) { ... }
This means that you can write objects that behave just like the built in "special" objects like Str
, Int
etc.
MOTIVATION
Allowing the user to declare new operators and "overload" existing ones makes user defined types just as powerful and useful as built in types. If the built in ones turn out to be insufficient, you can replace them with new ones that better fit your situation, without changing anything in the compiler.
It also removes the gap between using a language and modifying the language.
SEE ALSO
"language/functions#Defining%20Operators" in doc.perl6.org
http://design.perl6.org/S06.html#Operator_overloading
If you are interested in the technical background, ie how Perl 6 can implement such operator changes and other grammar changes, read http://perlgeek.de/en/article/mutable-grammar-for-perl-6.