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
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) {
...
}
Postcircumfix and Circumfix
Postcircumfix operators are method calls:
class OrderedHash is Hash {
method postcircumfix:<{ }>(Str $key) {
...
}
}
If you call that as $object{$stuff}, $stuff will be passed as an argument to the method, and $object is available as self.
Circumfix operators usually imply a different syntax (like in my @list = <a b c>;), and are thus implemented as macros:
macro circumfix:«< >»($text) is parsed / <-[>]>+ / {
return $text.comb(rx/\S+/);
}
The is parsed trait is followed by a regex that parses everything between the delimiters. If no such rule is given, it is parsed as normal Perl 6 code (which is usually not what you want if you introduce a new syntax). Str.comb searches for occurrences of a regex and returns a list of the text of all matches.
"Overload" existing operators
Most (if not all) existing operators are multi subs or methods, 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
http://perlcabal.org/syn/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.
Comments / Trackbacks:
Trackback URL:
/blog-en/perl-5-to-6/13-custom-operators.trackback
Write a comment
The comments on this blog post have been disabled; the comment form below will not work.