The Perl 6 homepage offers a comprehensive list of Perl 6 resources, including tutorials, how-tos and FAQs (Frequently Asked Questions).
Perl 6 compiler developers may also be interested in The Perl 6 Specification. Documentation for the different but related Perl 5 language can be found on the Perl 5 documentation website.
Part of this official documentation has been translated into Chinese. Here's the index to the pages that have been translated.
Using Perl 6 official documentation
Documenting a large language like Perl 6 has to balance several contradictory goals, such as being brief whilst being comprehensive, catering to professional developers with wide experience whilst also being accessible to newcomers to the language.
For a quick hands-on introduction, there is a short annotated programming example.
For programmers with experience in other languages, there are a number of Migration guides that compare and contrast the features of Perl 6 with other languages.
A number of Tutorials cover several areas in which Perl 6 is particularly innovative. The section headers should help navigate the remaining documents.
There are a number of useful resources listed elsewhere on the perl6.org site. These include articles, books, slide presentations, and videos.
It has been found that newcomers to Perl 6 often ask questions that indicate assumptions carried over from other programming paradigms. It is suggested that the following sections in the Fundamental topics section should be reviewed first.
Signatures - each routine, which includes subroutines and methods, has a signature. Understanding the information given in the signature of a sub or method provides a quick way to grasp the operation and effect of the routine.
Containers - variables, which are like the nouns of a computer language, are containers in which information is stored. The first letter in the formal name of a container, such as the '$' of $my-variable, or '@' of @an-array-of-things, or '%' of %the-scores-in-the-competition, conveys information about the container. However, Perl 6 is more abstract than other languages about what can be stored in a container. So, for example, a $scalar container can contain an object that is in fact an array.
Classes and Roles - Perl 6 is fundamentally based on objects, which are described in terms of classes and roles. Perl 6, unlike some languages, does not impose object-oriented programming practices, and useful programs can be written as if Perl 6 was purely procedural in nature. However, complex software, such as the Rakudo compiler of Perl 6, is made much simpler by writing in object-oriented idioms, which is why the Perl 6 documentation is more easily understood by reviewing what a class is and what a role is. Without understanding about classes and roles, it would be difficult to understand types, to which a whole section of the documentation is devoted.
Traps to Avoid - Several common assumptions lead to code that does not work as the programmer intended. This section identifies some of them. It is worth reviewing when something doesn't quite work out.
A basic introductory example of a Perl 6 program
Suppose that you host a table tennis tournament. The referees tell you the results of each game in the format Player1 Player2 | 3:2, which means that Player1 won against Player2 by 3 to 2 sets. You need a script that sums up how many matches and sets each player has won to determine the overall winner.
The input data (stored in a file called scores.txt) looks like this:
Beth Ana Charlie Dave Ana Dave | 3:0 Charlie Beth | 3:1 Ana Beth | 2:3 Dave Charlie | 3:0 Ana Charlie | 3:1 Beth Dave | 0:3
The first line is the list of players. Every subsequent line records a result of a match.
Here's one way to solve that problem in Perl 6:
use v6; # Single line comments like this one start with '#'. my $file = open 'scores.txt'; # Comments can also follow code on a line. my @names = $file.get.words; my %matches; my %sets; #`( Multiple line comments are denoted by a #, then `, then one of {,[, or ( and closed by the corresponding },], and ). Nested pairs of square brackets, curly braces and parentheses are matched, so something like this () will not end the comment. In this case, closed by: ) for $file.lines -> $line { next unless $line; # ignore any empty lines my ($pairing, $result) = $line.split(' | '); my ($p1, $p2) = $pairing.words; my ($r1, $r2) = $result.split(':'); %sets{$p1} += $r1; %sets{$p2} += $r2; if $r1 > $r2 { %matches{$p1}++; } else { %matches{$p2}++; } } #`[ This is another multi-line comment. ] #`{ So is this, though it's not actually multi-line. } my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse; for @sorted -> $n { my $match-noun = %matches{$n} == 1 ?? 'match' !! 'matches'; my $set-noun = %sets{$n} == 1 ?? 'set' !! 'sets'; say "$n has won %matches{$n} $match-noun and %sets{$n} $set-noun"; }
This produces the output:
Ana has won 2 matches and 8 sets Dave has won 2 matches and 6 sets Charlie has won 1 match and 4 sets Beth has won 1 match and 4 sets
Every Perl 6 program should begin with a line similar to use v6;. This line tells the compiler which version of Perl 6 the program expects. For instance, 6.c is an example of a Perl 6 version. Should you accidentally run the file with Perl 5, you'll get a helpful error message.
A Perl 6 program consists of zero or more statements. A statement ends with a semicolon or a curly brace at the end of a line:
my $file = open 'scores.txt';
my declares a lexical variable, which are visible only in the current block from the point of declaration to the end of the block. If there's no enclosing block, it's visible throughout the remainder of the file (which would effectively be the enclosing block). A block is any part of the code enclosed between curly braces { }.
A variable name begins with a sigil, which is a non-alpha-numeric symbol such as $, @, %, or & — or occasionally the double colon ::. Sigils indicate the structural interface for the variable, such as whether it should be treated as a single value, a compound value, a subroutine, etc. After the sigil comes an identifier, which may consist of letters, digits and the underscore. Between letters you can also use a dash - or an apostrophe ', so isn't and double-click are valid identifiers.
Sigils indicate the default access method for a variable. Variables with the @ sigil are accessed positionally; variables with the % sigil are accessed by string key. The $ sigil, however, indicates a general scalar container that can hold any single value and be accessed in any manner. A scalar can even contain a compound object like an Array or a Hash; the $ sigil signifies that it should be treated as a single value, even in a context that expects multiple values (as with an Array or Hash).
The built-in function open opens a file, here named scores.txt, and returns a filehandle — an object representing that file. The equality sign = assigns that filehandle to the variable on the left, which means that $file now stores the filehandle.
'scores.txt' is a string literal. A string is a piece of text, and a string literal is a string which appears directly in the program. In this line, it's the argument provided to open.
my @names = $file.get.words;
The right-hand side calls a method — a named group of behavior — named get on the filehandle stored in $file. The get method reads and returns one line from the file, removing the line ending. If you print the contents of $file after calling get, you will see that the first line is no longer in there. words is also a method, called on the string returned from get. words decomposes its invocant — the string on which it operates — into a list of words, which here means strings separated by whitespace. It turns the single string 'Beth Ana Charlie Dave' into the list of strings 'Beth', 'Ana', 'Charlie', 'Dave'.
Finally, this list gets stored in the Array @names. The @ sigil marks the declared variable as an Array. Arrays store ordered lists.
my %matches; my %sets;
These two lines of code declare two hashes. The % sigil marks each variable as a Hash. A Hash is an unordered collection of key-value pairs. Other programming languages call that a hash table, dictionary, or map. You can query a hash table for the value that corresponds to a certain $key with %hash{$key}.
In the score counting program, %matches stores the number of matches each player has won. %sets stores the number of sets each player has won. Both of these hashes are indexed by the player's name.
for $file.lines -> $line { ... }
for produces a loop that runs the block delimited by curly braces once for each item of the list, setting the variable $line to the current value of each iteration. $file.lines produces a list of the lines read from the file scores.txt, starting with the second line of the file since we already called $file.get once, and going all the way to the end of the file.
During the first iteration, $line will contain the string Ana Dave | 3:0; during the second, Charlie Beth | 3:1, and so on.
my ($pairing, $result) = $line.split(' | ');
my can declare multiple variables simultaneously. The right-hand side of the assignment is a call to a method named split, passing along the string ' | ' as an argument.
split decomposes its invocant into a list of strings, so that joining the list items with the separator ' | ' produces the original string.
$pairing gets the first item of the returned list, and $result the second.
After processing the first line, $pairing will hold the string Ana Dave and $result will hold 3:0.
The next two lines follow the same pattern:
my ($p1, $p2) = $pairing.words; my ($r1, $r2) = $result.split(':');
The first extracts and stores the names of the two players in the variables $p1 and $p2. The second extracts the results for each player and stores them in $r1 and $r2.
After processing the first line of the file, the variables contain the values:
Variable | Contents |
$line | 'Ana Dave | 3:0' |
$pairing | 'Ana Dave' |
$result | '3:0' |
$p1 | 'Ana' |
$p2 | 'Dave' |
$r1 | '3' |
$r2 | '0' |
The program then counts the number of sets each player has won:
%sets{$p1} += $r1; %sets{$p2} += $r2;
The += assignment operator is a shortcut for:
%sets{$p1} = %sets{$p1} + $r1; %sets{$p2} = %sets{$p2} + $r2;
+= $r1 means increase the value in the variable on the left by $r1. In the first iteration %sets{$p1} is not yet set, so it defaults to a special value called Any. The addition and incrementing operators treat Any as a number with the value of zero; the strings get automatically converted to numbers, as addition is a numeric operation.
Before these two lines execute, %sets is empty. Adding to an entry that is not in the hash yet will cause that entry to spring into existence just-in-time, with a value starting at zero. (This is autovivification). After these two lines have run for the first time, %sets contains 'Ana' => 3, 'Dave' => 0 . (The fat arrow => separates the key and the value in a Pair.)
if $r1 > $r2 { %matches{$p1}++; } else { %matches{$p2}++; }
If $r1 is numerically larger than $r2, %matches{$p1} increments by one. If $r1 is not larger than $r2, %matches{$p2} increments. Just as in the case of +=, if either hash value did not exist previously, it is autovivified by the increment operation.
$thing++ is short for $thing += 1 or $thing = $thing + 1, with the small exception that the return value of the expression is $thing before the increment, not the incremented value. As in many other programming languages, you can use ++ as a prefix. Then it returns the incremented value; my $x = 1; say ++$x prints 2.
my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
This line consists of three individually simple steps. An array's sort method returns a sorted version of the array's contents. However, the default sort on an array sorts by its contents. To print player names in winner-first order, the code must sort the array by the scores of the players, not their names. The sort method's argument is a block used to transform the array elements (the names of players) to the data by which to sort. The array items are passed in through the topic variable $_.
You have seen blocks before: both the for loop -> $line { ... } and the if statement worked on blocks. A block is a self-contained piece of Perl 6 code with an optional signature (the -> $line part).
The simplest way to sort the players by score would be @names.sort({ %matches{$_} }), which sorts by number of matches won. However Ana and Dave have both won two matches. That simple sort doesn't account for the number of sets won, which is the secondary criterion to decide who has won the tournament.
When two array items have the same value, sort leaves them in the same order as it found them. Computer scientists call this a stable sort. The program takes advantage of this property of Perl 6's sort to achieve the goal by sorting twice: first by the number of sets won (the secondary criterion), then by the number of matches won.
After the first sorting step, the names are in the order Beth Charlie Dave Ana. After the second sorting step, it's still the same, because no one has won fewer matches but more sets than someone else. Such a situation is entirely possible, especially at larger tournaments.
sort sorts in ascending order, from smallest to largest. This is the opposite of the desired order. Therefore, the code calls the .reverse method on the result of the second sort, and stores the final list in @sorted.
for @sorted -> $n { my $match-noun = %matches{$n} == 1 ?? 'match' !! 'matches'; my $set-noun = %sets{$n} == 1 ?? 'set' !! 'sets'; say "$n has won %matches{$n} $match-noun and %sets{$n} $set-noun"; }
To print out the players and their scores, the code loops over @sorted, setting $n to the name of each player in turn. Read this code as "For each element of sorted, set $n to the element, then execute the contents of the following block." The variable $match-noun will store either the string match if the player has won a single match or matches if the player has won zero or more matches. In order to do this, the ternary operator (?? !!) is used. If %matches{$n} == 1 evaluates to True, then match is returned. Otherwise, matches is returned. Either way, the returned value is stored in $match-noun. The same approach applies to <$set-noun>.
The statement say prints its arguments to the standard output (the screen, normally), followed by a newline. (Use print if you don't want the newline at the end.)
Note that say will truncate certain data structures by calling the .gist method so put is safer if you want exact output.
When you run the program, you'll see that say doesn't print the contents of that string verbatim. In place of $n it prints the contents of the variable $n — the names of players stored in $n. This automatic substitution of code with its contents is interpolation. This interpolation happens only in strings delimited by double quotes "...". Single quoted strings '...' do not interpolate:
my $names = 'things'; say 'Do not call me $names'; # OUTPUT: «Do not call me $names» say "Do not call me $names"; # OUTPUT: «Do not call me things»
Double quoted strings in Perl 6 can interpolate variables with the $ sigil as well as blocks of code in curly braces. Since any arbitrary Perl code can appear within curly braces, Arrays and Hashes may be interpolated by placing them within curly braces.
Arrays within curly braces are interpolated with a single space character between each item. Hashes within curly braces are interpolated as a series of lines. Each line will contain a key, followed by a tab character, then the value associated with that key, and finally a newline.
Let's see an example of this now.
In this example, you will see some special syntax that makes it easier to make a list of strings. This is the <...> quote-words construct. When you put words in between the < and > they are all assumed to be strings, so you do not need to wrap them each in double quotes "...".
say "Math: { 1 + 2 }"; # OUTPUT: «Math: 3» my @people = <Luke Matthew Mark>; say "The synoptics are: {@people}"; # OUTPUT: «The synoptics are: Luke Matthew Mark» say "{%sets}"; # OUTPUT (From the table tennis tournament): # Charlie 4 # Dave 6 # Ana 8 # Beth 4
When array and hash variables appear directly in a double-quoted string (and not inside curly braces), they are only interpolated if their name is followed by a postcircumfix — a bracketing pair that follows a statement. It's also ok to have a method call between the variable name and the postcircumfix.
my @flavors = <vanilla peach>; say "we have @flavors"; # OUTPUT: «we have @flavors» say "we have @flavors[0]"; # OUTPUT: «we have vanilla» # so-called "Zen slice" say "we have @flavors[]"; # OUTPUT: «we have vanilla peach» # method calls ending in postcircumfix say "we have @flavors.sort()"; # OUTPUT: «we have peach vanilla» # chained method calls: say "we have @flavors.sort.join(', ')"; # OUTPUT: «we have peach, vanilla»
1. The input format of the example program is redundant: the first line containing the name of all players is not necessary, because you can find out which players participated in the tournament by looking at their names in the subsequent rows.
How can you make the program run if you do not use the @names variable? Hint: %hash.keys returns a list of all keys stored in %hash.
Answer: Remove the line my @names = $file.get.words;, and change:
my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
... into:
my @sorted = %sets.keys.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
2. Instead of deleting the redundant @names variable, you can also use it to warn if a player appears that wasn't mentioned in the first line, for example due to a typo. How would you modify your program to achieve that?
Hint: Try using membership operators.
Answer: Change @names to @valid-players. When looping through the lines of the file, check to see that $p1 and $p2 are in @valid-players. Note that for membership operators you can also use (elem) and !(elem).
...; my @valid-players = $file.get.words; ...; for $file.lines -> $line { my ($pairing, $result) = $line.split(' | '); my ($p1, $p2) = $pairing.split(' '); if $p1 ∉ @valid-players { say "Warning: '$p1' is not on our list!"; } if $p2 ∉ @valid-players { say "Warning: '$p2' is not on our list!"; } ... }
How do I do what I used to do? (Perl 6 in a nutshell)
This page attempts to provide a fast-path to the changes in syntax and semantics from Perl 5 to Perl 6. Whatever worked in Perl 5 and must be written differently in Perl 6, should be listed here (whereas many new Perl 6 features and idioms need not).
Hence this should not be mistaken for a beginner tutorial or a promotional overview of Perl 6; it is intended as a technical reference for Perl 6 learners with a strong Perl 5 background and for anyone porting Perl 5 code to Perl 6 (though note that #Automated translation might be more convenient).
A note on semantics; when we say "now" in this document, we mostly just mean "now that you are trying out Perl 6." We don't mean to imply that Perl 5 is now suddenly obsolete. Quite the contrary, most of us love Perl 5, and we expect Perl 5 to continue in use for a good many years. Indeed, one of our more important goals has been to make interaction between Perl 5 and Perl 6 run smoothly. However, we do also like the design decisions in Perl 6, which are certainly newer and arguably better integrated than many of the historical design decisions in Perl 5. So many of us do hope that over the next decade or two, Perl 6 will become the more dominant language. If you want to take "now" in that future sense, that's okay too. But we're not at all interested in the either/or thinking that leads to fights.
See https://modules.perl6.org/.
If the module that you were using has not been converted to Perl 6, and no alternative is listed in this document, then its use under Perl 6 may not have been addressed yet.
The Inline::Perl5 project makes it possible to use Perl 5 modules directly from Perl 6 code by using an embedded instance of the perl interpreter to run Perl 5 code.
This is as simple as:
# the :from<Perl5> makes Perl 6 load Inline::Perl5 first (if installed) # and then load the Scalar::Util module from Perl 5 use Scalar::Util:from<Perl5> <looks_like_number>; say looks_like_number "foo"; # 0 say looks_like_number "42"; # 1
A number of Perl 5 modules have been ported to Perl 6, trying to maintain the API of these modules as much as possible, as part of the CPAN Butterfly Plan. These can be found at https://modules.perl6.org/t/CPAN5.
Many Perl 5 built-in functions (about a 100 so far) have been ported to Perl 6 with the same semantics. Think about the shift function in Perl 5 having magic shifting from @_ or @ARGV by default, depending on context. These can be found at https://modules.perl6.org/t/Perl5 as separately loadable modules, and in the P5built-ins bundle to get them all at once.
There are a few differences in syntax between the two languages, starting with how identifiers are defined.
Perl 6 allows the use of dashes (-), underscores (_), apostrophes ('), and alphanumerics in identifiers, :
sub test-doesn't-hang { ... } my $ความสงบ = 42; my \Δ = 72; say 72 - Δ;
If you've read any Perl 6 code at all, it's immediately obvious that method call syntax now uses a dot instead of an arrow:
$person->name # Perl 5
$person.name # Perl 6
The dot notation is both easier to type and more of an industry standard. But we also wanted to steal the arrow for something else. (Concatenation is now done with the ~ operator, if you were wondering.)
To call a method whose name is not known until runtime:
$object->$methodname(@args); # Perl 5
$object."$methodname"(@args); # Perl 6
If you leave out the quotes, then Perl 6 expects $methodname to contain a Method object, rather than the simple string name of the method. Yes, everything in Perl 6 can be considered an object.
Perl 5 allows a surprising amount of flexibility in the use of whitespace, even with strict mode and warnings turned on:
# unidiomatic but valid Perl 5 say"Hello ".ucfirst ($people [$ i] -> name)."!"if$greeted[$i]<1;
Perl 6 also endorses programmer freedom and creativity, but balanced syntactic flexibility against its design goal of having a consistent, deterministic, extensible grammar that supports single-pass parsing and helpful error messages, integrates features like custom operators cleanly, and doesn't lead programmers to accidentally misstate their intent. Also, the practice of "code golf" is slightly de-emphasized; Perl 6 is designed to be more concise in concepts than in keystrokes.
As a result, there are various places in the syntax where whitespace is optional in Perl 5, but is either mandatory or forbidden in Perl 6. Many of those restrictions are unlikely to concern much real-life Perl code (e.g., whitespace being disallowed between the sigil and name of a variable), but there are a few that will unfortunately conflict with some Perl hackers' habitual coding styles:
No space allowed before the opening parenthesis of an argument list.
substr ($s, 4, 1); # Perl 5 (in Perl 6 this would try to pass a single # argument of type List to substr)
substr($s, 4, 1); # Perl 6 substr $s, 4, 1; # Perl 6 - alternative parentheses-less style
Should this really be a problem for you, then you might want to have a look at the Slang::Tuxic module in the Perl 6 ecosystem: it changes the grammar of Perl 6 in such a way that you can have a space before the opening parenthesis of an argument list.
Space is required immediately after keywords
my($alpha, $beta); # Perl 5, tries to call my() sub in Perl 6
my ($alpha, $beta); # Perl 6
if($a < 0) { ... } # Perl 5, dies in Perl 6
if ($a < 0) { ... } # Perl 6 if $a < 0 { ... } # Perl 6, more idiomatic
while($x-- > 5) { ... } # Perl 5, dies in Perl 6
while ($x-- > 5) { ... } # Perl 6 while $x-- > 5 { ... } # Perl 6, more idiomatic
No space allowed after a prefix operator, or before a postfix/postcircumfix operator (including array/hash subscripts).
$seen {$_} ++; # Perl 5
%seen{$_}++; # Perl 6
Space required before an infix operator if it would conflict with an existing postfix/postcircumfix operator.
$n<1; # Perl 5 (in Perl 6 this would conflict with postcircumfix < >)
$n < 1; # Perl 6
However, whitespace is allowed before the period of a method call!
# Perl 5 my @books = $xml ->parse_file($file) # some comment ->findnodes("/library/book");
# Perl 6 my @books = $xml .parse-file($file) # some comment .findnodes("/library/book");
However, note that you can use unspace to add whitespace in Perl 6 code in places where it is otherwise not allowed.
See also other lexical conventions in the syntax page.
In Perl 5, arrays and hashes use changing sigils depending on how they are being accessed. In Perl 6 the sigils are invariant, no matter how the variable is being used - you can think of them as part of the variable's name.
The $ sigil is now always used with "scalar" variables (e.g. $name), and no longer for array indexing and Hash indexing. That is, you can still use $x[1] and $x{"foo"}, but it will act on $x, with no effect on a similarly named @x or %x. Those would now be accessed with @x[1] and %x{"foo"}.
The @ sigil is now always used with "array" variables (e.g. @months, @months[2], @months[2, 4]), and no longer for value-slicing hashes.
The % sigil is now always used with "hash" variables (e.g. %calories, %calories<apple>, %calories<pear plum>), and no longer for key/value-slicing arrays.
The & sigil is now used consistently (and without the help of a backslash) to refer to the function object of a named subroutine/operator without invoking it, i.e. to use the name as a "noun" instead of a "verb":
my $sub = \&foo; # Perl 5
my $sub = &foo; # Perl 6
callback => sub { say @_ } # Perl 5 - can't pass built-in sub directly
callback => &say # Perl 6 - & gives "noun" form of any sub
Since Perl 6 does not allow adding/removing symbols in a lexical scope once it has finished compiling, there is no equivalent to Perl 5's undef &foo;, and the closest equivalent to Perl 5's defined &foo would be defined ::('&foo') (which uses the "dynamic symbol lookup" syntax). However, you can declare a mutable named subroutine with my &foo; and then change its meaning at runtime by assigning to &foo.
In Perl 5, the ampersand sigil can additionally be used to call subroutines in special ways with subtly different behavior compared to normal sub calls. In Perl 6 those special forms are no longer available:
&foo(...) for circumventing a function prototype
In Perl 6 there are no prototypes, and it no longer makes a difference whether you, say, pass a literal code block or a variable holding a code object as an argument:
# Perl 5: first_index { $_ > 5 } @values; &first_index($coderef, @values); # (disabling the prototype that parses a # literal block as the first argument)
# Perl 6: first { $_ > 5 }, @values, :k; # the :k makes first return an index first $coderef, @values, :k;
&foo; and goto &foo; for re-using the caller's argument list / replacing the caller in the call stack. Perl 6 can use either callsame for re-dispatching or nextsame and nextwith, which have no exact equivalent in Perl 5.
sub foo { say "before"; &bar; say "after" } # Perl 5
sub foo { say "before"; bar(|@_); say "after" } # Perl 6 - have to be explicit
sub foo { say "before"; goto &bar } # Perl 5
proto foo (|) {*}; multi foo ( Any $n ) { say "Any"; say $n; }; multi foo ( Int $n ) { say "Int"; callsame; }; foo(3); # /language/functions#index-entry-dispatch_callsame
In Perl 5, the * sigil referred to the GLOB structure that Perl uses to store non-lexical variables, filehandles, subs, and formats.
You are most likely to encounter a GLOB in code written on an early Perl version that does not support lexical filehandles, when a filehandle needed to be passed into a sub.
# Perl 5 - ancient method sub read_2 { local (*H) = @_; return scalar(<H>), scalar(<H>); } open FILE, '<', $path or die; my ($line1, $line2) = read_2(*FILE);
You should refactor your Perl 5 code to remove the need for the GLOB, before translating into Perl 6.
# Perl 5 - modern use of lexical filehandles sub read_2 { my ($fh) = @_; return scalar(<$fh>), scalar(<$fh>); } open my $in_file, '<', $path or die; my ($line1, $line2) = read_2($in_file);
And here's just one possible Perl 6 translation:
# Perl 6 sub read-n($fh, $n) { return $fh.get xx $n; } my $in-file = open $path or die; my ($line1, $line2) = read-n($in-file, 2);
Index and slice operations on arrays no longer inflect the variable's sigil, and adverbs can be used to control the type of slice:
Indexing
say $months[2]; # Perl 5
say @months[2]; # Perl 6 - @ instead of $
Value-slicing
say join ',', @months[6, 8..11]; # Perl 5 and Perl 6
Key/value-slicing
say join ',', %months[6, 8..11]; # Perl 5
say join ',', @months[6, 8..11]:kv; # Perl 6 - @ instead of %; use :kv adverb
Also note that the subscripting square brackets are now a normal postcircumfix operator rather than a special syntactic form, and thus checking for existence of elements and unsetting elements is done with adverbs.
Index and slice operations on hashes no longer inflect the variable's sigil, and adverbs can be used to control the type of slice. Also, single-word subscripts are no longer magically autoquoted inside the curly braces; instead, the new angle brackets version is available which always autoquotes its contents (using the same rules as the qw// quoting construct):
Indexing
say $calories{"apple"}; # Perl 5
say %calories{"apple"}; # Perl 6 - % instead of $
say $calories{apple}; # Perl 5
say %calories<apple>; # Perl 6 - angle brackets; % instead of $ say %calories«"$key"»; # Perl 6 - double angles interpolate as a list of Str
Value-slicing
say join ',', @calories{'pear', 'plum'}; # Perl 5
say join ',', %calories{'pear', 'plum'}; # Perl 6 - % instead of @ say join ',', %calories<pear plum>; # Perl 6 (prettier version) my $keys = 'pear plum'; say join ',', %calories«$keys»; # Perl 6 the split is done after interpolation
Key/value-slicing
say join ',', %calories{'pear', 'plum'}; # Perl 5
say join ',', %calories{'pear', 'plum'}:kv; # Perl 6 - use :kv adverb say join ',', %calories<pear plum>:kv; # Perl 6 (prettier version)
Also note that the subscripting curly braces are now a normal postcircumfix operator rather than a special syntactic form, and thus checking for existence of keys and removing keys is done with adverbs.
In Perl 5, references to anonymous arrays and hashes and subs are returned during their creation. References to existing named variables and subs were generated with the \ operator. the "referencing/dereferencing" metaphor does not map cleanly to the actual Perl 6 container system, so we will have to focus on the intent of the reference operators instead of the actual syntax.
my $aref = \@aaa ; # Perl 5
This might be used for passing a reference to a routine, for instance. But in Perl 6, the (single) underlying object is passed (which you could consider to be a sort of pass by reference).
my @array = 4,8,15; { $_[0] = 66 }(@array); # run the block with @array aliased to $_ say @array; # OUTPUT: «[66 8 15]»
The underlying Array object of @array is passed, and its first value modified inside the declared routine.
In Perl 5, the syntax for dereferencing an entire reference is the type-sigil and curly braces, with the reference inside the curly braces. In Perl 6, this concept simply does not apply, since the reference metaphor does not really apply.
In Perl 5, the arrow operator, -> , is used for single access to a composite's reference or to call a sub through its reference. In Perl 6, the dot operator . is always used for object methods, but the rest does not really apply.
# Perl 5 say $arrayref->[7]; say $hashref->{'fire bad'}; say $subref->($foo, $bar);
In relatively recent versions of Perl 5 (5.20 and later), a new feature allows the use of the arrow operator for dereferencing: see Postfix Dereferencing. This can be used to create an array from a scalar. This operation is usually called decont, as in decontainerization, and in Perl 6 methods such as .list and .hash are used:
# Perl 5.20 use experimental qw< postderef >; my @a = $arrayref->@*; my %h = $hashref->%*; my @slice = $arrayref->@[3..7];
# Perl 6 my @a = $contains-an-array.list; # or @($arrayref) my %h = $contains-a-hash.hash; # or %($hashref)
The "Zen" slice does the same thing:
# Perl 6 my @a = $contains-an-array[]; my %h = $contains-a-hash{};
See the "Containers" section of the documentation for more information.
See the documentation for operators for full details on all operators.
Unchanged:
+ Numeric Addition
- Numeric Subtraction
* Numeric Multiplication
/ Numeric Division
% Numeric Modulus
** Numeric Exponentiation
++ Numeric Increment
-- Numeric Decrement
! && || ^ Booleans, high-precedence
not and or xor Booleans, low-precedence
== != < > <= >= Numeric comparisons
eq ne lt gt le ge String comparisons
Unchanged, but note that in order to flatten an array variable to a list (in order to append or prefix more items) one should use the | operator (see also Slip). For instance:
my @numbers = 100, 200, 300; my @more_numbers = 500, 600, 700; my @all_numbers = |@numbers, 400, |@more_numbers;
That way one can concatenate arrays.
Note that one does not need to have any parentheses on the right-hand side: the List Separator takes care of creating the list, not the parentheses!
In Perl 5, these operators returned -1, 0, or 1. In Perl 6, they return Order::Less, Order::Same, or Order::More.
cmp is now named leg; it forces string context for the comparison.
<=> still forces numeric context.
cmp in Perl 6 does either <=> or leg, depending on the existing type of its arguments.
While the operator has not changed, the rules for what exactly is matched depend on the types of both arguments, and those rules are far from identical in Perl 5 and Perl 6. See ~~ and the smartmatch operator
In Perl 5, & | ^ were invoked according to the contents of their arguments. For example, 31 | 33 returns a different result than "31" | "33".
In Perl 6, those single-character ops have been removed, and replaced by two-character ops which coerce their arguments to the needed context.
# Infix ops (two arguments; one on each side of the op) +& +| +^ And Or Xor: Numeric ~& ~| ~^ And Or Xor: String ?& ?| ?^ And Or Xor: Boolean # Prefix ops (one argument, after the op) +^ Not: Numeric ~^ Not: String ?^ Not: Boolean (same as the ! op)
Replaced by +< and +> .
say 42 << 3; # Perl 5
say 42 +< 3; # Perl 6
In Perl 5, => acted just like a comma, but also quoted its left-hand side.
In Perl 6, => is the Pair operator, which is quite different in principle, but works the same in many situations.
If you were using => in hash initialization, or in passing arguments to a sub that expects a hashref, then the usage is likely identical.
sub get_the_loot { ... }; # Perl 6 stub # Works in Perl 5 and Perl 6 my %hash = ( AAA => 1, BBB => 2 ); get_the_loot( 'diamonds', { quiet_level => 'very', quantity => 9 }); # Note the curly braces
If you were using => as a convenient shortcut to not have to quote part of a list, or in passing arguments to a sub that expects a flat list of KEY, VALUE, KEY, VALUE, then continuing to use => may break your code. The easiest workaround is to change that fat arrow to a regular comma, and manually add quotes to its left-hand side. Or, you can change the sub's API to slurp a hash. A better long-term solution is to change the sub's API to expect Pairs; however, this requires you to change all sub calls at once.
# Perl 5 sub get_the_loot { my $loot = shift; my %options = @_; # ... } # Note: no curly braces in this sub call get_the_loot( 'diamonds', quiet_level => 'very', quantity => 9 );
# Perl 6, original API sub get_the_loot( $loot, *%options ) { # The * means to slurp everything ... } get_the_loot( 'diamonds', quiet_level => 'very', quantity => 9 ); # Note: no curly braces in this API # Perl 6, API changed to specify valid options # The colon before the sigils means to expect a named variable, # with the key having the same name as the variable. sub get_the_loot( $loot, :$quiet_level?, :$quantity = 1 ) { # This version will check for unexpected arguments! ... } get_the_loot( 'diamonds', quietlevel => 'very' ); # Throws error for misspelled parameter name
The conditional operator ? : has been replaced by ?? !!:
my $result = $score > 60 ? 'Pass' : 'Fail'; # Perl 5
my $result = $score > 60 ?? 'Pass' !! 'Fail'; # Perl 6
Replaced by the tilde.
Mnemonic: think of "stitching" together the two strings with needle and thread.
$food = 'grape' . 'fruit'; # Perl 5
$food = 'grape' ~ 'fruit'; # Perl 6
In Perl 5, x is the Repetition operator, which behaves differently in scalar or list contexts:
in scalar context x repeats a string;
in list context x repeats a list, but only if the left argument is parenthesized!
Perl 6 uses two different Repetition operators to achieve the above:
x for string repetitions (in any context);
xx for list repetitions (in any context).
Mnemonic: x is short and xx is long, so xx is the one used for lists.
# Perl 5 print '-' x 80; # Print row of dashes @ones = (1) x 80; # A list of 80 1's @ones = (5) x @ones; # Set all elements to 5
# Perl 6 print '-' x 80; # Unchanged @ones = 1 xx 80; # Parentheses no longer needed @ones = 5 xx @ones; # Parentheses no longer needed
In Perl 5, .. was one of two completely different operators, depending on context.
In list context, .. is the familiar range operator. Ranges from Perl 5 code should not require translation.
In scalar context, .. and ... were the little-known Flipflop operators. They have been replaced by ff and fff.
In Perl 5, "${foo}s" deliminates a variable name from regular text next to it. In Perl 6, simply extend the curly braces to include the sigil too: "{$foo}s". This is in fact a very simple case of interpolating an expression.
These statements include conditionals and loops.
Mostly unchanged; parentheses around the conditions are now optional, but if used, must not immediately follow the keyword, or it will be taken as a function call instead. Binding the conditional expression to a variable is also a little different:
if (my $x = dostuff()) {...} # Perl 5
if dostuff() -> $x {...} # Perl 6
(You can still use the my form in Perl 6, but it will scope to the outer block, not the inner.)
The unless conditional only allows for a single block in Perl 6; it does not allow for an elsif or else clause.
The given-when construct is like a chain of if-elsif-else statements or like the switch-case construct in e.g. C. It has the general structure:
given EXPR { when EXPR { ... } when EXPR { ... } default { ... } }
In its simplest form, the construct is as follows:
given $value { # assigns $_ when "a match" { # if $_ ~~ "a match" # do-something(); } when "another match" { # elsif $_ ~~ "another match" # do-something-else(); } default { # else # do-default-thing(); } }
This is simple in the sense that a scalar value is matched in the when statements against $_, which was set by the given. More generally, the matches are actually smartmatches on $_ such that lookups using more complex entities such as regexps can be used instead of scalar values.
See also the warnings on the smartmatch op above.
Mostly unchanged; parentheses around the conditions are now optional, but if used, must not immediately follow the keyword, or it will be taken as a function call instead. Binding the conditional expression to a variable is also a little different:
while (my $x = dostuff()) {...} # Perl 5
while dostuff() -> $x {...} # Perl 6
(You can still use the my form in Perl 6, but it will scope to the outer block, not the inner.)
Note that reading line-by-line from a filehandle has changed.
In Perl 5, it was done in a while loop using the diamond operator. Using for instead of while was a common bug, because the for causes the whole file to be sucked in at once, swamping the program's memory usage.
In Perl 6, for statement is lazy, so we read line-by-line in a for loop using the .lines method.
while (<IN_FH>) { } # Perl 5
for $IN_FH.lines { } # Perl 6
Also note that in Perl 6, lines are chomped by default.
# Perl 5 do { ... } while $x < 10; do { ... } until $x >= 10;
The construct is still present, but do was renamed to repeat, to better represent what the construct does:
# Perl 6 repeat { ... } while $x < 10; repeat { ... } until $x >= 10;
Note first this common misunderstanding about the for and foreach keywords: Many programmers think that they distinguish between the C-style three-expression form and the list-iterator form; they do not! In fact, the keywords are interchangeable; the Perl 5 compiler looks for the semicolons within the parentheses to determine which type of loop to parse.
The C-style three-factor form now uses the loop keyword, and is otherwise unchanged. The parentheses are still required.
for ( my $i = 1; $i <= 10; $i++ ) { ... } # Perl 5
loop ( my $i = 1; $i <= 10; $i++ ) { ... } # Perl 6
The loop-iterator form is named for in Perl 6 and foreach is no longer a keyword. The for loop has the following rules:
parentheses are optional;
the iteration variable, if any, has been moved from appearing before the list, to appearing after the list and an added arrow operator;
the iteration variable is now always lexical: my is neither needed nor allowed;
the iteration variable is a read-only alias to the current list element (in Perl 5 it is a read-write alias!). If a read-write alias is required, change the -> before the iteration variable to a <->. When translating from Perl 5, inspect the use of the loop variable to decide if read-write is needed.
for my $car (@cars) {...} # Perl 5; read-write
for @cars -> $car {...} # Perl 6; read-only for @cars <-> $car {...} # Perl 6; read-write
If the default topic $_ is being used, it is also read-write.
for (@cars) {...} # Perl 5; $_ is read-write
for @cars {...} # Perl 6; $_ is read-write for @cars <-> $_ {...} # Perl 6; $_ is also read-write
It is possible to consume more than one element of the list in each iteration simply specifying more than one variable after the arrow operator:
my @array = 1..10; for @array -> $first, $second { say "First is $first, second is $second"; }
Here is the equivalent to Perl 5’s while…each(%hash) or while…each(@array) (i.e., iterating over both the keys/indices and values of a data structure) in Perl 6:
while (my ($i, $v) = each(@array)) { ... } # Perl 5
for @array.kv -> $i, $v { ... } # Perl 6
while (my ($k, $v) = each(%hash)) { ... } # Perl 5
for %hash.kv -> $k, $v { ... } # Perl 6
Unchanged:
next
last
redo
There is no longer a continue block. Instead, use a NEXT block (phaser) within the body of the loop.
# Perl 5 my $str = ''; for (1..5) { next if $_ % 2 == 1; $str .= $_; } continue { $str .= ':' }
# Perl 6 my $str = ''; for 1..5 { next if $_ % 2 == 1; $str ~= $_; NEXT { $str ~= ':' } }
Please note that phasers don't really need a block. This can be very handy when you don't want another scope:
# Perl 6 my $str = ''; for 1..5 { next if $_ % 2 == 1; $str ~= $_; NEXT $str ~= ':'; }
Builtins that previously accepted a bare block followed, without a comma, by the remainder of the arguments will now require a comma between the block and the arguments e.g. map, grep, etc.
my @results = grep { $_ eq "bars" } @foo; # Perl 5
my @results = grep { $_ eq "bars" }, @foo; # Perl 6
Turned into an adverb of the {} hash subscripting and [] array subscripting operators.
my $deleted_value = delete $hash{$key}; # Perl 5
my $deleted_value = %hash{$key}:delete; # Perl 6 - use :delete adverb
my $deleted_value = delete $array[$i]; # Perl 5
my $deleted_value = @array[$i]:delete; # Perl 6 - use :delete adverb
Turned into an adverb of the {} hash subscripting and [] array subscripting operators.
say "element exists" if exists $hash{$key}; # Perl 5
say "element exists" if %hash{$key}:exists; # Perl 6 - use :exists adverb
say "element exists" if exists $array[$i]; # Perl 5
say "element exists" if @array[$i]:exists; # Perl 6 - use :exists adverb
In Perl 5, matches and substitutions are done against a variable using the =~ regexp-binding op.
In Perl 6, the ~~ smartmatch op is used instead.
next if $line =~ /static/ ; # Perl 5
next if $line ~~ /static/ ; # Perl 6
next if $line !~ /dynamic/ ; # Perl 5
next if $line !~~ /dynamic/ ; # Perl 6
$line =~ s/abc/123/; # Perl 5
$line ~~ s/abc/123/; # Perl 6
Alternately, the new .match and .subst methods can be used. Note that .subst is non-mutating.
/(.+)/ and print $1; # Perl 5
/(.+)/ and print $0; # Perl 6
Move any modifiers from the end of the regex to the beginning. This may require you to add the optional m on a plain match like /abc/.
next if $line =~ /static/i ; # Perl 5
next if $line ~~ m:i/static/ ; # Perl 6
If the actual regex is complex, you may want to use it as-is, by adding the P5 modifier.
next if $line =~ m/[aeiou]/ ; # Perl 5
next if $line ~~ m:P5/[aeiou]/ ; # Perl 6, using P5 modifier next if $line ~~ m/ <[aeiou]> / ; # Perl 6, native new syntax
Please note that the Perl 5 regular expression syntax dates from many years ago and may lack features that have been added since the beginning of the Perl 6 project.
There are many cases of special matching syntax that Perl 5 regexes support. They won't all be listed here, but often instead of being surrounded by (), the assertions will be surrounded by <>.
For character classes, this means that:
[abc] becomes <[abc]>
[^abc] becomes <-[abc]>
[a-zA-Z] becomes <[a..zA..Z]>
[[:upper:]] becomes <:Upper>
[abc[:upper:]] becomes <[abc]+:Upper>
For lookaround assertions:
(?=[abc]) becomes <?[abc]>
(?=ar?bitrary* pattern) becomes <before ar?bitrary* pattern>
(?!=[abc]) becomes <![abc]>
(?!=ar?bitrary* pattern) becomes <!before ar?bitrary* pattern>
(?<=ar?bitrary* pattern) becomes <after ar?bitrary* pattern>
(?<!ar?bitrary* pattern) becomes <!after ar?bitrary* pattern>
For more info see lookahead assertions.
(Unrelated to <> syntax, the "lookaround" /foo\Kbar/ becomes /foo <( bar )> /
(?(?{condition))yes-pattern|no-pattern) becomes [ <?{condition}> yes-pattern | no-pattern ]
In Perl 6 regexes, | does LTM, which decides which alternation wins an ambiguous match based off of a set of rules, rather than about which was written first.
The simplest way to deal with this is just to change any | in your Perl 5 regex to a ||.
However, if a regex written with || is inherited or composed into a grammar that uses | either by design or typo, the result may not work as expected. So when the matching process becomes complex, you finally need to have some understanding of both, especially how LTM strategy works. Besides, | may be a better choice for grammar reuse.
These work in a slightly different way; also they only work in the latest versions of Perl 5.
use v5.22; "þor is mighty" =~ /is (?<iswhat>\w+)/n; say $+{iswhat};
The iswhat within a non-capturing group is used to actually capture what is behind, and up to the end of the group (the )). The capture goes to the %+ hash under the key with the name of the capture. In Perl 6 named captures work this way
"þor is mighty" ~~ /is \s+ $<iswhat>=(\w+)/; say $<iswhat>;
An actual assignment is made within the regular expression; that's the same syntax used for the variable outside it.
TODO more rules. Use L<< C<translate_regex.pl> from Blue Tiger|https://github.com/Util/Blue_Tiger/>> in the meantime.As with Perl 5, comments work as usual in regexes.
/ word #`(match lexical "word") /
Except for UNITCHECK, all of these special blocks exist in Perl 6 as well. In Perl 6, these are called Phasers. But there are some differences!
There is currently no direct equivalent of CHECK blocks in Perl 6. The CHECK phaser in Perl 6 has the same semantics as the UNITCHECK block in Perl 5: it gets run whenever the compilation unit in which it occurs has finished parsing. This is considered a much saner semantic than the current semantics of CHECK blocks in Perl 5. But for compatibility reasons, it was impossible to change the semantics of CHECK blocks in Perl 5, so a UNITCHECK block was introduced in 5.10. Consequently, it was decided that the Perl 6 CHECK phaser would follow the saner Perl 5 UNITCHECK semantics.
In Perl 5, these special blocks must have curly braces, which implies a separate scope. In Perl 6 this is not necessary, allowing these special blocks to share their scope with the surrounding lexical scope.
my $foo; # Perl 5 BEGIN { $foo = 42 }
BEGIN my $foo = 42; # Perl 6
If you put BEGIN and CHECK phasers in a module that is being precompiled, then these phasers will only be executed during precompilation and not when a precompiled module is being loaded. So when porting module code from Perl 5, you may need to change BEGIN and CHECK blocks to INIT blocks to ensure that they're run when loading that module.
Strict mode is now on by default.
Warnings are now on by default.
no warnings is currently NYI, but putting things in a quietly {} block will silence.
The functions which were altered by autodie to throw exceptions on error, now generally return Failures by default. You can test a Failure for definedness / truthiness without any problem. If you use the Failure in any other way, then the Exception that was encapsulated by the Failure will be thrown.
# Perl 5 open my $i_fh, '<', $input_path; # Fails silently on error use autodie; open my $o_fh, '>', $output_path; # Throws exception on error
# Perl 6 my $i_fh = open $input_path, :r; # Returns Failure on error my $o_fh = open $output_path, :w; # Returns Failure on error
Because you can check for truthiness without any problem, you can use the result of an open in an if statement:
# Perl 6 if open($input_path,:r) -> $handle { .say for $handle.lines; } else { # gracefully handle the fact that the open() failed }
Both use base and use parent have been replaced in Perl 6 by the is keyword, in the class declaration.
# Perl 5 package Cat; use base qw(Animal);
# Perl 6 class Cat is Animal {}
Note that the Animal class must be known at compilation time prior to be able to inherit from it.
No longer relevant.
Int is now arbitrary precision, as is the numerator of Rat (the denominator is limited to 2**64, after which it will automatically upgrade to Num to preserve performance). If you want a Rat with an arbitrary-precision denominator, FatRat is available.
In Perl 6, constant is a declarator for variables, just like my, except the variable is permanently locked to the result of its initialization expression (evaluated at compile time).
So, change the => to =.
use constant DEBUG => 0; # Perl 5
constant DEBUG = 0; # Perl 6
use constant pi => 4 * atan2(1, 1); # Perl 5
tau, pi, e, i; # built-in constants in Perl 6 τ, π, 𝑒 # and their unicode equivalents
Allows you to write your script in non-ascii or non-utf8. Perl 6 uses, for the time being, only utf8 for its scripts.
Perl pragma to use integer arithmetic instead of floating point. There is no such thing in Perl 6. If you use native integers in your calculations, then this will be the closest thing.
#Perl 6 my int $foo = 42; my int $bar = 666; say $foo * $bar; # uses native integer multiplication
Manipulate where modules are looked up at compile time. The underlying logic is very different from Perl 5, but in the case you are using an equivalent syntax, use lib in Perl 6 works the same as in Perl 5.
No longer relevant.
In Perl 6, method calls now always use the C3 method resolution order. If you need to find out parent classes of a given class, you can invoke the mro meta-method thusly:
say Animal.^mro; # .^ indicates calling a meta-method on the object
No longer relevant: in Perl 6, source code is expected to be in utf8 encoding.
Discouraged in Perl 5. See https://perldoc.perl.org/vars.html.
You should refactor your Perl 5 code to remove the need for use vars, before translating into Perl 6.
See the command line flags that Rakudo uses
Unchanged:
-c -e -h -I -n -p -v -V
Change your code to use .split manually.
Change your code to use .split manually.
This is now the default behavior.
Only -M remains. And, as you can no longer use the "no Module" syntax, the use of - with -M to "no" a module is no longer available.
Since all features are already enabled, just use lowercase -e .
Replaced with the ++BUG metasyntactic option.
Switch parsing is now done by the parameter list of the MAIN subroutine.
# Perl 5 #!/usr/bin/perl -s if ($xyz) { print "$xyz\n" } ./example.pl -xyz=5 5
# Perl 6 sub MAIN( Int :$xyz ) { say $xyz if $xyz.defined; }
perl6 example.p6 --xyz=5 5 perl6 example.p6 -xyz=5 5
-t
Removed.
-P -u -U -W -X
Removed. See Removed Syntactic Features.
-w
This is now the default behavior.
-S, -T.
This has been eliminated. Several ways to replicate "taint" mode are discussed in Reddit.
In Perl 5, a common idiom for reading the lines of a text file goes something like this:
open my $fh, "<", "file" or die "$!"; my @lines = <$fh>; # lines are NOT chomped close $fh;
In Perl 6, this has been simplified to
my @lines = "file".IO.lines; # auto-chomped
Do not be tempted to try slurping in a file and splitting the resulting string on newlines as this will give an array with a trailing empty element, which is one more than you probably expect (it's also more complicated), e.g.:
# initialize the file to read spurt "test-file", q:to/END/; first line second line third line END # read the file my @lines = "test-file".IO.slurp.split(/\n/); say @lines.elems; #-> 4
If for some reason you do want to slurp the file first, then you can call the lines method on the result of slurp instead:
my @lines = "test-file".IO.slurp.lines; # also auto-chomps
Also, be aware that $! is not really relevant for file IO operation failures in Perl 6. An IO operation that fails will return a Failure instead of throwing an exception. If you want to return the failure message, it is in the failure itself, not in $!. To do similar IO error checking and reporting as in Perl 5:
my $fh = open('./bad/path/to/file', :w) or die $fh;
Note: $fh instead of $!. Or, you can set $_ to the failure and die with $_:
my $fh = open('./bad/path/to/file', :w) orelse .die; # Perl 6
Any operation that tries to use the failure will cause the program to fault and terminate. Even just a call to the .self method is sufficient.
my $fh = open('./bad/path/to/file', :w).self;
Whereas in Perl 5 you would do:
my $arg = 'Hello'; my $captured = `echo \Q$arg\E`; my $captured = qx(echo \Q$arg\E);
Or using String::ShellQuote (because \Q…\E is not completely right):
my $arg = shell_quote 'Hello'; my $captured = `echo $arg`; my $captured = qx(echo $arg);
In Perl 6, you will probably want to run commands without using the shell:
my $arg = 'Hello'; my $captured = run('echo', $arg, :out).out.slurp; my $captured = run(«echo "$arg"», :out).out.slurp;
You can also use the shell if you really want to:
my $arg = 'Hello'; my $captured = shell("echo $arg", :out).out.slurp; my $captured = qqx{echo $arg};
But beware that in this case there is no protection at all! run does not use the shell, so there is no need to escape the arguments (arguments are passed directly). If you are using shell or qqx, then everything ends up being one long string which is then passed to the shell. Unless you validate your arguments very carefully, there is a high chance of introducing shell injection vulnerabilities with such code.
In Perl 5 one of the environment variables to specify extra search paths for Perl modules is PERL5LIB.
$ PERL5LIB="/some/module/lib" perl program.pl
In Perl 6 this is similar, one merely needs to change a number! As you probably guessed, you just need to use PERL6LIB:
$ PERL6LIB="/some/module/lib" perl6 program.p6
In Perl 5 one uses the ':' (colon) as a directory separator for PERL5LIB, but in Perl 6 one uses the ',' (comma). For example:
$ export PERL5LIB=/module/dir1:/module/dir2;
but
$ export PERL6LIB=/module/dir1,/module/dir2;
(Perl 6 does not recognize either the PERL5LIB or the older Perl environment variable PERLLIB.)
As with Perl 5, if you don't specify PERL6LIB, you need to specify the library path within the program via the use lib pragma:
use lib '/some/module/lib'
Note that PERL6LIB is more of a developer convenience in Perl 6 (as opposed to the equivalent usage of PERL5LIB in Perl5) and shouldn't be used by module consumers as it could be removed in the future. This is because Perl 6's module loading isn't directly compatible with operating system paths.
Unlike Perl 5, a string containing nothing but zero ('0') is True. As Perl 6 has types in core, that makes more sense. This also means the common pattern:
... if defined $x and length $x; # or just length() in modern perls
In Perl 6 becomes a simple
... if $x;
Gone.
The Perl 6 design allows for automatic and transparent saving-and-loading of compiled bytecode.
Rakudo supports this only for modules so far.
The FALLBACK method provides similar functionality.
In Perl 5 it is possible to selectively import functions from a given module like so:
use ModuleName qw{foo bar baz};
In Perl 6 one specifies the functions which are to be exported by using the is export role on the relevant subs; all subs with this role are then exported. Hence, the following module Bar exports the subs foo and bar but not baz:
unit module Bar; sub foo($a) is export { say "foo $a" } sub bar($b) is export { say "bar $b" } sub baz($z) { say "baz $z" }
To use this module, simply use Bar and the functions foo and bar will be available
use Bar; foo(1); #=> "foo 1" bar(2); #=> "bar 2"
If one tries to use baz an "Undeclared routine" error is raised at compile time.
So, how does one recreate the Perl 5 behavior of being able to selectively import functions? By defining an EXPORT sub inside the module which specifies the functions to be exported and removing the module Bar statement.
The former module Bar now is merely a file called Bar.pm6 with the following contents:
sub EXPORT(*@import-list) { my %exportable-subs = '&foo' => &foo, '&bar' => &bar, ; my %subs-to-export; for @import-list -> $import { if grep $sub-name, %exportable-subs.keys { %subs-to-export{$sub-name} = %exportable-subs{$sub-name}; } } return %subs-to-export; } sub foo($a, $b, $c) { say "foo, $a, $b, $c" } sub bar($a) { say "bar, $a" } sub baz($z) { say "baz, $z" }
Note that the subs are no longer explicitly exported via the is export role, but by an EXPORT sub which specifies the subs in the module we want to make available for export and then we are populating a hash containing the subs which will actually be exported. The @import-list is set by the use statement in the calling code thus allowing us to selectively import the subs made available by the module.
So, to import only the foo routine, we do the following in the calling code:
use Bar <foo>; foo(1); #=> "foo 1"
Here we see that even though bar is exportable, if we don't explicitly import it, it's not available for use. Hence this causes an "Undeclared routine" error at compile time:
use Bar <foo>; foo(1); bar(5); #!> "Undeclared routine: bar used at line 3"
However, this will work
use Bar <foo bar>; foo(1); #=> "foo 1" bar(5); #=> "bar 5"
Note also that baz remains unimportable even if specified in the use statement:
use Bar <foo bar baz>; baz(3); #!> "Undeclared routine: baz used at line 2"
In order to get this to work, one obviously has to jump through many hoops. In the standard use-case where one specifies the functions to be exported via the is export role, Perl 6 automatically creates the EXPORT sub in the correct manner for you, so one should consider very carefully whether or not writing one's own EXPORT routine is worthwhile.
If you would like to export groups of functions from a module, you just need to assign names to the groups, and the rest will work automagically. When you specify is export in a sub declaration, you are in fact adding this subroutine to the :DEFAULT export group. But you can add a subroutine to another group, or to multiple groups:
unit module Bar; sub foo() is export { } # added by default to :DEFAULT sub bar() is export(:FNORBL) { } # added to the FNORBL export group sub baz() is export(:DEFAULT:FNORBL) { } # added to both
So now you can use the Bar module like this:
use Bar; # imports foo / baz use Bar :FNORBL; # imports bar / baz use Bar :ALL; # imports foo / bar / baz
Note that :ALL is an auto-generated group that encompasses all subroutines that have an is export trait.
In Perl 5, the Data::Dumper module was used for serialization, and for debugging views of program data structures by the programmer.
In Perl 6, these tasks are accomplished with the .perl method, which every object has.
# Given: my @array_of_hashes = ( { NAME => 'apple', type => 'fruit' }, { NAME => 'cabbage', type => 'no, please no' }, ); # Perl 5 use Data::Dumper; $Data::Dumper::Useqq = 1; print Dumper \@array_of_hashes; # Note the backslash.
# Perl 6 say @array_of_hashes.perl; # .perl on the array, not on its reference.
In Perl 5, Data::Dumper has a more complex optional calling convention, which allows for naming the VARs.
In Perl 6, placing a colon in front of the variable's sigil turns it into a Pair, with a key of the var name, and a value of the var value.
# Given: my ( $foo, $bar ) = ( 42, 44 ); my @baz = ( 16, 32, 64, 'Hike!' ); # Perl 5 use Data::Dumper; print Data::Dumper->Dump( [ $foo, $bar, \@baz ], [ qw( foo bar *baz ) ], ); # Output # $foo = 42; # $bar = 44; # @baz = ( # 16, # 32, # 64, # 'Hike!' # );
# Perl 6 say [ :$foo, :$bar, :@baz ].perl; # OUTPUT: «["foo" => 42, "bar" => 44, "baz" => [16, 32, 64, "Hike!"]]»
There is also a Rakudo-specific debugging aid for developers called dd (Tiny Data Dumper, so tiny it lost the "t"). This will print the .perl representation plus some extra information that could be introspected, of the given variables on STDERR:
# Perl 6 dd $foo, $bar, @baz; # OUTPUT: «Int $foo = 42Int $bar = 44Array @baz = [16, 32, 64, "Hike!"]»
Switch parsing is now done by the parameter list of the MAIN subroutine.
# Perl 5 use 5.010; use Getopt::Long; GetOptions( 'length=i' => \( my $length = 24 ), # numeric 'file=s' => \( my $data = 'file.dat' ), # string 'verbose' => \( my $verbose ), # flag ) or die; say $length; say $data; say 'Verbosity ', ($verbose ? 'on' : 'off') if defined $verbose; perl example.pl 24 file.dat perl example.pl --file=foo --length=42 --verbose 42 foo Verbosity on perl example.pl --length=abc Value "abc" invalid for option length (number expected) Died at c.pl line 3.
# Perl 6 sub MAIN( Int :$length = 24, :file($data) = 'file.dat', Bool :$verbose ) { say $length if $length.defined; say $data if $data.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); }
perl6 example.p6 24 file.dat Verbosity off perl6 example.p6 --file=foo --length=42 --verbose 42 foo Verbosity on perl6 example.p6 --length=abc Usage: c.p6 [--length=<Int>] [--file=<Any>] [--verbose]
Note that Perl 6 auto-generates a full usage message on error in command-line parsing.
A quick way to find the Perl 6 version of a Perl 5 construct, is to run it through an automated translator.
NOTE: None of these translators are yet complete.
This project is dedicated to automated modernization of Perl code. It does not (yet) have a web front-end, and so must be locally installed to be useful. It also contains a separate program to translate Perl 5 regexes into Perl 6.
https://github.com/Util/Blue_Tiger/
Online translator!
This project is a suite of Perl cross-compilers, including Perl 5-to-6 translation. It has a web front-end, and so can be used without installation. It only supports a subset of Perl 5 syntax so far.
https://fglock.github.io/Perlito/perlito/perlito5.html
Jeff Goff's Perl::ToPerl6 module for Perl 5 is designed around Perl::Critic's framework. It aims to convert Perl5 to compilable (if not necessarily running) Perl 6 code with the bare minimum of changes. Code transformers are configurable and pluggable, so you can create and contribute your own transformers, and customize existing transformers to your own needs. You can install the latest release from CPAN, or follow the project live on GitHub. An online converter may become available at some point.
How do I do what I used to do?
These documents should not be mistaken for a beginner tutorial or a promotional overview of Perl 6; it is intended as a technical reference for Perl 6 learners with a strong Perl 5 background and for anyone porting Perl 5 code to Perl 6.
Perl 6 in a Nutshell provides a quick overview of things changed in syntax, operators, compound statements, regular expressions, command-line flags, and various other bits and pieces.
The Syntax section provides an overview of the syntactic differences between Perl 5 and Perl 6: how it is still mostly free form, additional ways to write comments, and how switch is very much a Perl 6 thing.
The Operators section guides you from the operators in Perl 5's perlop to the equivalent in Perl 6.
The Functions section describes all of the Perl 5 functions and their Perl 6 equivalent and any differences in behavior. It also provides references to ecosystem modules that provide the Perl 5 behavior of functions, either existing in Perl 6 with slightly different semantics (such as shift), or non-existing in Perl 6 (such as tie).
The Special Variables section describes if and how a lot of Perl 5's special (punctuation) variables are supported in Perl 6.
### Guidelines for contributions:
Headers should contain the text that a Perl 5 user might search for, since those headings will be in the Table of Contents generated for the top of the document.
We use POD =item instead of =head3 or =head4 for unchanged bits that need not appear in the table of contents.
This article does not describe the additions to syntax, nor details of possible improvements. For example, 0 + $string still works, even though we would write it as +$string now. (Blue Tiger will offer a Perl Modernization guide, with step-by-step procedures for translation, along with details of new idioms and "better ways to do it")
Example code and links to other documents should be favored over long explanations of details better found elsewhere.
Finally, if a real user asks a P5->P6 question not answered here, please add it to the document, even if we don't have a good answer yet. That will be better than losing the information about a real need.
Builtin functions in Perl 5 to Perl 6
A (hopefully) comprehensive list of Perl 5 builtin functions with their Perl 6 equivalents with notes on variations between them where necessary.
This document is an attempt to guide you from the functions in Perl 5's perlfunc document to their equivalents in Perl 6. For full documentation on the Perl 6 functions, follow the links in this document to their respective documentation.
One general comment: Perl 6 takes its objects a lot more seriously than Perl 5. In Perl 6, everything is an object, although the language is flexible enough to not force you to work in an object oriented manner if you do not wish to do so. What this does mean, however, is that a lot of things that are function calls of the form function(@args) are now also method calls of the form @args.function (In rare cases, there is only a method call). This should be obvious in the following text, but it probably behooves you to get into that frame of mind now.
Also, unless otherwise stated, the use of the term "function" here will mean a function in the style of func(@args), while "method" will refer to a function in the style of @args.func.
-X FILEHANDLE
-X EXPR
-X DIRHANDLE
-X
Perl 6 gives you a couple of options when it comes to file tests. You can do a smartmatch (~~) or you can call a method.
In Perl 6, you don't need to actually open a filehandle in the traditional way (although you can) to do a filetest. You can simply append .IO to the filename. For instance, here is how to check if a file is readable using smartmatch:
'/path/to/file'.IO ~~ :r
You can, of course, use an already opened filehandle. Here, using the filehandle $fh, is an example, using the method syntax for the file test:
$fh.r
Most of the former filetests have colon equivalents for use with smartmatch:
:e Exists |
:d Directory |
:f File |
:l Symbolic link |
:r Readable |
:w Writable |
:x Executable |
:s Size |
:z Zero size |
All of these tests can be used as methods (without the colon).
Three tests, however, only have method equivalents:
$fh.modified; # -M $fh $fh.accessed; # -A $fh $fh.changed; # -C $fh
The remaining filetests in Perl 5 do not appear to be implemented in Perl 6.
The documentation for this can be found at File test operators.
There is more information on reading and writing files at io. Also, the section on open() below may be helpful.
The Perl 6 ecosystem has a module P5-X which exports the behavior as much as possible in Perl 6.
abs VALUE
Works as a function (abs($x)), but also as a method. One gotcha, however - method calls bind more tightly than -, so, for example, -15.abs evaluates as -(15.abs) giving you -15. In this example, you would have to do something like (-15).abs.
abs also operates on $_ in the absence of a value, but not as a function, and as a method you need to call it as .abs rather than simply abs.
The Perl 6 ecosystem has a module P5math which exports an abs function that mimics the original Perl 5 behavior as much as possible.
accept NEWSOCKET, GENERICSOCKET
accept is a method you can call on a server, e. g. $server.accept(). Instead of returning a packed address, it returns a socket, most likely an IO::Socket object of some sort.
alarm SECONDS
alarm() is no more. But it is possible to have code execute after a certain time has elapsed, or at a given time:
Promise.in(5).then: { say "five seconds have passed" } Promise.at(now + 5).then: { say "five seconds have passed" }
In Perl 6, this does *not* involve any (dummy) signals.
atan2 Y, X
Available as a function as well as being able to be used as a method. For instance, these are equivalent:
atan2(100); 100.atan2;
bind SOCKET, NAME
[NEEDS FURTHER RESEARCH] No sign of a socket-related bind() in Perl 6. At a guess, whatever socket binding is needed happens when you create a new socket object.
binmode FILEHANDLE
Instead of this, you would use :bin as the file mode when opening the socket. E. g. my $fh = open("path/to/file", :bin);
bless REF, CLASSNAME
With the changes in class creation in Perl 6, this may find less use than in Perl 5, and is a method as well as a function. The Perl 6 docs say "Creates a new object of the same type as the invocant, uses the named arguments to initialize attributes, and returns the created object." If you're porting a module from Perl 5 to Perl 6, it's quite possible you'll want to use new for creating objects rather than bless, although there may be some situations in which the latter may still be useful.
break
Not in Perl 6. For breaking out of given blocks, you should probably take a look at proceed and succeed here.
caller EXPR
There are a couple different ways to get at caller information in Perl 6. The basic functionality is provided through callframe now. However, Perl 6 constructs call frames for regular blocks, not just for subroutines, so there are more frames to look through. The following will retrieve the basic information that caller can return:
my $frame = callframe(0); # OR just callframe() my ($subroutine, $package); if $frame.code ~~ Routine { $subroutine = $frame.code.name; $package = $frame.code.package; } my $file = $frame.file; my $line = $frame.line;
Many of the other details returned by caller are specific to Perl 5 and have no meaning in Perl 6.
You can also get some of the information for the current frame or routine frame by using the dynamic variables &?ROUTINE, &?BLOCK, $?PACKAGE, $?FILE, and $?LINE. For many purposes, Backtrace may provide an easier way to browse through the call stack.
The Perl 6 ecosystem has a module P5caller which exports a caller function that mimics the original Perl 5 behavior as much as possible.
chdir EXPR
Works as it does in Perl 5 but must take an argument. The behavior of chdir() (with regards to looking at HOME and LOGDIR) is not supported.
In Perl 6, chdir only changes the $*CWD dynamic variable. It does not actually change the default directory from the OS's point of view; the special dynamic-variable routine &*chdir can be used for that, if needed.
This is done this way, because there is no concept of a "default directory per OS thread". And since Perl 6 does not fork, but only does threading, it was felt that the "current directory" concept should be in the $*CWD dynamic variable, which can be lexically scoped, and thus can be thread-safe.
The Perl 6 ecosystem has a module P5chdir which exports a chdir function that mimics the original Perl 5 behavior as much as possible, including looking at HOME and LOGDIR.
chmod LIST
Functions as under Perl 5, with the difference that octal numbers are represented differently (0o755 rather than 0755). You may also use it as a method, e. g. $fh.chmod(0o755).
chomp VARIABLE
The behavior of chomp is different than in Perl 5. It leaves the target unaffected and returns a copy of the target with a final logical newline removed, e.g. $x = "howdy\n";$y = chomp($x); results in $x containing "howdy\n" and $y containing "howdy". Also works as a method, e.g. $y = $x.chomp. As with many other methods, also works with assignment to modify the target in place, e.g. $x.=chomp results in $x containing "howdy".
Note that chomp() (without arguments) is not supported in Perl 6.
The Perl 6 ecosystem has a module P5chomp which exports a chomp function that mimics the original Perl 5 behavior as much as possible.
chop VARIABLE
As with chomp, in Perl 6, this returns the chopped string, rather than chopping in place. I. e. $x = "howdy";$y = chop($x); results in $x being "howdy" and $y being "howd". Also works as a method: $y = $x.chop.
Note that chop() (without arguments) is not supported in Perl 6.
The Perl 6 ecosystem has a module P5chomp which exports a chop function that mimics the original Perl 5 behavior as much as possible.
.head2 chown
chown LIST
chown is not in Perl 6.
chr NUMBER
Similar to the Perl 5 version, coerces the target to an integer, and uses that as a Unicode code point to return the relevant character. Can be used as a function and a method:
chr(65); # "A" 65.chr; # "A"
Note that chr() (without arguments) is not supported in Perl 6.
The Perl 6 ecosystem has a module P5chr which exports a chr function that mimics the original Perl 5 behavior as much as possible.
chroot FILENAME
chroot is not in Perl 6.
close FILEHANDLE
As in Perl 5, closes a filehandle. Returns a boolean value. Both close $fh and $fh.close will work.
Note that close() (without arguments) is not supported in Perl 6.
closedir DIRHANDLE
Not supported in Perl 6.
The Perl 6 ecosystem has a module P5opendir which exports a closedir function that mimics the original Perl 5 behavior as much as possible.
connect SOCKET, NAME
Use connect from IO::Socket::Async for an asynchronous socket or create a IO::Socket::INET socket for a synchronous one.
continue BLOCK
continue
Instead of a continue block, you should use a NEXT block. The closest analog to a bare continue; in Perl 5 appears to be proceed/succeed.
cos EXPR
Works as in Perl 5.
cos also operates on $_ in the absence of a value, but not as a function, and as a method you need to call it as .cos rather than simply cos.
The Perl 6 ecosystem has a module P5math which exports a cos function that mimics the original Perl 5 behavior as much as possible.
crypt PLAINTEXT, SALT
Not available in Perl 6.
The Perl 6 ecosystem has a module P5math which exports a crypt function that mimics the original Perl 5 behavior as much as possible.
dbmclose HASH
dbmopen HASH, DBNAME, MASK
These functions have largely been superseded in Perl 5, and are unlikely to ever turn up in Perl 6 (although any assumptions about the Perl 6 database implementation may be premature).
defined EXPR
Probably does what you expect, but technically it returns False on the type object, and True otherwise. This may make more sense when you realize that $num.perl is the type Any if you haven't assigned anything to it, and the assigned value if you have. Can, of course be used as a method: $num.defined. And any newly created class can have its own .defined method, thereby deciding how and when it should be considered undefined.
Note that defined() (without arguments) is not supported in Perl 6.
The Perl 6 ecosystem has a module P5defined which exports a defined function that mimics the original Perl 5 behavior as much as possible.
delete EXPR
Perl 6 replaces this with the new adverb syntax, specifically the :delete adverb. E. g. my $deleted_value = %hash{$key}:delete; and my $deleted_value = @array[$i]:delete;.
die LIST
Works similarly to the Perl 5 version, but Perl 6's Exception mechanism may give you more power and flexibility than is available in Perl 5. See exceptions. To omit the stacktrace and location, like Perl 5's die "...\n", use:
note "..."; exit 1;
do BLOCK
Similar to the Perl 5 version. Note that there must be a space between the do and the block.
do EXPR
Has been replaced in Perl 6 by EVALFILE.
dump LABEL
According to S29, dump has been... dumped.
each HASH
There is no exact equivalent, but you can use %hash.kv which returns a list of keys and values. For example: for %hash.kv -> $k, $v { say "$k: $v" }
Incidentally, what we have there with the -> is called a pointy block and, though there are a number of examples in the documentation, there doesn't seem to be a really clear explanation of how they work. https://design.perl6.org/S04.html#The_for_statement may be of some help here, as well as the design document at https://design.perl6.org/S06.html#%22Pointy_blocks%22. There is also some information at https://en.wikibooks.org/wiki/Perl_6_Programming/Blocks_and_Closures#Pointy_Blocks
The Perl 6 ecosystem has a module P5each which exports an each function that mimics the original Perl 5 behavior as much as possible.
eof FILEHANDLE
In Perl 6, this is not usable as a function, but only as a method. I. e. $filehandle.eof. Returns True if at end of file.
eval EXPR
eval EXPR
The closest replacement is the EVAL function. However, this function has to be allowed explicitly using a pragma to work in the same way. Note that EVAL does not do any exception handling!
evalbytes EXPR
No equivalent.
exec LIST
Nothing in Perl 6 exactly replicates the Perl 5 exec. shell and run are similar to Perl 5's system, but exec's behavior of not returning after executing a system command would have to be emulated by something like shell($command);exit(); or possibly exit shell($command);.
Neither of these workarounds have the behavior (on Unix-like systems) of replacing your Perl program's process with the new program; notably, they will not work for the practice in some long-running daemons of periodically redoing exec on themselves to reset their state or force operating-system cleanup. Nor will they serve exec's function of returning stale resources to the operating system.
If you want exec for these behaviors, you can use an exec* function via the NativeCall interface. Consult your operating system manual pages for exec (or other similarly-named calls such as execl, execv, execvp, or execvpe). (Beware: these calls are not generally portable between Unix-like operating system families.) Given those caveats, the Perl 6 ecosystem Native::Exec module exports an exec function for Unix-like systems.
exists EXPR
In Perl 6, this is not a function, but an adverb:
%hash{$key}:exists; @array[$i]:exists;
exit EXPR
Appears to do the same thing as in Perl 5.
exp EXPR
Same as in Perl 5.
exp also operates on $_ in the absence of a value, but not as a function, and as a method you need to call it as .exp rather than simply exp.
The Perl 6 ecosystem has a module P5math which exports an exp function that mimics the original Perl 5 behavior as much as possible.
fc EXPR
Looks like it does the same thing as in Perl 5 except that calling it without arguments is not supported in Perl 6.
The Perl 6 ecosystem has a module P5fc which exports a fc function that mimics the original Perl 5 behavior as much as possible.
fcntl FILEHANDLE, FUNCTION, SCALAR
Appears not to be in Perl 6.
__FILE__
Replaced by $?FILE which is slightly different from __FILE__ in that it is always an absolute path, rather than a relative one in the Perl 5 case.
The Perl 6 ecosystem has a module P5__FILE__ which exports a __FILE__ term that mimics the original Perl 5 behavior as much as possible.
fileno FILEHANDLE
The native-descriptor method on IO::Handle returns the equivalent of fileno.
The Perl 6 ecosystem has a module P5fileno which exports a fileno function that mimics the original Perl 5 behavior as much as possible.
flock FILEHANDLE, OPERATION
Currently unimplemented.
fork
There is no built-in fork function. While it's possible to call it using NativeCall, it's highly unlikely that the resulting process will be usable.
Perl 6 provides extensive support for, and internally uses, threads. However, fork only clones the thread that called fork, resulting in a process that will be missing its other threads, which will have been in unknown states and probably holding locks. Even if a Perl 6 program doesn't knowingly start any threads, the compiler may create some of its own in the process of precompilation, and the VMs that Perl 6 runs on also create their own internal worker threads for doing things like optimization and GC in the background. Thus, the presence of threads is pretty much assured, and there's no reasonable way to make fork reliably work in this case.
format
formline PICTURE, LIST
Perl 6 does not have built-in formats.
getc FILEHANDLE
Reads a single character from the input stream as in Perl 5. May now also be used as a method: $filehandle.getc
getpeername SOCKET
S29 lists it, but the implementation does not seem clear or, for that matter, implemented.
getpgrp PID
Will not be implemented.
The Perl 6 ecosystem has a module P5getpriority which exports a getpgrp function that mimics the original Perl 5 behavior as much as possible.
getppid PID
Will not be implemented.
The Perl 6 ecosystem has a module P5getpriority which exports a getppid function that mimics the original Perl 5 behavior as much as possible.
getpriority WHICH, WHO
Will not be implemented.
The Perl 6 ecosystem has a module P5getpriority which exports a getpriority function that mimics the original Perl 5 behavior as much as possible.
endpwent
getlogin
getpwent
getpwnam NAME
getpwuid UID
setpwent
The Perl 6 ecosystem has a module P5getpwnam which exports the endpwent, getlogin, getpwent, getpwnam, getpwuid and setpwent functions that mimic the original Perl 5 behavior as much as possible.
endgrent
getgrent
getgrgid GID
getgrnam NAME
setgrent
The Perl 6 ecosystem has a module P5getgrnam which exports the endgrent, getgrent, getgrgid, getgrnam and setgrent functions that mimic the original Perl 5 behavior as much as possible.
endnetent
getnetbyaddr ADDR, ADDRTYPE
getnetbyname NAME
getnetent
setnetent STAYOPEN
The Perl 6 ecosystem has a module P5getnetbyname which exports the endnetent, getnetent, getnetbyaddr, getnetbyname and setnetent functions that mimic the original Perl 5 behavior as much as possible.
endservent
getservbyname NAME, PROTO
getservbyport PORT, PROTO
getservent
setservent STAYOPEN
The Perl 6 ecosystem has a module P5getservbyname which exports the endservent, getservent, getservbyname, getservbyport and setservent functions that mimic the original Perl 5 behavior as much as possible.
endprotoent
getprotobyname NAME
getprotobynumber NUMBER
getprotoent
setprotoent STAYOPEN
The Perl 6 ecosystem has a module P5getprotobyname which exports the endprotoent, getprotoent, getprotobyname, getprotobynumber and setprotoent functions that mimic the original Perl 5 behavior as much as possible.
gethostbyname NAME
gethostbyaddr ADDR, ADDRTYPE
gethostent
sethostent STAYOPEN
endhostent
[NEEDS FURTHER RESEARCH] Apparently this range of functions are to be handled by roles like User, Group, etc.
getsockname SOCKET
getsockopt SOCKET, LEVEL, OPTNAME
[NEEDS FURTHER RESEARCH] These are likely implemented by some kind of IO::Socket object, but details are unclear.
glob EXPR
Not available in core, although some of the functionality is offered by dir routine and its test argument.
See IO::Glob module in ecosystem
gmtime EXPR
Like the various parts of localtime, gmtime's functionality appears to in the DateTime object. To get a UTC version of a DateTime object for the current time, for instance, use my $gmtime = DateTime.now.utc.
The Perl 6 ecosystem has a module P5localtime which exports a gmtime function that mimics the original Perl 5 behavior as much as possible.
goto LABEL
goto EXPR
goto &NAME
The syntax for goto LABEL is already accepted, but the runtime part of goto is not yet implemented. So this will result in a runtime error:
FOO: goto FOO; # Label.goto() not yet implemented. Sorry.
grep BLOCK LIST
grep EXPR, LIST
Still in Perl 6, with the caveat that the block form now requires a comma after the block. I.e. @foo = grep { $_ = "bars" }, @baz. Can also be used as a method: @foo = @bar.grep(/^f/)
hex EXPR
In Perl 6 an expression must be specified.
Replaced by the adverbial form :16. E. g. :16("aF") returns 175. This is Str->Int.
The opposite result can be achieved (Int->Str) by using the .base method: 0xaF.base(10)
It just so happens that .Str defaults to base 10, so if you just say 0xaF, that will also print 175, but that may not be immediately obvious, so may not be the best way to go for this.
The Perl 6 ecosystem has a module P5hex which exports a hex function that mimics the original Perl 5 behavior as much as possible.
import LIST
Was never a builtin function in Perl 5 in the first place. In Perl 6, typically, one declares functions as exportable or not, and all the exportable ones are exported. Nevertheless, selective importing is possible, but beyond the scope of this document. For details, see this section.
index STR, SUBSTR, POSITION
Works as in Perl 5. Can also now be used as a method: "howdy!".index("how"); # 0. Main difference with Perl 5 is that Nil is returned instead of -1 when the substring is not found. This is very useful in combination with the with command:
with index("foo","o") -> $index { say "Found it at $index"; } else { say "Not found" }
The Perl 6 ecosystem has a module P5index which exports an index function that mimics the original Perl 5 behavior as much as possible.
int EXPR
There is a truncate function in Perl 6 (also usable as a method) that does what Perl 5's int does. You may want to use that as a direct translation of Perl 5 code, but in Perl 6, you can just as easily call the .Int method on the number. 3.9.Int; # 3 and 3.9.truncate are equivalent.
Please note that int does have a meaning in Perl 6. It is type that can be used to indicate a native integer:
my int $a = 42; # a native integer, similar to Perl 5's integer values
int also operates on $_ in the absence of a value, but not as a function, and as a method you need to call it as .int rather than simply int.
The Perl 6 ecosystem has a module P5math which exports an int function that mimics the original Perl 5 behavior as much as possible.
ioctl FILEHANDLE, FUNCTION, SCALAR
Currently unimplemented in Perl 6.
join EXPR, LIST
Works as in Perl 5, and also works as a method: @x.join(",")
keys HASH
Works as in Perl 5, and can also be used as a method: %hash.keys
kill SIGNAL, LIST
kill SIGNAL
No pre-defined core alternative exists. A non-portable method can be to use NativeCall:
use NativeCall; sub kill(int32, int32) is native {*}; kill $*PID, 9; # OUTPUT: «Killed»
To kill processes that were started by creating a Proc::Async, use Proc::Async.kill method.
last LABEL
last EXPR
last
Same as in Perl 5.
lc EXPR
Works as in Perl 5, and also as a method: "UGH".lc. In Perl 6 an expression must be specified.
The Perl 6 ecosystem has a module P5lc which exports an lc function that mimics the original Perl 5 behavior as much as possible.
lcfirst EXPR
Does not exist in Perl 6.
The Perl 6 ecosystem has a module P5lcfirst which exports an lcfirst function that mimics the original Perl 5 behavior as much as possible.
length EXPR
Replaced by chars, typically used as a method ($string.chars), but also works as a function.
The Perl 6 ecosystem has a module P5length which exports an length function that mimics the original Perl 5 behavior as much as possible.
__LINE__
Replaced by $?LINE.
The Perl 6 ecosystem has a module P5__FILE__ which exports a __LINE__ term that mimics the original Perl 5 behavior as much as possible.
link OLDFILE, NEWFILE
See link
listen SOCKET, QUEUESIZE
Not clearly documented, but it appears that listen will be a method you would call on some variety of IO::Socket object.
local EXPR
The Perl 6 equivalent is temp. Unlike local, however, the value of the given variable is not immediately unset: it retains its original value until assigned to.
localtime EXPR
Most of the functionality of localtime is found in DateTime. The specific parts of localtime can be found as follows:
my $d = DateTime.now; my $sec = $d.second; # Potentially includes fractional seconds my $min = $d.minute; my $hour = $d.hour; my $mday = $d.day-of-month; # or $d.day; 1..31 my $mon = $d.month; # 1..12 my $year = $d.year; my $wday = $d.day-of-week; # 1 => Monday, 2 => Tuesday, etc. my $yday = $d.day-of-year; # 1..366
Please note that ranges are not 0-based in Perl 6, as shown in the comments in the example.
There does not currently appear to be a way to get Perl 5's $isdst. Also, the result of scalar(localtime) that Perl 5 provides is not available. $d.Str will give something along the lines of "2015-06-29T12:49:31-04:00".
The Perl 6 ecosystem has a module P5localtime which exports a localtime function that mimics the original Perl 5 behavior as much as possible.
lock THING
There currently is no equivalent for this In Perl 6. There is a Lock class for creating a Lock object, that can be locked/unlocked as needed. But such a lock does not refer to any external objects.
log EXPR
Same as in Perl 5.
log also operates on $_ in the absence of a value, but not as a function, and as a method you need to call it as .log rather than simply log.
The Perl 6 ecosystem has a module P5math which exports a log function that mimics the original Perl 5 behavior as much as possible.
lstat FILEHANDLE
lstat EXPR
lstat DIRHANDLE
lstat
Likely implemented somewhere in one of the IO classes in Perl 6, but it is not clear where at this time.
m//
Regular expression syntax is somewhat different in Perl 6, but the match operator still exists. If you're trying to rewrite some Perl 5 code, the most important difference is that =~ is replaced by the smartmatch operator, ~~. Similarly, !~ is replaced by !~~. Options for regex operators are adverbs and are complicated. For details, see Adverbs
map BLOCK LIST
map EXPR, LIST
As a function, the only difference between Perl 5 and Perl 6 is that, if you're using a block, the block must be followed by a comma. Can also be used as a method: @new = @old.map: { $_ * 2 }
mkdir FILENAME, MASK
mkdir FILENAME
Works as in Perl 5. When giving a multi-level directory specification, it will automatically create non-existing intermediate directories with the same MASK (similar to what "make_path" does of the File::Path module in Perl 5).
mkdir
The zero argument (implicit $_) version is not permitted in Perl 6.
msgctl ID, CMD, ARG
msgget KEY, FLAGS
msgrcv ID, VAR, SIZE, TYPE, FLAGS
msgsnd ID, MSG, FLAGS
Not builtins in Perl 6. May appear in an external module at some point. Maybe.
my VARLIST
my TYPE VARLIST
my VARLIST : ATTRS
my TYPE VARLIST : ATTRS
Works as in Perl 5.
next LABEL
next EXPR
next
The same in Perl 6.
no MODULE VERSION
no MODULE LIST
no MODULE
no VERSION
In Perl 6, this is usable for pragmas such as strict, but not for modules or versions.
oct
Replaced by the adverbial form :8. E. g. :8("100") returns 64.
If you want to deal with strings that start in 0x, 0o, or 0b, you can just use the prefix:<+> operator.
The Perl 6 ecosystem has a module P5hex which exports an oct function that mimics the original Perl 5 behavior as much as possible.
open FILEHANDLE, EXPR
open FILEHANDLE, MODE, EXPR
open FILEHANDLE, MODE, EXPR, LIST
open FILEHANDLE, MODE, REFERENCE
open FILEHANDLE
The most obvious change from Perl 5 is the file mode syntax. To open a file for reading only, you would say open("file", :r). For write- only, read-write, and append, you would use :w, :rw, and :a respectively. There are also options for encoding and how the filehandle deals with newlines. Details here.
Another important change is that filehandles don't get automatically closed on scope exit. It's necessary to call close explicitly.
opendir DIRHANDLE, EXPR
No replacement. See &dir / IO::Path.dir for alternatives.
The Perl 6 ecosystem has a module P5opendir which exports an opendir function that mimics the original Perl 5 behavior as much as possible.
ord EXPR
Same as in Perl 5. May be used as a method: "howdy!".ord; # 104
Note that ord() (without arguments) is not supported in Perl 6.
The Perl 6 ecosystem has a module P5chr which exports a ord function that mimics the original Perl 5 behavior as much as possible.
our VARLIST
our TYPE VARLIST
our VARLIST : ATTRS
our TYPE VARLIST : ATTRS
The same in Perl 6.
pack TEMPLATE, LIST
Available in Perl 6 when use experimental :pack has been specified in the scope where pack needs to be called. The template options are currently more restricted than they are in Perl 5. The current documented list can be found at unpack.
The Perl 6 ecosystem has a module P5pack which exports a pack function that mimics the original Perl 5 behavior as much as possible and which has a bigger set of supported features than the experimental Perl 6 version.
package NAMESPACE
package NAMESPACE VERSION
package NAMESPACE BLOCK
package NAMESPACE VERSION BLOCK
S10 indicates that package can be used in Perl 6, but only with a block. I. e. package Foo { ... } means that the code within the block would be in package Foo. There is a special case where a declaration of the form package Foo; as the first statement in a file indicates that the rest of the file is Perl 5 code, but the usefulness of this is unclear. In fact, as modules and classes are declared with distinct keywords (such as class), it's unlikely you will use package directly in Perl 6.
__PACKAGE__
Replaced by $?PACKAGE which is slightly different from __PACKAGE__ in that it is the actual package object. You should call the .^name method on it to get a string.
The Perl 6 ecosystem has a module P5__FILE__ which exports a __PACKAGE__ term that mimics the original Perl 5 behavior as much as possible.
pipe READHANDLE, WRITEHANDLE
Depending on your needs, see Channel to shuttle data between threads (and Concurrency tutorial for other options), or see Proc type for piping to and from processes.
pop ARRAY
Works in Perl 6, and can also be used as a method. I. e. my $x = pop @a; and my $x = @a.pop; are equivalent.
The non-parameter version of pop does not exist. Also, if the array is empty, a Failure will be returned in Perl 6, which will throw if the value is actually used in a significant way.
If you are using only defined values in your array, you can use the with function to handle this case:
with pop @array -> $popped { say "popped '$popped' of the array"; } else { say "there was nothing to pop"; }
The Perl 6 ecosystem has a module P5push which exports a pop function that mimics the original Perl 5 behavior as much as possible.
pos SCALAR
Not available in Perl 6. The closest equivalent is the :c adverb, which defaults to $/.to if $/ is true, and 0 if it isn't. For information on :c, see Continue.
print FILEHANDLE LIST
print FILEHANDLE
print LIST
print can be used as a function in Perl 6, writing to standard out. To use print as a function with a filehandle instead of standard out, you can use a method call: $fh.print("howdy!")
The Perl 6 ecosystem has a module P5print which exports a print function that mimics the original Perl 5 behavior as much as possible.
printf FORMAT, LIST
printf
Perl 6 version is similar; see sprintf for details on acceptable format directives. To print to a filehandle other than STDOUT, use the .printf method on that filehandle.
The Perl 6 ecosystem has a module P5print which exports a printf function that mimics the original Perl 5 behavior as much as possible.
prototype FUNCTION
Not available in Perl 6. The closest equivalent is .signature. E. g. say &sprintf.signature results in "(Cool $format, *@args)".
push ARRAY, LIST
Works as in Perl 5, as well as being available as a method: @a.push("foo");. Note: the flattening behavior is different in Perl 6: @b.push: @a will push @a into @b as a single element. See also the append method.
Also note that push in Perl 6 returns the array to which was pushed, contrary to Perl 5 where it returns the new number of elements.
The Perl 6 ecosystem has a module P5push which exports a push function that mimics the original Perl 5 behavior as much as possible.
q/STRING/
qq/STRING/
qw/STRING/
qx/STRING/
These survive the transition to Perl 6. Some notes:
q/.../; # is still equivalent to using single quotes. qq/.../; # is still equivalent to using double quotes. qw/.../; # is more commonly rendered as C<< <...> >> in Perl 6.
There are some added quoting constructs and equivalents, as explained at quoting.
Has been replaced by rx/.../.
quotemeta EXPR
No direct equivalent, i.e. nothing that just returns the string with all the ASCII non-word characters backslashed. In regexes, however, using $foo will treat $foo as a literal string, and using <$foo> will interpret the contents of $foo as regex code. Note that the angle brackets are doing something different here than they do outside a regex. For more information on this, see https://design.perl6.org/S05.html#Extensible_metasyntax_(%3C...%3E)
The Perl 6 ecosystem has a module P5quotemeta which exports a quotemeta function that mimics the original Perl 5 behavior as much as possible.
rand EXPR
rand by itself works as it does in Perl 5, but you can no longer give it an argument. You can, however, use it as a method on a number to get that behavior. I. e. the Perl 5 rand(100) is equivalent to 100.rand in Perl 6. Additionally, you can get a random integer by using something like (^100).pick. For why you are able to do that, see ^ operator and pick.
The Perl 6 ecosystem has a module P5math which exports a rand function that mimics the original Perl 5 behavior as much as possible.
read FILEHANDLE, SCALAR, LENGTH, OFFSET
read is found in IO::Handle and IO::Socket in Perl 6. It reads the specified number of bytes (rather than characters) from the relevant handle or socket. The use of an offset available in Perl 5 is not documented to exist at this time.
readdir DIRHANDLE
Not a builtin function. To iterate through the contents of a directory, take a look at dir routine.
The Perl 6 ecosystem has a module P5opendir which exports a readdir function that mimics the original Perl 5 behavior as much as possible.
readline
Not available in Perl 6. You most likely want to use the .lines method in some way. For more detailed information on reading from files, see io.
readlink EXPR
Appears to be gone from Perl 6. There is a method resolve in IO::Path that will follow symlinks if the OS / Filesystem supports them.
The Perl 6 ecosystem has a module P5readlink which exports a readlink function that mimics the original Perl 5 behavior as much as possible.
readpipe EXPR
readpipe
Doesn't appear to be working in Perl 6, but qx// is functional, so it might be lurking around in some class that isn't obvious.
recv SOCKET, SCALAR, LENGTH, FLAGS
Appears to be in IO::Socket. Not extensively documented at this time.
redo LABEL
redo EXPR
redo
Unchanged in Perl 6.
ref EXPR
Gone. To quote S29, "If you really want the type name, you can use $var.WHAT.^name.
The Perl 6 ecosystem has a module P5ref which exports a ref function that mimics the original Perl 5 behavior as much as possible.
rename OLDNAME, NEWNAME
Still available in Perl 6.
require VERSION
No equivalent.
reset EXPR
No equivalent.
The Perl 6 ecosystem has a module P5reset which exports a reset function that mimics the original Perl 5 behavior as much as possible.
return EXPR
Appears to be available in Perl 6, although not clearly documented.
reverse LIST
In Perl 6, this only reverses the elements of a list. reverse(@a) or @a.reverse. To reverse the characters in a string, use the .flip method.
reverse without parameters is not supported in Perl 6.
The Perl 6 ecosystem has a module P5reverse which exports a reverse function that mimics the original Perl 5 behavior as much as possible.
rewinddir DIRHANDLE
Not supported in Perl 6.
The Perl 6 ecosystem has a module P5rewinddir which exports a rewinddir function that mimics the original Perl 5 behavior as much as possible.
rindex STR, SUBSTR, POSITION
Works as in Perl 5, and may also be used as a method. E. g. $x = "babaganush";say $x.rindex("a"); say $x.rindex("a", 3); # 5, 3. Main difference with Perl 5 is that Nil is returned instead of -1 when the substring is not found. This is very useful in combination with the with command:
with index("foo","o") -> $index { say "Found it at $index"; } else { say "Not found" }
The Perl 6 ecosystem has a module P5index which exports a rindex function that mimics the original Perl 5 behavior as much as possible.
rmdir FILENAME
Works in Perl 6 and can also be used as a method. rmdir "Foo"; and "Foo".IO.rmdir; are equivalent.
s///
Regular expression syntax is somewhat different in Perl 6, but the substitution operator exists. If you're trying to rewrite some Perl 5 code, the most important difference is that =~ is replaced by the smartmatch operator, ~~. Similarly, !~ is !~~. Options for regex operators are adverbs and are complicated. For details, see Adverbs page
say FILEHANDLE
say LIST
say
say can be used as a function, defaulting to standard out. To use say as a function with a filehandle instead of standard out, you need to put a colon after the filehandle. I. e. say $fh: "Howdy!". The use of the colon as an "invocant marker" here is discussed at https://design.perl6.org/S03.html#line_4019. Alternately, you can use a method call: $fh.say("howdy!")
The Perl 6 ecosystem has a module P5print which exports a say function that mimics the original Perl 5 behavior as much as possible.
scalar EXPR
Gone. Apparently "very" gone.
Some functions of the modules created for the CPAN Butterfly Plan accept a :scalar named parameter to indicate that the scalar behavior of the function is required.
seek FILEHANDLE, POSITION, WHENCE
Not documented in any real way yet, but listed as a method of the IO::Handle class.
The Perl 6 ecosystem has a module P5seek which exports a seek function that mimics the original Perl 5 behavior as much as possible.
seekdir DIRHANDLE, POS
Not supported in Perl 6.
The Perl 6 ecosystem has a module P5opendir which exports a seekdir function that mimics the original Perl 5 behavior as much as possible.
select FILEHANDLE
"[S]elect as a global concept is dead." When I asked around about select, I was told that $*OUT and such are overridable in dynamic scope, and that IO::Capture::Simple (at https://github.com/sergot/IO-Capture-Simple) may be of use for something you might be doing with the value of select.
semctl ID, SEMNUM, CMD, ARG
No longer in core.
semget KEY, NSEMS, FLAGS
No longer in core.
semop KEY, OPSTRING
No longer in core.
send SOCKET, MSG, FLAGS, TO
Can be found in the IO::Socket class.
setpgrp PID, PGRP
Will not be implemented.
The Perl 6 ecosystem has a module P5getpriority which exports a setpgrp function that mimics the original Perl 5 behavior as much as possible.
setpriority WHICH, WHO, PRIORITY
Will not be implemented.
The Perl 6 ecosystem has a module P5getpriority which exports a setpriority function that mimics the original Perl 5 behavior as much as possible.
setsockopt SOCKET, LEVEL, OPTNAME, OPTVAL
Not documented, but probably hiding in an IO class somewhere.
shift ARRAY
shift EXPR
shift
Works in Perl 6, and can also be used as a method. I. e. my $x = shift @a; and my $x = @a.shift; are equivalent.
The non-parameter version of shift does not exist. Also, if the array is empty, a Failure will be returned in Perl 6, which will throw if the value is actually used in a significant way.
If you are using only defined values in your array, you can use the with function to handle this case:
with shift @array -> $shifted { say "shifted '$shifted' of the array"; } else { say "there was nothing to shift"; }
The Perl 6 ecosystem has a module P5shift which exports a shift function that mimics the original Perl 5 behavior as much as possible.
shmctl ID, CMD, ARG
shmget KEY, SIZE, FLAGS
shmread ID, VAR, POS, SIZE
shmwrite ID, STRING, POS, SIZE
Gone from the core. May turn up in a module somewhere.
shutdown SOCKET, HOW
Not documented, but likely moved into IO::Socket.
sin EXPR
Same as in Perl 5.
sin also operates on $_ in the absence of a value, but not as a function, and as a method you need to call it as .sin rather than simply sin.
The Perl 6 ecosystem has a module P5math which exports a sin function that mimics the original Perl 5 behavior as much as possible.
sleep EXPR
Still works as in Perl 5, but is not limited to integer values for seconds. And it always returns Nil.
If you're interested in the return values of sleep to ensure sleeping until a specified time, then you should use sleep-until in Perl 6 (which takes an Instant).
If you're interested in running some code every N seconds, and you don't care on which thread it runs, you should probably use react and whenever with a Supply.interval.
The Perl 6 ecosystem has a module P5sleep which exports a sleep function that mimics the original Perl 5 behavior as much as possible.
socket SOCKET, DOMAIN, TYPE, PROTOCOL
socketpair SOCKET1, SOCKET2, DOMAIN, TYPE, PROTOCOL
Not currently documented, but will likely wind up in IO::Socket.
sort SUBNAME LIST
sort exists in Perl 6, but is somewhat different. $a and $b are no longer special (see Special Variables) and sort routines no longer return positive integers, negative integers, or 0, but rather Order::Less, Order::Same, or Order::More objects. See sort for details. May also be used as a method I. e. sort(@a) is equivalent to @a.sort.
splice ARRAY, OFFSET, LENGTH
splice ARRAY, OFFSET
splice ARRAY
splice EXPR, OFFSET, LENGTH, LIST
splice EXPR, OFFSET, LENGTH
splice EXPR, OFFSET
splice EXPR
Available in Perl 6. Can also be used as a method. splice(@foo, 2, 3, <M N O P>); is equivalent to @foo.splice(2, 3, <M N O P>); .
split /PATTERN/, EXPR, LIMIT
split /PATTERN/, EXPR
split /PATTERN/
Works mostly as in Perl 5. There are some exceptions, though. To get the special behavior of using the empty string, you must actually use the empty string - the special case of the empty pattern // being treated as the empty string does not apply. If you use a regex for the split, it will use the regex, while a literal string will be treated literally. If you wish to have the delimiters included in the resulting list, you need to use the named parameter :all, like this: split(';', "a;b;c", :all) # a ; b ; c Empty chunks are not removed from the result list as they are in Perl 5. For that behavior, see comb. Details on split are here. Unsurprisingly, split also now works as a method: "a;b;c".split(';')
split
The zero argument version must now be called with an explicit empty string, as described above.
sprintf FORMAT, LIST
Works as in Perl 5. The formats currently available are:
% | a literal percent sign |
c | a character with the given codepoint |
s | a string |
d | a signed integer, in decimal |
u | an unsigned integer, in decimal |
o | an unsigned integer, in octal |
x | an unsigned integer, in hexadecimal |
e | a floating-point number, in scientific notation |
f | a floating-point number, in fixed decimal notation |
g | a floating-point number, in %e or %f notation |
X | like x, but using uppercase letters |
E | like e, but using an uppercase "E" |
G | like g, but with an uppercase "E" (if applicable) |
Compatibility:
i | a synonym for %d |
D | a synonym for %ld |
U | a synonym for %lu |
O | a synonym for %lo |
F | a synonym for %f |
Perl 5 (non-)compatibility:
n | produces a runtime exception |
p | produces a runtime exception |
There are modifiers for integers, but they're mainly no-ops, as the semantics aren't settled:
h | interpret integer as native "short" (typically int16) |
l | interpret integer as native "long" (typically int32 or int64) |
ll | interpret integer as native "long long" (typically int64) |
L | interpret integer as native "long long" (typically uint64) |
q | interpret integer as native "quads" (typically int64 or larger) |
sqrt EXPR
Same as in Perl 5.
sqrt also operates on $_ in the absence of a value, but not as a function, and as a method you need to call it as .sqrt rather than simply sqrt.
The Perl 6 ecosystem has a module P5math which exports a sqrt function that mimics the original Perl 5 behavior as much as possible.
srand EXPR
Available in Perl 6.
stat EXPR
stat DIRHANDLE
stat
Unlikely to be implemented as a built in function since it's POSIX specific, but available through the NativeCall interface.
state VARLIST
state TYPE VARLIST
state VARLIST : ATTRS
state TYPE VARLIST : ATTRS
Available in Perl 6, see state.
study SCALAR
study
study is no more.
The Perl 6 ecosystem has a module P5study which exports a study function that mimics the original Perl 5 behavior as much as possible.
sub NAME BLOCK
sub NAME(PROTO) BLOCK
sub NAME : ATTRS BLOCK
sub NAME(PROTO) : ATTRS BLOCK
Unsurprisingly, we still have subroutines! You can have a signature in your subroutine which allows you to specify arguments. Nevertheless, in the absence of a signature (and only in the absence of a signature), @_ still contains what is passed to the function. So, in theory, you don't need to change that aspect of a function if porting from Perl 5 to Perl 6 (although you should probably consider the option of using a signature). For all the gory details, see functions.
__SUB__
Replaced by &?ROUTINE which is slightly different from __SUB__ in that it is the actual Sub (or Method) object. You should call the .name method on it to get a string.
The Perl 6 ecosystem has a module P5__FILE__ which exports a __SUB__ term that mimics the original Perl 5 behavior as much as possible.
substr EXPR, OFFSET, LENGTH, REPLACEMENT
substr EXPR, OFFSET, LENGTH
substr EXPR, OFFSET
Can be used as a function or a method. substr("hola!", 1, 3) and "hola!".substr(1, 3) both return "ola".
symlink OLDFILE, NEWFILE
See symlink.
syscall NUMBER, LIST
Not a builtin in Perl 6. Most likely out in a module somewhere, but it's currently unclear where.
sysopen FILEHANDLE, FILENAME, MODE
sysopen FILEHANDLE, FILENAME, MODE, PERMS
sysread FILEHANDLE, SCALAR, LENGTH, OFFSET
sysread FILEHANDLE, SCALAR, LENGTH
sysseek FILEHANDLE, POSITION, WHENCE
As with the non-sys versions of these functions, are probably lurking in the IO classes somewhere.
system LIST
system PROGRAM LIST
For this, you probably want (run) or (shell routine).
syswrite FILEHANDLE, SCALAR, LENGTH, OFFSET
syswrite FILEHANDLE, SCALAR, LENGTH
syswrite FILEHANDLE, SCALAR
As with sysopen and friends, this has moved into the IO classes.
tell FILEHANDLE
As a method on IO::Handle.
telldir DIRHANDLE
Not supported in Perl 6.
The Perl 6 ecosystem has a module P5opendir which exports a telldir function that mimics the original Perl 5 behavior as much as possible.
tie VARIABLE, CLASSNAME, LIST
tied VARIABLE
The Perl 6 alternative to tying a scalar, is the Proxy container. For example:
sub lval() { Proxy.new( FETCH => method () { ...}, STORE => method ($new) { ... } ) }
This makes lval a left-value sub. Whenever the value is requested, the FETCH method is called. And whenever it is used in an assignment, the STORE method is called.
For arrays and hashes (objects that do the Positional and/or Associative role), one only needs to provide the methods that these roles require to get the functionality that tie provides in Perl 5. These are documented in the Subscripts section.
The Perl 6 ecosystem has a module P5tie which exports tie / tied functions that mimics the original Perl 5 behavior as much as possible.
time
Number of seconds since epoch (as an Int), same as in Perl 5.
times
Not available in Perl 6.
The Perl 6 ecosystem has a module P5times which exports a times function that mimics the original Perl 5 behavior as much as possible.
tr///
Works similarly to how it does in Perl 5. The one caveat is that ranges are specified differently. Instead of using a range "a-z", you would use "a..z", i.e. with Perl's range operator. In Perl 6, tr/// has a method version, called trans, which offers a few additional features.
Perl 5's /r flag is instead implemented as TR/// operator. The y/// equivalent does not exist.
truncate FILEHANDLE, LENGTH
truncate EXPR, LENGTH
Not currently implemented (2018.04).
uc EXPR
Works as a function and a method. uc("ha") and "ha".uc both return "HA". There is no support for the parameterless version.
The Perl 6 ecosystem has a module P5lc which exports a uc function that mimics the original Perl 5 behavior as much as possible.
ucfirst EXPR
ucfirst
Perl 6 has done away with ucfirst. The title case function tc probably does what you need.
The Perl 6 ecosystem has a module P5lcfirst which exports a ucfirst function that mimics the original Perl 5 behavior as much as possible.
undef EXPR
There is no undef in Perl 6. You can't undefine a function, and the closest equivalent value is probably Nil, but you'll likely have no use for that.
If you were using something like (undef, $file, $line) = caller;, you would just get the filename and line number directly in Perl 6 instead of discarding the first result of caller. caller has been replaced by callframe in Perl 6, so the equivalent statement would be ($file, $line) = callframe.annotations<file line>;
The Perl 6 ecosystem has a module P5defined which exports an undef function that mimics the original Perl 5 behavior as much as possible.
Add a note here about Type-based undefined values.unlink LIST
Still available. Usable as a method: "filename".IO.unlink
unlink
The zero argument (implicit $_) version of unlink is not available in Perl 6.
unpack TEMPLATE, EXPR
unpack TEMPLATE
Available in Perl 6 when use experimental :pack has been specified in the scope where unpack needs to be called. The template options are currently more restricted than they are in Perl 5. The current documented list can be found at unpack.
The Perl 6 ecosystem has a module P5pack which exports an unpack function that mimics the original Perl 5 behavior as much as possible and which has a bigger set of supported features than the experimental Perl 6 version.
unshift ARRAY, LIST
unshift EXPR, LIST
Works as in Perl 5, as well as being available as a method: @a.unshift("foo");. Note: the flattening behavior is different in Perl 6: @b.unshift: @a will unshift @a into @b as a single element. See also the prepend method.
Also note that unshift in Perl 6 returns the array to which was pushed, contrary to Perl 5 where it returns the new number of elements.
The Perl 6 ecosystem has a module P5shift which exports an unshift function that mimics the original Perl 5 behavior as much as possible.
untie VARIABLE
Not supported in Perl 6, but see tie for the whole story.
The Perl 6 ecosystem has a module P5tie which exports an untie function that mimics the original Perl 5 behavior as much as possible.
use Module VERSION LIST
use Module VERSION
use Module LIST
use Module
use VERSION
In Perl 5, this requires a minimum version of the perl executable in order to run. In Perl 6, this requires a version of the specification, (e.g. 6.c), which can be implemented by various perl6 executables.
utime LIST
No equivalent.
values HASH
values ARRAY
values EXPR
Available in Perl 6. Can also be used as a method. values %hash is equivalent to %hash.values.
vec EXPR, OFFSET, BITS
There is no support for vec() in Perl 6.
S29 says "Should replace vec with declared buffer/array of bit, uint2, uint4, etc." Support for bit, uint2, uint4 has not landed yet. But support for uint8, int8, uint16, int16, uint32, int32, uint64, int64 as well as the system sized uint and int have landed. In scalar forms, as well as in array and shaped array (aka matrix) forms.
wait
[NEEDS FURTHER RESEARCH] Unclear where this has gone. There's a wait method in Supply, and an await method in both Channel and Promise. Which, if any or all, of these is a direct equivalent of Perl 5's wait is unclear.
waitpid PID, FLAGS
As with wait, the disposition of this is unclear.
wantarray
There is no wantarray in Perl 6; however, there are very easy ways to cover many of the use cases which wantarray filled.
First, since Perl 6 does not need special reference syntax to contain a List or Array in a Scalar, simply returning a list may be all that is needed:
sub listofstuff { return 1, 2, 3; } my $a = listofstuff(); print $a; # prints "123" print join("<", listofstuff()) # prints "1<2<3"
One of the most common use cases is to provide either an array of lines or elements, or a prettier string than would be produced by simply printing the array. One can mix in a custom .Str method for this purpose:
sub prettylist(*@origlist) { @origlist but role { method Str { self.join("<") } } } print prettylist(1, 2, 3); # prints "1<2<3" print join(">", prettylist(3, 2, 1)); # prints "3>2>1"
In the above example, the returned list may be lazy, and the .Str method is not called until stringification happens, so no extra work is done to generate something which is not asked for.
Another use case is to create methods which are mutators when called in void context but produce copies during assignment. It is generally considered better form in Perl 6 not to do so, even more so because void context does not exist in Perl 6, with the closest equivalent being sink context, since users can quite easily turn any copy-producing method into a mutator using the .= operator:
my $a = "foo\n"; $a.ords.say; # says "(102 111 111 10)" $a .= chomp; $a.ords.say; # says "(102 111 111)"
However if you have your heart set on using the same function name for both operations, you can get most of the way there by mixing in a .sink method, which will be called when the result finds itself in sink context. There are some caveats however, so again, this is not advised:
multi sub increment($b is rw) { ($b + 1) does role { method sink { $b++ } } } multi sub increment($b) { $b + 1 } my $a = 1; increment($a); say $a; # says "2" my $b = increment($a); say $a, $b; # says "2 3" # ...users will just have to be aware that they should not accidentally # sink a stored value later, though this requires some effort to # actually do: sub identity($c is rw) { $c }; $a = 1; $b = increment($a); identity($b); $a.say; # says "2"
warn LIST
warn throws a resumable exception. To simply print a message to $*ERR, you would use the note function. For more on exceptions, see Exceptions.
write FILEHANDLE
write EXPR
write
Formats are gone from Perl 6, so this no longer works.
y///
This synonym for tr/// is gone. For functionality, see the entry for tr///.
Operators in Perl 5 to Perl 6: equivalencies and variations
A (hopefully) comprehensive list of Perl 5 operators with their Perl 6 equivalents with notes on variations between them where necessary.
This document does not explain the operators in detail. This document is an attempt to guide you from the operators in Perl 5's perlop document to their equivalents in Perl 6. For full documentation on the Perl 6 equivalents, please see the Perl 6 documentation.
The operator precedence table is somewhat different in Perl 6 than it is in Perl 5, so it will not be detailed here. If you need to know the precedence and associativity of a given operator in Perl 6, refer to Operator Precedence.
The things listed in Perl 5's perlop document as unary and list operators in this section tend to be things that can also be thought of as functions, such as print and chdir. As such, you can find information about them in the functions guide. Parentheses are still used for grouping. There is one caveat: in Perl 6, it's the , (comma) that creates lists, not parentheses. So:
my @foo = 1,2,3,4,5; # no parentheses needed .say for 1,2,3,4,5; # also no parentheses my $scalar = (1); # *not* a list, as there is no comma my $list = (1,); # a List in a scalar container
As you typically will not be using references in Perl 6, the arrow is probably less useful as a dereferencing operator. If you do need to dereference something, however, the arrow is the dot. It is also the dot for method calls. So, Perl 5's $arrayref->[7] becomes $arrayref.[7] in Perl 6 and, similarly, $user->name becomes $user.name. The => arrow is used for constructing Pairs, see Pair term documentation.
Work as in Perl 5. The one possible caveat is that they function by calling the succ method for ++ and the pred method for --. For builtin numeric types, this is unlikely to do something unusual, but custom types can define their own succ and pred methods, so in those cases, you should probably take note of what ++ and -- will actually do.
Works as you would expect. The caveat in Perl 5's perlop about ** binding more tightly than unary minus (i. e. "-2**4" evaluates as "-(2**4)" rather than "(-2)**4)") is also true for Perl 6.
As in Perl 5, unary ! and - do logical and arithmetic negation, respectively. ?^ is used for bitwise logical negation, which the documentation indicates is equivalent to !. It may be relevant to note that these coerce their arguments to Bool and Numeric, respectively.
Unary ~ is the string context operator in Perl 6, so use prefix +^ for bitwise integer negation. Assumes two's complement.
+ does have an effect in Perl 6, coercing its argument to the Numeric type.
Unary \ is no more. If you really want to take a "reference" to an existing named variable, you can use item context, like so: $aref = item(@array), or maybe more familiarly by prefixing with a $: $aref = $@array. Please note that you're not really getting a reference, but a scalar container with the referenced object in it.
You can get a "reference" to a named subroutine by using the & sigil: $sref = &foo. Anonymous arrays, hashes, and subs return the underlying object during creation right away: $sref = sub { }.
=~ and !~ have been replaced by ~~ and !~~, respectively. Those of you who consider smartmatching broken in Perl 5 will be happy to hear that it works much better in Perl 6, as the stronger typing means less guesswork. See the smartmatch documentation for a more extensive explanation of how smartmatch works in Perl 6.
Binary *, /, and % do multiplication, division, and modulo, respectively, as in Perl 5.
Binary x is slightly different in Perl 6, and has a companion. print '-' x 80; gives you a string of 80 dashes, but for the Perl 5 behavior of @ones = (1) x 80; giving you a list of 80 "1"s, you would use @ones = 1 xx 80;.
Binary + and - do addition and subtraction, respectively, as you would expect.
As . is the method call operator, so binary ~ acts as the concatenation operator in Perl 6.
<< and >> have been replaced by +< and +> .
As noted above, you'll find these in the functions guide.
These all work as in Perl 5.
== and != both work as in Perl 5.
<=> and cmp have different behavior in Perl 6. <=> does a numeric comparison, but returns Order::Less, Order::Same, or Order::More instead of Perl 5's -1, 0, or 1. To get the Perl 5 behavior (with the change that it returns the Order objects, rather than integers) of cmp, you would use the leg operator.
cmp does either <=> or leg, depending on the existing type of its arguments.
~~ is the smartmatch operator as in Perl 5, but it's also just the match operator in Perl 6, as noted above. For how smartmatching works in Perl 6, see the smartmatch documentation.
See the smartmatch documentation for a more extensive explanation of how smartmatch works in Perl 6.
Binary & is +& in Perl 6.
Bitwise OR has changed from | in Perl 5 to +| in Perl 6. Similarly, bitwise XOR ^ is +^, except this operates on integers.
Unchanged.
Unchanged.
Remains in Perl 6 as //. Returns the first defined operand, or else the last operand. Also, there is a low precedence version, called orelse.
In list context, .. operates as the range operator and should not need to be changed. That said, there are exclusionary range operators that may be useful. These are:
infix ..^ which excludes the endpoint;
infix ^.. which excludes the starting point;
infix ^..^ which excludes both the starting and ending points;
prefix ^ which starts from zero excluding the endpoint.
The following example shows the effects of all the above range operators (please note parentheses are used only to allow the method call):
(1..^5).list; # (1 2 3 4) (1^..5).list; # (2 3 4 5) (1^..^5).list; # (2 3 4) (^5).list; # (0 1 2 3 4)
In Perl 5, in scalar context, the operators .. and ... work as flip-flop operators, even if they are little-known and probably less used. Those operators have been replaced in Perl 6 by ff and fff respectively.
The conditional operator ? : has been replaced by ?? !!:
$x = $ok ? $yes : $no; # Perl 5
$x = $ok ?? $yes !! $no; # Perl 6
Although not fully documented, S03 indicates that the mathematical and logical assignment operators should work as you would expect. The one noticeable change is that .= calls a mutating method on the object on the left (which can also be a type-object). This allows for the following useful idiom:
class LongClassName { has $.frobnicate; } my LongClassName $bar .= new( frobnicate => 42 ); # no need to repeat class name
This ensures that $bar will only be able to contain a LongClassName object, as well not having to repeat (and possibly misspell) the class name.
~= is the string concatenation assignment, as you might expect with the changes in . and ~. Also, the bitwise assignment operators are likely not separated into numeric and string versions (&=, etc., vs. &.=, etc.), as that feature is currently experimental in Perl 5 itself - although, again, this is not specifically documented.
The comma operator works mostly as expected, but technically it creates Lists) or separates arguments in function calls. Also, there is a : variant that turns function calls into method calls - see this page.
The => operator, or fat arrow, works similarly to the Perl 5 "fat comma" in that it allows an unquoted (ordinary) identifier on its left side, but in Perl 6 constructs Pair objects, rather than just functioning as a separator. If you are trying to just literally translate a line of Perl 5 code to Perl 6, it should behave as expected.
Like the Named Unary Operators, you'll find these discussed under Functions.
The lower precedence version of !. As with !, coerces its argument to Bool.
Lower precedence version of && as in Perl 5.
or is the low precedence version of ||, and xor is the low precedence version of ^^.
Additionally, there is a low precedence version of //, called orelse.
For all the gory details on quoting constructs, see quoting.
There is a quoting operator that allows absolute literal strings: Q or 「…」, although the latter might be difficult to find on your keyboard, depending on your keyboard... Backslash escapes do not apply in Q quoted strings. E. g. Q{This is still a closing curly brace → \} renders "This is still a closing curly brace → \".
q does what you expect, allowing backslash escapes. E. g. q{This is not a closing curly brace → \}, but this is → } returning "This is not a closing curly brace → }, but this is →". As in Perl 5, you can get this behavior with single quotes.
qq allows interpolation of variables. However, by default, only scalar variables are interpolated. To get other variables to interpolate, you need to put square brackets after them (the so-called zen-slice) to get them to interpolate. E.g. @a = <1 2 3>; say qq/@a[] example@example.com/; results in "1 2 3 example@example.com". Hashes interpolate in the same manner: %a = 1 => 2, 3 => 4;say "%a{}"; results in a space separating the pairs and tabs separating the key from the value in each pair (because that's the standard stringification of Pairs, and a hash acts as list of Pairs when stringified). You can also interpolate Perl 6 code in strings using curly braces. For all the details, see Interpolation.
qw works as in Perl 5, and can also be rendered as <...> . E. g. qw/a b c/ is equivalent to <a b c> .
There is also a version of qw that interpolates, which is qqw. So my $a = 42;say qqw/$a b c/; gives you "42 b c".
Shell quoting is available through qx, but you should note that backticks do not do shell quoting as in Perl 5, and Perl variables are not interpolated in qx strings. If you need to interpolate Perl variables in a shell command string, you can use qqx instead.
The qr operator is gone from Perl 6.
tr/// works similarly to how it does in Perl 5. The one caveat is that ranges are specified differently. Instead of using a range "a-z", you would use "a..z", i. e. with Perl's range operator. tr/// has a method version, which is better documented, called .trans. .trans uses a list of pairs, as follows: $x.trans(['a'..'c'] => ['A'..'C'], ['d'..'q'] => ['D'..'Q'], ['r'..'z'] => ['R'..'Z']); A much more extensive description of the uses of .trans can be found at https://design.perl6.org/S05.html#Transliteration. The y/// equivalent has been done away with.
Heredocs are specified differently in Perl 6. You use :to with your quoting operator, e. g. q:to/END/; would start a heredoc ending with "END". Similarly, you get escaping and interpolation based on your quoting operator, i. e. literals with Q, backslash escapes with q, and interpolation with qq.
The full details on Input/Output in Perl 6 can be found at io.
As <...> is the quote-words construct in Perl 6, <> is not used for reading lines from a file. You can do that by either making an IO object from a file name or using an open filehandle and then, in either case, calling .lines on it. I. e. either my @a = "filename".IO.lines; or my $fh = open "filename", :r;my @a = $fh.lines; (In the latter case, we are using :r to specifically open the file for reading). To do this in an iterative manner, you can use a for loop this way:
for 'huge-csv'.IO.lines -> $line { # Do something with $line }
Note the use of -> there. That's part of the Block syntax, and in Perl 6 is needed for if, for, while, etc.
If you want to slurp the entire file into a scalar, you would - surprise! - use the .slurp method. For instance
my $x = "filename".IO.slurp; # ... or ... my $fh = open "filename", :r; my $x = $fh.slurp;
As noted in the Special Variables guide, the ARGV magic input filehandle has been replaced by $*ARGFILES, and the @ARGV array of command line arguments has been replaced by @*ARGS.
1 while foo(); works in the same way as it does in Perl 5, however it generates a warning. In Perl 6 the idiom is now written as Nil while foo(); instead.
Documented individually above, but to summarize...
Bitwise integer negation is prefix +^. Bitwise boolean negation is ?^.
Bitwise and is +&.
Bitwise integer or is +|. Bitwise integer xor is infix +^. Bitwise boolean or is ?|.
Left shift and right shift are +< and +> .
Syntactic differences between Perl 5 and Perl 6
perlsyn - Perl syntax
A (hopefully) comprehensive description of the differences between Perl 5 and Perl 6 with regards to the syntax elements described in the perlsyn document.
I will not be explaining Perl 6 syntax in detail. This document is an attempt to guide you from how things work in Perl 5 to the equivalents in Perl 6. For full documentation on the Perl 6 syntax, please see the Perl 6 documentation.
Perl 6 is still largely free form. However, there are a few instances where the presence or lack of whitespace is now significant. For instance, in Perl 5, you can omit a space following a keyword (e. g. while($x < 5) or my($x, $y)). In Perl 6, that space is required, thus while ($x < 5) or my ($x, $y). In Perl 6, however, you can omit the parentheses altogether: while $x < 5 . This holds for if, for, etc.
Oddly, in Perl 5, you can leave spaces between an array or hash and its subscript, and before a postfix operator. So $seen {$_} ++ is valid. No more. That would now have to be %seen{$_}++.
If it makes you feel better, you can use backslashes to "unspace" whitespace, so you can use whitespace where it would otherwise be forbidden.
See Whitespace for details.
As noted in the Functions guide, there is no undef in Perl 6. A declared, but uninitialized scalar variable will evaluate to its type. In other words, my $x;say $x; will give you "(Any)". my Int $y;say $y; will give you "(Int)".
# starts a comment that runs to the end of the line as in Perl 5.
Embedded comments start with a hash character and a backtick (#`), followed by an opening bracketing character, and continue to the matching closing bracketing character. Like so:
if #`( why would I ever write an inline comment here? ) True { say "something stupid"; }
As in Perl 5, you can use pod directives to create multiline comments, with =begin comment before and =end comment after the comment.
The one difference between Perl 5 truth and Perl 6 truth is that, unlike Perl 5, Perl 6 treats the string "0" as true. Numeric 0 is still false, and you can use prefix + to coerce string "0" to numeric to get it to be false. Perl 6, additionally has an actual Boolean type, so, in many cases, True and False may be available to you without having to worry about what values count as true and false.
Mostly, statement modifiers still work, with a few exceptions.
First, for loops are exclusively what were known in Perl 5 as foreach loops and for is not used for C-style for loops in Perl 6. To get that behavior, you want loop. loop cannot be used as a statement modifier.
In Perl 6, you cannot use the form do {...} while $x. You will want to replace do in that form with repeat. Similarly for do {...} until $x.
The big change from Perl 5 is that given is not experimental or disabled by default in Perl 6. For the details on given see this page.
next, last, and redo have not changed from Perl 5 to Perl 6.
continue, however, does not exist in Perl 6. You would use a NEXT block in the body of the loop.
# Perl 5 my $str = ''; for (1..5) { next if $_ % 2 == 1; $str .= $_; } continue { $str .= ':' }
# Perl 6 my $str = ''; for 1..5 { next if $_ % 2 == 1; $str ~= $_; NEXT { $str ~= ':' } }
As noted above, C-style for loops are not called for loops in Perl 6. They are just loop loops. To write an infinite loop, you do not need to use the C idiom of loop (;;) {...}, but may just omit the spec completely: loop {...}
In Perl 5, for, in addition to being used for C-style for loops, is a synonym for foreach. In Perl 6, for is just used for foreach style loops.
Perl 6 has actual switch statements, provided by given with the individual cases handled by when and default. The basic syntax is:
given EXPR { when EXPR { ... } when EXPR { ... } default { ... } }
The full details can be found here.
goto is currently not implemented (yet). Labels are implemented, and can be used as a target for next, last and redo:
FOO: # Labels end with colons, like in Perl 5 for ^10 { say "outer for before"; for ^10 { say "inner for"; last FOO; } say "outer for after"; # Will not show because of the "last" } # outer for before # inner for
For what is planned for goto, see https://design.perl6.org/S04.html#The_goto_statement.
... (along with !!! and ???) are used to create stub declarations. This is a bit more complicated than the use of ... in Perl 5, so you'll probably want to look at https://design.perl6.org/S06.html#Stub_declarations for the gory details. That said, there doesn't seem to be an obvious reason why it shouldn't still fulfill the role it did in Perl 5, despite its role being expanded in Perl 6.
Pod has changed between Perl 5 and Perl 6. Probably the biggest difference is that you need to enclose your pod between =begin pod and =end pod directives. There are a few tweaks here and there as well. For instance, as I have discovered while writing these documents, the vertical bar ("|") is significant in X<> codes, and it's not clear how to get a literal "|" into them. Your best bet may be to use the Perl 6 interpreter to check your pod. You can do this by using the --doc switch. E. g. perl6 --doc Whatever.pod. This will output any problems to standard error. (Depending on how/where you've installed perl6, you may need to specify the location of Pod::To::Text.) Details on Perl 6 style pod is at https://design.perl6.org/S26.html.
A comparison of special variables in Perl 5 and Perl 6
A (hopefully) comprehensive list of Perl 5 Special Variables with their Perl 6 equivalents with notes on variations between them where necessary.
This document is an attempt to guide the reader from the Special Variables in Perl 5 to their equivalents in Perl 6. For full documentation on the Perl 6 Special Variables, please see the Perl 6 documentation for each of them.
Thankfully, $_ is the general default variable as in Perl 5. The main difference in Perl 6 is that you can now call methods on it. For instance, Perl 5's say $_ can be rendered in Perl 6 as $_.say. Furthermore, as it is the default variable, you don't even need to use the variable name. The previous example can also be achieved by using .say.
As Perl 6 now has function signatures, your arguments can go there, rather than depending on @_ for them. In fact, if you use a function signature, use of @_ will spit at you telling it cannot override an existing signature.
If, however, you do not use a function signature, @_ will contain the arguments you pass to the function as it did in Perl 5. Again, as with $_, you can call methods on it. Unlike $_ you cannot assume @_ as the default variable for those methods to operate on (i. e. @_.shift works, .shift does not).
Currently, there is no equivalent of the List Separator variable in Perl 6. Design document S28 says there isn't one, so you probably don't want to hold your breath.
$$ is replaced in Perl 6 by $*PID
You can access the program name in Perl 6 via $*PROGRAM-NAME.
Note: $0 in Perl 6 is the variable holding the first captured value from a regexp match (i. e. capture variables now start from $0 rather than $1).
In Perl 6 the group information is handled by $*GROUP, which holds an object of type IntStr and therefore can be used either within a string or a numeric context. The group id is therefore obtained via +$*GROUP, while the group name via ~$*GROUP.
The effective group id does not appear to be currently provided by Perl 6.
In Perl 6 the user information is handled by $*USER, which holds an object of type IntStr and therefore can be used either within a string or a numeric context (this is similar to how the group information is handled by the $*GROUP object). The user id is therefore obtained via +$*USER, while the username via ~$*USER.
The effective user id does not appear to be currently provided by Perl 6.
The subscript separator variable is not included in Perl 6. Frankly, if your Perl 5 code is using this, it's almost certainly really, really old.
$a and $b have no special meaning in Perl 6. sort() does not use them for anything special. They're just regular old variables.
This feature has been extended by having blocks with placeholder parameters which are more versatile. Placeholder variables are created with the ^ twigil (e. g. $^z. They can be used in a bare block or in a subroutine without an explicit parameter list. The arguments to the block are assigned to the placeholder variables in their Unicode order. I. e. even if the variables appear in the block in the order ($^q, $^z, $^a), they will be assigned in the order ($^a, $^q, $^z). Ergo:
sort { $^a cmp $^z }, 1, 5, 6, 4, 2, 3; # OUTPUT: «(1 2 3 4 5 6)» sort { $^g cmp $^a }, 1, 5, 6, 4, 2, 3; # OUTPUT: «(6 5 4 3 2 1)» for 1..9 { say $^c, $^a, $^b; last } # OUTPUT: «312»
For more on placeholder variables, see this page
%ENV has been replaced by %*ENV in Perl 6. Note that the keys of this hash may not be exactly the same between Perl 5 and Perl 6. For example, OLDPWD is missing from Perl 6's %ENV.
The running version of Perl 6 is kept by $*PERL special variable, that is an object. The running version is retrieved via $*PERL.version, which returns something like v6.c; the full stringified version of the Perl interpreter is obtained via ~$*PERL, which returns something like Perl 6 (6.c).
Although the design documents (S28) indicate that this will likely become $*SYS_FD_MAX, this has not yet been implemented.
[NEEDS FURTHER RESEARCH] A bit confusing at this point. Design doc S28 indicates that @F in Perl 5 is replaced by @_ in Perl 6, but it's unclear just how that works. On the other hand, it's currently something of a moot point, as the Perl 5 to Perl 6 Translation doc indicates that the -a and -F command-line switches are not yet implemented in rakudo.
No longer exists in Perl 6. Please use "use lib" to manipulate the module repositories to be searched. The closest thing to @INC is really $*REPO. But that works completely differently from @INC mostly because of the precompilation capabilities of Perl 6.
# Print out a list of compunit repositories .say for $*REPO.repo-chain;
No longer exists in Perl 6. Because each Repository is responsible for remembering which modules have been loaded already. You can get a list of all loaded modules (compilation units) like so:
use Test; use MyModule; say flat $*REPO.repo-chain.map(*.loaded); #-> (MyModule Test)
S28 suggests $*INPLACE_EDIT, but it does not yet exist.
S28 suggests $*EMERGENCY_MEMORY, but it does not yet exist.
This is somewhat unclear. It probably depends on what you mean by "the name of the operating system" as design document S28 has three different suggestions, all of which give different answers.
There are currently three main objects containing information about the "running environment":
$*KERNEL provides information about the running Operating System kernel;
$*DISTRO provides information about the Operating System distribution;
$*VM provides information about the running backend machine for Perl 6.
All the above objects have methods in common:
version provides the version number for that component;
name provides the mnemonic name for that component;
auth provides the known author(s) for that component.
As a short example, the following piece of code prints information about all the above components:
for $*KERNEL, $*DISTRO, $*VM -> $what { say $what.^name; say 'version ' ~ $what.version ~ ' named ' ~ $what.name ~ ' by ' ~ $what.auth; } # Kernel # version 4.10.0.42.generic named linux by unknown # Distro # version 17.04.Zesty.Zapus named ubuntu by https://www.ubuntu.com/ # VM # version 2017.11 named moar by The MoarVM Team
The Str method on all of the above produces the short version of the information, at the current time the name.
All the objects have other methods that can be useful when trying to identify the exact running instance, for more information use <.^methods> to introspect all the above.
No equivalent variable. To have your code executed on the reception of a signal, you can call the signal subroutine, which returns a Supply that can be tapped.
$SIG{"INT"} = sub { say "bye"; exit }
signal(SIGINT).tap: { say "bye"; exit }; loop {}
Or, if you have a generic code that want to know which signal it got:
signal(SIGINT).tap: -> $signal { say "bye with $signal"; exit }; loop {}
A more idiomatic way of using signals in an event driven situation:
react { whenever signal(SIGINT) { say "goodbye"; done } }
Replaced in Perl 6 by $*INIT-INSTANT. Unlike in Perl 5, this is not in seconds since epoch, but an Instant object, which is measured in atomic seconds, with fractions.
As with $] this has been replaced with $*PERL.version.
There is no analog to this in Perl 6.
This has been replaced by $*EXECUTABLE-NAME. Note that there is also $*EXECUTABLE, which is an IO object in Perl 6.
As shown below, $`, $&, and $' are gone from Perl 6, primarily replaced by variations on $/ and, with their elimination, the associated performance issues in Perl 5 do not apply.
These existing variables do the same thing in Perl 6 as they do in Perl 5, except that they now start at $0 rather than $1. Furthermore, they are synonyms for indexed items in the match variable $/. I. e. $0 is equivalent to $/[0], $1 is equivalent to $/[1], etc.
$/ now contains the match object, so the Perl 5 behavior of $& can be obtained by stringifying it, i. e. ~$/.
Please note that while $/.Str should also work, ~$/ is currently the more common idiom.
Since the former performance issues are done away with, this variable is not of use in Perl 6.
Replaced by $/.prematch.
Since the former performance issues are done away with, this variable is not of use in Perl 6.
Replaced by $/.postmatch.
Since the former performance issues are done away with, this variable is not of use in Perl 6.
Does not exist in Perl 6, but you can get the same information using $/[*- 1].Str ($/[*-1] would be the match object, not the actual string).
If you want to understand why that works, you can look at these documents:
...and possibly
...though the design documents are not always up to date.
S28 suggests $*MOST_RECENT_CAPTURED_MATCH, but there does not seem to be any implemented variable that matches $^N.
As with most regular expression related variables, this functionality is, at least in part, moved to the $/ variable in Perl 6. Or, in this case, the numbered variables that alias to the indexes of it. The offset is found by using the .to method. I. e. the first offset is $/[0].to, which is synonymous with $0.to. The value Perl 5 provides as $+[0] is provided by $/.to.
Once again, we move over to $/. The former $+{$match} is $/{$match}.
Similarly to @+ being replaced by using the .to method, @- is replaced by using the .from method on $/ and its variations. The first offset is $/[0].from or the equivalent $0.from. Perl 5's $- [0] is $/.from.
Much like %+, a use of %-{$match} would be replaced with $/{$match}.
No equivalent.
No equivalent.
No equivalent.
The name of the current file when reading lines can be obtained through $*ARGFILES.path.
@*ARGS contains the command line arguments.
This has been replaced by $*ARGFILES.
As the -i command line switch has not yet been implemented, there is not yet an equivalent of ARGVOUT.
Currently no obvious equivalent.
No direct replacement exists.
When iterating using lines method from IO::Path or IO::Handle types, you can call the .kv method on it to get an interleaved list of indexes and values (then iterate by 2 each loop):
for "foo".IO.lines.kv -> $n, $line { say "{$n + 1}: $line" } # OUTPUT: # 1: a # 2: b # 3: c # 4: d
For IO::CatHandle types (of which $*ARGFILES is one), you can use on-switch hook to reset line number on handle switch, and increment it manually. See also IO::CatHandle::AutoLines and LN modules that simplify this operation.
This is accessed through the .nl-in method on the filehandle. E. g. $*IN.nl-in.
This is accessed through the .nl-out method on the filehandle. E. g. $*OUT.nl-out.
No global alternative available. TTY handles are unbuffered by default, for others, set out-buffer to zero or use :!out-buffer with open on a specific IO::Handle.
Not implemented in Perl 6.
There are no built-in formats in Perl 6.
Because of how error variables have changed in Perl 6, they will not be detailed here individually.
To quote the Perl 6 docs, "$! is the error variable." That's it. All the error variables appear to have been eaten by $!. As with the rest of Perl 6, it's an object that will return various things depending on the type of error or exception.
In particular, when dealing with exceptions the $! provides information about the thrown exception, assuming the program has not halted:
try { fail "Boooh"; CATCH { # within the catch block # the exception is placed into $_ say 'within the catch:'; say $_.^name ~ ' : ' ~ $_.message; $_.resume; # do not abort } } # outside the catch block the exception is placed # into $! say 'outside the catch:'; say $!.^name ~ ' : ' ~ $!.message;
and the above code produces the following output
within the catch: X::AdHoc : Boooh outside the catch: X::AdHoc : Boooh
therefore, as stated before, the $! variable holds the exception object.
Currently no equivalents for either of these variables.
There may or may not be equivalents of these in Perl 6, but they're internal and you shouldn't be messing with them in the first place - certainly not if your understanding of Perl 6 requires you to read this document...
The chance of the Perl 6 debugger resembling the Perl 5 debugger is slim at best, and at this point there does not seem to be an equivalent of this variable.
S28 claims this variable is "pending". Not currently in Perl 6.
These Unicode-related variables do not appear to exist in Perl 6, but - maybe? - could have analogs in $?ENC somewhere. This, however, is totally unconfirmed.
Learning Perl 6 from Haskell, in a nutshell: what do I already know?
Haskell and Perl 6 are very different languages. This is obvious. However, that does not mean there are not similarities or shared ideas! This page attempts to get a Haskell user up and running with Perl 6. The Haskell user may find that they need not abandon all of their Haskelly thoughts while scripting in Perl 6.
Note that this should not be mistaken for a beginner tutorial or overview of Perl 6; it is intended as a technical reference for Perl 6 learners with a strong Haskell background.
In Haskell, you have type level programming and then value level programming.
plusTwo :: Integer -> Integer -- Types plusTwo x = x + 2 -- Values
You do not mix types and values in Haskell like the below
plusTwo 2 -- This is valid plusTwo Integer -- This is not valid
In Perl 6, types (AKA type objects) live on the same level as values
sub plus-two(Int $x --> Int) { $x + 2 } plus-two(2); # This is valid plus-two(Int); # This is valid
I will illustrate this unique aspect of Perl 6 with one more example:
multi sub is-string(Str $ --> True) {} multi sub is-string(Any $ --> False) {} is-string('hello'); #True is-string(4); #False
In Haskell, you have a Maybe type that allows you to forgo the worry of null types. Let's say you have a hypothetical function that parses a String to an Integer:
parseInt :: String -> Maybe Integer case parseInt myString of Just x -> x Nothing -> 0
In Perl 6, since type objects coexist with regular objects, we have the concept of Defined and Undefined objects. Plain type objects are undefined while instantiated objects are defined.
sub parse-int(Str $s --> Int) { ... } my $string = {...}; given parse-int($string) { when Int:D { $_ } when Int:U { 0 } }
So in Perl 6 we have type constraints that indicate the definedness of a type. These are
Int:D; # This is a defined Int. Int:U; # This is an undefined Int, AKA a type object Int:_; # This is either defined or undefined.
If we wanted to be explicit in the above example (probably a good idea), we could add the :_ constraint on the return type. This would let the user know that they should account for both defined and undefined return values. We could also use other methods and constructs that specifically test for definedness.
sub parse-int(Str $s --> Int:_) { ... } # One way to do it my $string = {...}; given parse-int($string) { when Int:D { $_ } when Int:U { 0 } } # Another way to do it my Int $number = parse-int($string); if $number.defined { $number } else { 0 } # A better way with parse-int($string) { $_ } else { 0 } # With the defined-or operator parse-int($string) // 0
The with operator that you see above is like if, except it explicitly tests for definedness and then passes the result to the following block. Similarly, without tests that the object is undefined and also passes the result to the following block.
For more natural control flow with undefined and defined types, Perl 6 introduces andthen and orelse.
sub parse-int(Str $s --> Int:_) { ... } my $string = {...}; my $result = parse-int($string) orelse 0; sub hello() { say 'hi' } hello() andthen say 'bye';TODO: include a better example for andthen that makes sense. Maybe using promise objects?
So in practice, Perl 6 does not have the concept of a null type, but rather of defined or undefined types.
Perl 6 is fundamentally an object oriented language. However, it also gives you the freedom to write in virtually any paradigm you wish. If you only want to pure functions that take an object and return a new object, you can certainly do so.
Here is a Haskell code example:
data Point = Point x y moveUp :: Point -> Point moveUp (Point x y) = Point x (y + 1)
And an equivalent Perl 6 example:
class Point { has $.x; has $.y; } sub move-up(Point $p --> Point) { Point.new(x => $p.x, y => $p.y + 1) }
The code I illustrated above is an example of a Product Type. If instead you'd like to write a Sum Type, there is not an exact equivalent in Perl 6. The closest thing would be an Enum.
data Animal = Dog | Cat | Bird | Horse testAnimal :: Animal -> String testAnimal Dog = "Woof" testAnimal Horse = "Neigh"
Although it does not fit the same exact use cases, it can be used in putting constraints on types.
enum Animal < Dog Cat Bird Horse >; proto sub test-animal( Animal ) {*} multi sub test-animal( Dog ) { 'Woof' } multi sub test-animal( Animal::Horse ) { 'Neigh' } # more explicit say test-animal Animal::Dog; # more explicit say test-animal Horse;
In Haskell, you can alias an existing type to simply increase clarity of intent and re-use existing types.
type Name = String fullName :: Name -> Name -> Name fullName first last = first ++ last
The equivalent in Perl 6 is the following.
my constant Name = Str; sub full-name ( Name \first, Name \last --> Name ) { first ~ last }
It should be noted that in Perl 6, one can also create a subset of an existing type.
subset Name of Str where *.chars < 20; sub full-name(Name $first, Name $last) { $first ~ $last } full-name("12345678901234567890111", "Smith") # This does not compile, as the first parameter # doesn't fit the Name type
TODO
explain how Perl 6 roles compare to Haskell typeclassesMatching
Haskell makes heavy use of pattern matching in function definitions.
greeting :: String -> String greeting "" = "Hello, World!" greeting "bub" = "Hey bub." greeting name = "Hello, " ++ name ++ "!"
Perl 6 does this as well! You just use the multi keyword to signify that it is a multiple dispatch function.
proto greeting ( Str --> Str ) {*} multi greeting ( "" --> "Hello, World!" ) {} multi greeting ( "bub" --> "Hey bub." ) {} multi greeting ( \name ) { "Hello, " ~ name ~ "!" }
The proto declarator is not necessary, but can sometimes aid in making sure that all multis follow your business rules. Using a variable name in the signature of the proto would provide more information in error messages, and for introspection.
proto greeting ( Str \name --> Str ) {*} say &greeting.signature; # (Str \name --> Str)
An interesting thing to note in the Perl 6 code above is that passing values like 'bub' as a function parameter is just syntax sugar for a where guard.
Using the example from the "Pattern Matching" section of this page, you can see the guards that are used behind the scenes to constrain our function arguments.
multi greeting ( "" --> "Hello, World!" ) {} multi greeting ( "bub" --> "Hey bub." ) {} # The above is the same as the below multi greeting(Str \name where '' ) {'Hello, World!'} multi greeting(Str \name where 'bub' ) {'Hey bub.'} # The above is the same as the below, again. multi greeting(Str \name where $_ ~~ '' ) {'Hello, World!'} multi greeting(Str \name where $_ ~~ 'bub') {'Hey bub.'}
$_ is known as the topic variable. It assumes the form of whatever is appropriate. The smartmatch operator ~~ figures out the best way to determine if the left matches the right, be it number ranges, strings, etc. Our three examples above go from most sugared (top), to least sugared (bottom).
The bottom examples above could be wrapped in curly braces, making it more obvious that it is a code block. Note that a where clause may also take an explicit Callable.
multi greeting(Str \name where { $_ ~~ '' } ) {'Hello, World!'} multi greeting(Str \name where -> $thing { $thing ~~ '' } ) {'Hello, World!'} multi greeting ( Str \name where { Bool.pick } --> 'True' ){} multi greeting ( Str \name where &some-subroutine ){…}
If you read the section in this page on subsets, you'll notice that "where" is used in the making of subsets as well as here. The usage of "where" in both areas is exactly the same.
When using where, note that the order of definition is important, just like in Haskell.
multi greeting ( Str \name where '' --> 'Hello, World!' ){} multi greeting ( Str \name where { Bool.pick } --> 'True' ){} multi greeting ( Str \name where 'bub' --> 'Hey, bub.' ){} say greeting '' ; # will never say True say greeting 'bub'; # about 50% of the time it will say True
Deconstruction
TODO
TODO
.assuming vs currying
method chaining vs currying
TODO
show function composition operator. Maybe explain a more perl6ish way to do this though.
Haskell makes heavy use of case matching like the below:
case number of 2 -> "two" 4 -> "four" 8 -> "eight" _ -> "don't care"
In Perl 6 you can achieve this same thing with the given/when structure:
my $number = {...}; given $number { when 2 { "two" } when 4 { "four" } when 8 { "eight" } default { "don't care" } }
Note that the order of the when's is also significant, just like with the where's in the guard section of this page.
TODO
explain difference between perl6 Array, Sequence, List. Explain data shapes in regards to the @ sigil. Explain how you can convert an Array to a flattened list of objects with |@
data shapes become quite intuitive, but it takes a bit of practice.
There are no explicit list comprehensions in Perl6. But rather, you can achieve list comprehensions a couple of different ways.
Here is a trivial example in Haskell:
evens = [ x | x <- [0..100], even x ]
And now in Perl6 :
# using `if` and `for` my @evens = ($_ if $_ %% 2 for 0..100); # using gather/take to build a Seq my $evens = gather for 0..100 { take $_ if $_ %% 2 }; # using gather/take to build an Array my @evens = gather for 0..100 { take $_ if $_ %% 2 };
Since for is always eager it is generally better to use map or grep which will inherit the laziness or eagerness of its list argument.
my @evens = map { $_ if $_ %% 2 }, 0..100; my @evens = grep { $_ %% 2 }, 0..100; # using a Whatever lambda my @evens = grep * %% 2, 0..100;
Here is the creation of tuples in Haskell:
tuples = [(i,j) | i <- [1,2], j <- [1..4] ] -- [(1,1),(1,2),(1,3),(1,4),(2,1),(2,2),(2,3),(2,4)]
And in Perl6:
my @tuples = 1,2 X 1..4; # [(1,1), (1,2), (1,3), (1,4), (2,1), (2,2), (2,3), (2,4)]
See this design document for more information on what kinds of list comprehensions are possible in Perl6: https://design.perl6.org/S04.html#The_do-once_loop.
As you can see, when you get into some more advanced Haskell list comprehensions, Perl6 does not translate exactly the same, but it's possible to do the same things, nonetheless.
Fold in Haskell is called Reduce in Perl 6.
mySum = foldl `+` 0 numList
my @numbers = {...}; reduce { $^a + $^b }, 0, |@numbers; @numbers.reduce({$^a + $^b}, with => 0)
However, in Perl 6, if you want to use an infix operator (+ - / % etc) there is a nice little helper called the Reduction metaoperator.
my @numbers = {...}; [+] @numbers # This is the same [+] 0, @numbers # as this
It inserts the operator in between all values in the list and produces a result, just like Fold.
In Haskell you, you have foldl and foldr. In Perl 6, this difference is determined by the associativity attached to the operator/subroutine.
sub two-elem-list ( \a, \b ) { ( a, b ) } # you can use a subroutine as an infix operator say 'a' [&two-elem-list] 'b'; # (a b) # as the reduction prefix metaoperator takes an infix operator, it will work there too; [[&two-elem-list]] 1..5; # ((((1 2) 3) 4) 5) say (1..5).reduce: &two-elem-list; # ((((1 2) 3) 4) 5) # right associative sub right-two-elem-list( \a, \b ) is assoc<right> { ( a, b ) } say (1..5).reduce: &right-two-elem-list; # (1 (2 (3 (4 5)))) # XXX there is possibly a bug here as this currently doesn't look at # XXX the associativity of &right-two-elem-list and just always does left assoc say [[&right-two-elem-list]] 1..5; # chaining say [<] 1..5; # True say (1..5).reduce: &[<]; # True
TODO
Haskell and Perl 6 both allow you to specify ranges of values.
myRange1 = 10..100 myRange2 = 1.. -- Infinite myRange3 = 'a'..'h' -- Letters work too
my $range1 = 10..100; my $range2 = 1..*; # Infinite my $range3 = 'a'..'h'; # Letters work too
In the examples above, you have the concept of laziness displayed very plainly. Perl 6 has laziness only where it makes the most sense. For example, in the range 10..100, this is eager because it has a definite end. If a list does not have a definite end, then the list should clearly be lazy.
(1 .. 100).is-lazy; # False (1 .. Inf).is-lazy; # True
These are the "sane defaults" that Perl 6 takes pride in. But they are still defaults and can be changed into one or the other.
(1 .. 100).lazy.is-lazy; # True (1 .. 100).lazy.eager.is-lazy; # False
TODO
explain how given/when and with/without and for loops open lexical scopes with the argument as the context.
compare it to let/in and where constructs maybe?
TODO
### Guidelines for contributions:
Headers should contain the text that a Haskell user might search for, since those headings will be in the Table of Contents generated for the top of the document.
We use POD =item instead of =head3 or =head4 for identical bits that need not appear in the table of contents.
This article does not describe in detail language features that Haskell doesn't have at all, instead referring to other documents.
Example code and links to other documents should be favored over long explanations of details better found elsewhere.
Finally, if a real user asks a Haskell to Perl 6 question that is not being answered here, please add it to the document. Even if we do not have a good answer yet, that will be better than losing the information about a real need.
Learning Perl 6 from Node.js, in a nutshell
This page attempts to provide a way for users experienced in Node.js to learn Perl 6. Features shared between the two languages will be explained here, as well as major differences in syntax and features.
This is not a tutorial for learning Perl 6; this is a reference for users who are already at an intermediate to advanced skill level with Node.js.
Let's start with the typical first program when learning new languages. In Node.js, a hello world program would be written like this:
console.log('Hello, world!');
Here are a couple ways to write this in the same way in Perl 6:
say('Hello, world!'); say 'Hello, world!';
Parentheses are optional for function calls in Perl 6. While semicolons are, for the most part, optional in Node.js, they are mandatory for expressions in Perl 6.
Now that we've greeted the world, let's greet our good friend, Joe. We'll start with Node.js again:
let name = 'Joe'; console.log('What\'s up,' + name + '?'); console.log(`What's up, ${name}?`); console.log("What's up, ", name, "?");
Since he didn't hear us, let's greet him again, this time in Perl 6:
my $name = 'Joe'; say 'What\'s up, ' ~ $name ~ '?'; say "What's up, $name?"; say "What's up, ", $name, "?";
Here, there are only a couple differences: most variables in Perl 6 have what are called sigils, which are what the $ in front of its name is, and string concatenation uses the ~ operator instead of +. What the two languages share in common here is support for string interpolation.
Now that the basic examples are out of the way, let's explain the similarities between the two languages in greater detail.
Variables in Node.js can be defined like this;
var foo = 1; // Lexically scoped with functions and modules let foo = 1; // Lexically scoped with blocks const foo = 1; // Lexically scoped with blocks; constant // No equivalent to Perl 6 dynamic variables exists. global.foo = 1; // Globally scoped foo = 1; // Ditto, but implicit; forbidden in strict mode
In Perl 6 there is no equivalent to var. An important note to make is that there is no variable hoisting in Perl 6; variables are defined and assigned at the line they're on, not defined at the top of its scope and later assigned at that line.
In addition to regular variables, in Perl 6 there are what is known as dynamic variables. Dynamic variables are looked up using the caller's scope, rather than the outer scope. This is what the equivalent variable declarations look like in Perl 6:
my $foo = 1; # Lexically scoped our $foo = 1; # Package scoped
my constant foo = 1; # Lexically scoped; constant
constant foo = 1; # Package scoped; constant
my $*foo = 1; # Dynamic variable; lexically scoped our $*foo = 1; # Dynamic variable; package scoped
GLOBAL::<$foo> := 1; # Globally scoped
Use my where you'd use let, our for variables you'd define in the outermost scope needed, and constant where you'd uses const.
You may have noticed the $ and $* symbols placed before variable names. These are known as sigils and twigils respectively, and define what container the variable has. Refer to the documentation on variables for more information on sigils, twigils, and containers.
Variables in Node.js can override others from outer scopes with the same name (though linters will usually complain about it depending on how they're configured):
let foo = 1; function logDupe() { let foo = 2; console.log(foo); } logDupe(2); // OUTPUT: 2 console.log(foo); // OUTPUT: 1
Perl 6 also allows this:
my $foo = 1; sub log-dupe { my $foo = 2; say $foo; } log-dupe; # OUTPUT: 2 say $foo; # OUTPUT: 1
The = operator works the same across both languages.
The := operator in Perl 6 binds a value to a variable. Binding a variable to another variable gives them the same value and container, meaning mutating attributes of one will mutate the other's as well. Bound variables cannot be reassigned with = or mutated with ++, --, etc. but they can be bound to another value again:
my %map; # This is a hash, roughly equivalent to a JS object or map my %unbound = %map; my %bound := %map; %map<foo> = 'bar'; say %unbound; # OUTPUT: {} say %bound; # OUTPUT: {foo => bar} %bound := %unbound; say %bound; # OUTPUT: {}
Node.js has two equality operators: == and ===.
== is the loose equality operator. When comparing operands with the same type, it will return true if both operands are equal. However, if the operands are different types, they are both cast to their primitives before being compared, meaning these will return true:
console.log(1 == 1); // OUTPUT: true console.log('1' == 1); // OUTPUT: true console.log([] == 0); // OUTPUT: true
Similarly, in Perl 6, both operands are cast to Numeric before comparison if they don't share the same type:
say 1 == 1; # OUTPUT: True say '1' == 1; # OUTPUT: True say [1,2,3] == 3; # OUTPUT: True, since the array has three elements
The inverse of == is !=.
Perl 6 has another operator similar to ==: eq. Instead of casting operands to Numeric if they're different types, eq will cast them to strings:
say '1' eq '1'; # OUTPUT: True say 1 eq '1'; # OUTPUT: True
The inverse of eq is ne or !eq.
=== is the strict equality operator. This returns true if both operands are the same value. When comparing objects, this will only return true if they are the exact same object:
console.log(1 === 1); // OUTPUT: true console.log('1' === 1); // OUTPUT: false console.log({} === {}); // OUTPUT: false let obj = {}; let obj2 = obj; console.log(obj === obj2); // OUTPUT: true;
In Perl 6, the operator behaves the same, with one exception: two objects that have the same value, but different containers, will return false:
say 1 === 1; # OUTPUT: «True» say '1' === 1; # OUTPUT: «False» say 'ayy lmao' === 'ayy lmao'; # OUTPUT: «True» say {} === {}; # OUTPUT: «False» my \hash = {}; my %hash = hash; say hash === %hash; # OUTPUT: False
In the last case it's the same object, but containers are different, which is why it returns False.
The inverse of === is !==.
This is where Perl 6's other equality operators are useful. If the values have different containers, the eqv operator can be used. This operator can be also be used to check for deep equality, which you would normally need to use a library for in Node.js:
say {a => 1} eqv {a => 1}; # OUTPUT: True my \hash = {}; my %hash := hash; say hash eqv %hash; # OUTPUT: True
In the case you need to check if two variables have the same container and value, use the =:= operator.
my @arr = [1,2,3]; my @arr2 := @arr; # Bound variables keep the container of the other variable say @arr =:= @arr2; # OUTPUT: True
Perl 6 has one last operator for comparing values, but it is not exactly an equality operator. This is ~~, the smartmatch operator. This has several uses: it can be used like instanceof in Node.js, to match a regex, and to check if a value is a key in a hash, bag, set, or map:
say 'ayy lmao' ~~ Str; # OUTPUT: True my %hash = a => 1; say 'a' ~~ %hash; # OUTPUT: True my $str = 'abc'; $str ~~ s/abc/def/; # Mutates $str, like foo.replace('abc', 'def') say $str; # OUTPUT: def
While we are talking about instanceof, the equivalent to the constructor property on Node.js objects in Perl 6 is the WHAT attribute:
console.log('foo'.constructor); // OUTPUT: String
say 'foo'.WHAT; # OUTPUT: Str
Node.js has +, -, /, *, %, and (in ES6) ** as numeric operators. When the operands are different types, similarly to the equality operators, are cast to their primitives before following through with the operation, making this possible:
console.log(1 + 2); // OUTPUT: 3 console.log([] + {}); // OUTPUT: [object Object] console.log({} + []); // OUTPUT: 0
In Perl 6, again, they are converted to a Numeric type, as before:
say 1 + 2; # OUTPUT: 3 say [] + {}; # OUTPUT: 0 say {} + [1,2,3]; # OUTPUT: 3
In addition, Perl 6 has div and %%. div behaves like int division in C, while %% checks if one number is cleanly divisible by another or not:
say 4 div 3; # OUTPUT: 1 say 4 %% 3; # OUTPUT: False say 6 %% 3; # OUTPUT: True
Node.js has &, |, ^, ~, <<, >>, >>>, and ~ for bitwise operators:
console.log(1 << 1); // OUTPUT: 2 console.log(1 >> 1); // OUTPUT: 0 console.log(1 >>> 1); // OUTPUT: 0 console.log(1 & 1); // OUTPUT: 1 console.log(0 | 1); // OUTPUT: 1 console.log(1 ^ 1); // OUTPUT: 0 console.log(~1); // OUTPUT: -2
In Perl 6, there is no equivalent to >>>. All bitwise operators are prefixed with +, however bitwise negation uses +^ instead of ~:
say 1 +< 1; # OUTPUT: 2 say 1 +> 1; # OUTPUT: 0 # No equivalent for >>> say 1 +& 1; # OUTPUT: 1 say 0 +| 1; # OUTPUT: 1 say 1 +^ 1; # OUTPUT: 0 say +^1; # OUTPUT: -2
Node.js does not allow operator overloading without having to use a Makefile or build Node.js with a custom version of V8. Perl 6 allows custom operators and operator overloading natively! Since all operators are subroutines, you can define your own like so:
multi sub infix:<||=>($a, $b) is equiv(&infix:<+=>) { $a || $b } my $foo = 0; $foo ||= 1; say $foo; # OUTPUT: 1
Operators can be defined as prefix, infix, or postfix. The is tighter, is equiv, and is looser traits optionally define the operator's precedence. In this case, ||= has the same precedence as +=.
Note how multi is used when declaring the operator subroutines. This allows multiple subroutines with the same name to be declared while also having different signatures. This will be explained in greater detail in the Functions section. For now, all we need to know is that it allows us to override any native operator we want:
# Using the `is default` trait here forces this subroutine to be chosen first, # so long as the signature of the subroutine matches. multi sub prefix:<++>($a) is default { $a - 1 } my $foo = 1; say ++$foo; # OUTPUT: 0
You should be familiar with how if/else looks in JavaScript:
let diceRoll = Math.ceil(Math.random() * 6) + Math.ceil(Math.random() * 6); if (diceRoll === 2) { console.log('Snake eyes!'); } else if (diceRoll === 16) { console.log('Boxcars!'); } else { console.log(`Rolled ${diceRoll}.`); }
In Perl 6, if/else works largely the same, with a few key differences. One, parentheses are not required. Two, else if is written as elsif. Three, the if clause may be written after a statement:
my Int $dice-roll = ceiling rand * 12 + ceiling rand * 12; if $dice-roll == 2 { say 'Snake eyes!'; } elsif $dice-roll == 16 { say 'Boxcars!'; } else { say "Rolled $dice-roll."; }
Alternatively, though less efficient, this could be written to use if after statements:
my Int $dice-roll = ceiling rand * 12 + ceiling rand * 12; say 'Snake eyes!' if $dice-roll == 2; say 'Boxcars!' if $dice-roll == 16; say "Rolled $dice-roll." if $dice-roll != 2 && $dice-roll != 16;
Perl 6 also has when, which is like if, but if the condition given is true, no code past the when block within the block it's in is executed:
{ when True { say 'In when block!'; # OUTPUT: In when block! } say 'This will never be output!'; }
Additionally, Perl 6 has with, orwith, and without, which are like if, else if, and else respectively, but instead of checking whether their condition is true, they check if it's defined.
Switch statements are a way of checking for equality between a given value and a list of values and run some code if one matches. case statements define each value to compare to. default, if included, acts as a fallback for when the given value matches no cases. After matching a case, break is typically used to prevent the code from the cases that follow the one matched from being executed, though rarely this is intentionally omitted.
const ranklist = [2, 3, 4, 5, 6, 7, 8, 9, 'Jack', 'Queen', 'King', 'Ace']; const ranks = Array.from(Array(3), () => ranklist[Math.floor(Math.random() * ranks.length)]); let score = 0; for (let rank of ranks) { switch (rank) { case 'Jack': case 'Queen': case 'King': score += 10; break; case 'Ace'; score += (score <= 11) ? 10 : 1; break; default: score += rank; break; } }
In Perl 6, given can be used like switch statements. There is no equivalent to break since when blocks are most commonly used like case statements. One major difference between switch and given is that a value passed to a switch statement will only match cases that are exactly equal to the value; given values are smartmatched (~~) against the when values.
my @ranklist = [2, 3, 4, 5, 6, 7, 8, 9, 'Jack', 'Queen', 'King', 'Ace']; my @ranks = @ranklist.pick: 3; my Int $score = 0; for @ranks -> $rank { # The when blocks implicitly return the last statement they contain. $score += do given $rank { when 'Jack' | 'Queen' | 'King' { 10 } when 'Ace' { $score <= 11 ?? 10 !! 1 } default { $_ } }; }
If there are multiple when blocks that match the value passed to given and you wish to run more than one of them, use proceed. succeed may be used to exit both the when block it's in and the given block, preventing any following statements from being executed:
given Int { when Int { say 'Int is Int'; proceed } when Numeric { say 'Int is Numeric'; proceed } when Any { say 'Int is Any'; succeed } when Mu { say 'Int is Mu' } # Won't output } # OUTPUT: # Int is Int # Int is Numeric # Int is Any
There are three different types of for loops in JavaScript:
// C-style for loops const letters = {}; for (let ord = 0x61; ord <= 0x7A; ord++) { let letter = String.fromCharCode(ord); letters[letter] = letter.toUpperCase(); } // for..in loops (typically used on objects) for (let letter in letters) { console.log(letters[letter]); } # OUTPUT: # A # B # C # etc. // for..of loops (typically used on arrays, maps, and sets) for (let letter of Object.values(letters)) { console.log(letter); } # OUTPUT: # A # B # C # etc.
Perl 6 for loops most closely resemble for..of loops, since they work on anything as long as it's iterable. C-style loops are possible to write using loop, but this is discouraged since they're better written as for loops using ranges. Like if statements, for may follow a statement, with the current iteration being accessible using the $_ variable (known as "it"). Methods on $_ may be called without specifying the variable:
my Str %letters{Str}; %letters{$_} = .uc for 'a'..'z'; .say for %letters.values; # OUTPUT: # A # B # C # etc.
while loops work identically between JavaScript and Perl 6. Perl 6 also has until loops, where instead of iterating until the given condition is false, they iterate until the condition is true.
do/while loops are known as repeat/while loops in Perl 6. Likewise with while, repeat/until loops also exist and loop until the given condition is false.
To write infinite loops in Perl 6, use loop rather than for or while.
In JavaScript, continue is used to skip to the next iteration in a loop, and break is used to exit a loop early:
let primes = new Set(); let i = 2; do { let isPrime = true; for (let prime of primes) { if (i % prime == 0) { isPrime = false; break; } } if (!isPrime) continue; primes.add(i); } while (++i < 20); console.log(primes); # OUTPUT: Set { 2, 3, 5, 7, 11, 13, 17, 19 }
In Perl 6, these are known as next and last respectively. There is also redo, which repeats the current iteration without evaluating the loop's condition again.
next/redo/last statements may be followed by a label defined before an outer loop to make the statement work on the loop the label refers to, rather than the loop the statement is in:
my %primes is SetHash; my Int $i = 2; OUTSIDE: repeat { next OUTSIDE if $i %% $_ for %primes.keys; %primes{$i}++; } while ++$i < 20; say %primes; # OUTPUT: SetHash(11 13 17 19 2 3 5 7)
do is not currently a feature in JavaScript, however a proposal has been made to add it to ECMAScript. do expressions evaluate a block and return the result:
constant VERSION = v2.0.0; constant VERSION_NUMBER = do { my @digits = VERSION.Str.comb(/\d+/); :16(sprintf "%02x%02x%04x", |@digits) }; say VERSION_NUMBER; # OUTPUT: 33554432
In JavaScript, types are created by making a class (or a constructor in ES5 and earlier). If you've used TypeScript, you can define a type as a subset of other types like so:
type ID = string | number;
In Perl 6, classes, roles, subsets, and enums are considered types. Creating classes and roles will be discussed in the OOP section of this article. Creating an ID subset can be done like so:
subset ID where Str | Int;
See the documentation on subset and Junction for more information.
TypeScript enums may have numbers or strings as their values. Defining the values is optional; by default, the value of the first key is 0, the next key, 1, the next, 2, etc. For example, here is an enum that defines directions for extended ASCII arrow symbols (perhaps for a TUI game):
enum Direction ( UP = '↑', DOWN = '↓', LEFT = '←', RIGHT = '→' );
Enums in Perl 6 may have any type as their keys' values. Enum keys (and optionally, values) can be defined by writing enum, followed by the name of the enum, then the list of keys (and optionally, values), which can be done using < >, « », or ( ). ( ) must be used if you want to define values for the enum's keys. Here is the Direction enum as written in Perl 6:
enum Direction ( UP => '↑', DOWN => '↓', LEFT => '←', RIGHT => '→' );
See the documentation on enum for more information.
In TypeScript, you can define the type of variables. Attempting to assign a value that doesn't match the type of the variable will make the transpiler error out. This is done like so:
enum Name (Phoebe, Daniel, Joe); let name: string = 'Phoebe'; name = Phoebe; # Causes tsc to error out let hobbies: [string] = ['origami', 'playing instruments', 'programming']; let todo: Map<string, boolean> = new Map([ ['clean the bathroom', false], ['walk the dog', true], ['wash the dishes', true] ]); let doJob: (job: string) => boolean = function (job: string): boolean { todo.set(job, true); return true; };
In Perl 6, variables can be typed by placing the type between the declarator (my, our, etc.) and the variable name. Assigning a value that doesn't match the variable's type will throw either a compile-time or runtime error, depending on how the value is evaluated:
enum Name <Phoebe Daniel Joe>; my Str $name = 'Phoebe'; $name = Phoebe; # Throws a compile-time error # The type here defines the type of the elements of the array. my Str @hobbies = ['origami', 'playing instruments', 'programming']; # The type between the declarator and variable defines the type of the values # of the hash. # The type in the curly braces defines the type of the keys of the hash. my Bool %todo{Str} = ( 'clean the bathroom' => False, 'walk the dog' => True, 'wash the dishes' => True ); # The type here defines the return value of the routine. my Bool &do-job = sub (Str $job --> Bool) { %todo{$job} = True; };
Here is a table of some JavaScript types and their equivalents in Perl 6:
JavaScript | Perl 6 |
---|---|
Object | Mu, Any, Hash |
Array | List, Array, Seq |
String | Str |
Number | Int, Num, Rat |
Boolean | Bool |
Map | Map, Hash |
Set | Set, SetHash |
Object is both a superclass of all types in JavaScript and a way to create a hash. In Perl 6, Mu is a superclass of all types, though usually you want to use Any instead, which is a subclass of Mu but also a superclass of nearly every type, with Junction being an exception. When using Object as a hash, Hash is what you want to use. One key difference between Object and Hash is that Object preserves the order of its keys; Hash does not by default.
There are three types equivalent to Array. Array is most similar to Array, since it acts as a mutable array. List is similar to Array, but is immutable. Seq is used to create lazy arrays.
String and Str are for the most part used identically.
There are several different types in Perl 6 equivalent to Number, but the three you'll most commonly see are Int, Num, and Rat. Int represents an integer. Num represents a floating-point number, making it the most similar to Number. Rat represents a fraction of two numbers, and is used when Num cannot provide precise enough values.
Boolean and Bool are for the most part used identically.
Map has both a mutable and an immutable equivalent in Perl 6. Map is the immutable one, and Hash is the mutable one. Don't get them mixed up! Like Map in JavaScript, Map and Hash can have any type of key or value, not just strings for keys.
Like Map, Set also has both a mutable and an immutable equivalent in Perl 6. Set is the immutable one, and SetHash is the mutable one.
# TBD
# TBD
# TBD
In Perl 6, there are two APIs for dealing with networking: IO::Socket::INET (for synchronous networking), and IO::Socket::Async (for asynchronous networking).
IO::Socket::INET currently only supports TCP connections. Its API resembles that of C's socket API. If you're familiar with that, then it won't take long to understand how to use it. For example, here's an echo server that closes the connection after receiving its first message:
my IO::Socket::INET $server .= new: :localhost<localhost>, :localport<8000>, :listen; my IO::Socket::INET $client .= new: :host<localhost>, :port<8000>; $client.print: 'Hello, world!'; my IO::Socket::INET $conn = $server.accept; my Str $msg = $conn.recv; say $msg; # OUTPUT: Hello, world! $conn.print($msg); say $client.recv; # OUTPUT: Hello, world! $conn.close; $client.close; $server.close;
By default, IO::Socket::INET connections are IPv4 only. To use IPv6 instead, pass :family(PF_INET6) when constructing a server or a client.
In contrast, IO::Socket::Async supports both IPv4 and IPv6 without the need to specify which family you wish to use. It also supports UDP sockets. Here's how you would write the same echo server as above asynchronously (note that Supply.tap is multithreaded; if this is undesirable, use Supply.act instead:
my $supply = IO::Socket::Async.listen('localhost', 8000); my $server = $supply.tap(-> $conn { $conn.Supply.tap(-> $data { say $data; # OUTPUT: Hello, world! await $conn.print: $data; $conn.close; }) }); my $client = await IO::Socket::Async.connect('localhost', 8000); $client.Supply.tap(-> $data { say $data; # OUTPUT: Hello, world! $client.close; $server.close; }); await $client.print: 'Hello, world!';
The equivalent code in Node.js looks like this:
const net = require('net'); const server = net.createServer(conn => { conn.setEncoding('utf8'); conn.on('data', data => { console.log(data); # OUTPUT: Hello, world! conn.write(data); conn.end(); }); }).listen(8000, 'localhost'); const client = net.createConnection(8000, 'localhost', () => { client.setEncoding('utf8'); client.on('data', data => { console.log(data); # OUTPUT: Hello, world! client.end(); server.close(); }); client.write("Hello, world!"); });
Perl 6 doesn't natively support HTTP/HTTPS. However, CPAN packages such as Cro help fill the gap.
Perl 6 does not currently support the majority of the features that Node.js's DNS module implements. IO::Socket::INET and IO::Socket::Async can resolve hostnames, but features like resolving DNS records and reverse IP lookups are not implemented yet. There are some modules that are a work in progress, such as Net::DNS::BIND::Manage, that aim to improve DNS support.
Punycode support is available through the Net::LibIDN, Net::LibIDN2, and IDNA::Punycode modules on CPAN.
# TBD
# TBD
Learning Perl 6 from Python, in a nutshell
This page is an attempt to provide a way to learn Perl 6 for folks coming from a Python background. We discuss the equivalent syntax in Perl 6 for a number of Python constructs and idioms.
Let's start with printing "Hello, world!". The put keyword in Perl 6 is the equivalent of print in Python. Like Python 2, parentheses are optional. A newline is added to the end of the line.
Python 2
print "Hello, world!"
Python 3
print("Hello, world!")
Perl 6
put "Hello, world!"
There is also the say keyword, which behaves similarly, but will call the gist method of its argument.
Perl 6
my $hello = "Hello, world!"; say $hello; # also prints "Hello, world!" # same as: put $hello.gist
In Python, ' and " are interchangeable. In Perl 6, both may be used for quoting, but double quotes (") signify that interpolation should be performed. For instance, variables that start with a $, and expressions contained in curly braces are interpolated.
Perl 6
my $planet = 'earth'; say "Hello, $planet"; # Hello, earth say 'Hello, $planet'; # Hello, $planet say "Hello, planet number { 1 + 2 }"; # Hello, planet number 3
In Python, a newline signifies the end of a statement. There are a few exceptions: A backslash before a newline continues a statement across lines. Also if there is an unmatched opening parentheses, square bracket, or curly brace, the statement continues across lines, until the matching curly braces are closed.
In Perl 6, a semicolon signifies the end of a statement. The semicolon may be omitted if it is the last statement of a block. The semicolon may also be omitted if there is a closing curly brace followed by a newline.
Python
print 1 + 2 + \ 3 + 4 print ( 1 + 2 )
Perl 6
say 1 + 2 + 3 + 4; say 1 + 2;
In Python, indentation is used to indicate a block. Perl 6 uses curly braces.
Python
if 1 == 2: print "Wait, what?" else: print "1 is not 2."
Perl 6
if 1 == 2 { say "Wait, what?" } else { say "1 is not 2." }
Parentheses are optional in both languages for expressions in conditionals, as shown above.
In Python, variables are declared and initialized at the same time:
foo = 12 bar = 19
In Perl 6, the my declarator declares a lexical variable. A variable can be initialized with =. This variable can either be declared first and later initialized or declared and initialized at once.
my $foo; # declare $foo = 12; # initialize my $bar = 19; # both at once
Also, as you may have noticed, variables in Perl 6 usually start with sigils -- symbols indicating the type of their container. Variables starting with a $ hold scalars. Variables starting with an @ hold arrays, and variables starting with a % hold a hash (dict). Sigilless variables, declared with a \ but used without them, are bound to the value they are assigned to and are thus immutable.
Please note that, from now on, we are going to use sigilless variables in most examples just to illustrate the similarity with Python. That is technically correct, but in general we are going to use sigilless variables in places where their immutability (or independence of type, when they are used in signatures) is needed or needs to be highlighted.
Python
s = 10 l = [1, 2, 3] d = { a : 12, b : 99 } print s print l[2] print d['a'] # 10, 2, 12
Perl 6
my $s = 10; my @l = 1, 2, 3; my %d = a => 12, b => 99; my \x = 99; say $s; say @l[1]; say %d<a>; # or %d{'a'} say x; # 10, 2, 12, 99
In Python, functions and classes create a new scope, but no other block constructor (e.g. loops, conditionals) creates a scope. In Python 2, list comprehensions do not create a new scope, but in Python 3, they do.
In Perl 6, every block creates a lexical scope.
Python
if True: x = 10 print x # x is now 10
Perl 6
if True { my $x = 10 } say $x # error, $x is not declared in this scope
my $x; if True { $x = 10 } say $x # ok, $x is 10
Python
x = 10 for x in 1, 2, 3: pass print x # x is 3
Perl 6
my \x = 10; for 1, 2, 3 -> \x { # do nothing } say x; # x is 10
Lambdas in Python can be written as blocks or pointy blocks in Perl 6.
Python
l = lambda i: i + 12
Perl 6
my $l = -> $i { $i + 12 }
Another Perl 6 idiom for constructing lambdas is the Whatever star, *.
Perl 6
my $l = * + 12 # same as above
A * in an expression will become a placeholder for the argument, and transform the expression into a lambda at compile time. Each * in an expression is a separate positional parameter.
See the section below for more constructs regarding subroutines and blocks.
Another example (from the Python FAQ):
Python
squares = [] for x in range(5): squares.append(lambda: x ** 2) print squares[2]() print squares[4]() # both 16 since there is only one x
Perl 6
my \squares = []; for ^5 -> \x { squares.append({ x² }); } say squares[2](); say squares[4](); # 4, 16 since each loop iteration has a lexically scoped x,
Note that ^N is like range(N). Similarly, N..^M works like range(N, M) (a list from N to M - 1). The range N..M is a list from N to M. The ^ before or after the .. indicates that the beginning or ending endpoint of the list (or both) should be excluded.
Also, x² is a cute way of writing x ** 2 (which also works fine); the unicode superscript 2 squares a number. Many of the other unicode operators work as you would expect (exponents, fractions, π), but every unicode operator or symbol that can be used in Perl 6 has an ASCII equivalent.
Python has for loops and while loops:
for i in 1, 2: print i j = 1 while j < 3: print j j += 1
# 1, 2, 1, 2
Perl 6 also has for loops and while loops:
for 1, 2 -> $i { say $i } my $j = 1; while $j < 3 { say $j; $j += 1 }
(Perl 6 also has a few more looping constructs: repeat...until, repeat...while, until, and loop.)
last leaves a loop in Perl 6, and is analogous to break in Python. continue in Python is next in Perl 6.
Python
for i in range(10): if i == 3: continue if i == 5: break print i
Perl 6
for ^10 -> $i { next if $i == 3; last if $i == 5; say $i; }
Using if as a statement modifier (as above) is acceptable in Perl 6, even outside of a list comprehension.
The yield statement within a for loop in Python, which produces a generator, is like a gather/take construct in Perl 6. These both print 1, 2, 3.
Python
def count(): for i in 1, 2, 3: yield i for c in count(): print c
Perl 6
sub count { gather { for 1, 2, 3 -> $i { take $i } } } for count() -> $c { say $c; }
Declaring a function (subroutine) with def in Python is accomplished with sub in Perl 6.
def add(a, b): return a + b sub add(\a, \b) { return a + b }
The return is optional; the value of the last expression is used as the return value:
sub add(\a, \b) { a + b }
# using variables with sigils sub add($a, $b) { $a + $b }
Python 2 functions can be called with positional arguments or keyword arguments. These are determined by the caller. In Python 3, some arguments may be "keyword only". In Perl 6, positional and named arguments are determined by the signature of the routine.
Python
def speak(word, times): for i in range(times): print word speak('hi', 2) speak(word='hi', times=2)
Perl 6
Positional parameters:
sub speak($word, $times) { say $word for ^$times } speak('hi', 2);
Named parameters start with a colon:
sub speak(:$word, :$times) { say $word for ^$times } speak(word => 'hi', times => 2); speak(:word<hi>, :times<2>); # Alternative, more idiomatic
Perl 6 supports multiple dispatch, so several signatures could be made available by declaring a routine as a multi.
multi sub speak($word, $times) { say $word for ^$times } multi sub speak(:$word, :$times) { speak($word, $times); } speak('hi', 2); speak(:word<hi>, :times<2>);
Named parameters can be sent using a variety of formats:
sub hello {...}; # all the same hello(name => 'world'); # fat arrow syntax hello(:name('world')); # pair constructor hello :name<world>; # <> quotes words and makes a list my $name = 'world'; hello(:$name); # lexical var with the same name
Creating an anonymous function can be done with sub, with a block or with a pointy block.
Python
square = lambda x: x ** 2
Perl 6
my $square = sub ($x) { $x ** 2 }; # anonymous sub my $square = -> $x { $x ** 2 }; # pointy block my $square = { $^x ** 2 }; # placeholder variable my $square = { $_ ** 2 }; # topic variable
Placeholder variables are lexicographically ordered to form positional parameters. Thus these are the same:
my $power = { $^x ** $^y }; my $power = -> $x, $y { $x ** $y };
Postfix statement modifiers and blocks can be combined to easily create list comprehensions in Perl 6.
Python
print [ i * 2 for i in 3, 9 ] # OUTPUT: «[6, 18]»
Perl 6
say ( $_ * 2 for 3, 9 ); # OUTPUT: «(6 18)» say ( { $^i * 2 } for 3, 9 ); # OUTPUT: «(6 18)» say ( -> \i { i * 2 } for 3, 9 ); # OUTPUT: «(6 18)»
Conditionals can be applied, but the if keyword comes first, unlike in Python where the if comes second.
print [ x * 2 for x in 1, 2, 3 if x > 1 ] # OUTPUT: «[4, 6]»
vs
say ( $_ * 2 if $_ > 1 for 1, 2, 3 ); # OUTPUT: «(4 6)»
For nested loops, the cross product operator X will help:
print [ i + j for i in 3,9 for j in 2,10 ] # OUTPUT: «[5, 13, 11, 19]»
becomes either of these:
say ( { $_[0] + $_[1] } for (3,9) X (2,10) ); # OUTPUT: «(5 13 11 19)» say ( -> (\i, \j) { i + j } for (3,9) X (2,10) ); # OUTPUT: «(5 13 11 19)» say ( -> ($i, $j) { $i + $j } for (3,9) X (2,10) );# OUTPUT: «(5 13 11 19)» say ( { $^a[0] + $^a[1] } for (3,9) X (2,10) ); # OUTPUT: «(5 13 11 19)»
Using map (which is just like Python's map) and grep (which is like Python's filter) is an alternative.
Here's an example from the Python docs. First let's go over "instance variables" which are known as attributes in Perl 6:
Python:
class Dog: def __init__(self, name): self.name = name
Perl 6:
class Dog { has $.name; }
For each created class, Perl 6 provides the constructor method new by default which takes named arguments.
Python:
d = Dog('Fido') e = Dog('Buddy') print d.name print e.name
Perl 6
my $d = Dog.new(:name<Fido>); # or: Dog.new(name => 'Fido') my $e = Dog.new(:name<Buddy>); say $d.name; say $e.name;
Class attributes in Perl 6 can be declared in a few ways. One way is to just declare a lexical variable and a method for accessing it.
Python:
class Dog: kind = 'canine' # class attribute def __init__(self, name): self.name = name # instance attribute d = Dog('Fido') e = Dog('Buddy') print d.kind print e.kind print d.name print e.name
Perl 6:
class Dog { my $kind = 'canine'; # class attribute method kind { $kind } has $.name; # instance attribute } my $d = Dog.new(:name<Fido>); my $e = Dog.new(:name<Buddy>); say $d.kind; say $e.kind; say $d.name; say $e.name;
In order to mutate attributes in Perl 6, you must use the is rw trait on the attributes:
Python:
class Dog: def __init__(self, name): self.name = name d = Dog() d.name = 'rover'
Perl 6:
class Dog { has $.name is rw; } my $d = Dog.new; $d.name = 'rover';
Inheritance is done using is:
Python
class Animal: def jump(self): print ("I am jumping") class Dog(Animal): pass d = Dog() d.jump()
Perl 6
class Animal { method jump { say "I am jumping" } } class Dog is Animal { } my $d = Dog.new; $d.jump;
Multiple inheritance is possible by using the is trait as many times as required. Alternatively, it can be used in conjunction with the also keyword.
Python
class Dog(Animal, Friend, Pet): pass
Perl 6
class Animal {}; class Friend {}; class Pet {}; ...; class Dog is Animal is Friend is Pet {};
or
class Animal {}; class Friend {}; class Pet {}; ...; class Dog is Animal { also is Friend; also is Pet; ... }
Decorators in Python are a way of wrapping a function in another one. In Perl 6, this is done with wrap.
Python
def greeter(f): def new(): print 'hello' f() return new @greeter def world(): print 'world' world();
Perl 6
sub world { say 'world' } &world.wrap(sub () { say 'hello'; callsame; }); world;
An alternative would be to use a trait:
# declare the trait 'greeter' multi sub trait_mod:<is>(Routine $r, :$greeter) { $r.wrap(sub { say 'hello'; callsame; }) } sub world is greeter { say 'world'; } world;
Context managers in Python declare actions that happen when entering or exiting a scope.
Here's a Python context manager that prints the strings 'hello', 'world', and 'bye'.
class hello: def __exit__(self, type, value, traceback): print 'bye' def __enter__(self): print 'hello' with hello(): print 'world'
For "enter" and "exit" events, passing a block as an argument would be one option:
sub hello(Block $b) { say 'hello'; $b(); say 'bye'; } hello { say 'world'; }
A related idea is 'Phasers' which may be set up to run on entering or leaving a block.
{ LEAVE say 'bye'; ENTER say 'hello'; say 'world'; }
In Python 3, the input keyword is used to prompt the user. This keyword can be provided with an optional argument which is written to standard output without a trailing newline:
user_input = input("Say hi → ") print(user_input)
When prompted, you can enter Hi or any other string, which will be stored in the user_input variable. This is similar to prompt in Perl 6:
my $user_input = prompt("Say hi → "); say $user_input; # OUTPUT: whatever you entered.
Learning Perl 6 from Ruby, in a nutshell: what do I already know?
This page attempts to index the high-level differences in syntax and semantics between Ruby and Perl 6. Whatever works in Ruby and must be written differently in Perl 6 should be listed here (whereas many Perl 6 features and idioms won't be).
Hence this should not be mistaken for a beginner tutorial or overview of Perl 6; it is intended as a technical reference for Perl 6 learners with a strong Ruby background.
Ruby detects the end of most statements with a newline (and a few exceptions), as long as the expression is complete. It is common break up a long expression by leaving an operator dangling at the end of a line to ensure that the parsing will continue:
foo + # In Ruby a trailing operator means parsing should continue bar + baz
In Perl 6 you must explicitly terminate statements with a ;, which allows for better feedback and more flexibility in breaking up long lines. Two exceptions not needing an explicit ; are the last statement in a block, and after the closing curly brace of the block itself (if there is nothing else on that line):
my $x; ...; if 5 < $x < 10 { say "Yep!"; $x = 17 # No ; required before closing } } # No ; required after closing } because of the newline say "Done!"; # The ; is not required here if nothing follows
Ruby allows a surprising amount of flexibility in the use of whitespace, even with strict mode and warnings turned on:
# unidiomatic but valid Ruby puts"Hello "+ (people [ i] . name ) . upcase+"!"if$greeted[i]<1
Perl 6 also endorses programmer freedom and creativity, but balanced syntactic flexibility against its design goal of having a consistent, deterministic, extensible grammar that supports single-pass parsing and helpful error messages, integrates features like custom operators cleanly, and doesn't lead programmers to accidentally misstate their intent. Also, the practice of "code golf" is slightly de-emphasized; Perl 6 is designed to be more concise in concepts than in keystrokes.
As a result, there are various places in the syntax where whitespace is optional in Ruby, but is either mandatory or forbidden in Perl 6. Many of those restrictions are unlikely to concern much real-life Perl code (e.g. whitespace being disallowed between an array variable and its square brackets), but there are a few that will unfortunately conflict with some Ruby hackers' habitual coding styles:
No space allowed before the opening parenthesis of an argument list.
foo (3, 4, 1); # Not right in Ruby or Perl 6 (in Perl 6 this would # try to pass a single argument of type List to foo)
foo(3, 4, 1); # Ruby and Perl 6 foo 3, 4, 1; # Ruby and Perl 6 - alternative parentheses-less style
Space is required immediately after keywords
if(a < 0); ...; end # OK in Ruby
my $a; ...; if ($a < 0) { ... } # Perl 6 if $a < 0 { ... } # Perl 6, more idiomatic
while(x > 5); ...; end # OK in Ruby
my $x; ...; while ($x > 5) { ... } # Perl 6 while $x > 5 { ... } # Perl 6, more idiomatic
No space allowed before a postfix/postcircumfix operator (including array/hash subscripts).
seen [ :fish ] = 1 # Ruby, not idiomatic but allowed
%seen< fish > = 1; # Perl 6, no space allowed after 'seen'
Space required before an infix operator if it would conflict with an existing postfix/postcircumfix operator.
n<1 # Ruby (in Perl 6 this would conflict with postcircumfix < >)
$n < 1; # Perl 6
Method call syntax uses a dot just like Ruby:
person.name # Ruby
my $person; ...; $person.name # Perl 6
To call a method whose name is not known until runtime:
object.send(methodname, args); # Ruby
my $object; my Str $methodname; my @args; ...; $object."$methodname"(@args); # Perl 6
If you leave out the quotes, then Perl 6 expects $methodname to contain a Method object, rather than the simple string name of the method.
In Ruby, variables use sigils primarily to indicate scope. $ for global scope, @@ for class scope, @ for instance scope, and no sigil for local variables (including parameters). The & sigil is also used to indicate method references. Symbols are prefixed with :, but they are not variable and so not really sigils.
In Perl 6 sigils are primarily used to indicate a role that the contained value implements, indicating the type (or at least the interface) of the value. The sigils are invariant, no matter how the variable is being used - you can think of them as part of the variable's name.
The scope of a variable is instead indicated by the declaration itself (my, has, our, etc).
For local variables, Ruby uses implicit variable declaration upon assignment and limited to the current block. In Ruby the content of an if or while built-in construct is not a block or scope.
Perl 6 uses explicit scope indicators, and never creates variables implicitly. Every place you see { ... } is a scope, including the body of a conditional or loop. The commonly used scope declarations:
foo = 7 # Ruby, variable scope is defined by first assignment and # extends to the end of the current block
my $foo = 7; # Perl 6, lexical scoped to the current block our $foo = 7; # Perl 6, package scoped has $!foo = 7; # Perl 6, instance scoped (attribute)
The $ sigil is always used with "scalar" variables (e.g. $name). These are single-value containers.
This is the most general-purpose variable type, with no restrictions on its contents. Note that you can still address/use its contents, like $x[1], $x{"foo"}, and $f("foo").
The @ sigil is always used with "array" variables (e.g. @months, @months[2], @months[2, 4] for an array slice). Variables using the @ sigil can only contain things that do the Positional role, indicating positional indexing and slicing capabilities.
Indexing
puts months[2]; # Ruby
say @months[2]; # Perl 6
Value-slicing
puts months[8..11].join(',') # Ruby
say @months[8..11].join(',') # Perl 6
The % sigil is always used with "hash" variables (e.g. %calories, %calories<apple>, %calories<pear plum>). Variables using the % sigil can only contain things that do the Associative role.
Ruby uses square brackets to access values for both Arrays and Hashes. Perl 6 uses curly braces for hashes instead. The angle brackets version is available which always autoquotes its contents (strings without quotes):
Adverbs can be used to control the type of slice.
Indexing
puts calories["apple"] # Ruby
say %calories{"apple"}; # Perl 6
puts calories["apple"] # Ruby puts calories[:apple] # Ruby, symbols for keys are common
say %calories<apple>; # Perl 6 - angle brackets instead of single-quotes say %calories«"$key"»; # Perl 6 - double angles interpolate as double-quotes
Value-slicing
puts calories.values_at('pear', 'plum').join(',') # Ruby puts calories.values_at(%w(pear plum)).join(',') # Ruby, pretty?
say %calories{'pear', 'plum'}.join(','); # Perl 6 say %calories<pear plum>.join(','); # Perl 6 (prettier) my $keys = 'pear plum'; say %calories« $keys ».join(','); # Perl 6, interpolated split
Key/value-slicing
say calories.slice('pear', 'plum').join(','); # Ruby, with ActiveRecord
say %calories{'pear', 'plum'}:kv.join(','); # Perl 6 - use :kv adverb say %calories<pear plum>:kv.join(','); # Perl 6 (prettier version)
The & sigil is used very similarly to Ruby's & to refer to the function object of a named subroutine/operator without invoking it, i.e. to use the name as a "noun" instead of a "verb". Variables using the & sigil can only contain things that do the Callable role.
add = -> n, m { n + m } # Ruby lambda for an addition function add.(2, 3) # => 5, Ruby invocation of a lambda add.call(2, 3) # => 5, Ruby invocation of a lambda
my &add = -> $n, $m { $n + $m }; # Perl 6 addition function &add(2, 3); # => 5, you can keep the sigil add(2, 3); # => 5, and it works without it
foo_method = &foo; # Ruby
sub foo { ... }; my &foo_method = &foo; # Perl 6
some_func(&say) # Ruby pass a function reference
sub some_func { ... }; some_func(&say) # Perl 6 passes function references the same way
Often in Ruby we pass a block as the last parameter, which is especially used for DSLs. This can be an implicit parameter called by yield, or an explicit block prefixed with &. In Perl 6 a Callable parameter is always listed and called by the variable name (instead of yield), and there are a variety of ways of invoking the function.
# Ruby, declare a method and call the implicit block argument def f yield 2 end # Ruby, invoke f, pass it a block with 1 argument f do |n| puts "Hi #{n}" end
# Perl 6, declare a method with an explicit block argument sub f(&g:($)) { g(2) } # Perl 6, invoke f, pass it a block with 1 argument # There are several other ways to do this f(-> $n { say "Hi {$n}" }); # Explicit argument f -> $n { say "Hi {$n}" }; # Explicit argument, no parenthesis # Additionally, if 'f' is a method on instance 'obj' you can use ':' # instead of parenthesis my $obj; ...; $obj.f(-> $n { say "Hi {$n}" }); # Explicit argument $obj.f: -> $n { say "Hi {$n}" }; # Explicit argument, no parenthesis
In Ruby you can declare an argument to slurp the remainder of the passed parameters into an array using a * prefix. It works similarly in Perl 6:
def foo(*args); puts "I got #{args.length} args!"; end # Ruby
sub foo(*@args) { say "I got #{@args.elems} args!" } # Perl 6
The Perl 6 version above is slightly different in that when it slurps in the arguments into @args, one level of nesting, if any, is automatically removed:
sub foo(*@args) { say @args.perl } foo([1, [2, 3], 4], 5, [6, 7]); # [1, [2, 3], 4, 5, 6, 7]
To preserve the structure of the arguments, you can use **:
sub foo(**@args) { say @args.perl } foo([1, [2, 3], 4], 5, [6, 7]); # [[1, [2, 3], 4], 5, [6, 7]]
You might want to expand an array into a set of arguments. In Perl 6 this is done using a Slip |:
args = %w(a b c) # Ruby foo(*args)
sub foo($q, $r, $s) { ... }; my @args = <a b c>; # Perl 6 foo(|@args);
Perl 6 has many more advanced ways of passing parameters and receiving arguments, see Signatures and Captures.
Perl 6 additionally uses "twigils", which are further indicators about the variable and go between the sigil and the rest of the variable name. Examples:
Variable | Description |
---|---|
$foo | Scalar with no twigil |
$!foo | Private instance variable |
$.foo | Instance variable accessor |
$*foo | Dynamically scoped variable |
$^foo | A positional (placeholder) parameter to a block |
$:foo | A named (placeholder) parameter to a block |
$=foo | POD (documentation) variables |
$?FILE | Current source filename. The ? twigil indicates a compile-time value |
$~foo | Sublanguage seen by parser, uncommon |
Though each of these examples use the $ sigil, most could use @ (Positional) or % (Associative).
Perl 6 generally uses strings in the places where Ruby uses symbols. A primary example of this is in hash keys.
address[:joe][:street] # Typical Ruby nested hash with symbol keys
my %address; ...; %address<joe><street> # Typical Perl 6 nested hash with string keys
Perl 6 has colon-pair syntax, which can sometimes look like Ruby symbols.
:age # Ruby symbol
# All of these are equivalent for Perl 6 :age ;# Perl 6 pair with implicit True value :age(True) ;# Perl 6 pair with explicit True value age => True ;# Perl 6 pair using arrow notation "age" => True ;# Perl 6 pair using arrow notation and explicit quotes
You could probably get away with using a colon-pair without an explicit value and pretend that it is a Ruby symbol a lot of the time, but it isn't idiomatic Perl 6.
Many operators have a similar usage in both Ruby and Perl 6:
, List Separator
+ Numeric Addition
- Numeric Subtraction
* Numeric Multiplication
/ Numeric Division
% Numeric Modulus
** Numeric Exponentiation
! && || Booleans, high-precedence
not and or Booleans, low-precedence
You may use $x++ instead of x += 1 as a shortcut for incrementing a variable. This can be used as a pre-increment ++$x (increment, return new value) or post-increment $x++ (increment, return old value).
You may use $x-- instead of x -= 1 as a shortcut for decrementing a variable. This can be used as a pre-decrement --$x (decrement, return new value) or post-decrement $x-- (decrement, return old value).
Comparisons in Perl 6 are separated between numeric and string to avoid common errors.
== != < > <= >= Comparisons
eq ne lt gt le ge String comparisons
For example, using == tries to convert the values to numbers, and eq tries to convert the values to strings.
In Ruby, the <=> operator returns -1, 0, or 1. In Perl 6, they return Order::Less, Order::Same, or Order::More.
<=> forces numeric context for the comparison.
leg ("Less, Equal, or Greater?") forces string context for the comparison.
cmp does either <=> or leg, depending on the existing type of its arguments.
This is a very common matching operator which is similar to === in Ruby. Here are some examples:
my $foo; ...; say "match!" if $foo ~~ /bar/; # Regex match say "match!" if $foo ~~ "bar"; # String match say "match!" if $foo ~~ :(Int, Str); # Signature match (destructure)
An equivalent in Ruby would be
$foo = 'bar'; puts "match 1!" if /bar/ === $foo; # Regex match puts "match 2!" if $foo === "bar"; # String match puts "match 3!" if String === $foo; # Class match
Please note that, in this case, === is not symmetric; in the first and last case, the variable has to be in the right-hand side. There is no equivalent to the signature class in Ruby, either.
See S03/Smartmatching for more information on this feature.
In Perl 6, these single-character ops have been removed, and replaced by two-character ops which coerce their arguments to the needed context.
# Infix ops (two arguments; one on each side of the op) +& +| +^ And Or Xor: Numeric ~& ~| ~^ And Or Xor: String ?& ?| ?^ And Or Xor: Boolean # Prefix ops (one argument, after the op) +^ Not: Numeric ~^ Not: String ?^ Not: Boolean (same as the ! op)
Ruby uses the &. operator to chain methods without raising an error if one invocation returns nil. In Perl 6 use .? for the same purpose.
Replaced by +< and +> .
puts 42 << 3 # Ruby
say 42 +< 3; # Perl 6
Note that Ruby often uses the << operator as the "shovel operator", which is similar to .push. This usage isn't common in Perl 6.
In Ruby, => is used in the context of key/value pairs for Hash literal declaration and parameter passing. : is used as a shorthand when the left side is a symbol.
In Perl 6, => is the Pair operator, which is quite different in principle, but works the same in many situations.
If you are using => in a hash literal, then the usage is very similar:
hash = { "AAA" => 1, "BBB" => 2 } # Ruby, though symbol keys are more common
my %hash = ( AAA => 1, BBB => 2 ); # Perl 6, uses ()'s though {} usually work
In Perl 6, this is spelled with two question marks instead of one question mark, and two exclamation points instead of one colon. This deviation from the common ternary operators disambiguates several situations and makes the false-case stand out more.
result = ( score > 60 ) ? 'Pass' : 'Fail'; # Ruby
my $score; ...; my $result = ( $score > 60 ) ?? 'Pass' !! 'Fail'; # Perl 6
Replaced by the tilde. Mnemonic: think of "stitching" together the two strings with needle and thread.
$food = 'grape' + 'fruit' # Ruby
my $food = 'grape' ~ 'fruit'; # Perl 6
In Ruby, "#{foo}s" deliminates a block embedded in a double-quoted string. In Perl 6 drop the # prefix: "{$foo}s". As in Ruby, you can place arbitrary code into the embedded block and it will be rendered in string context.
Simple variables can be interpolated into a double-quoted string without using the block syntax:
# Ruby name = "Bob" puts "Hello! My name is #{name}!"
# Perl 6 my $name = "Bob"; say "Hello! My name is $name!"
The result of an embedded block in Ruby uses .to_s to get string context. Perl 6 uses .Str, or .gist for the same affect.
This work very similarly between Ruby and Perl 6, but Perl 6 uses { } to clearly delineate the blocks.
# Ruby if x > 5 puts "Bigger!" elsif x == 5 puts "The same!" else puts "Smaller!" end
# Perl 6 my $x; ...; if $x > 5 { say "Bigger!" } elsif $x == 5 { say "The same!" } else { say "Smaller!" }
Binding the conditional expression to a variable is a little different:
if x = dostuff(); ...; end # Ruby
sub dostuff() {...}; if dostuff() -> $x {...} # Perl 6, block-assignment uses arrow
The unless conditional only allows for a single block in Perl 6; it does not allow for an elsif or else clause.
The Perl 6 given-when construct is like a chain of if-elsif-else statements or like the case-when construct in Ruby. A big difference is that Ruby uses the == comparison for each condition, but Perl 6 uses the more general smartmatch ~~ operator.
It has the general structure:
given EXPR { when EXPR { ... } when EXPR { ... } default { ... } }
In its simplest form, the construct is as follows:
my $value; ...; given $value { when "a match" { # do-something(); } when "another match" { # do-something-else(); } default { # do-default-thing(); } }
This is simple in the sense that a scalar value is matched in the when statements. More generally, the matches are actually smartmatches on the input value such that lookups using more complex entities such as regexps can be used instead of scalar values.
Mostly unchanged; parentheses around the conditions are optional, but if used, must not immediately follow the keyword, or it will be taken as a function call instead. Binding the conditional expression to a variable is also a little different:
while x = dostuff(); ...; end # Ruby
sub dostuff {...}; ...; while dostuff() -> $x {...} # Perl 6
for loops are rare in Ruby, instead we typically use .each on an enumerable. The most direct translation to Perl 6 would be to use .map for both .each and .map, but we typically use a for loop directly.
# Ruby for loop for n in 0..5 puts "n: #{n}" end # Ruby, more common usage of .each (0..5).each do |n| puts "n: #{n}" end
# Perl 6 for 0..5 -> $n { say "n: $n"; } # Perl 6, misusing .map (0..5).map: -> $n { say "n: $n"; }
In Ruby, the iteration variable for .each is a copy of the list element, and modifying it does nothing to the original list. Note that it is a copy of the REFERENCE, so you can still change the values to which it refers.
In Perl 6, that alias is read-only (for safety) and thus behaves exactly like Ruby, unless you change -> to <->.
cars.each { |car| ... } # Ruby; read-only reference
my @cars; ...; for @cars -> $car {...} # Perl 6; read-only for @cars <-> $car {...} # Perl 6; read-write
Same as Ruby:
next
redo
break
This is last in Perl 6.
Regular expressions in Perl 6 are significantly different, and more powerful, than in Ruby. By default whitespace is ignored and all characters must be escaped, for example. Regexes can be easily combined and declared in ways to build efficient grammars.
There are many powerful features of Perl 6 regexes, especially defining entire grammars using the same syntax. See Regexes and Grammars.
In Ruby, regex matches can be done against a variable using the =~ regexp match operator or the .match method. In Perl 6, the ~~ smartmatch op is used instead, or the .match method.
next if line =~ /static/ # Ruby next if line !~ /dynamic/; # Ruby next if line.match(/static/) # Ruby
my $line; ...; next if $line ~~ /static/; # Perl 6 next if $line !~~ /dynamic/ ; # Perl 6 next if $line.match(/static/); # Perl 6
Alternately, the .match and .subst methods can be used. Note that .subst is non-mutating. See S05/Substitution.
In Perl 6 you typically use the s/// operator to do regex substitution.
fixed = line.sub(/foo/, 'bar') # Ruby, non-mutating
my $line; ...; my $fixed = $line.subst(/foo/, 'bar') # Perl 6, non-mutating
line.sub!(/foo/, 'bar') # Ruby, mutating
my $line; ...; $line ~~ s/foo/bar/; # Perl 6, mutating
Move any options from the end of the regex to the beginning. This may require you to add the optional m on a plain match like /abc/.
next if $line =~ /static/i # Ruby
my $line; ...; next if $line ~~ m:i/static/; # Perl 6
In order to aid in readability and reusability, whitespace is not significant in Perl 6 regexes.
/this is a test/ # Ruby, boring string /this.*/ # Ruby, possibly interesting string
/ this " " is " " a " " test /; # Perl 6, each space is quoted / "this is a test" /; # Perl 6, quoting the whole string / this .* /; # Perl 6, possibly interesting string
There are many cases of special matching syntax that Perl 6 regexes support. They won't all be listed here, but often instead of being surrounded by (), the assertions will be surrounded by <>.
For character classes, this means that:
[abc] becomes <[abc]>
[^abc] becomes <-[abc]>
[a-zA-Z] becomes <[a..zA..Z]>
[[:upper:]] becomes <:upper>
[abc[:upper:]] becomes <[abc]+:Upper>
For look-around assertions:
(?=[abc]) becomes <?[abc]>
(?=ar?bitrary* pattern) becomes <before ar?bitrary* pattern>
(?!=[abc]) becomes <![abc]>
(?!=ar?bitrary* pattern) becomes <!before ar?bitrary* pattern>
(?<=ar?bitrary* pattern) becomes <after ar?bitrary* pattern>
(?<!ar?bitrary* pattern) becomes <!after ar?bitrary* pattern>
(Unrelated to <> syntax, the "lookaround" /foo\Kbar/ becomes /foo <( bar )> /
(?(?{condition))yes-pattern|no-pattern) becomes [ <?{condition}> yes-pattern | no-pattern ]
In Perl 6 regexes, | does Longest Token Match (LTM), which decides which alternation wins an ambiguous match based off of a set of rules, rather than about which was written first in the regex.
To avoid the new logic, change any | in your Ruby regex to a ||.
Both Ruby and Perl 6 make it easy to read all of the lines in a file into a single variable, and in both cases each line has the newline removed.
lines = File.readlines("file") # Ruby
my @lines = "file".IO.lines; # Perl 6, create an IO object from a string
Reading the entire file into memory isn't recommended. The .lines method in Perl 6 returns a lazy sequence, but assigning to an array forces the file to be read. It is better to iterate over the results:
# Ruby File.foreach("file") do |line| puts line end
# Perl 6 for "file".IO.lines -> $line { say $line }
Classes are defined similarly between Ruby and Perl 6, using the class keyword. Ruby uses def for methods, whereas Perl 6 uses method.
# Ruby class Foo def greet(name) puts "Hi #{name}!" end end
# Perl 6 class Foo { method greet($name) { say "Hi $name!" } }
In Ruby you can use an attribute without declaring it beforehand, and you can tell it is an attribute because of the @ sigil. You can also easily create accessors using attr_accessor and its variants. In Perl 6 you use a has declaration and a variety of sigils. You can use the ! twigil for private attributes or . to create an accessor.
# Ruby class Person attr_accessor :age # Declare .age as an accessor method for @age def initialize @name = 'default' # Assign default value to private instance var end end
# Perl 6 class Person { has $.age; # Declare $!age and accessor methods has $!name = 'default'; # Assign default value to private instance var }
Creating a new instance of the class uses the .new method. In Ruby you must manually assign instance variables as needed inside initialize. In Perl 6 you get a default constructor that accepts key/value pairs of accessor attributes, and can do further setup in the BUILD method. Like with Ruby, you can override new itself for more advanced functionality, but this is rare.
# Ruby class Person attr_accessor :name, :age def initialize(attrs) @name = attrs[:name] || 'Jill' @age = attrs[:age] || 42 @birth_year = Time.now.year - @age end end p = Person.new( name: 'Jack', age: 23 )
# Perl 6 class Person { has $.name = 'Jill'; has $.age = 42; has $!birth_year; method BUILD { $!birth_year = now.Date.year - $.age; } } my $p = Person.new( name => 'Jack', age => 23 )
Private methods in Perl 6 are declared with a ! prefixed in their name, and are invoked with a ! instead of a ..
# Ruby class Foo def visible puts "I can be seen!" hidden end private def hidden puts "I cannot easily be called!" end end
# Perl 6 class Foo { method visible { say "I can be seen!"; self!hidden; } method !hidden { say "I cannot easily be called!"; } }
An important note is that in Ruby child objects can see parent private methods (so they are more like "protected" methods in other languages). In Perl 6 child objects cannot call parent private methods.
Here are a few examples of meta-programming. Note that Perl 6 separates the meta-methods from the regular methods with a caret.
# Ruby person = Person.new person.class person.methods person.instance_variables
# Perl 6 class Person {}; ... my $person = Person.new; $person.^name; # Perl 6, returns Person (class) $person.^methods; # Perl 6, using .^ syntax to access meta-methods $person.^attributes;
Like Ruby, in Perl 6, everything is an object, but not all operations are equivalent to .send. Many operators are global functions that use typed multi-dispatch (function signatures with types) to decide which implementation to use.
5.send(:+, 3) # => 8, Ruby
&[+](5, 3) # => 8, Perl 6, reference to infix addition operator &[+].^candidates # Perl 6, lists all signatures for the + operator
See Meta-Object Protocol for lots of further details.
In Ruby, one of the environment variables to specify extra search paths for modules is RUBYLIB.
$ RUBYLIB="/some/module/lib" ruby program.rb
In Perl 6 this is similar, you merely needs to change the name. As you probably guessed, you just need to use PERL6LIB:
$ PERL6LIB="/some/module/lib" perl6 program.p6
As with Ruby, if you don't specify PERL6LIB, you need to specify the library path within the program via the use lib pragma:
# Ruby and Perl 6 use lib '/some/module/lib';
In Ruby there is no built-in way to selectively import/export methods from a module.
In Perl 6 you specify the functions which are to be exported by using the is export role on the relevant subs and all subs with this role are then exported. Hence, the following module Bar exports the subs foo and bar but not baz:
unit module Bar; # remainder of the file is in module Bar { ... } sub foo($a) is export { say "foo $a" } sub bar($b) is export { say "bar $b" } sub baz($z) { say "baz $z" }
To use this module, simply use Bar and the functions foo and bar will be available:
use Bar; foo(1); #=> "foo 1" bar(2); #=> "bar 2"
If you try to use baz an "Undeclared routine" error is raised at compile time.
Some modules allow for selectively importing functions, which would look like:
use Bar <foo>; # Import only foo foo(1); #=> "foo 1" bar(2); # Error!
Command line argument switch parsing in Perl 6 is done by the parameter list of the MAIN subroutine.
# Ruby require 'optparse' options = {} OptionParser.new do |opts| opts.banner = 'Usage: example.rb --length=abc' opts.on("--length", "Set the file") do |length| raise "Length must be > 0" unless length.to_i > 0 options[:length] = length end opts.on("--filename", "Set the file") do |filename| options[:file] = filename end opts.on("--verbose", "Increase verbosity") do |verbose| options[:verbose] = true end end.parse! puts options[:length] puts options[:filename] puts 'Verbosity ', (options[:verbose] ? 'on' : 'off')
ruby example.rb --filename=foo --length=42 --verbose 42 foo Verbosity on ruby example.rb --length=abc Length must be > 0
# Perl 6 sub MAIN ( Int :$length where * > 0, :$filename = 'file.dat', Bool :$verbose ) { say $length; say $filename; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); }
perl6 example.p6 --file=foo --length=42 --verbose 42 foo Verbosity on perl6 example.p6 --length=abc Usage: example.p6 [--length=<Int>] [--file=<Any>] [--verbose]
Note that Perl 6 auto-generates a full usage message on error in command-line parsing.
See https://modules.perl6.org/, where a growing number of Perl 6 libraries are available along with the tools to manage them.
If the module that you were using has not been converted to Perl 6, and no alternative is listed in this document, then its use under Perl 6 may not have been addressed yet.
You can experiment with Inline::Ruby to call existing Ruby code from your Perl 6 programs. This uses an embedded instance of the ruby interpreter to run Ruby code called from your Perl 6 script. Note that this is an EXPERIMENTAL library. You can similarly call other language's libraries with Inline::Perl5, Inline::Python, and others.
### Guidelines for contributions:
Headers should contain the text that a Ruby user might search for, since those headings will be in the Table of Contents generated for the top of the document.
We use POD =item instead of =head3 or =head4 for identical bits that need not appear in the table of contents.
This article does not describe in detail language features that Ruby doesn't have at all, instead referring to other documents.
Example code and links to other documents should be favored over long explanations of details better found elsewhere.
Finally, if a real user asks a Ruby to Perl 6 question that is not being answered here, please add it to the document. Even if we do not have a good answer yet, that will be better than losing the information about a real need.
A tutorial about creating and using classes in Perl 6
Perl 6 has a rich built-in syntax for defining and using classes.
A default constructor allows the setting of attributes for the created object:
class Point { has Int $.x; has Int $.y; } class Rectangle { has Point $.lower; has Point $.upper; method area() returns Int { ($!upper.x - $!lower.x) * ( $!upper.y - $!lower.y); } } # Create a new Rectangle from two Points my $r = Rectangle.new(lower => Point.new(x => 0, y => 0), upper => Point.new(x => 10, y => 10)); say $r.area(); # OUTPUT: «100»
In the two classes, the default constructor is being used. This constructor will use named parameters in its invocation: Point.new(x => 0, y => 0).
You can also provide your own constructor and BUILD implementation. You need to do it for cases in which there are private attributes that might need to be populated during object construction, as in the example below:
# Example taken from # https://medium.freecodecamp.org/a-short-overview-of-object-oriented-software-design-c7aa0a622c83 class Hero { has @!inventory; has Str $.name; submethod BUILD( :$name, :@inventory ) { $!name = $name; @!inventory = @inventory } method act { return @!inventory.pick; } } my $hero = Hero.new(:name('Þor'), :inventory(['Mjölnir','Chariot','Bilskirnir'])); say $hero.act;
In this case, we encapsulate the private attribute @!inventory; but private instance variables cannot be set by the default constructor, which is why we add a BUILD submethod that takes care of that.
The following, more elaborate example, shows how a dependency handler might look in Perl 6. It showcases custom constructors, private and public attributes, Submethods, methods, and various aspects of signatures. It's not a lot of code, and yet the result is interesting and useful.
class Task { has &!callback; has Task @!dependencies; has Bool $.done; # Normally doesn't need to be written method new(&callback, *@dependencies) { return self.bless(:&callback, :@dependencies); } # BUILD is the equivalent of a constructor in other languages submethod BUILD(:&!callback, :@!dependencies) { } method add-dependency(Task $dependency) { push @!dependencies, $dependency; } method perform() { unless $!done { .perform() for @!dependencies; &!callback(); $!done = True; } } } my $eat = Task.new({ say 'eating dinner. NOM!' }, Task.new({ say 'making dinner' }, Task.new({ say 'buying food' }, Task.new({ say 'making some money' }), Task.new({ say 'going to the store' }) ), Task.new({ say 'cleaning kitchen' }) ) ); $eat.perform();
In this case, BUILD is needed since we have overridden the default new constructor. bless is eventually invoking it with the two named arguments that correspond to the two properties without a default value. With its signature, BUILD converts the two positionals to the two attributes, &!callback and @!dependencies, and returns the object (or turns it in to the next phase, TWEAK, if available).
Declaring new as a method and not as a multi method prevents us from using the default constructor; this implicit constructor uses the attributes as named parameters. This is one of the reasons why using new as a method's name is discouraged. If you need to declare it anyway, use multi method new if you do not want to disable the default constructor.
TWEAK is the last submethod to be called, and it has the advantage of having the object properties available without needing to use the meta object protocol. It can be used, for instance, to assign values to instance variables based on the values of other attributes or instance variables:
class Str-with-ID is Str { my $.counter = 0; has Str $.string; has Int $.ID; method TWEAK() { $!ID = $.counter++; } } say Str-with-ID.new(string => 'First').ID; # OUTPUT: «0» say Str-with-ID.new(string => 'Second').ID; # OUTPUT: «1»
In this case, we need to compute $.ID from the value of a counter that is a class variable, $.counter, thus we simply assign a value to it and increment the counter at the same time. Please check also this section on TWEAK in the Object Orientation (OO) document for the mechanics of object construction.
DESTROY is the submethod that gets called when an object is garbage collected. That is going to happen only if the runtime needs the memory, so we can't rely on when it's going to happen. In particular, it could happen in the middle of some running code in a thread, so we must take special care to not assume any context during that event. We can use it to close any kind of handles or supplies or delete temporary files that are no longer going to be used.
my $in_destructor = 0; class Foo { submethod DESTROY { $in_destructor++ } } my $foo; for 1 .. 6000 { $foo = Foo.new(); } say "DESTROY called $in_destructor times";
This might print something like DESTROY called 5701 times, but it only kicks in after we have stomped over former instances of Foo 6000 times. We can't rely, however, on the order of destruction, for instance.
Perl 6, like many other languages, uses the class keyword to define a class. The block that follows may contain arbitrary code, just as with any other block, but classes commonly contain state and behavior declarations. The example code includes attributes (state), introduced through the has keyword, and behaviors, introduced through the method keyword.
Declaring a class creates a new type object which, by default, is installed into the current package (just like a variable declared with our scope). This type object is an "empty instance" of the class. For example, types such as Int and Str refer to the type object of one of the Perl 6 built-in classes. The example above uses the class name Task so that other code can refer to it later, such as to create class instances by calling the new method.
You can use the .DEFINITE method to find out if what you have is an instance or a type object:
say Int.DEFINITE; # OUTPUT: «False» (type object) say 426.DEFINITE; # OUTPUT: «True» (instance) class Foo {}; say Foo.DEFINITE; # OUTPUT: «False» (type object) say Foo.new.DEFINITE; # OUTPUT: «True» (instance)
You can also use type "smileys" to only accept instances or type objects:
multi foo (Int:U) { "It's a type object!" } multi foo (Int:D) { "It's an instance!" } say foo Int; # OUTPUT: «It's a type object!» say foo 42; # OUTPUT: «It's an instance!»
In the Task class, the first three lines inside the block all declare attributes (called fields or instance storage in other languages). Just as a my variable cannot be accessed from outside its declared scope, attributes are not accessible outside of the class. This encapsulation is one of the key principles of object oriented design.
The first declaration specifies instance storage for a callback (i.e., a bit of code to invoke in order to perform the task that an object represents):
has &!callback;
The & sigil indicates that this attribute represents something invocable. The ! character is a twigil, or secondary sigil. A twigil forms part of the name of the variable. In this case, the ! twigil emphasizes that this attribute is private to the class.
The second declaration also uses the private twigil:
has Task @!dependencies;
However, this attribute represents an array of items, so it requires the @ sigil. These items each specify a task that must be completed before the present one is completed. Furthermore, the type declaration on this attribute indicates that the array may only hold instances of the Task class (or some subclass of it).
The third attribute represents the state of completion of a task:
has Bool $.done;
This scalar attribute (with the $ sigil) has a type of Bool. Instead of the ! twigil, the . twigil is used. While Perl 6 does enforce encapsulation on attributes, it also saves you from writing accessor methods. Replacing the ! with a . both declares a private attribute and an accessor method named after the attribute. In this case, both the attribute $!done and the accessor method done are declared. It's as if you had written:
has Bool $!done; method done() { return $!done }
Note that this is not like declaring a public attribute, as some languages allow; you really get both a private attribute and a method, without having to write the method by hand. You are free instead to write your own accessor method, if at some future point you need to do something more complex than returning the value.
Note that using the . twigil has created a method that will provide read-only access to the attribute. If instead the users of this object should be able to reset a task's completion state (perhaps to perform it again), you can change the attribute declaration:
has Bool $.done is rw;
The is rw trait causes the generated accessor method to return a container so external code can modify the value of the attribute.
You can also supply default values to attributes (which works equally for those with and without accessors):
has Bool $.done = False;
The assignment is carried out at object build time. The right-hand side is evaluated at that time, and can even reference earlier attributes:
has Task @!dependencies; has $.ready = not @!dependencies;
Writable attributes are accessible through writable containers:
class a-class { has $.an-attribute is rw; } say (a-class.new.an-attribute = "hey"); # OUTPUT: «hey»
This attribute can also be accessed using the .an-attribute or .an-attribute() syntax. See also the is rw trait on classes for examples on how this works on the whole class.
A class declaration can also include class variables, which are variables whose value is shared by all instances, and can be used for things like counting the number of instantiations or any other shared state. Class variables use the same syntax as the rest of the attributes, but are declared as my or our, depending on the scope; our variables will be shared by subclasses, since they have package scope.
class Str-with-ID is Str { my $counter = 0; our $hierarchy-counter = 0; has Str $.string; has Int $.ID; method TWEAK() { $!ID = $counter++; $hierarchy-counter++; } } class Str-with-ID-and-tag is Str-with-ID { has Str $.tag; } say Str-with-ID.new(string => 'First').ID; # OUTPUT: «0» say Str-with-ID.new(string => 'Second').ID; # OUTPUT: «1» say Str-with-ID-and-tag.new( string => 'Third', tag => 'Ordinal' ).ID; # OUTPUT: «2» say $Str-with-ID::hierarchy-counter; # OUTPUT: «4»
In this case, using new might be the easiest way to initialize the $.ID field and increment the value of the counter at the same time. new, through bless, will invoke the default BUILD, assigning the values to their properties correctly. You can obtain the same effect using TWEAK, which is considered a more p6y way of achieving such effect. Please check the section on submethods for an alternative example on how to do this. Since TWEAK is called in every object instantiation, it's incremented twice when creating objects of class Str-with-ID-and-tag; this is a class hierarchy variable that is shared by all subclasses of Str-with-ID. Additionally, class variables declared with package scope are visible via their fully qualified name (FQN), while lexically scoped class variables are "private".
Perl 6 has no static keyword. Nevertheless, any class may declare anything that a module can, so making a scoped variable sounds like a good idea.
class Singleton { my Singleton $instance; method new {!!!} submethod instance { $instance = Singleton.bless unless $instance; $instance; } }
Class attributes defined by my or our may also be initialized when being declared, however we are implementing the Singleton pattern here and the object must be created during its first use. It is not 100% possible to predict the moment when attribute initialization will be executed, because it can take place during compilation, runtime or both, especially when importing the class using the use keyword.
class HaveStaticAttr { my Foo $.foo = some_complicated_subroutine; }
Class attributes may also be declared with a secondary sigil – in a similar manner to instance attributes – that will generate read-only accessors if the attribute is to be public.
While attributes give objects state, methods give objects behaviors. Let's ignore the new method temporarily; it's a special type of method. Consider the second method, add-dependency, which adds a new task to a task's dependency list:
method add-dependency(Task $dependency) { push @!dependencies, $dependency; }
In many ways, this looks a lot like a sub declaration. However, there are two important differences. First, declaring this routine as a method adds it to the list of methods for the current class, thus any instance of the Task class can call it with the . method call operator. Second, a method places its invocant into the special variable self.
The method itself takes the passed parameter – which must be an instance of the Task class – and pushes it onto the invocant's @!dependencies attribute.
The perform method contains the main logic of the dependency handler:
method perform() { unless $!done { .perform() for @!dependencies; &!callback(); $!done = True; } }
It takes no parameters, working instead with the object's attributes. First, it checks if the task has already completed by checking the $!done attribute. If so, there's nothing to do.
Otherwise, the method performs all of the task's dependencies, using the for construct to iterate over all of the items in the @!dependencies attribute. This iteration places each item – each a Task object – into the topic variable, $_. Using the . method call operator without specifying an explicit invocant uses the current topic as the invocant. Thus the iteration construct calls the .perform() method on every Task object in the @!dependencies attribute of the current invocant.
After all of the dependencies have completed, it's time to perform the current Task's task by invoking the &!callback attribute directly; this is the purpose of the parentheses. Finally, the method sets the $!done attribute to True, so that subsequent invocations of perform on this object (if this Task is a dependency of another Task, for example) will not repeat the task.
Just like attributes, methods can also be private. Private methods are declared with a prefixed exclamation mark. They are called with self! followed by the method's name. To call a private method of another class the calling class has to be trusted by the called class. A trust relationship is declared with trusts and the class to be trusted must already be declared. Calling a private method of another class requires an instance of that class and the fully qualified name (FQN) of the method. Trust also allows access to private attributes.
class B {...} class C { trusts B; has $!hidden = 'invisible'; method !not-yours () { say 'hidden' } method yours-to-use () { say $!hidden; self!not-yours(); } } class B { method i-am-trusted () { my C $c.=new; $c!C::not-yours(); } } C.new.yours-to-use(); # the context of this call is GLOBAL, and not trusted by C B.new.i-am-trusted();
Trust relationships are not subject to inheritance. To trust the global namespace, the pseudo package GLOBAL can be used.
Perl 6 is rather more liberal than many languages in the area of constructors. A constructor is anything that returns an instance of the class. Furthermore, constructors are ordinary methods. You inherit a default constructor named new from the base class Mu, but you are free to override new, as this example does:
method new(&callback, *@dependencies) { return self.bless(:&callback, :@dependencies); }
The biggest difference between constructors in Perl 6 and constructors in languages such as C# and Java is that rather than setting up state on a somehow already magically created object, Perl 6 constructors create the object themselves. The easiest way to do this is by calling the bless method, also inherited from Mu. The bless method expects a set of named parameters to provide the initial values for each attribute.
The example's constructor turns positional arguments into named arguments, so that the class can provide a nice constructor for its users. The first parameter is the callback (the thing which will execute the task). The rest of the parameters are dependent Task instances. The constructor captures these into the @dependencies slurpy array and passes them as named parameters to bless (note that :&callback uses the name of the variable – minus the sigil – as the name of the parameter).
Private attributes really are private. This means that bless is not allowed to bind things to &!callback and @!dependencies directly. To do this, we override the BUILD submethod, which is called on the brand new object by bless:
submethod BUILD(:&!callback, :@!dependencies) { }
Since BUILD runs in the context of the newly created Task object, it is allowed to manipulate those private attributes. The trick here is that the private attributes (&!callback and @!dependencies) are being used as the bind targets for BUILD's parameters. Zero-boilerplate initialization! See objects for more information.
The BUILD method is responsible for initializing all attributes and must also handle default values:
has &!callback; has @!dependencies; has Bool ($.done, $.ready); submethod BUILD( :&!callback, :@!dependencies, :$!done = False, :$!ready = not @!dependencies, ) { }
See Object Construction for more options to influence object construction and attribute initialization.
After creating a class, you can create instances of the class. Declaring a custom constructor provides a simple way of declaring tasks along with their dependencies. To create a single task with no dependencies, write:
my $eat = Task.new({ say 'eating dinner. NOM!' });
An earlier section explained that declaring the class Task installed a type object in the namespace. This type object is a kind of "empty instance" of the class, specifically an instance without any state. You can call methods on that instance, as long as they do not try to access any state; new is an example, as it creates a new object rather than modifying or accessing an existing object.
Unfortunately, dinner never magically happens. It has dependent tasks:
my $eat = Task.new({ say 'eating dinner. NOM!' }, Task.new({ say 'making dinner' }, Task.new({ say 'buying food' }, Task.new({ say 'making some money' }), Task.new({ say 'going to the store' }) ), Task.new({ say 'cleaning kitchen' }) ) );
Notice how the custom constructor and the sensible use of whitespace makes task dependencies clear.
Finally, the perform method call recursively calls the perform method on the various other dependencies in order, giving the output:
making some money going to the store buying food cleaning kitchen making dinner eating dinner. NOM!
Object Oriented Programming provides the concept of inheritance as one of the mechanisms for code reuse. Perl 6 supports the ability for one class to inherit from one or more classes. When a class inherits from another class it informs the method dispatcher to follow the inheritance chain to look for a method to dispatch. This happens both for standard methods defined via the method keyword and for methods generated through other means, such as attribute accessors.
class Employee { has $.salary; } class Programmer is Employee { has @.known_languages is rw; has $.favorite_editor; method code_to_solve( $problem ) { return "Solving $problem using $.favorite_editor in " ~ $.known_languages[0]; } }
Now, any object of type Programmer can make use of the methods and accessors defined in the Employee class as though they were from the Programmer class.
my $programmer = Programmer.new( salary => 100_000, known_languages => <Perl5 Perl6 Erlang C++>, favorite_editor => 'vim' ); say $programmer.code_to_solve('halting problem'), " will get \$ {$programmer.salary()}"; # OUTPUT: «Solving halting problem using vim in Perl5 will get $100000»
Of course, classes can override methods and attributes defined by parent classes by defining their own. The example below demonstrates the Baker class overriding the Cook's cook method.
class Cook is Employee { has @.utensils is rw; has @.cookbooks is rw; method cook( $food ) { say "Cooking $food"; } method clean_utensils { say "Cleaning $_" for @.utensils; } } class Baker is Cook { method cook( $confection ) { say "Baking a tasty $confection"; } } my $cook = Cook.new( utensils => <spoon ladle knife pan>, cookbooks => 'The Joy of Cooking', salary => 40000 ); $cook.cook( 'pizza' ); # OUTPUT: «Cooking pizza» say $cook.utensils.perl; # OUTPUT: «["spoon", "ladle", "knife", "pan"]» say $cook.cookbooks.perl; # OUTPUT: «["The Joy of Cooking"]» say $cook.salary; # OUTPUT: «40000» my $baker = Baker.new( utensils => 'self cleaning oven', cookbooks => "The Baker's Apprentice", salary => 50000 ); $baker.cook('brioche'); # OUTPUT: «Baking a tasty brioche» say $baker.utensils.perl; # OUTPUT: «["self cleaning oven"]» say $baker.cookbooks.perl; # OUTPUT: «["The Baker's Apprentice"]» say $baker.salary; # OUTPUT: «50000»
Because the dispatcher will see the cook method on Baker before it moves up to the parent class the Baker's cook method will be called.
To access methods in the inheritance chain, use re-dispatch or the MOP.
As mentioned before, a class can inherit from multiple classes. When a class inherits from multiple classes the dispatcher knows to look at both classes when looking up a method to search for. Perl 6 uses the C3 algorithm to linearize multiple inheritance hierarchies, which is better than depth-first search for handling multiple inheritance.
class GeekCook is Programmer is Cook { method new( *%params ) { push( %params<cookbooks>, "Cooking for Geeks" ); return self.bless(|%params); } } my $geek = GeekCook.new( books => 'Learning Perl 6', utensils => ('stainless steel pot', 'knife', 'calibrated oven'), favorite_editor => 'MacVim', known_languages => <Perl6> ); $geek.cook('pizza'); $geek.code_to_solve('P =? NP');
Now all the methods made available to the Programmer and the Cook classes are available from the GeekCook class.
While multiple inheritance is a useful concept to know and occasionally use, it is important to understand that there are more useful OOP concepts. When reaching for multiple inheritance it is good practice to consider whether the design wouldn't be better realized by using roles, which are generally safer because they force the class author to explicitly resolve conflicting method names. For more information on roles, see Roles.
Classes to be inherited from can be listed in the class declaration body by prefixing the is trait with also. This also works for the role composition trait does.
class GeekCook { also is Programmer; also is Cook; # ... } role A {}; role B {}; class C { also does A; also does B; # ... }
Introspection is the process of gathering information about some objects in your program, not by reading the source code, but by querying the object (or a controlling object) for some properties, such as its type.
Given an object $o and the class definitions from the previous sections, we can ask it a few questions:
my Programmer $o .= new; if $o ~~ Employee { say "It's an employee" }; say $o ~~ GeekCook ?? "It's a geeky cook" !! "Not a geeky cook"; say $o.^name; say $o.perl; say $o.^methods(:local)».name.join(', ');
The output might look like this:
It's an employee Not a geeky cook (Programmer) Programmer.new(known_languages => ["Perl", "Python", "Pascal"], favorite_editor => "gvim", salary => "too small") code_to_solve, known_languages, favorite_editor Programmer
The first two tests each smartmatch against a class name. If the object is of that class, or of an inheriting class, it returns true. So the object in question is of class Employee or one that inherits from it, but not GeekCook.
The .WHAT method returns the type object associated with the object $o, which tells us the exact type of $o: in this case Programmer.
$o.perl returns a string that can be executed as Perl code, and reproduces the original object $o. While this does not work perfectly in all cases, it is very useful for debugging simple objects.
The syntax of calling a method with .^ instead of a single dot means that it is actually a method call on its meta class, which is a class managing the properties of the Programmer class – or any other class you are interested in. This meta class enables other ways of introspection too:
say $o.^attributes.join(', '); say $o.^parents.map({ $_.^name }).join(', ');
Finally $o.^name calls the name method on the meta object, which unsurprisingly returns the class name.
Introspection is very useful for debugging and for learning the language and new libraries. When a function or method returns an object you don't know about, by finding its type with .WHAT, seeing a construction recipe for it with .perl, and so on, you'll get a good idea of what its return value is. With .^methods, you can learn what you can do with the class.
But there are other applications too. For instance, a routine that serializes objects to a bunch of bytes needs to know the attributes of that object, which it can find out via introspection.
Some classes might need its own version of gist, which overrides the terse way it is printed when called to provide a default representation of the class. For instance, exceptions might want to write just the payload and not the full object so that it is clearer what to see what's happened. However, this isn't limited to exceptions; you can do that with every class:
class Cook { has @.utensils is rw; has @.cookbooks is rw; method cook( $food ) { return "Cooking $food"; } method clean_utensils { return "Cleaning $_" for @.utensils; } multi method gist(Cook:U:) { '⚗' ~ self.^name ~ '⚗' } multi method gist(Cook:D:) { '⚗ Cooks with ' ~ @.utensils.join( " ‣ ") ~ ' using ' ~ @.cookbooks.map( "«" ~ * ~ "»").join( " and ") } } my $cook = Cook.new( utensils => <spoon ladle knife pan>, cookbooks => ['Cooking for geeks','The French Chef Cookbook']); say Cook.gist; # OUTPUT: «⚗Cook⚗» say $cook.gist; # OUTPUT: «⚗ Cooks with spoon ‣ ladle ‣ knife ‣ pan using «Cooking for geeks» and «The French Chef Cookbook»»
Usually you will want to define two methods, one for the class and another for class instances; in this case, the class method uses the alembic symbol, and the instance method, defined below it, aggregates the data we have on the cook to show it in a narrative way.
Creating your own CLI in Perl 6
The default command line interface of Perl 6 scripts consists of three parts:
This looks at the values in @*ARGS, interprets these according to some policy, and creates a Capture/type/Capture object out of that. An alternative way of parsing may be provided by the developer or installed using a module.
Standard multi dispatch is used to call the MAIN subroutine with the generated Capture object. This means that your MAIN subroutine may be a multi sub, each candidate of which is responsible for some part of processing the given command line arguments.
If multi dispatch failed, then the user of the script should be informed as well as possible as to why it failed. By default, this is done by inspecting the signature of each MAIN candidate sub, and any associated Pod information. The result is then shown to the user on STDERR (or on STDOUT if --help was specified). An alternative way of generating the usage information may be provided by the developer or installed using a module.
The sub with the special name MAIN will be executed after all relevant entry phasers (BEGIN, CHECK, INIT, PRE, ENTER) have been run and the mainline of the script has been executed. No error will occur if there is no MAIN sub: your script will then just have to do the work, such as argument parsing, in the mainline of the script.
Any normal exit from the MAIN sub will result in an exit code of 0, indicating success. Any return value of the MAIN sub will be ignored. If an exception is thrown that is not handled inside the MAIN sub, then the exit code will be 1. If the dispatch to MAIN failed, a usage message will be displayed on STDERR and the exit code will be 2.
The command line parameters are present in the @*ARGS dynamic variable and may be altered in the mainline of the script before the MAIN unit is called.
The signature of (the candidates of the multi) sub MAIN determines which candidate will actually be called using the standard multi dispatch semantics.
A simple example:
# inside file 'hello.p6' sub MAIN($name) { say "Hello $name, how are you?" }
If you call that script without any parameters, you get the following usage message:
$ perl6 hello.p6 Usage: hello.p6 <name>
However, if you give a default value for the parameter, running the script either with or without specifying a name will always work:
# inside file 'hello.p6' sub MAIN($name = 'bashful') { say "Hello $name, how are you?" }
$ perl6 hello.p6 Hello bashful, how are you?
$ perl6 hello.p6 Liz Hello Liz, how are you?
Another way to do this is to make sub MAIN a multi sub:
# inside file 'hello.p6' multi sub MAIN() { say "Hello bashful, how are you?" } multi sub MAIN($name) { say "Hello $name, how are you?" }
Which would give the same output as the examples above. Whether you should use either method to achieve the desired goal is entirely up to you.
A more complicated example using a single positional and multiple named parameters:
# inside "frobnicate.p6" sub MAIN( Str $file where *.IO.f = 'file.dat', Int :$length = 24, Bool :$verbose ) { say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); }
With file.dat present, this will work this way:
$ perl6 frobnicate.p6 24 file.dat Verbosity off
Or this way with --verbose:
$ perl6 frobnicate.p6 --verbose 24 file.dat Verbosity on
If the file file.dat is not present, or you've specified another filename that doesn't exist, you would get the standard usage message created from introspection of the MAIN sub:
$ perl6 frobnicate.p6 doesntexist.dat Usage: frobnicate.p6 [--length=<Int>] [--verbose] [<file>]
Although you don't have to do anything in your code to do this, it may still be regarded as a bit terse. But there's an easy way to make that usage message better by providing hints using pod features:
# inside "frobnicate.p6" sub MAIN( Str $file where *.IO.f = 'file.dat', #= an existing file to frobnicate Int :$length = 24, #= length needed for frobnication Bool :$verbose, #= required verbosity ) { say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); }
Which would improve the usage message like this:
$ perl6 frobnicate.p6 doesntexist.dat Usage: frobnicate.p6 [--length=<Int>] [--verbose] [<file>] [<file>] an existing file to frobnicate --length=<Int> length needed for frobnication --verbose required verbosity
As any other subroutine, MAIN can define aliases for its named parameters.
sub MAIN( Str $file where *.IO.f = 'file.dat', #= an existing file to frobnicate Int :size(:$length) = 24, #= length/size needed for frobnication Bool :$verbose, #= required verbosity ) { say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); }
In which case, these aliases will also be listed as alternatives with --help:
Usage: frobnicate.p6 [--size|--length=<Int>] [--verbose] [<file>] [<file>] an existing file to frobnicate --size|--length=<Int> length needed for frobnication --verbose required verbosity
It's possible to alter how arguments are processed before they're passed to sub MAIN {} by setting options in the %*SUB-MAIN-OPTS hash. Due to the nature of dynamic variables, it is required to set up the %*SUB-MAIN-OPTS hash and fill it with the appropriate settings. For instance:
my %*SUB-MAIN-OPTS = :named-anywhere, # allow named variables at any location # other possible future options / custom options ; sub MAIN ($a, $b, :$c, :$d) { say "Accepted!" }
Available options are:
By default, named arguments passed to the program (i.e., MAIN) cannot appear after any positional argument. However, if %*SUB-MAIN-OPTS<named-anywhere> is set to a true value, named arguments can be specified anywhere, even after positional parameter. For example, the above program can be called with:
$ perl6 example.p6 1 --c=2 3 --d=4
Sometimes you want to exclude a MAIN candidate from being shown in any automatically generated usage message. This can be achieved by adding a hidden-from-USAGE trait to the specification of the MAIN candidate you do not want to show. Expanding on an earlier example:
# inside file 'hello.p6' multi sub MAIN() is hidden-from-USAGE { say "Hello bashful, how are you?" } multi sub MAIN($name) { #= the name by which you would like to be called say "Hello $name, how are you?" }
So, if you would call this script with just a named variable, you would get the following usage:
$ perl6 hello.p6 --verbose Usage: hello.p6 <name> -- the name by which you would like to be called
Without the hidden-from-USAGE trait on the first candidate, it would have looked like this:
$ perl6 hello.p6 --verbose Usage: hello.p6 hello.p6 <name> -- the name by which you would like to be called
Which, although technically correct, doesn't read as well.
If the entire program body resides within MAIN, you can use the unit declarator as follows (adapting an earlier example):
unit sub MAIN( Str $file where *.IO.f = 'file.dat', Int :$length = 24, Bool :$verbose, ); # <- note semicolon here say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); # rest of script is part of MAIN
Note that this is only appropriate if you can get by with just a single (only) sub MAIN.
If no multi candidate of MAIN is found for the given command line parameters, the sub USAGE is called. If no such method is found, the compiler will output a default usage message.
#|(is it the answer) multi MAIN(Int $i) { say $i == 42 ?? 'answer' !! 'dunno' } #|(divide two numbers) multi MAIN($a, $b){ say $a/$b } sub USAGE() { print Q:c:to/EOH/; Usage: {$*PROGRAM-NAME} [number] Prints the answer or 'dunno'. EOH }
The default usage message is available inside sub USAGE via the read-only $*USAGE variable. It will be generated based on available sub MAIN candidates and their parameters. As shown before, you can specify an additional extended description for each candidate using a #|(...) Pod block to set WHY.
You can replace or augment the default way of argument parsing by supplying a ARGS-TO-CAPTURE subroutine yourself, or by importing one from any of the Getopt modules available in the ecosystem.
The ARGS-TO-CAPTURE subroutine should accept two parameters: a Callable representing the MAIN unit to be executed (so it can be introspected if necessary) and an array with the arguments from the command line. It should return a Capture object that will be used to dispatch the MAIN unit. The following is a very contrived example that will create a Capture depending on some keyword that was entered (which can be handy during testing of a command line interface of a script):
sub ARGS-TO-CAPTURE(&main, @args --> Capture) { # if we only specified "frobnicate" as an argument @args == 1 && @args[0] eq 'frobnicate' # then dispatch as MAIN("foo","bar",verbose => 2) ?? Capture.new( list => <foo bar>, hash => { verbose => 2 } ) # otherwise, use default processing of args !! &*ARGS-TO-CAPTURE(&main, @args) }
Note that the dynamic variable &*ARGS-TO-CAPTURE is available to perform the default command line arguments to Capture processing so you don't have to reinvent the whole wheel if you don't want to.
You can replace or augment the default way of usage message generation (after a failed dispatch to MAIN) by supplying a GENERATE-USAGE subroutine yourself, or by importing one from any of the Getopt modules available in the ecosystem.
Defined as:
sub RUN-MAIN(&main, $mainline, :$in-as-argsfiles)
This routine allows complete control over the handling of MAIN. It gets a Callable that is the MAIN that should be executed, the return value of the mainline execution and additional named variables: :in-as-argsfiles which will be True if STDIN should be treated as $*ARGFILES.
If RUN-MAIN is not provided, a default one will be run that looks for subroutines of the old interface, such as MAIN_HELPER and USAGE. If found, it will execute following the "old" semantics.
class Hero { has @!inventory; has Str $.name; submethod BUILD( :$name, :@inventory ) { $!name = $name; @!inventory = @inventory } } sub new-main($name, *@stuff ) { Hero.new(:name($name), :inventory(@stuff) ).perl.say } RUN-MAIN( &new-main, Nil );
This will print the name (first argument) of the generated object.
The GENERATE-USAGE subroutine should accept a Callable representing the MAIN subroutine that didn't get executed because the dispatch failed. This can be used for introspection. All the other parameters are the parameters that were set up to be sent to MAIN. It should return the string of the usage information you want to be shown to the user. An example that will just recreate the Capture that was created from processing the arguments:
sub GENERATE-USAGE(&main, |capture) { capture<foo>:exists ?? "You're not allowed to specify a --foo" !! &*GENERATE-USAGE(&main, |capture) }
You can also use multi subroutines to create the same effect:
multi sub GENERATE-USAGE(&main, :$foo!) { "You're not allowed to specify a --foo" } multi sub GENERATE-USAGE(&main, |capture) { &*GENERATE-USAGE(&main, |capture) }
Note that the dynamic variable &*GENERATE-USAGE is available to perform the default usage message generation so you don't have to reinvent the whole wheel if you don't want to.
An older interface enabled one to intercept the calling to MAIN completely. This depended on the existence of a MAIN_HELPER subroutine that would be called if a MAIN subroutine was found in the mainline of a program.
This interface was never documented. However, any programs using this undocumented interface will continue to function until v6.e. From v6.d onward, the use of the undocumented API will cause a DEPRECATED message.
Ecosystem modules can provide both the new and the old interface for compatibility with older versions of Perl 6: if a newer Perl 6 recognizes the new (documented) interface, it will use that. If there is no new interface subroutine available, but the old MAIN_HELPER interface is, then it will use the old interface.
If a module developer decides to only offer a module for v6.d or higher, then the support for the old interface can be removed from the module.
Concurrency and asynchronous programming
In common with most modern programming languages, Perl 6 is designed to support parallelism, asynchronicity and concurrency. Parallelism is about doing multiple things at once. Asynchronous programming, which is sometimes called event driven or reactive programming, is about supporting changes in the program flow caused by events triggered elsewhere in the program. Finally, concurrency is about the coordination of access and modification of some shared resources.
The aim of the Perl 6 concurrency design is to provide a high-level, composable and consistent interface, regardless of how a virtual machine may implement it for a particular operating system, through layers of facilities as described below.
I'm not quite clear which specific features should be included below hyper-operators, autothreading junctions?Additionally, certain Perl features may implicitly operate in an asynchronous fashion, so in order to ensure predictable interoperation with these features, user code should, where possible, avoid the lower level concurrency APIs (e.g., Thread and Scheduler) and use the higher-level interfaces.
A Promise (also called future in other programming environments) encapsulates the result of a computation that may not have completed or even started at the time the promise is obtained. A Promise starts from a Planned status and can result in either a Kept status, meaning the promise has been successfully completed, or a Broken status meaning that the promise has failed. Usually this is much of the functionality that user code needs to operate in a concurrent or asynchronous manner.
my $p1 = Promise.new; say $p1.status; # OUTPUT: «Planned» $p1.keep('Result'); say $p1.status; # OUTPUT: «Kept» say $p1.result; # OUTPUT: «Result» # (since it has been kept, a result is available!) my $p2 = Promise.new; $p2.break('oh no'); say $p2.status; # OUTPUT: «Broken» say $p2.result; # dies, because the promise has been broken CATCH { default { say .^name, ': ', .Str } }; # OUTPUT: «X::AdHoc+{X::Promise::Broken}: oh no»
Promises gain much of their power by being composable, for example by chaining, usually by the then method:
my $promise1 = Promise.new(); my $promise2 = $promise1.then( -> $v { say $v.result; "Second Result" } ); $promise1.keep("First Result"); say $promise2.result; # OUTPUT: «First ResultSecond Result»
Here the then method schedules code to be executed when the first Promise is kept or broken, itself returning a new Promise which will be kept with the result of the code when it is executed (or broken if the code fails). keep changes the status of the promise to Kept setting the result to the positional argument. result blocks the current thread of execution until the promise is kept or broken, if it was kept then it will return the result (that is the value passed to keep), otherwise it will throw an exception based on the value passed to break. The latter behavior is illustrated with:
my $promise1 = Promise.new(); my $promise2 = $promise1.then(-> $v { say "Handled but : "; say $v.result}); $promise1.break("First Result"); try $promise2.result; say $promise2.cause; # OUTPUT: «Handled but : First Result»
Here the break will cause the code block of the then to throw an exception when it calls the result method on the original promise that was passed as an argument, which will subsequently cause the second promise to be broken, raising an exception in turn when its result is taken. The actual Exception object will then be available from cause. If the promise had not been broken cause would raise a X::Promise::CauseOnlyValidOnBroken exception.
A Promise can also be scheduled to be automatically kept at a future time:
my $promise1 = Promise.in(5); my $promise2 = $promise1.then(-> $v { say $v.status; 'Second Result' }); say $promise2.result;
The method in creates a new promise and schedules a new task to call keep on it no earlier than the supplied number of seconds, returning the new Promise object.
A very frequent use of promises is to run a piece of code, and keep the promise once it returns successfully, or break it when the code dies. The start method provides a shortcut for that:
my $promise = Promise.start( { my $i = 0; for 1 .. 10 { $i += $_ }; $i} ); say $promise.result; # OUTPUT: «55»
Here the result of the promise returned is the value returned from the code. Similarly if the code fails (and the promise is thus broken), then cause will be the Exception object that was thrown:
my $promise = Promise.start({ die "Broken Promise" }); try $promise.result; say $promise.cause;
This is considered to be such a commonly required pattern that it is also provided as a keyword:
my $promise = start { my $i = 0; for 1 .. 10 { $i += $_ } $i } my $result = await $promise; say $result;
The subroutine await is almost equivalent to calling result on the promise object returned by start but it will also take a list of promises and return the result of each:
my $p1 = start { my $i = 0; for 1 .. 10 { $i += $_ } $i }; my $p2 = start { my $i = 0; for 1 .. 10 { $i -= $_ } $i }; my @result = await $p1, $p2; say @result; # OUTPUT: «[55 -55]»
In addition to await, two class methods combine several Promise objects into a new promise: allof returns a promise that is kept when all the original promises are kept or broken:
my $promise = Promise.allof( Promise.in(2), Promise.in(3) ); await $promise; say "All done"; # Should be not much more than three seconds later
And anyof returns a new promise that will be kept when any of the original promises is kept or broken:
my $promise = Promise.anyof( Promise.in(3), Promise.in(8600) ); await $promise; say "All done"; # Should be about 3 seconds later
Unlike await however the results of the original kept promises are not available without referring to the original, so these are more useful when the completion or otherwise of the tasks is more important to the consumer than the actual results, or when the results have been collected by other means. You may, for example, want to create a dependent Promise that will examine each of the original promises:
my @promises; for 1..5 -> $t { push @promises, start { sleep $t; Bool.pick; }; } say await Promise.allof(@promises).then({ so all(@promises>>.result) });
Which will give True if all of the promises were kept with True, False otherwise.
If you are creating a promise that you intend to keep or break yourself then you probably don't want any code that might receive the promise to inadvertently (or otherwise) keep or break the promise before you do. For this purpose there is the method vow, which returns a Vow object which becomes the only mechanism by which the promise can be kept or broken. If an attempt to keep or break the Promise is made directly then the exception X::Promise::Vowed will be thrown, as long as the vow object is kept private, the status of the promise is safe:
sub get_promise { my $promise = Promise.new; my $vow = $promise.vow; Promise.in(10).then({$vow.keep}); $promise; } my $promise = get_promise(); # Will throw an exception # "Access denied to keep/break this Promise; already vowed" $promise.keep; CATCH { default { say .^name, ': ', .Str } }; # OUTPUT: «X::Promise::Vowed: Access denied to keep/break this Promise; already vowed»
The methods that return a promise that will be kept or broken automatically such as in or start will do this, so it is not necessary to do it for these.
A Supply is an asynchronous data streaming mechanism that can be consumed by one or more consumers simultaneously in a manner similar to "events" in other programming languages and can be seen as enabling event driven or reactive designs.
At its simplest, a Supply is a message stream that can have multiple subscribers created with the method tap on to which data items can be placed with emit.
The Supply can either be live or on-demand. A live supply is like a TV broadcast: those who tune in don't get previously emitted values. An on-demand broadcast is like Netflix: everyone who starts streaming a movie (taps a supply), always starts it from the beginning (gets all the values), regardless of how many people are watching it right now. Note that no history is kept for on-demand supplies, instead, the supply block is run for each tap of the supply.
A live Supply is created by the Supplier factory, each emitted value is passed to all the active tappers as they are added:
my $supplier = Supplier.new; my $supply = $supplier.Supply; $supply.tap( -> $v { say $v }); for 1 .. 10 { $supplier.emit($_); }
Note that the tap is called on a Supply object created by the Supplier and new values are emitted on the Supplier.
An on-demand Supply is created by the supply keyword:
my $supply = supply { for 1 .. 10 { emit($_); } } $supply.tap( -> $v { say $v });
In this case the code in the supply block is executed every time the Supply returned by supply is tapped, as demonstrated by:
my $supply = supply { for 1 .. 10 { emit($_); } } $supply.tap( -> $v { say "First : $v" }); $supply.tap( -> $v { say "Second : $v" });
The tap method returns a Tap object which can be used to obtain information about the tap and also to turn it off when we are no longer interested in the events:
my $supplier = Supplier.new; my $supply = $supplier.Supply; my $tap = $supply.tap( -> $v { say $v }); $supplier.emit("OK"); $tap.close; $supplier.emit("Won't trigger the tap");
Calling done on the supply object calls the done callback that may be specified for any taps, but does not prevent any further events being emitted to the stream, or taps receiving them.
The method interval returns a new on-demand supply which periodically emits a new event at the specified interval. The data that is emitted is an integer starting at 0 that is incremented for each event. The following code outputs 0 .. 5 :
my $supply = Supply.interval(2); $supply.tap(-> $v { say $v }); sleep 10;
A second argument can be supplied to interval which specifies a delay in seconds before the first event is fired. Each tap of a supply created by interval has its own sequence starting from 0, as illustrated by the following:
my $supply = Supply.interval(2); $supply.tap(-> $v { say "First $v" }); sleep 6; $supply.tap(-> $v { say "Second $v"}); sleep 10;
A live Supply that keeps values until first tapped can be created with Supplier::Preserving.
The whenever keyword can be used in supply blocks or in react blocks. From the 6.d version, it needs to be used within the lexical scope of them. It introduces a block of code that will be run when prompted by an asynchronous event that it specifies - that could be a Supply, a Channel, a Promise or an Iterable.
In this example we are watching two supplies.
my $bread-supplier = Supplier.new; my $vegetable-supplier = Supplier.new; my $supply = supply { whenever $bread-supplier.Supply { emit("We've got bread: " ~ $_); }; whenever $vegetable-supplier.Supply { emit("We've got a vegetable: " ~ $_); }; } $supply.tap( -> $v { say "$v" }); $vegetable-supplier.emit("Radish"); # OUTPUT: «We've got a vegetable: Radish» $bread-supplier.emit("Thick sliced"); # OUTPUT: «We've got bread: Thick sliced» $vegetable-supplier.emit("Lettuce"); # OUTPUT: «We've got a vegetable: Lettuce»
Please note that one should keep the code inside the whenever as small as possible, as only one whenever block will be executed at any time. One can use a start block inside the whenever block to run longer running code.
The react keyword introduces a block of code containing one or more whenever keywords to watch asynchronous events. The main difference between a supply block and a react block is that the code in a react block runs where it appears in the code flow, whereas a supply block has to be tapped before it does anything.
Another difference is that a supply block can be used without the whenever keyword, but a react block requires at least one whenever to be of any real use.
react { whenever Supply.interval(2) -> $v { say $v; done() if $v == 4; } }
Here the whenever keyword uses .act to create a tap on the Supply from the provided block. The react block is exited when done() is called in one of the taps. Using last to exit the block would produce an error indicating that it's not really a loop construct.
An on-demand Supply can also be created from a list of values that will be emitted in turn, thus the first on-demand example could be written as:
react { whenever Supply.from-list(1..10) -> $v { say $v; } }
An existing supply object can be filtered or transformed, using the methods grep and map respectively, to create a new supply in a manner like the similarly named list methods: grep returns a supply such that only those events emitted on the source stream for which the grep condition is true is emitted on the second supply:
my $supplier = Supplier.new; my $supply = $supplier.Supply; $supply.tap(-> $v { say "Original : $v" }); my $odd_supply = $supply.grep({ $_ % 2 }); $odd_supply.tap(-> $v { say "Odd : $v" }); my $even_supply = $supply.grep({ not $_ % 2 }); $even_supply.tap(-> $v { say "Even : $v" }); for 0 .. 10 { $supplier.emit($_); }
map returns a new supply such that for each item emitted to the original supply a new item which is the result of the expression passed to the map is emitted:
my $supplier = Supplier.new; my $supply = $supplier.Supply; $supply.tap(-> $v { say "Original : $v" }); my $half_supply = $supply.map({ $_ / 2 }); $half_supply.tap(-> $v { say "Half : $v" }); for 0 .. 10 { $supplier.emit($_); }
If you need to have an action that runs when the supply finishes, you can do so by setting the done and quit options in the call to tap:
$supply.tap: { ... }, done => { say 'Job is done.' }, quit => { when X::MyApp::Error { say "App Error: ", $_.message } };
The quit block works very similar to a CATCH. If the exception is marked as seen by a when or default block, the exception is caught and handled. Otherwise, the exception continues to up the call tree (i.e., the same behavior as when quit is not set).
If you are using the react or supply block syntax with whenever, you can add phasers within your whenever blocks to handle the done and quit messages from the tapped supply:
react { whenever $supply { ...; # your usual supply tap code here LAST { say 'Job is done.' } QUIT { when X::MyApp::Error { say "App Error: ", $_.message } } } }
The behavior here is the same as setting done and quit on tap.
A Channel is a thread-safe queue that can have multiple readers and writers that could be considered to be similar in operation to a "fifo" or named pipe except it does not enable inter-process communication. It should be noted that, being a true queue, each value sent to the Channel will only be available to a single reader on a first read, first served basis: if you want multiple readers to be able to receive every item sent you probably want to consider a Supply.
An item is queued onto the Channel with the method send, and the method receive removes an item from the queue and returns it, blocking until a new item is sent if the queue is empty:
my $channel = Channel.new; $channel.send('Channel One'); say $channel.receive; # OUTPUT: «Channel One»
If the channel has been closed with the method close then any send will cause the exception X::Channel::SendOnClosed to be thrown, and a receive will throw a X::Channel::ReceiveOnClosed if there are no more items on the queue.
The method list returns all the items on the Channel and will block until further items are queued unless the channel is closed:
my $channel = Channel.new; await (^10).map: -> $r { start { sleep $r; $channel.send($r); } } $channel.close; for $channel.list -> $r { say $r; }
There is also the non-blocking method poll that returns an available item from the channel or Nil if there is no item or the channel is closed, this does of course mean that the channel must be checked to determine whether it is closed:
my $c = Channel.new; # Start three Promises that sleep for 1..3 seconds, and then # send a value to our Channel ^3 .map: -> $v { start { sleep 3 - $v; $c.send: "$v from thread {$*THREAD.id}"; } } # Wait 3 seconds before closing the channel Promise.in(3).then: { $c.close } # Continuously loop and poll the channel, until it's closed my $is-closed = $c.closed; loop { if $c.poll -> $item { say "$item received after {now - INIT now} seconds"; } elsif $is-closed { last; } say 'Doing some unrelated things...'; sleep .6; } # Doing some unrelated things... # Doing some unrelated things... # 2 from thread 5 received after 1.2063182 seconds # Doing some unrelated things... # Doing some unrelated things... # 1 from thread 4 received after 2.41117376 seconds # Doing some unrelated things... # 0 from thread 3 received after 3.01364461 seconds # Doing some unrelated things...
The method closed returns a Promise that will be kept (and consequently will evaluate to True in a boolean context) when the channel is closed.
The .poll method can be used in combination with .receive method, as a caching mechanism where lack of value returned by .poll is a signal that more values need to be fetched and loaded into the channel:
sub get-value { return $c.poll // do { start replenish-cache; $c.receive }; } sub replenish-cache { for ^20 { $c.send: $_ for slowly-fetch-a-thing(); } }
Channels can be used in place of the Supply in the whenever of a react block described earlier:
my $channel = Channel.new; my $p = start { react { whenever $channel { say $_; } } } await (^10).map: -> $r { start { sleep $r; $channel.send($r); } } $channel.close; await $p;
It is also possible to obtain a Channel from a Supply using the Channel method which returns a Channel which is fed by a tap on the Supply:
my $supplier = Supplier.new; my $supply = $supplier.Supply; my $channel = $supply.Channel; my $p = start { react { whenever $channel -> $item { say "via Channel: $item"; } } } await (^10).map: -> $r { start { sleep $r; $supplier.emit($r); } } $supplier.done; await $p;
Channel will return a different Channel fed with the same data each time it is called. This could be used, for instance, to fan-out a Supply to one or more Channels to provide for different interfaces in a program.
Proc::Async builds on the facilities described to run and interact with an external program asynchronously:
my $proc = Proc::Async.new('echo', 'foo', 'bar'); $proc.stdout.tap(-> $v { print "Output: $v" }); $proc.stderr.tap(-> $v { print "Error: $v" }); say "Starting..."; my $promise = $proc.start; await $promise; say "Done."; # Output: # Starting... # Output: foo bar # Done.
The path to the command as well as any arguments to the command are supplied to the constructor. The command will not be executed until start is called, which will return a Promise that will be kept when the program exits. The standard output and standard error of the program are available as Supply objects from the methods stdout and stderr respectively which can be tapped as required.
If you want to write to the standard input of the program you can supply the :w adverb to the constructor and use the methods write, print or say to write to the opened pipe once the program has been started:
my $proc = Proc::Async.new(:w, 'grep', 'foo'); $proc.stdout.tap(-> $v { print "Output: $v" }); say "Starting..."; my $promise = $proc.start; $proc.say("this line has foo"); $proc.say("this one doesn't"); $proc.close-stdin; await $promise; say "Done."; # Output: # Starting... # Output: this line has foo # Done.
Some programs (such as grep without a file argument in this example, ) won't exit until their standard input is closed so close-stdin can be called when you are finished writing to allow the Promise returned by start to be kept.
The lowest level interface for concurrency is provided by Thread. A thread can be thought of as a piece of code that may eventually be run on a processor, the arrangement for which is made almost entirely by the virtual machine and/or operating system. Threads should be considered, for all intents, largely un-managed and their direct use should be avoided in user code.
A thread can either be created and then actually run later:
my $thread = Thread.new(code => { for 1 .. 10 -> $v { say $v }}); # ... $thread.run;
Or can be created and run at a single invocation:
my $thread = Thread.start({ for 1 .. 10 -> $v { say $v }});
In both cases the completion of the code encapsulated by the Thread object can be waited on with the finish method which will block until the thread completes:
$thread.finish;
Beyond that there are no further facilities for synchronization or resource sharing which is largely why it should be emphasized that threads are unlikely to be useful directly in user code.
The next level of the concurrency API is supplied by classes that implement the interface defined by the role Scheduler. The intent of the scheduler interface is to provide a mechanism to determine which resources to use to run a particular task and when to run it. The majority of the higher level concurrency APIs are built upon a scheduler and it may not be necessary for user code to use them at all, although some methods such as those found in Proc::Async, Promise and Supply allow you to explicitly supply a scheduler.
The current default global scheduler is available in the variable $*SCHEDULER.
The primary interface of a scheduler (indeed the only method required by the Scheduler interface) is the cue method:
method cue(:&code, Instant :$at, :$in, :$every, :$times = 1; :&catch)
This will schedule the Callable in &code to be executed in the manner determined by the adverbs (as documented in Scheduler) using the execution scheme as implemented by the scheduler. For example:
my $i = 0; my $cancellation = $*SCHEDULER.cue({ say $i++}, every => 2 ); sleep 20;
Assuming that the $*SCHEDULER hasn't been changed from the default, will print the numbers 0 to 10 approximately (i.e with operating system scheduling tolerances) every two seconds. In this case the code will be scheduled to run until the program ends normally, however the method returns a Cancellation object which can be used to cancel the scheduled execution before normal completion:
my $i = 0; my $cancellation = $*SCHEDULER.cue({ say $i++}, every => 2 ); sleep 10; $cancellation.cancel; sleep 10;
should only output 0 to 5.
Despite the apparent advantage the Scheduler interface provides over that of Thread all of functionality is available through higher level interfaces and it shouldn't be necessary to use a scheduler directly, except perhaps in the cases mentioned above where a scheduler can be supplied explicitly to certain methods.
A library may wish to provide an alternative scheduler implementation if it has special requirements, for instance a UI library may want all code to be run within a single UI thread, or some custom priority mechanism may be required, however the implementations provided as standard and described below should suffice for most user code.
The ThreadPoolScheduler is the default scheduler, it maintains a pool of threads that are allocated on demand, creating new ones as necessary up to maximum number given as a parameter when the scheduler object was created (the default is 16.) If the maximum is exceeded then cue may queue the code until such time as a thread becomes available.
Rakudo allows the maximum number of threads allowed in the default scheduler to be set by the environment variable RAKUDO_MAX_THREADS at the time the program is started.
The CurrentThreadScheduler is a very simple scheduler that will always schedule code to be run straight away on the current thread. The implication is that cue on this scheduler will block until the code finishes execution, limiting its utility to certain special cases such as testing.
The class Lock provides the low level mechanism that protects shared data in a concurrent environment and is thus key to supporting thread-safety in the high level API, this is sometimes known as a "Mutex" in other programming languages. Because the higher level classes (Promise, Supply and Channel) use a Lock where required it is unlikely that user code will need to use a Lock directly.
The primary interface to Lock is the method protect which ensures that a block of code (commonly called a "critical section") is only executed in one thread at a time:
my $lock = Lock.new; my $a = 0; await (^10).map: { start { $lock.protect({ my $r = rand; sleep $r; $a++; }); } } say $a; # OUTPUT: «10»
protect returns whatever the code block returns.
Because protect will block any threads that are waiting to execute the critical section the code should be as quick as possible.
Some shared data concurrency issues are less obvious than others. For a good general write-up on this subject see this blog post.
One particular issue of note is when container autovivification or extension takes place. When an Array or a Hash entry is initially assigned the underlying structure is altered and that operation is not async safe. For example, in this code:
my @array; my $slot := @array[20]; $slot = 'foo';
The third line is the critical section as that is when the array is extended. The simplest fix is to use a Lock to protect the critical section. A possibly better fix would be to refactor the code so that sharing a container is not necessary.
Core modules that may be useful to module authors
The Rakudo implementation has a few modules included you may want to use. The following is a list of them, along with links to their source code.
These modules are mostly used by distribution build tools, and are not intended to be used (at least until version 6.c) by the final user.
NativeCall Native Calling Interface (docs)
NativeCall::Types Used by NativeCall
NativeCall::Compiler::GNU Used by NativeCall
NativeCall::Compiler::MSVC Used by NativeCall
Pod::To::Text Used by several external modules
Different mathematical paradigms and how they are implemented in this language
Perl 6 includes the Set data type, as well as support for most set operations. Union and intersection are not only native operations, they use their natural symbols, ∩ and ∪. For instance, this code would check the fundamental laws of the arithmetic of sets for a limited number of sets:
my @arbitrary-numbers = ^100; my \U = @arbitrary-numbers.Set; my @sets; @sets.push: Set.new( @arbitrary-numbers.pick( @arbitrary-numbers.elems.rand)) for @arbitrary-numbers; my (@union, @intersection); for @sets -> $set { @union.push: $set ∩ $set === $set; @intersection.push: $set ∪ $set === $set; } say "Idempotent union is ", so @union.all; # OUTPUT: «Idempotent union is True» say "Idempotent intersection is ", so @intersection.all; # OUTPUT: «Idempotent intersection is True» my (@universe, @empty-set, @id-universe, @id-empty); for @sets -> \A { @universe.push: A ∪ U === U; @id-universe.push: A ∩ U === A; @empty-set.push: A ∩ ∅ === ∅; @id-empty.push: A ∪ ∅ === A; } say "Universe dominates ", so @universe.all; # OUTPUT: «Universe dominates True» say "Empty set dominates ", so @empty-set.all; # OUTPUT: «Empty set dominates True» say "Identity with U ", so @id-universe.all; # OUTPUT: «Identity with U True» say "Identity with ∅ ", so @id-empty.all; # OUTPUT: «Identity with ∅ True»
In this code, which uses the empty set which is already defined by Perl 6, not only do we check if the equalities in the algebra of sets hold, we also use, via sigilless variables and the Unicode form of the set operators, expressions that are as close as possible to the original form; A ∪ U === U, for example, except for the use of the value identity operator === is very close to the actual mathematical expression in the Wikipedia entry.
We can even test De Morgan's law, as in the code below:
my @alphabet = 'a'..'z'; my \U = @alphabet.Set; sub postfix:<⁻>(Set $a) { U ⊖ $a } my @sets; @sets.push: Set.new( @alphabet.pick( @alphabet.elems.rand)) for @alphabet; my ($de-Morgan1,$de-Morgan2) = (True,True); for @sets X @sets -> (\A, \B){ $de-Morgan1 &&= (A ∪ B)⁻ === A⁻ ∩ B⁻; $de-Morgan2 &&= (A ∩ B)⁻ === A⁻ ∪ B⁻; } say "1st De Morgan is ", $de-Morgan1; say "2nd De Morgan is ", $de-Morgan2;
We declare ⁻ as the complement operation, which computes the symmetrical difference ⊖ between the Universal set U and our set. Once that is declared, it is relatively easy to express operations such as the complementary of the union of A and B, (A ∪ B)⁻, with a notation that is very close to the original mathematical notation.
Perl 6 can do arithmetic using different data types. Num, Rat and Complex can all operate as a field under the operations of addition, subtraction, multiplication and division (technically, it should be noted that data types dealing with floating point number representations are not a field in the mathematical sense due to the inherent imprecisions of their arithmetic. However, they constitute an approximate enough, computer friendly version of such mathematical objects for most of the cases). The equivalent mathematical fields are:
Perl 6 class | Field |
---|---|
Rat | ℚ |
Num | ℝ |
Complex | ℂ |
The Ints or ℤ, as they're usually called in mathematics, are not a mathematical field but rather a ring, since they are not closed under multiplicative inverses. However, if the integer division div is used, their operations will always yield other integers; if / is used, on the other hand, in general the result will be a Rat.
Besides, Int can do infinite-precision arithmetic (or at least infinite as memory allows; Numeric overflow can still occur), without falling back to Num if the number is too big:
my @powers = 2, 2 ** * ... Inf; say @powers[4].chars; # OUTPUT: «19729»
Also strictly speaking, the Rational class that behaves like a mathematical field is FatRat. For efficiency reasons, operating with Rats will fall back to Num when the numbers are big enough or when there is a big difference between numerator and denominator. FatRat can work with arbitrary precision, the same as the default Int class.
Some modules in the ecosystem can work with additional data types mathematically:
Math::Vector basic operations for vectors.
Math::Matrix operates on matrices rings over numeric rings.
Math::Quaternion operates on the quaternion algebra, ℍ, which are a generalization of complex numbers.
Math::Polynomial works with polynomials, and is able to do simple arithmetic with them.
Math::Symbolic, for symbolic math.
Numbers are duck-typed automatically to the numeric class they actually represent:
.^name.say for (4, ⅗, 1e-9, 3+.1i); # OUTPUT: «IntRatNumComplex»
Arithmetic operations are performed by taking into account the type of operands:
say .33-.22-.11 == 0; # OUTPUT: «True»
In this case, all numbers are interpreted as Rats, which makes the operation exact. In general, most other languages would interpret them as floating point numbers, which can also be achieved in Perl 6 if needed:
say .33.Num -.22.Num - .11.Num; # OUTPUT: «1.3877787807814457e-17»
For cases such as this, Perl 6 also includes an approximately equal operator, ≅
say .33.Num -.22.Num - .11.Num ≅ 0; # OUTPUT: «True»
A sequence is an enumerated collection of objects in which repetitions are allowed, and also a first-class data type in Perl 6 called Seq. Seq is able to represent infinite sequences, like the natural numbers:
my \𝕟 = 1,2 … ∞; say 𝕟[3]; # OUTPUT: «4»
Infinite sequences use ∞, Inf or * (Whatever) as terminator. … is the list generator, which in fact can understand arithmetic and geometric progression sequences as long as you insert the first numbers:
say 1,5,9 … * > 100; # OUTPUT: «(1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 97 101)» say 1,3,9 … * > 337; # OUTPUT: «(1 3 9 27 81 243 729)»
The first sequence will be terminated when the generated number is bigger than 100; the second sequence, which is a geometric progression, when it is bigger than 337.
The fact that an arbitrary generator can be used makes easy to generate sequences such as Fibonacci numbers:
say 1,1, * + * … * > 50;# OUTPUT: «(1 1 2 3 5 8 13 21 34 55)»
We can, in fact, compute the approximation to the golden ratio this way:
my @phis = (2.FatRat, 1 + 1 / * ... *); my @otherphi = (1 - @phis[200], 1 + 1 / * ... *); say @otherphi[^10, |(20, 30 ... 100)]; # OUTPUT: # «((-0.61803398874989484820458683436563811772030918 # -0.61803398874989484820458683436563811772030918 # -0.61803398874989484820458683436563811772030918 # -0.61803398874989484820458683436563811772030918 # -0.61803398874989484820458683436563811772030918 # -0.618033…»
The Math::Sequences module includes many mathematical sequences, already defined for you. It has many sequences from the encyclopedia, some of them with their original name, such as ℤ.
Some set operators also operate on sequences, and they can be used to find out if an object is part of it:
say 876 ∈ (7,14 … * > 1000) ; # OUTPUT: «False»
In this particular case, we can find out if 876 is a multiple of 7 straight away, but the same principle holds for other sequences using complicated generators. And we can use set inclusion operators too:
say (55,89).Set ⊂ (1,1, * + * … * > 200); # OUTPUT: «True»
That said, it does not take into account if it is effectively a subsequence, just the presence of the two elements here. Sets have no order, and even if you don't explicitly cast the subsequence into a Set or explicitly cast it into a Seq it will be coerced into such for the application of the inclusion operator.
Perl 6 includes a set of mathematical constants:
say π; # OUTPUT: «3.141592653589793» say τ; # Equivalent to 2π; OUTPUT: «6.283185307179586» say 𝑒; # OUTPUT: «2.718281828459045»
These constants are also available through ASCII equivalents: e, pi and tau.
The Math::Constants module includes an additional series of physical and mathematical constants such as the previously mentioned golden ratio φ or the Planck's constant ℎ.
Since Perl 6 allows for definition of variables that use Unicode graphemes, and also variable and constant names without any kind of sigil, it is considered a good practice to use the actual mathematical name of concepts to denominate them wherever possible.
Perl 6 is an amazing programming language, and of course, you can do a lot of cool math with it. A great amount of work during an applied mathematician's work is to simulate the models they create. For this reason, in every coding language, a numerical integrator is a must-have. Learning how to do this in Perl 6 can be very useful.
In Perl 6 there are some modules in the ecosystem that can make it easier:
Math::Model which lets you write mathematical and physical models in an easy and natural way.
Math::RungeKutta Runge-Kutta integration for systems of ordinary, linear differential equations.
For this example we are going to use Math::Model for its useful syntax, but remember that this module requires Math::RungeKutta as well. Simply install them with zef before using these examples.
Let's start with the 'Hello World' of mathematical Ecology: Malthusian growth model. A Malthusian growth model, sometimes called a simple exponential growth model, is essentially exponential growth based on the idea of the function being proportional to the speed to which the function grows. The equation, then, looks like this:
dx/dt = g*x
x(0) = x_0
Where g is the population growth rate, sometimes called Malthusian parameter.
How can we translate that into Perl 6? Well Math::Model brings some help with a very understandable way to do that:
use Math::Model; my $m = Math::Model.new( derivatives => { velocity => 'x', }, variables => { velocity => { $:growth_constant * $:x }, growth_constant => { 1 }, # basal growth rate }, initials => { x => 3, }, captures => ('x'), ); $m.integrate(:from(0), :to(8), :min-resolution(0.5)); $m.render-svg('population growth malthus.svg', :title('population growth'));
To fully understand what is going on, let's go through it step by step.
First we load the module that make the calculations: Math::Model.
use Math::Model;
We create the model to add all the information in it.
my $m = Math::Model.new(
We declare the derivatives that are in our model. In this case, if you remember our equation, we have our variable x and its derivative x' (usually know as the velocity).
derivatives => { velocity => 'x', },
After that, we declare how our models evolve. We just need formulas for the derivatives that are not also integration variables (in this case, only x), and for other variables we use in the formulas (the growth rate).
variables => { velocity => { $:growth_constant * $:x}, growth_constant => { 1 }, # basal growth rate },
Finally we declare our initial conditions and use captures to tell Math::Model which variable or variables to record while the simulation is running.
initials => { x => 3, }, captures => ('x'),
At this point our model is set. We need to run the simulation and render a cool plot about our results:
$m.integrate(:from(0), :to(8), :min-resolution(0.5)); $m.render-svg('population growth malthus.svg', :title('population growth'));
There, we select our time limits and the resolution. Next, we generate a plot. All understood? Well, let's see our result!
Looks great! But to be honest, it is quite unrepresentative. Let's explore other examples from more complex situations!
Resources aren't infinite and our population is not going to grow forever. P-F Verhulst thought the same thing, so he presented the logistic model. This model is a common model of population growth, where the rate of reproduction is proportional to both the existing population and the amount of available resources, all else being equal. It looks like this:
dx/dt = g*x*(1-x/k)
x(0)=x_0
where the constant g defines the growth rate and k is the carrying capacity. Modifying the above code we can simulate its behavior in time:
use Math::Model; my $m = Math::Model.new( derivatives => { velocity => 'x', }, variables => { velocity => { $:growth_constant * $:x - $:growth_constant * $:x * $:x / $:k }, growth_constant => { 1 }, # basal growth rate k => { 100 }, # carrying capacity }, initials => { x => 3, }, captures => ('x'), ); $m.integrate(:from(0), :to(8), :min-resolution(0.5)); $m.render-svg('population growth logistic.svg', :title('population growth'));
Let's look at our cool plot: link to the image
As you can see population growths till a maximum.
Interesting, isn't it? Even if these equations seem basic they are linked to a lot of behaviors in our world, like tumor growth. But, before end, let me show you a curious case. Logistic model could be accurate but... What happens when, from a certain threshold, the population size is so small that the survival rate and / or the reproductive rate drops due to the individual's inability to find other ones?
Well, this is an interesting phenomenon described by W.C.Allee, usually known as Allee effect. A simple way to obtain different behaviors associated with this effect is to use the logistic model as a departure, add some terms, and get a cubic growth model like this one:
dx/dt=r*x*(x/a-1)*(1-x/k)
where all the constants are the same as before and A is called critical point.
Our code would be:
use Math::Model; my $m = Math::Model.new( derivatives => { velocity_x => 'x', }, variables => { velocity_x => { $:growth_constant * $:x *($:x/$:a -1)*(1- $:x/$:k) }, growth_constant => { 0.7 }, # basal growth rate k => { 100 }, # carrying capacity a => { 15 }, # critical point }, initials => { x => 15, }, captures => ('x'), ); $m.integrate(:from(0), :to(100), :min-resolution(0.5)); $m.render-svg('population growth allee.svg', :title('population growth'));
Try to execute this one yourself to see the different behaviors that arise when you change the initial condition around the critical point!
Whilst the strong Allee effect is a demographic Allee effect with a critical population size or density, the weak Allee effect is a demographic Allee effect without a critical population size or density, i.e., a population exhibiting a weak Allee effect will possess a reduced per capita growth rate at lower population density or size. However, even at this low population size or density, the population will always exhibit a positive per capita growth rate. This model differs lightly from the strong one, getting a new formula:
dx/dt=r*x*(1-x/k)*(x/a)**n, with n>0
Our code would be:
use Math::Model; my $m = Math::Model.new( derivatives => { velocity_x => 'x', }, variables => { velocity_x => { $:growth_constant * $:x *(1- $:x/$:k)*($:x/$:a)**$:n }, growth_constant => { 0.7 }, # basal growth rate k => { 100 }, # carrying capacity a => { 15 }, # critical point n => { 4 } }, initials => { x => 15, }, captures => ('x'), ); $m.integrate(:from(0), :to(100), :min-resolution(0.5)); $m.render-svg('population growth allee.svg', :title('population growth'));
Do you like physics? Check the original post by the creator of the modules that have been used, Moritz Lenz: https://perlgeek.de/blog-en/perl-6/physical-modelling.html.
Input methods for unicode characters in terminals, the shell, and editors
Perl 6 allows the use of unicode characters as variable names. Many operators are defined with unicode symbols (in particular the set/bag operators) as well as some quoting constructs. Hence it is good to know how to enter these symbols into editors, the Perl 6 shell and the command line, especially if the symbols aren't available as actual characters on a keyboard.
General information about entering unicode under various operating systems and environments can be found on the Wikipedia unicode input page.
Xorg includes digraph support using a Compose key . The default of AltGr + Shift can be remapped to something easier such as Capslock. In GNOME 2 and MATE this can be setup under Preferences → Keyboard → Layouts → Options → Position of Compose Key. So, for example, to input »+« you could type CAPSLOCK > > + CAPSLOCK < <
XCompose allows customizing the digraph sequences using a .XCompose file and https://github.com/kragen/xcompose/blob/master/dotXCompose is an extremely complete one. In GNOME, XCompose was overridden and replaced with a hardcoded list, but it is possible to restore XCompose by setting GTK_IM_MODULE=xim in your environment. It might be necessary to install a xim bridge as well, such as uim-xim.
You may have issues using the compose key in all programs. In that case you can try ibus.
input_module=xim export GTK_IM_MODULE=$input_module export XMODIFIERS=@im=$input_module export QT_IM_MODULE=$input_module
If you want this to be for all users you can put this in a file /etc/profile.d/compose.sh, which is the easiest way, since you won't have to deal with how different GUI environments set up their environment variables.
If you use KDE you can put this file in ~/.config/plasma-workspace/env/compose.sh and that should work. Other desktop environments will be different. Look up how to set environment variables in yours or use the system-wide option above.
If you have problems entering high codepoint symbols such as 🐧 using the xim input module, you can instead use ibus. You will have to install the ibus package for your distribution. Then you will have to set it to start on load of your Desktop environment. The command that needs to be run is:
ibus-daemon --xim --verbose --daemonize --replace
Setting --xim should also allow programs not using ibus to still use the xim input method and be backward compatible.
If you are using KDE, open the start menu and type in “Autostart” and click Autostart which should be the first result. In the settings window that opens, click Add program, type in ibus-daemon and click OK. Then go into the Application tab of the window that pops up. In the Command field, enter in the full ibus-daemon command as shown above, with the --desktop option set to --desktop=plasma. Click OK. It should now launch automatically when you log in again.
WinCompose adds compose key functionality to Windows. It can be installed either via the WinCompose releases page on GitHub, or with the Chocolatey package manager.
Once the program is installed and running, right click the tray icon and select Options → Composing → Behavior → Compose Key to set your desired key.
WinCompose has multiple sources to choose from in Options → Composing → Sequences. It is recommended to enable XCompose and disable Xorg, as there are a handful of operators which Xorg does not provide sequences for, and Xorg also has sequences which conflict with operator sequences present in XCompose. Sequences can be viewed by right clicking the tray icon and selecting Show Sequences. If you wish to add your own sequences, you can do so by either adding/modifying .XCompose in %USERPROFILE%, or editing user-defined sequences in the options menu.
Unicode support is enabled in XTerm primarily by setting its utf8 and utf8Fonts options to 1, along with its locale option to UTF-8, in ~/.Xdefaults. Here is a sample configuration that supports displaying enough of unicode to program in Perl 6:
XTerm*faceName: xft:Noto Mono:style=Regular XTerm*faceNameDoublesize: xft:Noto Emoji:style=Regular XTerm*faceSize: 10 XTerm*locale: UTF-8 XTerm*titleModes: 16 XTerm*utf8: 1 XTerm*utf8Fonts: 1 XTerm*utf8Title: true
Similarly to XTerm, unicode support is enabled in URxvt primarily by setting its locale option to en_US.UTF-8 in ~/.Xdefaults. Here is a sample configuration that supports displaying enough of unicode to program in Perl 6:
URxvt*font: xft:Noto Mono:pixelsize=14:style=Regular,\ xft:Noto Emoji:pixelsize=14:style=Regular URxvt*letterSpace: -1 URxvt*locale: en_US.UTF-8 URxvt*skipBuiltInGlyphs: true
At the bash shell, one enters unicode characters by using entering Ctrl-Shift-u, then the unicode code point value followed by enter. For instance, to enter the character for the element-of operator (∈) use the following key combination (whitespace has been added for clarity):
Ctrl-Shift-u 2208 Enter
This also the method one would use to enter unicode characters into the perl6 REPL, if one has started the REPL inside a Unix shell.
GNU Screen does sport a digraph command but with a rather limited digraph table. Thanks to bindkey and exec an external program can be used to insert characters to the current screen window.
bindkey ^K exec .! digraphs
This will bind control-k to the shell command digraphs. You can use digraphs if you prefer a Perl 6 friendly digraph table over RFC 1345 or change it to your needs.
In Vim, unicode characters are entered (in insert-mode) by pressing first Ctrl-V (also denoted ^V), then u and then the hexadecimal value of the unicode character to be entered. For example, the Greek letter λ (lambda) is entered via the key combination:
^Vu03BB
You can also use Ctrl-K/^K along with a digraph to type in some characters. So an alternative to the above using digraphs looks like this:
^Kl*
The list of digraphs Vim provides is documented here; you can add your own with the :digraph command.
Further information about entering special characters in Vim can be found on the Vim Wikia page about entering special characters.
The vim-perl6 plugin for Vim can be configured to optionally replace ASCII based ops with their Unicode based equivalents. This will convert the ASCII based ops on the fly while typing them.
In Emacs, unicode characters are entered by first entering the chord C-x 8 RET at which point the text Unicode (name or hex): appears in the minibuffer. One then enters the unicode code point hexadecimal number followed by the enter key. The unicode character will now appear in the document. Thus, to enter the Greek letter λ (lambda), one uses the following key combination:
C-x 8 RET 3bb RET
Further information about unicode and its entry into Emacs can be found on the Unicode Encoding Emacs wiki page.
You can also use RFC 1345 character mnemonics by typing:
C-x RET C-\ rfc1345 RET
Or C-u C-\ rfc1345 RET.
To type special characters, type & followed by a mnemonic. Emacs will show the possible characters in the echo area. For example, Greek letter λ (lambda) can be entered by typing:
&l*
You can use C-\ to toggle input method.
Another input method you can use to insert special characters is TeX. Select it by typing C-u C-\ TeX RET. You can enter a special character by using a prefix such as \. For example, to enter λ, type:
\lambda
To view characters and sequences provided by an input method, run the describe-input-method command:
C-h I TeX
These characters are used in different languages as quotation marks. In Perl 6 they are used as quoting characters
Constructs such as these are now possible:
say 「What?!」; say ”Whoa!“; say „This works too!”; say „There are just too many ways“; say “here: “no problem” at all!”; # You can nest them!
This is very useful in shell:
perl6 -e 'say ‘hello world’'
since you can just copy and paste some piece of code and not worry about quotes.
These characters are used in French and German as quotation marks. In Perl 6 they are used as interpolation word quotes, hyper operators and as an angle bracket alternative in POD6.
symbol | unicode code point | ascii equivalent |
---|---|---|
« | U+00AB | << |
» | U+00BB | >> |
Thus constructs such as these are now possible:
say (1, 2) »+« (3, 4); # OUTPUT: «(4 6)» - element-wise add [1, 2, 3] »+=» 42; # add 42 to each element of @array say «moo»; # OUTPUT: «moo» my $baa = "foo bar"; say «$baa $baa ber».perl; # OUTPUT: «("foo", "bar", "foo", "bar", "ber")»
The set/bag operators all have set-theory-related symbols, the unicode code points and their ascii equivalents are listed below. To compose such a character, it is merely necessary to enter the character composition chord (e.g. Ctrl-V u in Vim; Ctrl-Shift-u in Bash) then the unicode code point hexadecimal number.
operator | unicode code point | ascii equivalent |
---|---|---|
∈ | U+2208 | (elem) |
∉ | U+2209 | !(elem) |
∋ | U+220B | (cont) |
∌ | U+220C | !(cont) |
⊆ | U+2286 | (<=) |
⊈ | U+2288 | !(<=) |
⊂ | U+2282 | (<) |
⊄ | U+2284 | !(<) |
⊇ | U+2287 | (>=) |
⊉ | U+2289 | !(>=) |
⊃ | U+2283 | (>) |
⊅ | U+2285 | !(>) |
∪ | U+222A | (|) |
∩ | U+2229 | (&) |
∖ | U+2216 | (-) |
⊖ | U+2296 | (^) |
⊍ | U+228D | (.) |
⊎ | U+228E | (+) |
Wikipedia contains a full list of mathematical operators and symbols in unicode as well as links to their mathematical meaning.
Greek characters may be used as variable names. For a list of Greek and Coptic characters and their unicode code points see the Greek in Unicode Wikipedia article.
For example, to assign the value 3 to π, enter the following in Vim (whitespace added to the compose sequences for clarity):
my $ Ctrl-V u 03C0 = 3; # same as: my $π = 3; say $ Ctrl-V u 03C0 ; # 3 same as: say $π;
A limited set of superscripts and subscripts can be created directly in unicode by using the U+207x, U+208x and (less often) the U+209x ranges. However, to produce a value squared (to the power of 2) or cubed (to the power of 3), one needs to use U+00B2 and U+00B3 since these are defined in the Latin1 supplement Unicode block.
Thus, to write the Taylor series expansion around zero of the function exp(x) one would input into e.g. vim the following:
exp(x) = 1 + x + x Ctrl-V u 00B2 /2! + x Ctrl-V u 00B3 /3! + ... + x Ctrl-V u 207F /n! # which would appear as exp(x) = 1 + x + x²/2! + x³/3! + ... + xⁿ/n!
Or to specify the elements in a list from 1 up to k:
A Ctrl-V u 2081 , A Ctrl-V u 2082 , ..., A Ctrl-V u 2096 # which would appear as A₁, A₂, ..., Aₖ
An introduction to grammars
Grammars parse strings and return data structures from those strings. Grammars can be used to prepare a program for execution, to determine if a program can run at all (if it's a valid program), to break down a web page into constituent parts, or to identify the different parts of a sentence, among other things.
If you have strings to tame or interpret, grammars provide the tools to do the job.
The string could be a file that you're looking to break into sections; perhaps a protocol, like SMTP, where you need to specify which "commands" come after what user-supplied data; maybe you're designing your own domain specific language. Grammars can help.
Regular expressions (Regexes) work well for finding patterns in strings. However, for some tasks, like finding multiple patterns at once, or combining patterns, or testing for patterns that may surround strings regular expressions, alone, are not enough.
When working with HTML, you could define a grammar to recognize HTML tags, both the opening and closing elements, and the text in between. You could then organize these elements into data structures, such as arrays or hashes.
Grammars are a special kind of class. You declare and define a grammar exactly as you would any other class, except that you use the grammar keyword instead of class.
grammar G { ... }
As such classes, grammars are made up of methods that define a regex, a token, or a rule. These are all varieties of different types of match methods. Once you have a grammar defined, you call it and pass in a string for parsing.
my $matchObject = G.parse($string);
Now, you may be wondering, if I have all these regexes defined that just return their results, how does that help with parsing strings that may be ahead or backwards in another string, or things that need to be combined from many of those regexes... And that's where grammar actions come in.
For every "method" you match in your grammar, you get an action you can use to act on that match. You also get an overarching action that you can use to tie together all your matches and to build a data structure. This overarching method is called TOP by default.
As already mentioned, grammars are declared using the grammar keyword and its "methods" are declared with regex, or token, or rule.
Regex methods are slow but thorough, they will look back in the string and really try.
Token methods are faster than regex methods and ignore whitespace.
Rule methods are the same as token methods except whitespace is not ignored.
When a method (regex, token or rule) matches in the grammar, the string matched is put into a match object and keyed with the same name as the method.
grammar G { token TOP { <thingy> .* } token thingy { 'clever_text_keyword' } }
If you were to use my $match = G.parse($string) and your string started with 'clever_text_keyword', you would get a match object back that contained 'clever_text_keyword' keyed by the name of <thingy> in your match object. For instance:
grammar G { token TOP { <thingy> .* } token thingy { 'Þor' } } my $match = G.parse("Þor is mighty"); say $match.perl; # OUTPUT: «Match.new(made => Any, pos => 13, orig => "Þor is mighty",...» say $/.perl; # OUTPUT: «Match.new(made => Any, pos => 13, orig => "Þor is mighty",...» say $/<thingy>.perl; # OUTPUT: «Match.new(made => Any, pos => 3, orig => "Þor is mighty", hash => Map.new(()), list => (), from => 0)»
The two first output lines show that $match contains a Match objects with the results of the parsing; but those results are also assigned to the match variable $/. Either match object can be keyed, as indicated above, by thingy to return the match for that particular token.
The TOP method (whether regex, token, or rule) is the overarching pattern that must match everything (by default). If the parsed string doesn't match the TOP regex, your returned match object will be empty (Nil).
As you can see above, in TOP, the <thingy> token is mentioned. The <thingy> is defined on the next line. That means that 'clever_text_keyword' must be the first thing in the string, or the grammar parse will fail and we'll get an empty match. This is great for recognizing a malformed string that should be discarded.
Let's suppose we'd like to parse a URI into the component parts that make up a RESTful request. We want the URIs to work like this:
The first part of the URI will be the "subject", like a part, or a product, or a person.
The second part of the URI will be the "command", the standard CRUD functions (create, retrieve, update, or delete).
The third part of the URI will be arbitrary data, perhaps the specific ID we'll be working with or a long list of data separated by "/"'s.
When we get a URI, we'll want 1-3 above to be placed into a data structure that we can easily work with (and later enhance).
So, if we have "/product/update/7/notify", we would want our grammar to give us a match object that has a subject of "product", a command of "update", and data of "7/notify".
We'll start by defining a grammar class and some match methods for the subject, command, and data. We'll use the token declarator since we don't care about whitespace.
grammar REST { token subject { \w+ } token command { \w+ } token data { .* } }
So far, this REST grammar says we want a subject that will be just word characters, a command that will be just word characters, and data that will be everything else left in the string.
Next, we'll want to arrange these matching tokens within the larger context of the URI. That's what the TOP method allows us to do. We'll add the TOP method and place the names of our tokens within it, together with the rest of the patterns that makes up the overall pattern. Note how we're building a larger regex from our named regexes.
grammar REST { token TOP { '/' <subject> '/' <command> '/' <data> } token subject { \w+ } token command { \w+ } token data { .* } }
With this code, we can already get the three parts of our RESTful request:
my $match = REST.parse('/product/update/7/notify'); say $match; # OUTPUT: «「/product/update/7/notify」 # subject => 「product」 # command => 「update」 # data => 「7/notify」»
The data can be accessed directly by using $match<subject> or $match<command> or $match<data> to return the values parsed. They each contain match objects that you can work further with, such as coercing into a string ( $match<command>.Str ).
So far, the grammar will handle retrieves, deletes and updates. However, a create command doesn't have the third part (the data portion). This means the grammar will fail to match if we try to parse a create URI. To avoid this, we need to make that last data position match optional, along with the '/' preceding it. This is accomplished by adding a question mark to the grouped '/' and data components of the TOP token, to indicate their optional nature, just like a normal regex.
So, now we have:
grammar REST { token TOP { '/' <subject> '/' <command> [ '/' <data> ]? } token subject { \w+ } token command { \w+ } token data { .* } } my $m = REST.parse('/product/create'); say $m<subject>, $m<command>; # OUTPUT: «「product」「create」»
Next, assume that the URIs will be entered manually by a user and that the user might accidentally put spaces between the '/'s. If we wanted to accommodate for this, we could replace the '/'s in TOP with a token that allowed for spaces.
grammar REST { token TOP { <slash><subject><slash><command>[<slash><data>]? } token subject { \w+ } token command { \w+ } token data { .* } token slash { \s* '/' \s* } } my $m = REST.parse('/ product / update /7 /notify'); say $m; # OUTPUT: «「/ product / update /7 /notify」 # slash => 「/ 」 # subject => 「product」 # slash => 「 / 」 # command => 「update」 # slash => 「 /」 # data => 「7 /notify」»
We're getting some extra junk in the match object now, with those slashes. There's techniques to clean that up that we'll get to later.
Since grammars are classes, they behave, OOP-wise, in the same way as any other class; specifically, they can inherit from base classes that include some tokens or rules, this way:
grammar Letters { token letters { \w+ } } grammar Quote-Quotes { token quote { "\""|"`"|"'" } } grammar Quote-Other { token quote { "|"|"/"|"¡" } } grammar Quoted-Quotes is Letters is Quote-Quotes { token TOP { ^ <quoted> $} token quoted { <quote>? <letters> <quote>? } } grammar Quoted-Other is Letters is Quote-Other { token TOP { ^ <quoted> $} token quoted { <quote>? <letters> <quote>? } } my $quoted = q{"enhanced"}; my $parsed = Quoted-Quotes.parse($quoted); say $parsed; #OUTPUT: #「"enhanced"」 # quote => 「"」 # letters => 「enhanced」 #quote => 「"」 $quoted = "|barred|"; $parsed = Quoted-Other.parse($quoted); say $parsed; #OUTPUT: #|barred|」 #quote => 「|」 #letters => 「barred」 #quote => 「|」
This example uses multiple inheritance to compose two different grammars by varying the rules that correspond to quotes. In this case, besides, we are rather using composition than inheritance, so we could use Roles instead of inheritance.
role Letters { token letters { \w+ } } role Quote-Quotes { token quote { "\""|"`"|"'" } } role Quote-Other { token quote { "|"|"/"|"¡" } } grammar Quoted-Quotes does Letters does Quote-Quotes { token TOP { ^ <quoted> $} token quoted { <quote>? <letters> <quote>? } } grammar Quoted-Other does Letters does Quote-Other { token TOP { ^ <quoted> $} token quoted { <quote>? <letters> <quote>? } }
Will output exactly the same as the code above. Symptomatic of the difference between Classes and Roles, a conflict like defining token quote twice using Role composition will result in an error:
grammar Quoted-Quotes does Letters does Quote-Quotes does Quote-Other { ... } # OUTPUT: ... Error while compiling ... Method 'quote' must be resolved ...
We want our RESTful grammar to allow for CRUD operations only. Anything else we want to fail to parse. That means our "command" above should have one of four values: create, retrieve, update or delete.
There are several ways to accomplish this. For example, you could change the command method:
token command { \w+ } # …becomes… token command { 'create'|'retrieve'|'update'|'delete' }
For a URI to parse successfully, the second part of the string between '/'s must be one of those CRUD values, otherwise the parsing fails. Exactly what we want.
There's another technique that provides greater flexibility and improved readability when options grow large: proto-regexes.
To utilize these proto-regexes (multimethods, in fact) to limit ourselves to the valid CRUD options, we'll replace token command with the following:
proto token command {*} token command:sym<create> { <sym> } token command:sym<retrieve> { <sym> } token command:sym<update> { <sym> } token command:sym<delete> { <sym> }
The sym keyword is used to create the various proto-regex options. Each option is named (e.g., sym<update>), and for that option's use, a special <sym> token is auto-generated with the same name.
The <sym> token, as well as other user-defined tokens, may be used in the proto-regex option block to define the specific match condition. Regex tokens are compiled forms and, once defined, cannot subsequently be modified by adverb actions (e.g., :i). Therefore, as it's auto-generated, the special <sym> token is useful only where an exact match of the option name is required.
If, for one of the proto-regex options, a match condition occurs, then the whole proto's search terminates. The matching data, in the form of a match object, is assigned to the parent proto token. If the special <sym> token was employed and formed all or part of the actual match, then it's preserved as a sub-level in the match object, otherwise it's absent.
Using proto-regex like this gives us a lot of flexibility. For example, instead of returning <sym>, which in this case is the entire string that was matched, we could instead enter our own string, or do other funny stuff. We could do the same with the token subject method and limit it also to only parsing correctly on valid subjects (like 'part' or 'people', etc.).
This is what we have for processing our RESTful URIs, so far:
grammar REST { token TOP { <slash><subject><slash><command>[<slash><data>]? } proto token command {*} token command:sym<create> { <sym> } token command:sym<retrieve> { <sym> } token command:sym<update> { <sym> } token command:sym<delete> { <sym> } token subject { \w+ } token data { .* } token slash { \s* '/' \s* } }
Let's look at various URIs and see how they work with our grammar.
my @uris = ['/product/update/7/notify', '/product/create', '/item/delete/4']; for @uris -> $uri { my $m = REST.parse($uri); say "Sub: $m<subject> Cmd: $m<command> Dat: $m<data>"; } # OUTPUT: «Sub: product Cmd: update Dat: 7/notify # Sub: product Cmd: create Dat:  # Sub: item Cmd: delete Dat: 4»
Note that since <data> matches nothing on the second string, $m<data> will be Nil, then using it in string context in the say function warns.
With just this part of a grammar, we're getting almost everything we're looking for. The URIs get parsed and we get a data structure with the data.
The data token returns the entire end of the URI as one string. The 4 is fine. However from the '7/notify', we only want the 7. To get just the 7, we'll use another feature of grammar classes: actions.
Grammar actions are used within grammar classes to do things with matches. Actions are defined in their own classes, distinct from grammar classes.
You can think of grammar actions as a kind of plug-in expansion module for grammars. A lot of the time you'll be happy using grammars all by their own. But when you need to further process some of those strings, you can plug in the Actions expansion module.
To work with actions, you use a named parameter called actions which should contain an instance of your actions class. With the code above, if our actions class called REST-actions, we would parse the URI string like this:
my $matchObject = REST.parse($uri, actions => REST-actions.new); # …or if you prefer… my $matchObject = REST.parse($uri, :actions(REST-actions.new));
If you name your action methods with the same name as your grammar methods (tokens, regexes, rules), then when your grammar methods match, your action method with the same name will get called automatically. The method will also be passed the corresponding match object (represented by the $/ variable).
Let's turn to an example.
Here we are back to our grammar.
grammar REST { token TOP { <slash><subject><slash><command>[<slash><data>]? } proto token command {*} token command:sym<create> { <sym> } token command:sym<retrieve> { <sym> } token command:sym<update> { <sym> } token command:sym<delete> { <sym> } token subject { \w+ } token data { .* } token slash { \s* '/' \s* } }
Recall that we want to further process the data token "7/notify", to get the 7. To do this, we'll create an action class that has a method with the same name as the named token. In this case, our token is named data so our method is also named data.
class REST-actions { method data($/) { $/.split('/') } }
Now when we pass the URI string through the grammar, the data token match will be passed to the REST-actions' data method. The action method will split the string by the '/' character and the first element of the returned list will be the ID number (7 in the case of "7/notify").
But not really; there's a little more.
If the grammar calls the action above on data, the data method will be called, but nothing will show up in the big TOP grammar match result returned to our program. In order to make the action results show up, we need to call make on that result. The result can be many things, including strings, array or hash structures.
You can imagine that the make places the result in a special contained area for a grammar. Everything that we make can be accessed later by made.
So instead of the REST-actions class above, we should write:
class REST-actions { method data($/) { make $/.split('/') } }
When we add make to the match split (which returns a list), the action will return a data structure to the grammar that will be stored separately from the data token of the original grammar. This way, we can work with both if we need to.
If we want to access just the ID of 7 from that long URI, we access the first element of the list returned from the data action that we made:
my $uri = '/product/update/7/notify'; my $match = REST.parse($uri, actions => REST-actions.new); say $match<data>.made[0]; # OUTPUT: «7» say $match<command>.Str; # OUTPUT: «update»
Here we call made on data, because we want the result of the action that we made (with make) to get the split array. That's lovely! But, wouldn't it be lovelier if we could make a friendlier data structure that contained all of the stuff we want, rather than having to coerce types and remember arrays?
Just like Grammar's TOP, which matches the entire string, actions have a TOP method as well. We can make all of the individual match components, like data or subject or command, and then we can place them in a data structure that we will make in TOP. When we return the final match object, we can then access this data structure.
To do this, we add the method TOP to the action class and make whatever data structure we like from the component pieces.
So, our action class becomes:
class REST-actions { method TOP ($/) { make { subject => $<subject>.Str, command => $<command>.Str, data => $<data>.made } } method data($/) { make $/.split('/') } }
Here in the TOP method, the subject remains the same as the subject we matched in the grammar. Also, command returns the valid <sym> that was matched (create, update, retrieve, or delete). We coerce each into .Str, as well, since we don't need the full match object.
We want to make sure to use the made method on the $<data> object, since we want to access the split one that we made with make in our action, rather than the proper $<data> object.
After we make something in the TOP method of a grammar action, we can then access all the custom values by calling the made method on the grammar result object. The code now becomes
my $uri = '/product/update/7/notify'; my $match = REST.parse($uri, actions => REST-actions.new); my $rest = $match.made; say $rest<data>[0]; # OUTPUT: «7» say $rest<command>; # OUTPUT: «update» say $rest<subject>; # OUTPUT: «product»
If the complete return match object is not needed, you could return only the made data from your action's TOP.
my $uri = '/product/update/7/notify'; my $rest = REST.parse($uri, actions => REST-actions.new).made; say $rest<data>[0]; # OUTPUT: «7» say $rest<command>; # OUTPUT: «update» say $rest<subject>; # OUTPUT: «product»
Oh, did we forget to get rid of that ugly array element number? Hmm. Let's make something new in the grammar's custom return in TOP... how about we call it subject-id and have it set to element 0 of <data>.
class REST-actions { method TOP ($/) { make { subject => $<subject>.Str, command => $<command>.Str, data => $<data>.made, subject-id => $<data>.made[0] } } method data($/) { make $/.split('/') } }
Now we can do this instead:
my $uri = '/product/update/7/notify'; my $rest = REST.parse($uri, actions => REST-actions.new).made; say $rest<command>; # OUTPUT: «update» say $rest<subject>; # OUTPUT: «product» say $rest<subject-id>; # OUTPUT: «7»
Here's the final code:
grammar REST { token TOP { <slash><subject><slash><command>[<slash><data>]? } proto token command {*} token command:sym<create> { <sym> } token command:sym<retrieve> { <sym> } token command:sym<update> { <sym> } token command:sym<delete> { <sym> } token subject { \w+ } token data { .* } token slash { \s* '/' \s* } } class REST-actions { method TOP ($/) { make { subject => $<subject>.Str, command => $<command>.Str, data => $<data>.made, subject-id => $<data>.made[0] } } method data($/) { make $/.split('/') } }
Above we see how to associate grammars with action objects and perform actions on the match object. However, when we want to deal with the match object, that isn't the only way. See the example below:
grammar G { rule TOP { <function-define> } rule function-define { 'sub' <identifier> { say "func " ~ $<identifier>.made; make $<identifier>.made; } '(' <parameter> ')' '{' '}' { say "end " ~ $/.made; } } token identifier { \w+ { make ~$/; } } token parameter { \w+ { say "param " ~ $/; } } } G.parse('sub f ( a ) { }'); # OUTPUT: «func fparam aend f»
This example is a reduced portion of a parser. Let's focus more on the feature it shows.
First, we can add actions inside the grammar itself, and such actions are performed once the control flow of the regex arrives at them. Note that action object's method will always be performed after the whole regex item matched. Second, it shows what make really does, which is no more than a sugar of $/.made = .... And this trick introduces a way to pass messages from within a regex item.
Hopefully this has helped introduce you to the grammars in Perl 6 and shown you how grammars and grammar action classes work together. For more information, check out the more advanced Perl Grammar Guide.
For more grammar debugging, see Grammar::Debugger. This provides breakpoints and color-coded MATCH and FAIL output for each of your grammar tokens.
File-related operations
Here we present a quick overview of the file-related input/output operations. Details can be found in the documentation for the IO role, as well as the IO::Handle and IO::Path types.
One way to read the contents of a file is to open the file via the open function with the :r (read) file mode option and slurp in the contents:
my $fh = open "testfile", :r; my $contents = $fh.slurp; $fh.close;
Here we explicitly close the filehandle using the close method on the IO::Handle object. This is a very traditional way of reading the contents of a file. However, the same can be done more easily and clearly like so:
my $contents = "testfile".IO.slurp; # or in procedural form: $contents = slurp "testfile"
By adding the IO role to the file name string, we are effectively able to refer to the string as the file object itself and thus slurp in its contents directly. Note that the slurp takes care of opening and closing the file for you.
Of course, we also have the option to read a file line-by-line. The new line separator (i.e., $*IN.nl-in) will be excluded.
for 'huge-csv'.IO.lines -> $line { # Do something with $line } # or if you'll be processing later my @lines = 'huge-csv'.IO.lines;
To write data to a file, again we have the choice of the traditional method of calling the open function – this time with the :w (write) option – and printing the data to the file:
my $fh = open "testfile", :w; $fh.print("data and stuff\n"); $fh.close;
Or equivalently with say, thus the explicit newline is no longer necessary:
my $fh = open "testfile", :w; $fh.say("data and stuff"); $fh.close;
We can simplify this by using spurt to open the file in write mode, writing the data to the file and closing it again for us:
spurt "testfile", "data and stuff\n";
By default all (text) files are written as UTF-8, however if necessary, an explicit encoding can be specified via the :enc option:
spurt "testfile", "latin1 text: äöüß", enc => "latin1";
To write formatted strings to a file, use the printf function of IO::Handle.
my $fh = open "testfile", :w; $fh.printf("formatted data %04d\n", 42); $fh.close;
To append to a file, specify the :a option when opening the filehandle explicitly,
my $fh = open "testfile", :a; $fh.print("more data\n"); $fh.close;
or equivalently with say, thus the explicit newline is no longer necessary,
my $fh = open "testfile", :a; $fh.say("more data"); $fh.close;
or even simpler with the :append option in the call to spurt:
spurt "testfile", "more data\n", :append;
To explicitly write binary data to a file, open it with the :bin option. The input/output operations then will take place using the Buf type instead of the Str type.
Routines copy, rename, and move are available to avoid low-level system commands. See details at copy, rename, and move. Some examples:
my $filea = 'foo'; my $fileb = 'foo.bak'; my $filec = '/disk1/foo'; # note 'diskN' is assumed to be a physical storage device copy $filea, $fileb; # overwrites $fileb if it exists copy $filea, $fileb, :createonly; # fails if $fileb exists rename $filea, 'new-foo'; # overwrites 'new-foo' if it exists rename $filea, 'new-foo', :createonly; # fails if 'new-foo' exists # use move when a system-level rename may not work move $fileb, '/disk2/foo'; # overwrites '/disk2/foo' if it exists move $fileb, '/disk2/foo', :createonly; # fails if '/disk2/foo' exists
Use the e method on an IO::Handle object to test whether the file or directory exists.
if "nonexistent_file".IO.e { say "file exists"; } else { say "file doesn't exist"; }
It is also possible to use the colon pair syntax to achieve the same thing:
if "path/to/file".IO ~~ :e { say 'file exists'; }
my $file = "path/to/file"; if $file.IO ~~ :e { say 'file exists'; }
Similarly to the file existence check, one can also check to see if a path is a directory. For instance, assuming that the file testfile and the directory lib exist, we would obtain from the existence test method e the same result, namely that both exist:
say "testfile".IO.e; # OUTPUT: «True» say "lib".IO.e; # OUTPUT: «True»
However, since only one of them is a directory, the directory test method d will give a different result:
say "testfile".IO.d; # OUTPUT: «False» say "lib".IO.d; # OUTPUT: «True»
Naturally the tables are turned if we check to see if the path is a file via the file test method f:
say "testfile".IO.f; # OUTPUT: «True» say "lib".IO.f; # OUTPUT: «False»
There are other methods that can be used to query a file or directory, some useful ones are:
my $f = "file"; say $f.IO.modified; # return time of last file (or directory) change say $f.IO.accessed; # return last time file (or directory) was read say $f.IO.s; # return size of file (or directory inode) in bytes
See more methods and details at IO::Path.
To list the contents of the current directory, use the dir function. It returns a list of IO::Path objects.
say dir; # OUTPUT: «"/path/to/testfile".IO "/path/to/lib".IO»
To list the files and directories in a given directory, simply pass a path as an argument to dir:
say dir "/etc/"; # OUTPUT: «"/etc/ld.so.conf".IO "/etc/shadow".IO ....»
To create a new directory, simply call the mkdir function with the directory name as its argument:
mkdir "newdir";
The function returns the name of the created directory on success and Nil on failure. Thus the standard Perl idiom works as expected:
mkdir "newdir" or die "$!";
Use rmdir to remove empty directories:
rmdir "newdir" or die "$!";
Programs running other programs and communicating with them
Many programs need to be able to run other programs, and we need to pass information to them and receive their output and exit status. Running a program in Perl 6 is as easy as:
run 'git', 'status';
This line runs the program named "git" and passes "git" and "status" to its command-line. It will find the program using the %*ENV<PATH> setting.
If you would like to run a program by sending a command-line to the shell, there's a tool for that as well. All shell meta characters are interpreted by the shell, including pipes, redirects, environment variable substitutions and so on.
shell 'ls -lR | gzip -9 > ls-lR.gz';
Caution should be taken when using shell with user input.
Both run and shell return a Proc object, which can be used to communicate with the process in more detail. Please note that unless you close all output pipes, the program will usually not terminate.
my $git = run 'git', 'log', '--oneline', :out; for $git.out.lines -> $line { my ($sha, $subject) = $line.split: ' ', 2; say "$subject [$sha]"; } $git.out.close();
If the program fails (exits with a non-zero exit code), it will throw an exception when the returned Proc object is sunk. You can save it into a variable, even anonymous one, to prevent the sinking:
$ = run '/bin/false'; # does not sink the Proc and so does not throw
You can tell the Proc object to capture output as a filehandle by passing the :out and :err flags. You may also pass input via the :in flag.
my $echo = run 'echo', 'Hello, world', :out; my $cat = run 'cat', '-n', :in($echo.out), :out; say $cat.out.get; $cat.out.close();
You may also use Proc to capture the PID, send signals to the application, and check the exitcode.
my $crontab = run 'crontab', '-l'; if $crontab.exitcode == 0 { say 'crontab -l ran ok'; } else { say 'something went wrong'; }
When you need more control over the communication with and from another process, you will want to make use of Proc::Async. This class provides support for asynchronous communication with a program, as well as the ability to send signals to that program.
# Get ready to run the program my $log = Proc::Async.new('tail', '-f', '/var/log/system.log'); $log.stdout.tap(-> $buf { print $buf }); $log.stderr.tap(-> $buf { $*ERR.print($buf) }); # Start the program my $done = $log.start; sleep 10; # Tell the program to stop $log.kill('QUIT'); # Wait for the program to finish await $done;
The small program above uses the "tail" program to print out the contents of the log named system.log for 10 seconds and then tells the program to stop with a QUIT signal.
Whereas Proc provides access to output using IO::Handles, Proc::Async provides access using asynchronous supplies (see Supply).
If you want to run a program and do some work while you wait for the original program to finish, the start routine returns a Promise, which is kept when the program quits.
Use the write method to pass data into the program.
Functionalities available for visiting all items in a complex data structure
Perl 6 is a functional language, but functions need something to hold on to when working on complex data structures. In particular, they need a uniform interface that can be applied to all data structures in the same way. One of these kind of interfaces is provided by the Iterator and Iterable roles.
The Iterable role is relatively simple. It provides a stub for the iterator method, which is the one actually used by statements such as for. for will call .iterator on the variable it precedes, and then run a block once for every item. Other methods, such as array assignment, will make the Iterable class behave in the same way.
class DNA does Iterable { has $.chain; method new ($chain where { $chain ~~ /^^ <[ACGT]>+ $$ / and $chain.chars %% 3 } ) { self.bless( :$chain ); } method iterator(DNA:D:){ $.chain.comb.rotor(3).iterator } }; my @longer-chain = DNA.new('ACGTACGTT'); say @longer-chain.perl; # OUTPUT: «[("A", "C", "G"), ("T", "A", "C"), ("G", "T", "T")]» say @longer-chain».join("").join("|"); #OUTPUT: «ACG|TAC|GTT»
In this example, which is an extension of the example in Iterable that shows how for calls .iterator, the iterator method will be called in the appropriate context only when the created object is assigned to a Positional variable, @longer-chain; this variable is an Array and we operate on it as such in the last example.
The (maybe a bit confusingly named) Iterator role is a bit more complex than Iterable. First, it provides a constant, IterationEnd. Then, it also provides a series of methods such as .pull-one, which allows for a finer operation of iteration in several contexts: adding or eliminating items, or skipping over them to access other items. In fact, the role provides a default implementation for all the other methods, so the only one that has to be defined is precisely pull-one, of which only a stub is provided by the role. While Iterable provides the high-level interface loops will be working with, Iterator provides the lower-level functions that will be called in every iteration of the loop. Let's extend the previous example with this role.
class DNA does Iterable does Iterator { has $.chain; has Int $!index = 0; method new ($chain where { $chain ~~ /^^ <[ACGT]>+ $$ / and $chain.chars %% 3 } ) { self.bless( :$chain ); } method iterator( ){ self } method pull-one( --> Mu){ if $!index < $.chain.chars { my $codon = $.chain.comb.rotor(3)[$!index div 3]; $!index += 3; return $codon; } else { return IterationEnd; } } }; my $a := DNA.new('GAATCC'); .say for $a; # OUTPUT: «(G A A)(T C C)»
We declare a DNA class which does the two roles, Iterator and Iterable; the class will include a string that will be constrained to have a length that is a multiple of 3 and composed only of ACGT.
Let us look at the pull-one method. This one is going to be called every time a new iteration occurs, so it must keep the state of the last one. An $.index attribute will hold that state across invocations; pull-one will check if the end of the chain has been reached and will return the IterationEnd constant provided by the role. Implementing this low-level interface, in fact, simplifies the implementation of the Iterable interface. Now the iterator will be the object itself, since we can call pull-one on it to access every member in turn; .iterator will thus return just self; this is possible since the object will be, at the same time, Iterable and Iterator.
This need not always be the case, and in most cases .iterator will have to build an iterator type to be returned (that will, for instance, keep track of the iteration state, which we are doing now in the main class), such as we did in the previous example; however, this example shows the minimal code needed to build a class that fulfills the iterator and iterable roles.
for and other loops place the item produced in every iteration into the topic variable $_, or capture them into the variables that are declared along with the block. These variables can be directly used inside the loop, without needing to declare them, by using the ^ twigil.
Implicit iteration occurs when using the sequence operator.
say 1,1,1, { $^a²+2*$^b+$^c } … * > 300; # OUTPUT: «(1 1 1 4 7 16 46 127 475)
The generating block is being run once while the condition to finish the sequence, in this case the term being bigger than 300, is not met. This has the side effect of running a loop, but also creating a list that is output.
This can be done more systematically through the use of the gather/take blocks, which are a different kind of iterating construct that instead of running in sink context, returns an item every iteration. This Advent Calendar tutorial explains use cases for this kind of loops; in fact, gather is not so much a looping construct, but a statement prefix that collects the items produced by take and creates a list out of them.
Classic for loops, with a loop variable being incremented, can be done in Perl 6 through the loop keyword. Other repeat and while loops are also possible.
However, in general, they are discouraged. Perl 6 is a functional and concurrent language; when coding in Perl 6, you should look at loops in a functional way: processing, one by one, the items produced by an iterator, that is, feeding an item to a block without any kind of secondary effects. This functional view allows also easy parallelization of the operation via the hyper or race auto-threading methods.
If you feel more comfortable with your good old loops, the language allows you to use them. However, it is considered more p6y to try and use, whenever possible, functional and concurrent iterating constructs.
*Note: Since version 6.d loops can produce a list of values from the values of last statements.*
What can help you write/test/improve your module(s)
Here is a list of modules that you can find in the Perl 6 ecosystem which aim to make the experience of developing Perl 6 modules more fun.
Some modules and tools to help you with generating files that are part of a module distribution.
App::Assixt The module developer's assistant
App::Mi6 Minimal authoring tool for Perl 6
META6 Do things with Perl 6 META files
Module::Skeleton Generate a skeleton module
p6doc Generate documentation end-products
Some tests of module quality.
Test::META Test your META6.json file
Test::Output Test the output to STDOUT and STDERR your program generates
Test::Screen Use GNU screen to test full screen VT applications
Test::When Control when your tests are run (author testing, online testing, etc.)
Here some modules to help you work with NativeCall.
NativeHelpers::Array Provides routines to deal with CArray
App::GPTrixie Generate NativeCall code from C headers file
NativeCall::TypeDiag Provides routines to test your CStruct
Modules that exist only as minimalist examples, tests for installers, or skeletons.
Foo A module with two distributions of different versions
Creating module packages for code reuse
N.B. "Module" is an overloaded term in Perl 6; this document focuses on use of the module declarator.
Modules, like classes and grammars, are a kind of package. Module objects are instances of the ModuleHOW metaclass; this provides certain capabilities useful for creating namespaces, versioning, delegation and data encapsulation (see also class and role).
To create a module, use the module declarator:
module M {} say M.HOW; # OUTPUT: «Perl6::Metamodel::ModuleHOW.new»
Here we define a new module named M; introspection with HOW confirms that the metaclass underlying M is Perl6::Metamodel::ModuleHOW.
Modules are primarily useful for encapsulating code and data that do not belong inside a class or role definition. Module contents (classes, subroutines, variables, etc.) can be exported from a module with the is export trait; these are available in the caller's namespace once the module has been imported with import or use. A module can also selectively expose symbols within its namespace for qualified reference via our.
To illustrate module scoping and export rules, let's begin by defining a simple module M:
module M { sub greeting ($name = 'Camelia') { "Greetings, $name!" } our sub loud-greeting (--> Str) { greeting().uc } sub friendly-greeting is export { greeting('friend') } }
Recall that subroutines are lexically scoped unless otherwise specified (declarator sub is equivalent to my sub), so greeting in the above example is lexically scoped to the module and inaccessible outside of it. We've also defined loud-greeting with the our declarator, which means that in addition to being lexically scoped it is aliased in the module's symbol table. Finally, friendly-greeting is marked for export; it will be registered in the caller's symbol table when the module is imported:
import M; # import the module say M::loud-greeting; # OUTPUT: «GREETINGS, CAMELIA!» say friendly-greeting; # OUTPUT: «Greetings, friend!»
While .pm and .pm6 files (hereafter: .pm6) are sometimes referred to as "modules", they are really just normal files that are loaded and compiled when you write need, use or require.
For a .pm6 file to provide a module in the sense that we've been using, it needs to declare one with module as documented above. For example, by placing module M inside Foo.pm6, we can load and use the module as follows:
use Foo; # find Foo.pm6, run need followed by import say M::loud-greeting; # OUTPUT: «GREETINGS, CAMELIA!» say friendly-greeting; # OUTPUT: «Greetings, friend!»
Note the decoupling between file and module names—a .pm6 file can declare zero or more modules with arbitrary identifiers.
Often we want a .pm6 file to provide a single module and nothing more. Here a common convention is for the file basename to match the module name. Returning to Foo.pm6, it is apparent that it only provides a single module, M; in this case, we might want to rename M to Foo. The amended file would then read:
module Foo { sub greeting ($name = 'Camelia') { "Greetings, $name!" } our sub loud-greeting (--> Str) { greeting().uc } sub friendly-greeting is export { greeting('friend') } }
which can be used more consistently by the caller (note the relationship between the use Foo and Foo::):
use Foo; say Foo::loud-greeting; # OUTPUT: «GREETINGS, CAMELIA!» say friendly-greeting; # OUTPUT: «Greetings, friend!»
If Foo.pm6 is placed deeper within the source tree, e.g. at lib/Utils/Foo.pm6, we can elect to name the module Utils::Foo to maintain consistency.
Files that only provide a single module can be written more concisely with the unit keyword; unit module specifies that the rest of the compilation unit is part of the declared module. Here's Foo.pm6 rewritten with unit:
unit module Foo; sub greeting ($name = 'Camelia') { "Greetings, $name!" } our sub loud-greeting (--> Str) { greeting().uc } sub friendly-greeting is export { greeting('friend') }
Everything following the unit declaration is part of the Foo module specification.
(Note that unit can also be used with class, grammar and role.)
To better understand what the module declarator is doing in Foo.pm6, let's contrast it with a variant file, Bar.pm6, that omits the declaration. The subroutine definitions below are almost identical (the only difference is in the body of greeting, modified for clarity):
sub greeting ($name = 'Camelia') { "Greetings from Bar, $name!" } our sub loud-greeting (--> Str) { greeting().uc } sub friendly-greeting is export { greeting('friend') }
As a reminder, here's how we used Foo.pm6 before,
use Foo; say Foo::loud-greeting; # OUTPUT: «GREETINGS, CAMELIA!» say friendly-greeting; # OUTPUT: «Greetings, friend!»
and here's how we use Bar.pm6,
use Bar; say loud-greeting; # OUTPUT: «GREETINGS FROM BAR, CAMELIA!» say friendly-greeting; # OUTPUT: «Greetings from Bar, friend!»
Note the use of loud-greeting rather than Bar::loud-greeting as Bar is not a known symbol (we didn't create a module of that name in Bar.pm6). But why is loud-greeting callable even though we didn't mark it for export? The answer is simply that Bar.pm6 doesn't create a new package namespace—$?PACKAGE is still set to GLOBAL—so when we declare loud-greeting as our, it is registered in the GLOBAL symbol table.
Thankfully, Perl 6 protects us from accidentally clobbering call site definitions (e.g. builtins). Consider the following addition to Bar.pm6:
our sub say ($ignored) { print "oh dear\n" }
This creates a lexical alias, hiding the say builtin inside Bar.pm6 but leaving the caller's say unchanged. Consequently, the following call to say still works as expected:
use Bar; say 'Carry on, carry on...'; # OUTPUT: «Carry on, carry on...»
How to create, use and distribute Perl 6 modules
A module is usually a source file or set of source files that expose Perl 6 constructs.
Modules are typically packages (classes, roles, grammars), subroutines, and sometimes variables. In Perl 6 module can also refer to a type of package declared with the module keyword (see Module Packages and the examples below) but here we mostly mean "module" as a set of source files in a namespace.
zef is the application used for installing modules in Perl 6. Modules are listed in the Perl 6 ecosystem and can be searched there or from the command line using zef search:
zef search WWW
will return a list of modules that includes WWW in their name, for instance. Then,
zef install WWW
will install the module with that particular name, if it is not already installed.
Module distributions (in the set of related source files sense) in Perl 6 have the same structure as any distribution in the Perl family of languages: there is a main project directory containing a README and a LICENSE file, a lib directory for the source files, which may be individually referred to as modules and/or may themselves define modules with the module keyword
Source files generally use the .pm6 extension, and scripts or executables use the .p6. Test files use the .t extension. Files which contain documentation use the .pod6 extension.
Loading a module makes the packages in the same namespace declared within available in the file scope of the loader. Importing from a module makes the symbols exported available in the lexical scope of the importing statement.
need loads a compunit at compile time.
need MyModule;
Any packages in the namespace defined within will also be available.
# MyModule.pm6 unit module MyModule; class Class {}
MyModule::Class will be defined when MyModule is loaded, and you can use it directly employing its fully qualified name (FQN). Classes and other types defined that way are not automatically exported; you will need to explicitly export it if you want to use it by its short name:
# MyModule.pm6 unit module MyModule; class Class is export {}
And then
use MyModule; my $class = Class.new(); say $class.perl;
use loads and then imports from a compunit at compile time. It will look for files that end in .pm6 (.pm is also supported, but discouraged). See here for where the runtime will look for modules.
use MyModule;
This is equivalent to:
need MyModule; import MyModule;
See also selective importing to restrict what you import.
require loads a compunit and imports definite symbols at runtime.
say "loading MyModule"; require MyModule;
The compunit name can be in a runtime variable if you put it inside an indirect lookup.
my $name = 'MyModule'; require ::($name);
The symbols provided by the loaded module will not be imported into the current scope. You may use dynamic lookup or dynamic subsets to use them by providing the fully qualified name of a symbol, for instance:
require ::("Test"); my &mmk = ::("Test::EXPORT::DEFAULT::&ok"); mmk('oi‽'); # OUTPUT: «ok 1 - »
The FQN of ok is Test::EXPORT::DEFAULT::&ok. We are aliasing it to mmk so that we can use that symbol provided by Test in the current scope.
To import symbols you must define them at compile time. NOTE: require is lexically scoped:
sub do-something { require MyModule <&something>; say ::('MyModule'); # MyModule symbol exists here something() # &something will be defined here } say ::('MyModule'); # This will NOT contain the MyModule symbol do-something(); # &something will not be defined here
If MyModule doesn't export &something then require will fail.
A require with compile-time symbol will install a placeholder package that will be updated to the loaded module, class, or package. Note that the placeholder will be kept, even if require failed to load the module. This means that checking if a module loaded like this is wrong:
# *** WRONG: *** try require Foo; if ::('Foo') ~~ Failure { say "Failed to load Foo!"; } # *** WRONG: ***
As the compile-time installed package causes ::('Foo') to never be a Failure. The correct way is:
# Use return value to test whether loading succeeded: (try require Foo) === Nil and say "Failed to load Foo!"; # Or use a runtime symbol lookup with require, to avoid compile-time # package installation: try require ::('Foo'); if ::('Foo') ~~ Failure { say "Failed to load Foo!"; }
Perl 6 takes great care to avoid global state, i.e. whatever you do in your module, it should not affect other code. For instance, that's why subroutine definitions are lexically (my) scoped by default. If you want others to see them, you need to explicitly make them our scoped or export them.
Classes are exported by default on the assumption that loading a module will not be of much use when you cannot access the classes it contains. Loaded classes are thus registered only in the scope which loaded them in the first place
use Foo; # Foo has "use Bar" somewhere. use Bar; my $foo = Foo.new; my $bar = Bar.new;
Packages, subroutines, variables, constants and enums are exported by marking them with the is export trait (also note the tags available for indicating authors and versions).
unit module MyModule:ver<1.0.3>:auth<John Hancock (jhancock@example.com)>; our $var is export = 3; sub foo is export { ... }; constant FOO is export = "foobar"; enum FooBar is export <one two three>; # for multi methods, if you declare a proto you # only need to mark the proto with is export proto sub quux(Str $x, |) is export { * }; multi sub quux(Str $x) { ... }; multi sub quux(Str $x, $y) { ... }; # for multi methods, you only need to mark one with is export # but the code is most consistent if all are marked multi sub quux(Str $x) is export { ... }; multi sub quux(Str $x, $y) is export { ... }; # Packages like classes can be exported too class MyClass is export {}; # If a subpackage is in the namespace of the current package # it doesn't need to be explicitly exported class MyModule::MyClass {};
As with all traits, if applied to a routine, is export should appear after any argument list.
sub foo(Str $string) is export { ... }
You can pass named parameters to is export to group symbols for exporting so that the importer can pick and choose. There are three predefined tags: ALL, DEFAULT and MANDATORY.
# lib/MyModule.pm6 unit module MyModule; sub bag is export { ... } # objects with tag ':MANDATORY' are always exported sub pants is export(:MANDATORY) { ... } sub sunglasses is export(:day) { ... } sub torch is export(:night) { ... } sub underpants is export(:ALL) { ... }
# main.p6 use lib 'lib'; use MyModule; # bag, pants use MyModule :DEFAULT; # the same use MyModule :day; # pants, sunglasses use MyModule :night; # pants, torch use MyModule :ALL; # bag, pants, sunglasses, torch, underpants
Note: there currently is no way for the user to import a single object if the module author hasn't made provision for that, and it is not an easy task at the moment (see RT #127305). One way the author can provide such access is to give each export trait its own unique tag. (And the tag can be the object name!). Then the user can either (1) import all objects:
use Foo :ALL;
or (2) import one or more objects selectively:
use Foo :bar, :s5;
Notes:
1. The :MANDATORY tag on an exported sub ensures it will be exported no matter whether the using program adds any tag or not.
2. All exported subs without an explicit tag are implicitly :DEFAULT.
3. The space after the module name and before the tag is mandatory.
4. Multiple import tags may be used (separated by commas). For example:
# main.p6 use lib 'lib'; use MyModule :day, :night; # pants, sunglasses, torch
5. Multiple tags may be used in the export trait, but they must all be separated by either commas, or whitespace, but not both.
sub foo() is export(:foo :s2 :net) {} sub bar() is export(:bar, :s3, :some) {}
Beneath the surface, is export is adding the symbols to a UNIT scoped package in the EXPORT namespace. For example, is export(:FOO) will add the target to the UNIT::EXPORT::FOO package. This is what Perl 6 is really using to decide what to import.
unit module MyModule; sub foo is export { ... } sub bar is export(:other) { ... }
Is the same as:
unit module MyModule; my package EXPORT::DEFAULT { our sub foo { ... } } my package EXPORT::other { our sub bar { ... } }
For most purposes, is export is sufficient but the EXPORT packages are useful when you want to produce the exported symbols dynamically. For example:
# lib/MyModule.pm6 unit module MyModule; my package EXPORT::DEFAULT { for <zero one two three four>.kv -> $number, $name { for <sqrt log> -> $func { OUR::{'&' ~ $func ~ '-of-' ~ $name } := sub { $number."$func"() }; } } }
# main.p6 use MyModule; say sqrt-of-four; # OUTPUT: «2» say log-of-zero; # OUTPUT: «-Inf»
You can export arbitrary symbols with an EXPORT sub. EXPORT must return a Map, where the keys are the symbol names and the values are the desired values. The names should include the sigil (if any) for the associated type.
# lib/MyModule.pm6 class MyModule::Class { } sub EXPORT { %( '$var' => 'one', '@array' => <one two three>, '%hash' => %( one => 'two', three => 'four' ), '&doit' => sub { say 'Greetings from exported sub' }, 'ShortName' => MyModule::Class ) }
# main.p6 use lib 'lib'; use MyModule; say $var; # OUTPUT: «one» say @array; # OUTPUT: «(one two three)» say %hash; # OUTPUT: «{one => two, three => four}» doit(); # OUTPUT: «Greetings from exported sub» say ShortName.new; # OUTPUT: «MyModule::Class.new»
Note, EXPORT can't be declared inside a package because it is part of the compunit rather than the package.
Whereas UNIT::EXPORT packages deal with the named parameters passed to use, the EXPORT sub handles positional parameters. If you pass positional parameters to use, they will be passed to EXPORT. If a positional is passed, the module no longer exports default symbols. You may still import them explicitly by passing :DEFAULT to use along with your positional parameters.
# lib/MyModule class MyModule::Class {} sub EXPORT($short_name?) { %( do $short_name => MyModule::Class if $short_name ) } sub always is export(:MANDATORY) { say "works" } #import with :ALL or :DEFAULT to get sub shy is export { say "you found me!" }
# main.p6 use lib 'lib'; use MyModule 'foo'; say foo.new(); # OUTPUT: «MyModule::Class.new» always(); # OK - is imported shy(); # FAIL - won't be imported
You can combine EXPORT with type captures for interesting effect. This example creates a ? postfix which will only work on Cools.
# lib/MakeQuestionable.pm6 sub EXPORT(::Questionable) { my multi postfix:<?>(Questionable $_) { .so }; %( '&postfix:<?>' => &postfix:<?>, ) }
use MakeQuestionable Cool; say ( 0?, 1?, {}?, %( a => "b" )? ).join(' '); # OUTPUT: «False True False True»
To list exported symbols of a module first query the export tags supported by the module.
use URI::Escape; say URI::Escape::EXPORT::.keys; # OUTPUT: «(DEFAULT ALL)»
Then use the tag you like and pick the symbol by its name.
say URI::Escape::EXPORT::DEFAULT::.keys; # OUTPUT: «(&uri-escape &uri-unescape &uri_escape &uri_unescape)» my &escape-uri = URI::Escape::EXPORT::DEFAULT::<&uri_escape>;
Be careful not to put sub EXPORT after unit declarator. If you do so, it'll become just a sub inside your package, rather than the special export sub:
unit module Bar; sub EXPORT { %(Foo => &say) } # WRONG!!! Sub is scoped wrong
sub EXPORT { %(Foo => &say) } # RIGHT!!! Sub is outside the module unit module Bar;
It is up to the module installer to know where compunit expects modules to be placed. There will be a location provided by the distribution and in the current home directory. In any case, letting the module installer deal with your modules is a safe bet.
cd your-module-dir zef --force install .
A user may have a collection of modules not found in the normal ecosystem, maintained by a module or package manager, but needed regularly. Instead of using the use lib pragma one can use the PERL6LIB environment variable to point to module locations. For example:
export PERL6LIB=/path/to/my-modules,/path/to/more/modules
Note that the comma (',') is used as the directory separator.
The include path will be searched recursively for any modules when Rakudo is started. Directories that start with a dot are ignored and symlinks are followed.
If you've written a Perl 6 module and would like to share it with the community, we'd be delighted to have it listed in the Perl 6 modules directory. :)
Currently there are two different module ecosystems (module distribution networks) available:
CPAN This is the same ecosystem Perl5 is using. Modules are uploaded as .zip or .tar.gz files on PAUSE.
p6c Up until recently the only ecosystem. It is based on Github repositories which are directly accessed. It has only limited capability for versioning.
The process of sharing your module consists of two steps, preparing the module and uploading the module to one of the ecosystems.
For a module to work in any of the ecosystems, it needs to follow a certain structure. Here is how to do that:
Create a project directory named after your module. For example, if your module is Vortex::TotalPerspective, then create a project directory named Vortex-TotalPerspective.
Make your project directory look like this:
Vortex-TotalPerspective/ ├── lib │ └── Vortex │ └── TotalPerspective.pm6 ├── LICENSE ├── META6.json ├── README.md └── t └── basic.t
If your project contains other modules that help the main module do its job, they should go in your lib directory like so:
lib └── Vortex ├── TotalPerspective.pm6 └── TotalPerspective ├── FairyCake.pm6 └── Gargravarr.pm6
If you have any additional files (such as templates or a dynamic library) that you wish to have installed so you can access them at runtime, they should be placed in a resources sub-directory of your project, e.g.:
resources └── templates └── default-template.mustache
The file must then be referenced in META6.json (see below for more on META6.json) so that the distribution path can be provided to the program.
{ "name" : "Vortex::TotalPerspective", "provides" : { "Vortex::TotalPerspective" : "lib/Vortex/TotalPerspective.pm6" }, "resources": [ "templates/default-template.mustache"] }
The additional file can then be accessed inside module code:
my $template-text = %?RESOURCES<templates/default-template.mustache>.slurp; # Note that %?RESOURCES provides a C<IO> path object
The README.md file is a markdown-formatted text file, which will later be automatically rendered as HTML by GitHub/GitLab for modules kept in those ecosystems or by modules.perl6.org website for modules kept on CPAN.
Regarding the LICENSE file, if you have no other preference, you might just use the same one that Rakudo Perl 6 uses. Just copy/paste the raw form of its license into your own LICENSE file.
The license field in META6.json The license field should be one of the standardized names listed here: https://spdx.org/licenses/. In the case of the Artistic 2.0 license, which is what many of our ecosystem modules use, its identifier is Artistic-2.0. Having standardized identifiers make it easy for humans and computers alike to know which license was actually used by looking at the metadata!
Your license is not on spdx.org or you have your own license: If you can't find your license on spdx.org or you use your own license, you should put the license's name in the license field, and under more details here https://design.perl6.org/S22.html#license.
If you don't yet have any tests, you can leave out the t directory and basic.t file for now. For more info on how to write tests (for now), you might have a look at how other modules use Test.
To document your modules, use Perl 6 Pod markup inside them. Module documentation is most appreciated and will be especially important once the Perl 6 module directory (or some other site) begins rendering Pod docs as HTML for easy browsing. If you have extra docs (in addition to the Pod docs in your module(s)), create a doc directory for them. Follow the same folder structure as the lib directory like so:
doc └── Vortex └── TotalPerspective.pod6
Make your META6.json file look something like this:
{ "perl" : "6.c", "name" : "Vortex::TotalPerspective", "api" : "1", "auth" : "github:SomeAuthor", "version" : "0.0.1", "description" : "Wonderful simulation to get some perspective.", "authors" : [ " Your Name " ], "license" : "Artistic-2.0", "provides" : { "Vortex::TotalPerspective" : "lib/Vortex/TotalPerspective.pm6" }, "depends" : [ ], "build-depends" : [ ], "test-depends" : [ ], "resources" : [ ], "tags": [ "Vortex", "Total", "Perspective" ], "source-url" : "git://github.com/ you /Vortex-TotalPerspective.git" }
The attributes in this file are analyzed by the META6 class. They are divided into optional, mandatory and customary. Mandatory are the ones you need to insert into your file, and customary are those used by the current Perl 6 ecosystem and possibly displayed on the module page if it's published, but you have no obligation to use it.
For choosing a version numbering scheme, try and use "major.minor.patch" (see the spec on versioning for further details). This will go into the version key of META6.json. This field is optional, but used by installation to match against installed version, if one exists. The description field is also mandatory, and includes a short description of the module.
The name key is compulsory, and zef will fail if you do not include it. Even if you have created a META6.json file just to express the dependencies for a series of scripts, this section must be included.
Optionally, you can set an api field. Incrementing this indicates that the interface provided by your module is not backwards compatible with a previous version. You can use it if you want to adhere to Semantic Versioning. A best practice is to simply keep the api field to the same value as your major version number. A dependency can then depend on your module by including a :api part, which will ensure backwards incompatible releases will not be pulled in.
The auth section identifies the author in GitHub or other repository hosting site, such as Bitbucket or GitLab. This field is customary, since it's used to identify the author in the ecosystem, and opens the possibility of having modules with the same name and different authors.
The authors section includes a list of all the module authors. In the case there is only one author, a single element list must be supplied. This field is optional.
In the provides section, include all the namespaces provided by your distribution and that you wish to be installed; only module files that are explicitly included here will be installed and available with use or require in other programs. This field is mandatory.
Set perl version to the minimum perl version your module works with. This field is mandatory. Use 6.c if your module is valid for Christmas release and newer ones, use 6.d if it requires, at least, the Diwali version.
The resources section is optional, but, if present, should contain a list of the files in your resources directory that you wish to be installed. These will be installed with hashed names alongside your library files. Their installed location can be determined through the %?RESOURCES Hash indexed on the name provided. The tags section is also optional. It is used to describe the module in the Perl 6 ecosystem.
The depends, build-depends and test-depends sections include different modules that are used in those phases of the of installation. All are optional, but they must obviously contain the modules that are going to be needed in those particular phases. These dependencies might optionally use Version specification strings; zef will check for the presence and versions of these modules and install or upgrade them if needed.
//... "depends": [ "URI", "File::Temp", "JSON::Fast", "Pod::To::BigPage:ver<0.5.0+>", "Pod::To::HTML:ver<0.6.1+>", "OO::Monitors", "File::Find", "Test::META" ], //...
Additionally, depends can be either an array as above or a hash that uses two keys, runtime and build, whose function should be self-descriptive, and which are used, for instance, in Inline::Python:
//... "depends" : { "build": { "requires": [ "Distribution::Builder::MakeFromJSON", { "from" : "bin", "name" : { "by-distro.name" : { "macosx" : "python2.7-config", "debian" : "python2.7-config", "" : "python2-config" } } } ] }, "runtime": { "requires": [ "python2.7:from<native>" ] } }, // ...
In general, the array form will be more than enough for most cases.
Finally, source-url indicates the URL of the repository where the module is developed; this is one of the customary modules if you are going to publish it in the module ecosystem. The current module ecosystem will link this URL from the project description.
The Test::META module can help you check the correctness of the META6.json file; this module will check for all the mandatory fields and that the type used for all of them is correct.
There are more fields described in the META design documents, but not all of these are implemented by existing package managers. Hence you should stick to the fields described in the above example block to ensure compatibility with existing package managers such as zef. You can also check Moritz Lenz's repository of all modules for examples, but bear in mind that some of them might use fields, such as source-type above, which are currently ignored.
If you want to test your module you can use the following command to install the module directly from the module folder you just created.
zef install ./your-module-folder
Note that doing so precompiles and installs your module. If you make changes to the source, you'll need to re-install the module. (See use lib pragma, -I command line switch, or PERL6LIB env variable, to include a path to your module source while developing it, so you don't have to install it at all).
Uploading a module to CPAN is the preferred way of distributing Perl 6 modules.
A prerequisite for this is a PAUSE user account. If you don't have an account already, you can create one here The process takes about 5 minutes and some e-mail back and forth.
Create a package of your module:
cd your-module-folder tar czf Vortex-TotalPerspective-0.0.1.tar.gz \ --transform s/^\./Vortex-TotalPerspective-0.0.1/ --exclude-vcs\ --exclude=.[^/]*
If you use git you can also use the following command to create a package directly for a given commit.
git archive --prefix=Vortex-TotalPerspective-0.0.1/ \ -o ../Vortex-TotalPerspective-0.0.1.tar.gz HEAD
Go to PAUSE, log in and navigate to Upload a file to CPAN.
Make sure you select Perl6 as the Target Directory. For your first upload, you have to enter the string Perl6 in the text field. On subsequent uploads, you can select the Perl6 directory from the selection box right below the input field.
Select your file and click Upload! If everything was fine with your dist, you should see your module tar file in your Perl6 directory along with both a meta and a readme file named after your module filename.
Make sure you have a META6.json file in your dist and that the dist version you're uploading is higher than the currently uploaded version. Those are the most common upload errors.
If you want to use the p6c ecosystem you need to use git for your module's version control. The instructions herein assume that you have a GitHub account so that your module can be shared from its GitHub repository, however another provider such as GitLab should work as long as it works in a similar way.
Put your project under git version control if you haven't done so already.
Once you're happy with your project, create a repository for it on GitHub. See GitHub's help docs if necessary. Your GitHub repository should be named the same as your project directory. Immediately after creating the GitHub repo, GitHub shows you how to configure your local repository to know about your GitHub repository.
Push your project to GitHub.
Consider setting up automated testing (see https://docs.travis-ci.com/user/languages/perl6).
Create a PR on ecosystem adding your module to META.list, or ping someone on IRC (#perl6 at freenode) to get help having it added.
After the pull request has been accepted, wait for an hour. If your module doesn't show up on https://modules.perl6.org/, please view the log file at https://modules.perl6.org/update.log to see if it identifies an error with your module or meta file.
That's it! Thanks for contributing to the Perl 6 community!
If you'd like to try out installing your module, use the zef module installer tool which is included with Rakudo Star Perl 6:
zef install Vortex::TotalPerspective
This will download your module to its own working directory (~/.zef), build it there, and install the module into your local Perl 6 installation directory.
To use Vortex::TotalPerspective from your scripts, just write use Vortex::TotalPerspective, and your Perl 6 implementation will know where to look for the module file(s).
You can find a list of modules and tools that aim to improve the experience of writing/test modules at Modules Extra
To discuss module development in general, or if your module would fill a need in the ecosystem, naming, etc., you can use the #perl6 on irc.freenode.net IRC channel.
To discuss toolchain specific questions, you can use the #perl6-toolchain on irc.freenode.net IRC channel. A repository to discuss tooling issues is also available at https://github.com/perl6/toolchain-bikeshed.
A short tutorial on how to declare operators and create new ones.
Operators are declared by using the sub keyword followed by prefix, infix, postfix, circumfix, or postcircumfix; then a colon and the operator name in a quote construct. For (post-)circumfix operators separate the two parts by white space.
sub hello { say "Hello, world!"; } say &hello.^name; # OUTPUT: «Sub» hello; # OUTPUT: «Hello, world!» my $s = sub ($a, $b) { $a + $b }; say $s.^name; # OUTPUT: «Sub» say $s(2, 5); # OUTPUT: «7» # Alternatively we could create a more # general operator to sum n numbers sub prefix:<Σ>( *@number-list ) { [+] @number-list } say Σ (13, 16, 1); # OUTPUT: «30» sub infix:<:=:>( $a is rw, $b is rw ) { ($a, $b) = ($b, $a) } my ($num, $letter) = ('A', 3); say $num; # OUTPUT: «A» say $letter; # OUTPUT: «3» # Swap two variables' values $num :=: $letter; say $num; # OUTPUT: «3» say $letter; # OUTPUT: «A» sub postfix:<!>( Int $num where * >= 0 ) { [*] 1..$num } say 0!; # OUTPUT: «1» say 5!; # OUTPUT: «120» sub postfix:<♥>( $a ) { say „I love $a!“ } 42♥; # OUTPUT: «I love 42!» sub postcircumfix:<⸨ ⸩>( Positional $a, Whatever ) { say $a[0], '…', $a[*-1] } [1,2,3,4]⸨*⸩; # OUTPUT: «1…4» constant term:<♥> = "♥"; # We don't want to quote "love", do we? sub circumfix:<α ω>( $a ) { say „$a is the beginning and the end.“ }; α♥ω; # OUTPUT: «♥ is the beginning and the end.»
These operators use the extended identifier syntax; that is what enables the use of any kind of codepoint to refer to them.
Some tips on regexes and grammars
To help with robust regexes and grammars, here are some best practices for code layout and readability, what to actually match, and avoiding common pitfalls.
Without the :sigspace adverb, whitespace is not significant in Perl 6 regexes. Use that to your own advantage and insert whitespace where it increases readability. Also, insert comments where necessary.
Compare the very compact
my regex float { <[+-]>?\d*'.'\d+[e<[+-]>?\d+]? }
to the more readable
my regex float { <[+-]>? # optional sign \d* # leading digits, optional '.' \d+ [ # optional exponent e <[+-]>? \d+ ]? }
As a rule of thumb, use whitespace around atoms and inside groups; put quantifiers directly after the atom; and vertically align opening and closing square brackets and parentheses.
When you use a list of alternations inside parentheses or square brackets, align the vertical bars:
my regex example { <preamble> [ || <choice_1> || <choice_2> || <choice_3> ]+ <postamble> }
Regexes are often more compact than regular code. Because they do so much with so little, keep regexes short.
When you can name a part of a regex, it's usually best to put it into a separate, named regex.
For example, you could take the float regex from earlier:
my regex float { <[+-]>? # optional sign \d* # leading digits, optional '.' \d+ [ # optional exponent e <[+-]>? \d+ ]? }
And decompose it into parts:
my token sign { <[+-]> } my token decimal { \d+ } my token exponent { 'e' <sign>? <decimal> } my regex float { <sign>? <decimal>? '.' <decimal> <exponent>? }
That helps, especially when the regex becomes more complicated. For example, you might want to make the decimal point optional in the presence of an exponent.
my regex float { <sign>? [ || <decimal>? '.' <decimal> <exponent>? || <decimal> <exponent> ] }
Often the input data format has no clear-cut specification, or the specification is not known to the programmer. Then, it's good to be liberal in what you expect, but only so long as there are no possible ambiguities.
For example, in ini files:
[section] key=value
What can be inside the section header? Allowing only a word might be too restrictive. Somebody might write [two words], or use dashes, etc. Instead of asking what's allowed on the inside, it might be worth asking instead: what's not allowed?
Clearly, closing square brackets are not allowed, because [a]b] would be ambiguous. By the same argument, opening square brackets should be forbidden. This leaves us with
token header { '[' <-[ \[\] ]>+ ']' }
which is fine if you are only processing one line. But if you're processing a whole file, suddenly the regex parses
[with a newline in between]
which might not be a good idea. A compromise would be
token header { '[' <-[ \[\] \n ]>+ ']' }
and then, in the post-processing, strip leading and trailing spaces and tabs from the section header.
The :sigspace adverb (or using the rule declarator instead of token or regex) is very handy for implicitly parsing whitespace that can appear in many places.
Going back to the example of parsing ini files, we have
my regex kvpair { \s* <key=identifier> '=' <value=identifier> \n+ }
which is probably not as liberal as we want it to be, since the user might put spaces around the equals sign. So, then we may try this:
my regex kvpair { \s* <key=identifier> \s* '=' \s* <value=identifier> \n+ }
But that's looking unwieldy, so we try something else:
my rule kvpair { <key=identifier> '=' <value=identifier> \n+ }
But wait! The implicit whitespace matching after the value uses up all whitespace, including newline characters, so the \n+ doesn't have anything left to match (and rule also disables backtracking, so no luck there).
Therefore, it's important to redefine your definition of implicit whitespace to whitespace that is not significant in the input format.
This works by redefining the token ws; however, it only works for grammars:
grammar IniFormat { token ws { <!ww> \h* } rule header { \s* '[' (\w+) ']' \n+ } token identifier { \w+ } rule kvpair { \s* <key=identifier> '=' <value=identifier> \n+ } token section { <header> <kvpair>* } token TOP { <section>* } } my $contents = q:to/EOI/; [passwords] jack = password1 joy = muchmoresecure123 [quotas] jack = 123 joy = 42 EOI say so IniFormat.parse($contents);
Besides putting all regexes into a grammar and turning them into tokens (because they don't need to backtrack anyway), the interesting new bit is
token ws { <!ww> \h* }
which gets called for implicit whitespace parsing. It matches when it's not between two word characters (<!ww> , negated "within word" assertion), and zero or more horizontal space characters. The limitation to horizontal whitespace is important, because newlines (which are vertical whitespace) delimit records and shouldn't be matched implicitly.
Still, there's some whitespace-related trouble lurking. The regex \n+ won't match a string like "\n \n", because there's a blank between the two newlines. To allow such input strings, replace \n+ with \n\s*.
Meta-documentation
This document collection represents the on-going effort to document the Perl 6 programming language with the goals of being: comprehensive, easy to use, easy to navigate, and useful to both newcomers and experienced Perl 6 programmers.
An HTML version of the documentation is located online at https://docs.perl6.org.
The official source for this documentation is located at perl6/doc on GitHub.
This particular document is a quick overview of the process described in more detail in CONTRIBUTING on GitHub. This document also provides a short introduction to writing Perl 6 Pod files, which can be rendered into HTML and other formats.
All of the documentation is written in Perl 6 Pod and kept in the doc/ directory, and the doc/Language/ and doc/Type/ sub-directories. These files are processed as collections of definitions or "documentables", which are then post-processed and linked together.
To generate HTML from the Pod files, you'll need:
A recent version of the Rakudo Perl 6 compiler
The Perl 6 modules Pod::To::HTML, Pod::To::BigPage, and URI::Escape which all can be installed via zef. For instance, zef install Pod::To::HTML to install Pod::To::HTML.
Optional: GraphViz, for creating graphs of the relationships between Perl 6 types.
Optional: Atom Highlights and language-perl6, for syntax highlighting.
To generate the documentation into the html/ folder, run:
perl6 htmlify.p6
To host the documentation from a web server, have Perl 5 and Mojolicious::Lite installed, then run:
perl app.pl daemon
The documentation is written in Perl 6 Pod.
For a quick introduction to Perl 6 Pod, see Perl 6 Pod.
For full details about the Perl 6 Pod specification, see Synopsis 26, Documentation.
Documentables can be defined using an =headN Pod directive, where N is greater than zero (e.g., =head1, =head2, …).
All of the paragraphs and blocks following that directive, up until the next directive of the same level, will be considered part of the documentable. So, in:
=head2 My Definition Some paragraphs, followed by some code: =begin code my Code $examples = "amazing"; =end code Mind === blown. =head3 Minor details about My Definition It's fantastic. =head2 And now, for something completely different …
The documentable My Definition extends down to the =head2 And now….
Documentables may contain other documentables. Class documentables, for example, often contain the methods the class implements.
Definitions must be in one of the following forms to be recognized as the start of a documentable named, say, þ. First the code in the document source:
=item X<C<How to use the þ infix> | infix,þ> (This a special case, which is always considered a definition) =item C<The þ Infix> =item B<The C<þ> Infix> =item C<Infix þ> =item B<Infix C<þ>> =item C<trait is cached> (A special case for the L<trait|/language/functions#Traits> documentables)
Then the results on the rendered page:
The þ Infix
The þ Infix
Infix þ
Infix þ
trait is cached (A special case for the trait documentables)
These items should now be searchable by using the search field in the HTML docs.
You can add emphasis with bold ( B<> ) or italicized ( I<> ), with or without code formatting ( C<> ). Due to current parser limitations, special steps have to be taken to use X<> with other formatting codes; for example:
=item X<B<foo>|foo> a fancy subroutine
renders like this
Notice that text after a pipe ('|') has no formatting. Also note that C<> preserves spaces and treats text as verbatim.
Information about the people working on and using Perl 6
"Perl 5 was my rewrite of Perl. I want Perl 6 to be the community's rewrite of Perl and of the community." - Larry Wall
There is a large presence on the #perl6 channel on freenode.net, who are happy to provide support and answer questions, or just use as a friendly place to hang out. Check out this IRC lingo resource for the abbreviations frequently used there. StackOverflow is also a great resource for asking questions and helping others with their Perl 6 problems and challenges. More resources can be found in the perl6.org community page.
Perl 6 is also a common topic at Perl conferences and Perl Monger meetings and other meetups. If you prefer in-person meetings, these are warmly recommended!
Camelia, the multi-color butterfly with P 6 in her wings, is the symbol of this diverse and welcoming community.
Elizabeth Mattijsen usually posts in the "Perl 6 Weekly" blog, a summary of Perl 6 posts, tweets, comments and other interesting tidbits. If you want a single resource to know what is going on in the Perl community now, this is your best resource.
The Perl 6 community publishes every December an Advent Calendar, with Perl 6 tutorials every day until Christmas. Organization and assignment of days is done through the different Perl 6 channels and the Perl6/advent repository. If you want to participate, its organization starts by the end of October, so check out the channels above to keep up to date.
HOW TO WRITE: One topic/point/idea per sentence, one sentence per line - to make diffs & translation easier.Frequently asked questions about Perl 6
Properly speaking, Rakudo is an implementation of Perl 6. It's currently the most developed, but there have been other implementations in the past and there will likely be others in the future. Perl 6 (which can also be called "Raku") is the definition of the language. When talking about the current interpreter, Rakudo and Perl 6 can be used interchangeably.
The Rakudo 2015.12 implementation version was released on December 25th 2015.
No. The first stable language specification version is v6.c ("Christmas"). Future versions of the spec may have point releases (e.g. v6.d.2) or major releases (e.g., v6.e).
Running perl6 -v will display the language version your compiler implements:
$ perl6 -v This is Rakudo version 2017.07 built on MoarVM version 2017.07 implementing Perl 6.c.
The v6.d Specification was released on Diwali 2018, which was November 6–7 2018, in a convenient time zone. 6.d was enabled by default in the Rakudo compiler release of 2018.11.
The vast majority of 6.d features were already implemented and available in the Rakudo compiler without requiring any special pragmas, as they did not conflict with the 6.c specification. A smaller set of features and behaviors is available automatically if you have the use v6.d pragma at the top of the file. The rest of about 3100 new commits to the language specification simply clarify previously undefined behavior.
Mac users can use the latest Rakudo Star DMG binary installer at https://rakudo.org/downloads/star
Windows users can use the Rakudo Star MSI binary installer. You will need Windows Git and Strawberry Perl 5 to use zef to install library modules.
Linux users probably want to download Rakudo Star and follow the compilation instructions at https://www.perl6.org/downloads/.
There should be Linux and Mac binaries available from vendors and third parties, although vendor versions may be outdated. Versions before Rakudo release of 2015.12 should be avoided.
There's an official Rakudo Star docker image at https://hub.docker.com/_/rakudo-star/
An option is to clone the repository and build it. This will install work in progress which is minimally-tested and may contain severe bugs. If you're interested in contributing to Rakudo Perl 6 compiler, you may find Z-Script helper tool useful.
To install the last official monthly release, check out the tag visible at https://raw.githubusercontent.com/rakudo/rakudo/master/VERSION or set up a helper command.
Some users choose to use rakudobrew, which allows installation of multiple versions of rakudo. Be sure to read its documentation.
In either case you will probably need to also install zef and p6doc from the ecosystem.
See the official documentation website (especially its "Language" section) as well as the Resources page. You can also consult this great cheatsheet.
perl6book.com contains a list of dead tree and electronic books.
Be mindful of publication dates when reading third-party articles. Anything published before December, 2015 likely describes a pre-release version of Perl 6.
You can always get help from a live human in our help chat or search the chat logs to find previous conversations and discussions.
Here are some available books, in alphabetical order:
Learning Perl 6, by brian d foy
Learning to program with Perl 6: First Steps, by JJ Merelo
Metagenomics, by Ken Youens-Clark
Parsing with Perl 6 Regexes and Grammars, by Moritz Lenz
Perl 6 at a Glance, by Andrew Shitov
Perl 6 Fundamentals, by Moritz Lenz
Perl 6 Deep Dive, by Andrew Shitov
Think Perl 6: How to Think Like a Computer Scientist, by Laurent Rosenfeld.
A list of books published or in progress is maintained in perl6.org.
The specification refers to the official test suite for Perl 6. It's called roast and is hosted on github. Any compiler that passes the tests is deemed to implement that version of the Perl 6 specification.
Roast's master branch corresponds to the latest development that isn't necessarily part of any specification yet. Other branches correspond to specific versions; for example, "6.c-errata".
So 6.c-errata is a released language version we don't change other than to fix errors in tests (the "errata") whereas master is the unreleased work-in-progress that may become the next language version. Its current state is not necessarily prescriptive of the next language version's behavior since new additions will be reviewed for inclusion into the release.
Yes, see glossary.
There are several Perl 5 to Perl 6 guides in the Language section of the documentation, most notable of which is the Overview.
See the rb-nutshell guide.
Yes, it's the same CPAN as for Perl 5! The only difference is when using PAUSE to upload the module, you'd select Perl 6 as the target directory and the uploaded modules show up on modules.perl6.org instead of MetaCPAN. The App::Mi6 tool can simplify the uploading process. Latest versions of zef module installer automatically check for latest versions of a module on CPAN as well as our GitHub-based ecosystem.
Yes, it's called p6doc and is present in the ecosystem under that name. It comes bundled in with Rakudo Star but needs to be manually installed with zef if you are using a Rakudo monthly release.
Yes, with Inline::Perl5, which works well with most Perl 5 modules. It can even run Perl 5 Catalyst and DBI.
Nativecall makes this particularly easy.
This is commonly seen on Debian-like systems. You need to install libfoo-dev package, to set a symlink for the missing file.
It's fairly easy to use NativeCall to access them.
An ecosystem module POSIX is also available.
Rakudo Star distribution does come with many useful modules.
Rakudo compiler-only release includes only a couple of the most basic modules.
Many more modules can be found in the ecosystem.
Use --target=optimize command line option to view the AST of your program, e.g., perl6 --target=optimize -e 'say "hi"'
The target optimize gives the AST after the static optimizer does its job, while target ast gives the AST before that step. To get the full list of available targets, run perl6 --stagestats -e ""
When you load a module for the first time, Rakudo compiles it into bytecode. Then, Rakudo both stores the compiled bytecode on disk and uses it, because that tends to be significantly faster.
No, you can't have circular dependencies, and you should get a Circular module loading detected error if you have them between your modules.
Very likely you can accomplish what you are trying to do using roles. Instead of A.pm6 depending on B.pm6 and B.pm6 depending on A.pm6, you can have A-Role.pm6 and B-Role.pm6 and classes in A.pm6 and B.pm6 implementing these roles respectively. Then you can depend on A-Role.pm6 and B-Role.pm6 without the need for the circular dependency.
One of the reasons why circular dependencies do not work in Perl 6 is one pass parsing. We have to know what A means when we parse B, and we have to know what B means when we parse A, which is clearly an infinite loop.
Note that Perl 6 has no “1 file = 1 class” limitation, and circular dependencies within a single compilation unit (e.g. file) are possible through stubbing. Therefore another possible solution is to move classes into the same compilation unit.
Typical options are to use the say routine that uses the gist method which gives the "gist" of the object being dumped. More detailed output can be obtained by calling the perl method that typically returns an object's representation in EVAL-able code.
If you're using the rakudo implementation, you can use the rakudo-specific dd routine for dumping, whose output is similar to perl, but with more information.
Examples:
my $foo = %( foo => 'bar' ); say $foo.perl; # OUTPUT: «${:foo("bar")}» say $foo; # OUTPUT: «{foo => bar}» # non-standard routine available in rakudo implementation: dd $foo; # OUTPUT: «Hash $foo = ${:foo("bar")}»
There are also several ecosystem modules that provide more control over how data structures are dumped, including support for colored output.
Install Linenoise from the ecosystem.
An alternative for UNIX-like systems is to install rlwrap. This can be done on Debian-ish systems by running:
sudo apt-get install rlwrap
If SORRY! is present in the output, the error is a compile time error. Otherwise, it's a runtime error.
Example:
sub foo( Int $a, Int $b ) {...} foo(1) # ===SORRY!=== Error while compiling ...
say 1/0; # Attempt to divide 1 by zero using div
Any is a top level class most objects inherit from. The Any type object is the default value on variables and parameters without an explicit type constraint, which means you'll likely see (Any) printed when you output a gist of a variable without any value by using, for instance, the say routine:
my $foo; say $foo; # OUTPUT: «(Any)» my Int $baz; say $baz; # OUTPUT: «(Int)» my $bar = 70; say $bar; # OUTPUT: «70»
To test whether a variable has any defined values, see DEFINITE and defined routines. Several other constructs exist that test for definiteness, such as with , orwith , and without statements, //, andthen, notandthen, and orelse operators, as well as type constraint smileys.
so is a loose precedence operator that coerces to Bool.
It has the same semantics as the ? prefix operator, just like and is the low-precedence version of &&.
Example:
say so 1|2 == 2; # OUTPUT: «True»
In this example, the result of the comparison (which is a Junction), is converted to Bool before being printed.
In Perl 6, classes and other types are objects and pass type checks of their own type.
For example, if you declare a variable
my Int $x = 42;
then not only can you assign integers (that is, instances of class Int) to it, but the Int type object itself:
$x = Int
If you want to exclude type objects, you can append the :D type smiley, which stands for "definite":
my Int:D $x = 42; $x = Int; # dies with: # Type check failed in assignment to $x; # expected Int:D but got Int
Likewise, :U constrains to undefined values, that is, type objects.
To explicitly allow either type objects or instances, you can use :_.
--> is a return constraint, either a type or a definite value.
Example of a type constraint:
sub divide-to-int( Int $a, Int $b --> Int ) { return ($a / $b).narrow; } divide-to-int(3, 2) # Type check failed for return value; expected Int but got Rat
Example of a definite return value:
sub discard-random-number( --> 42 ) { rand } say discard-random-number; # OUTPUT: «42»
In this case, the final value is thrown away because the return value is already specified in the signature.
If you want to extract the values (eigenstates) from a Junction, you are probably doing something wrong and should be using a Set instead.
Junctions are meant as matchers, not for doing algebra with them.
If you want to do it anyway, you can abuse autothreading for that:
sub eigenstates(Mu $j) { my @states; -> Any $s { @states.push: $s }.($j); @states; } say eigenstates(1|2|3).join(', '); # prints 1, 2, 3 or a permutation thereof
In Perl 6, values of many basic types are immutable, but the variables holding them are not. The s/// operator works on a variable, into which it puts a newly created string object. Likewise, $i++ works on the $i variable, not just on the value in it.
Knowing this, you would not try to change a literal string (e.g. like 'hello' ~~ s/h/H/;), but you might accidentally do something equivalent using map as follows.
my @foo = <hello world>.map: { s/h/H/ }; # dies with # Cannot modify an immutable Str (hello) my @bar = <hello world>».subst-mutate: 'h', 'H'; # dies with # Cannot resolve caller subst-mutate(Str: Str, Str); # the following candidates match the type but require # mutable arguments: ...
Instead of modifying the original value in place, use a routine or operator that returns a new value:
my @foo = <hello world>.map: { S/h/H/ }; # ['Hello','world'] my @bar = <hello world>».subst: 'h', 'H'; # ['Hello','world']
See the documentation on containers for more information.
In Perl 6, nearly everything is a reference, so talking about taking references doesn't make much sense. Scalar variables can also contain arrays directly:
my @a = 1, 2, 3; say @a; # OUTPUT: «[1 2 3]» say @a.^name; # OUTPUT: «Array» my $scalar = @a; say $scalar; # OUTPUT: «[1 2 3]» say $scalar.^name; # OUTPUT: «Array»
The big difference is that arrays inside a scalar act as one value in list context, whereas arrays will be happily iterated over.
my @a = 1, 2, 3; my $s = @a; for @a { ... } # loop body executed 3 times for $s { ... } # loop body executed only once my @flat = flat @a, @a; say @flat.elems; # OUTPUT: «6» my @nested = flat $s, $s; say @nested.elems; # OUTPUT: «2»
You can force list context with @( ... ) or by calling the .list method on an expression, and item context with $( ... ) or by calling the .item method on an expression.
See the Perl 6: Sigils, Variables, and Containers article to learn more.
There are several reasons:
they make it easy to interpolate variables into strings
they form micro-namespaces for different variables and twigils, thus avoiding name clashes
they allow easy single/plural distinction
they work like natural languages that use mandatory noun markers, so our brains are built to handle it
they aren't mandatory, since you can declare sigilless names (if you don't mind the ambiguity)
You likely tried to mix string interpolation and key characters, like HTML tags:
my $foo = "abc"; say "$foo<html-tag>";
Perl 6 thinks $foo to be a Hash and <html-tag> to be a string literal hash key. Use a closure to help it to understand you.
my $foo = "abc"; say "{$foo}<html-tag>";
Perl 6 has no yield statement like Python does, but it does offer similar functionality through lazy lists. There are two popular ways to write routines that return lazy lists:
# first method, gather/take my @values = gather while have_data() { # do some computations take some_data(); # do more computations } # second method, use .map or similar method # on a lazy list my @squares = (1..*).map(-> \x { x² });
The say statement in the following code sample
class A { has $!x; method show-x { return $!x; } } say A.new(x => 5).show-x;
does not print 5. Private attributes are private, which means invisible to the outside world. If the default constructor could initialize them, they would leak into the public API. Thus, in this particular code sample the attribute $!x isn't initialized during object construction by the default constructor.
If you still want to initialize private attributes with the default constructor, you can add a submethod BUILD to achieve such task:
class B { has $!x; submethod BUILD(:$!x) { } method show-x { return $!x; } } say B.new(x => 5).show-x;
BUILD is called by the default constructor (indirectly, see Object Construction for more details) with all the named arguments that the user passes to the constructor. :$!x is a named parameter with name x, and when called with a named argument of name x, its value is bound to the attribute $!x.
However, you shouldn't do that. If the attribute is declared as private, then it shouldn't be exposed to the environment outside the class (e.g., during object construction). On the other hand, if the attribute is public, there is no downside to declaring it that way with $.x since the external view is read-only by default, and you can still access it internally with $!x.
The most obvious difference is that say and put append a newline at the end of the output, and print does not.
But there's another difference: print and put convert its arguments to a string by calling the Str method on each item passed to them while say uses the gist method. The gist method, which you can also create for your own classes, is intended to create a Str for human interpretation. So it is free to leave out information about the object deemed unimportant to understanding the essence of the object.
Or phrased differently, $obj.Str gives a string representation, $obj.gist provides a short summary of that object suitable for fast recognition by a human, and $obj.perl gives a Perlish representation from which the object could be re-created.
For example, when the Str method is invoked on a type object, also known as an "undefined value", the type is stringified to an empty string and a warning is thrown. On the other hand, the gist method returns the name of the type between parentheses (to indicate there's nothing in that value except the type).
my Date $x; # $x now contains the Date type object print $x; # empty string plus warning say $x; # OUTPUT: «(Date)»
If you'd like to show a debugging version of an object, it is probably better to use the rakudo-specific dd routine. It essentially does a $obj.perl and shows that on STDERR rather than STDOUT, so it won't interfere with any "normal" output of your program.
In short, say is optimized for casual human interpretation, dd is optimized for casual debugging output and print and put are more generally suitable for producing output.
put is thus a hybrid of print and say; like print, it calls the Str method on the object. And like say, it adds a newline at the end of the output.
regex, token and rule introduce regexes, but with slightly different semantics.
token implies the :ratchet or :r modifier, which prevents the rule from backtracking.
rule implies both the :ratchet and :sigspace (short :s) modifier, which means a rule doesn't backtrace, and it treats whitespace in the text of the regex as <.ws> calls (i.e., matches whitespace, which is optional except between two word characters). Whitespace at the start of the regex and at the start of each branch of an alternation is ignored.
regex declares a plain regex without any implied modifiers.
die throws an exception.
fail returns a Failure object. (If the caller has declared use fatal; in the calling lexical scope, fail throws an exception instead of returning it.)
A Failure is an "unthrown" or "lazy" exception. It's an object that contains the exception, and throws the exception if you try to use the Failure as an ordinary object or ignore it in sink context.
A Failure returns False from a defined check, and you can extract the exception with the exception method.
OpaquePointer is deprecated and has been replaced with Pointer.
Identifiers can include colon pairs, which become part of their name. According to Larry Wall's answer to the issue, We already had the colon pair mechanism available, so it was a no-brainer to use that to extend any name that needs to be able to quote uniquefying but non-standard characters (or other information with a unique stringification to such characters).
It depends on the operating system, windowing environment and/or editors. This page on entering Unicode characters specifies how it is done in the most popular operating systems and editors.
Currently the best developed is Rakudo (using multiple Virtual Machine backends). Historic implementations include Niecza (.NET) and Pugs (Haskell). Others are listed at Perl 6 Compilers
A short answer is that Rakudo is written almost entirely in Perl 6. A more detailed answer is that Rakudo is written in a mixture of Perl 6 and NQP ("Not Quite Perl"). NQP is a lightweight Perl 6-like environment for virtual machines; it's designed to be a high-level way to create compilers and libraries for virtual machines (such as MoarVM and JVM) using Perl 6 syntax.
NQP is a mixture of (1) NQP code, (2) whatever language the underlying virtual machine is using, (3) some third-party C and Java libraries, and (4) some bootstrapping files created by earlier runs of the build process.
(not (not Nil))
Tools like App::InstallerMaker::WiX allow you to create an installer that will package the compiler and your script. However, the currently available compilers do not support creating a standalone executable yet.
If you wish to help out, the Rakudo compiler on MoarVM backend has https://github.com/MoarVM/MoarVM/issues/875 Issue opened as a place to discuss this problem.
A Rakudo Star release is typically produced quarterly, with release announcements posted on rakudo.org.
… As opposed to some other name that didn't imply all the things that the higher number might indicate on other languages.
The short answer is that it was Larry's choice under Rule 1.
The community considers Perl 5 and Perl 6 sister languages - they have a lot in common, address many of the same problem spaces, but Perl 6 is not intended to replace Perl 5. In fact, both languages interoperate with each other.
Readiness of programming languages and their compilers is not a binary decision. As the language and the implementations evolve, they grow steadily more usable. Depending on your needs, Perl 6 and its compilers may or may not be ready for you.
That said, version 6.c (Christmas 2015) is the first official release of Perl 6 as a language, along with a validation suite and a compiler that passes it.
Perl 6 unifies many great ideas that aren't usually found in other programming languages. While several other languages offer some of these features, none of them offer all of them.
Perl 6 offers procedural, object-oriented AND functional programming methodologies.
Easy to use consistent syntax, using invariable sigils for data-structures.
Full grapheme based Unicode support, including Annex #29.
Clean, more readable regular expressions; taken to the next level of usability, with a lot more functionality. Named regular expressions improve ease of use.
Junctions allowing easy checking of multiple possibilities; e.g., $a == 1|3|42 (Is $a equal to 1 or 3 or 42?).
Dynamic variables provide a lexically scoped alternative to global variables.
Emphasis on composability and lexical scoping to prevent “action at a distance”; e.g., imports are always lexically scoped.
Easy to understand consistent scoping rules and closures.
Powerful object orientation, with classes and roles (everything can be seen as an object). Inheritance. Subtyping. Code-reuse.
Introspection into objects and meta-objects (turtles all the way down).
Meta Object Protocol allowing for meta-programming without needing to generate / parse code.
Subroutine and method signatures for easy unpacking of positional and named parameters.
Multi dispatch for identically named subroutines/methods with different signatures, based on arity, types and optional additional code.
Compile time error reporting on unknown subroutines / impossible dispatch.
Optional gradual type-checking at no additional runtime cost. With optional type annotations.
Advanced error reporting based on introspection of the compiler/runtime state. This means more useful, more precise error messages.
Phasers (like BEGIN / END) allow code to be executed at scope entry / exit, loop first / last / next and many more special contexts.
High level concurrency model, both for implicit as well as explicit multi-processing, which goes way beyond primitive threads and locks. Perl 6's concurrency offers a rich set of (composable) tools.
Multiple-core computers are getting used more and more, and with Perl 6 these can be used thanks to parallelism, both implicit (e.g., with the >>. method) and explicit ( start { code } ). This is important, because Moore's Law is ending.
Structured language support is provided to enable programming for asynchronous execution of code.
Supplies allow code to be executed when something happens (like a timer, or a signal, or a filesystem event).
react / whenever / supply keywords allows easy construction of interactive, event driven applications.
Lazy evaluation when possible, eager evaluation when wanted or necessary. This means, for example, lazy lists, and even infinite lazy lists, like the Fibonacci sequence, or all prime numbers.
Native data types for faster, closer to the metal, processing.
Interfacing to external libraries in C / C++ is fairly easy with NativeCall.
Interfacing with Perl 5 (CPAN) / Python modules is fairly easy with Inline::Perl5 and Inline::Python
Can have multiple versions of a module installed and loaded simultaneously.
System administration simplified due to simpler update/upgrade policies.
Simple numeric computation without precision loss because of Rats (rational numbers).
Extensible grammars for parsing data or code (which Perl 6 uses to parse itself).
Perl 6 is a very mutable language (define your own functions, operators, traits and data-types, which modify the parser for you).
Large selection of data-types, plus the possibility to create your own types.
Multi-dimensional shaped and/or native arrays with proper bounds checking.
Execute code at any time during parsing of a grammar, or when a certain match occurred.
Adding a custom operator or adding a trait is as simple as writing a subroutine.
Automatic generation of hyper-operators on any operator (system or custom added).
Runs on a variety of back-ends. Currently MoarVM & JVM, JavaScript in development, more may follow.
Runtime optimization of hot code paths during execution (JIT).
Runs on small (e.g., Raspberry Pi) and large multi-processor hardware.
Garbage collection based: no timely destruction, so no ref-counting necessary. Use phasers for timely actions.
Methods can be mixed into any instantiated object at runtime; e.g., to allow adding out-of-band data.
Easy command-line interface accessible by MAIN subroutine with multiple dispatch and automated usage message generation.
Fewer lines of code allow for more compact program creation. Huffman-coding of names allows for better readability.
Lazy lists defined with a simple iterator interface, which any class can supply by minimally supplying a single method.
Perl 6's mottos remain the same as they have been for Perl all along: “Perl is different. In a nutshell, Perl is designed to make the easy jobs easy, without making the hard jobs impossible.” and “There Is More Than One Way To Do It”. Now with even more -Ofun added.
Please see the feature comparison matrix for an overview of implemented features.
That depends on what you are doing. Rakudo has been developed with the philosophy of "make it work right then make it work fast". It's fast for some things already but needs work for others. Since Perl 6 provides lots of clues to the JIT that other dynamic languages don't, we think we'll have a lot of headroom for performance improvements.
The following crude benchmarks, with all the usual caveats about such things, show that Perl 6 can be faster than Perl 5 for similar tasks if the big weaponry is included, that is, if Perl 6 features are used to its full extent; at the same time, Perl 5 can be faster if only the bare bones are included. Similar situation can be observed when comparing Perl 6 to other languages.
Try it on your system. You may be pleasantly surprised!
Examples:
# Perl 6 version use v6.c; class Foo { has $.i is rw }; for 1..1_000_000 -> $i { my $obj = Foo.new; $obj.i = $i; }
# Perl 5 version package Foo; use Moose; has i => (is => 'rw'); __PACKAGE__->meta->make_immutable; for my $i (1..1_000_000) { my $obj = Foo->new; $obj->i($i); } 1; # Another Perl 5 version that offers bare-bones set of features # compared to Moose/Perl 6's version but those are not needed in this # specific, simple program anyway. package Foo; use Mojo::Base -base; has 'i'; for my $i (1..1_000_000) { my $obj = Foo->new; $obj->i($i); } 1;
You might want to use this program for comparing performance, too. It works under both languages, as long as perl -Mbigint is used for invocation for Perl 5.
my ($prev, $current) = (1, 0); for (0..100_000) { ($prev, $current) = ($current, $prev + $current); } print $current;
Glossary of Perl 6 terminology
The generic Computer Science term "abstract class" defines the interface or API of a class. In Perl 6, this is implemented using roles with stubbed methods.
role Canine { method bark { ... } # the ... indicates a stub } class Dog does Canine { method bark { say "woof" } # *MUST* be implemented by class }
In the context of Perl 6, a yearly set of blog posts for each day from the 1st until the 25th of December, to be found at https://perl6advent.wordpress.com.
Generically, an adverb is a named argument to a function. There are also some specific syntax forms that allow adverbs to be tucked into some convenient places:
q:w"foo bar"; # ":w" is a Quotelike form modifier adverb m:g/a|b|c/; # ":g" is too @h{3}:exists; # ":exists" is too, but is known as a subscript adverb
Adverbs are usually expressed with colon pair notation, and for this reason colon pair notation is also known as the adverbial pair form:
:a(4) # Same as "a" => 4
Some other forms that use a colon in ways that have adverb-like semantics are called adverbial forms. One special form starts with an integer value, followed by a name (for the key):
:20seconds # same as seconds => 20
Also see #Colon pair and colon list.
A generalized form of pair notation. They all start with the colon, as shown in the following examples:
adverbial pair | pair notation |
---|---|
:foo<bar> | foo => 'bar' |
:foo(42) | foo => 42 |
:42foo | foo => 42 |
:$foo | foo => $foo |
:foo | foo => True |
:!foo | foo => False |
Also see #Adverb and #Colon pair and colon list.
A type that has two related values which may be used depending on the context. For example IntStr allomorph is both an Int and a Str, so it will be accepted by anything that expects an Int, a Str, or an IntStr. Keep in mind that certain constructs, such as sets, bags, and mixes care about object identity, and so will not accept an allomorph as equivalent of its components alone.
The allomorph types IntStr, NumStr, RatStr and ComplexStr may be created as a result of parsing a quoted string:
say <42>.^name; # OUTPUT: «IntStr» say <42.1e0>.^name; # OUTPUT: «NumStr» say <42.1>.^name; # OUTPUT: «RatStr»
Note: angle brackets can also be used to create literals for which you'd normally need to use some operator (e.g. / for Rat or + for Complex). This allows you to use such literals in places where expressions are not allowed, for example, as literals in signatures:
# Wrong, can't use an operator there: multi foo (1/3) { say "It's one third!" }
# Right, a Rat literal: multi foo (<1/3>) { say "It's one third!" }
If you do want an allomorph and not a literal Numeric, then include whitespace around angle brackets:
say <42/1>.^name; # OUTPUT: «Rat» say <42+0i>.^name; # OUTPUT: «Complex» say < 42+0i >.^name; # OUTPUT: «ComplexStr» say < 42/1 >.^name; # OUTPUT: «RatStr»
Please see the Numerics page for a more complete description on how to work with these allomorphs.
A subroutine, method or submethod is called anonymous if it can't be called by name.
# named subroutine sub double($x) { 2 * $x }; # anonymous subroutine, stored in a named scalar my $double = sub ($x) { 2 * $x };
Note that it is still allowed to have a name, but you cannot call it by that name:
# anonymous, but knows its own name my $s = anon sub triple($x) { 3 * $x } say $s.name; # OUTPUT: «triple»
say triple(42); # OUTPUT: «Undeclared routine: triple»
Application Programming Interface. Ideally, someone using your system or library should be able to do so with knowledge only of the API, but not necessarily knowing anything about the internals or the implementation details.
See also #Abstract class.
A document originally written by #TimToady, in which he processed the initial barrage of RFCs that came out of the Perl community. Now only kept as a historical document for reference. See also #Exegesis and #Synopsis.
The number of positional operands expected by an operator, subroutine, method or callable block.
sub infix:<+>(Foo $a, Foo $b) { $a.Int + $b.Int } # arity of "+" is 2 sub frobnicate($x) { ... } # arity of 1 sub the-answer() { 42 } # arity of 0 -> $key, $value { ... } # arity of 2
The arity of a Callable is one of the main selectors in multi-dispatch.
The ASCII variant of a non-ASCII Unicode operator or symbol. For instance, (elem) corresponds to the ∈ ("Is this an element of that set?") operator that comes from set theory. ASCII operators are a workaround to the problem that people don't know how to type Unicode yet. Culturally, while we encourage people to use the Unicode symbols in a vague sort of way, we do not disparage the use of the ASCII variants. Well, maybe just a little...
Autothreading is what happens if you pass a Junction to a subroutine that expects a parameter of type Any or a subtype thereof (such as anything Cool). The call is then executed for each value of the junction. The result of these calls is assembled in a new junction of the same type as the original junction.
sub f($x) { 2 * $x }; say f(1|2|3) == 4; # OUTPUT: «any(False, True, False)»
Here f() is a sub with one parameter, and since it has no explicit type, it is implicitly typed as Any. The Junction argument causes the f(1|2|3) call to be internally executed as f(1)|f(2)|f(3), and the resulting junction is 2|4|6. These are then all compared to 4, resulting in a junction False|True|False. This process of separating junction arguments into multiple calls to a function is called autothreading.
If you use the resulting junction in a boolean context, such as with an if, it collapses into a single boolean which is True if any of the values in the junction are True.
if f(1|2|3) == 4 { # fires because f(2) == 4 is true say 'success'; }
Backtracking is the default way a regexp is matched. The engine is allowed to explore several ways moving backward in the string characters in order to allow every piece of a regexp to match something. For more information, see Regexp Backtracking section.
When you pass an argument list to a function (or any other callable, like a method or a block), the argument list gets bound to the parameters in the signature. The code that does this is called the binder.
Blocks are code object with its own lexical scope, which allows them to define variables without interfering with other in the containing block.
Although Perl 6 looks like an interpreted language, since it uses the #! form to run its scripts (and they are called scripts), it is actually compiled to run in a virtual machine so the compiler (currently Rakudo) generates bytecode that runs either in MoarVM or the Java Virtual Machine, the two VMs currently supported.
A butterfly image intended primarily to represent Perl 6, The Language.
A colon pair is a shorthand syntax used to create or visually present a Pair object. The two most common forms are:
:a(4) # Same as "a" => 4, same as Pair.new("a", 4) :a<4> # Same as "a" => "4", same as Pair.new("a", val("4"))
This is also known as the adverbial pair form.
Note: when the part after the colon and before the balanced delimiters is not a legal identifier, other semantics apply, not all of which produce Pair objects.
Two other common forms are:
:a # Same as :a(True) :!a # Same as :a(False)
A colon list just means that a list that contains only colon pairs, does not need commas, or even spaces:
:a(4):c:!d:c # Same as a => 4, c => True, d => False, c => True
Finally, if there is a variable with the same name as an intended adverbial pair, you don't have to specify the name twice, but just specify the adverb with the appropriate sigil:
variable only | same as |
---|---|
:$foo | foo => $foo |
:@bar | bar => @bar |
:%mapper | mapper => %mapper |
:&test | test => &test |
See also #Adverb.
See https://perl6.org/community/ for information about how to participate in the friendly Perl 6 community.
Original author of the #Exegesis (among many other things). See also https://en.wikipedia.org/wiki/Damian_Conway.
Short for "decontainerize", meaning to remove an item from its Scalar container, often to obtain a different behavior for items that have it.
See operator. It means the type of the operator result is sufficiently different from its arguments that op= makes little sense.
A document originally written by #TheDamian, in which he tried to explain the Apocalypses to the common (wo)man. Now only kept as an historical document for reference. See also #Synopsis.
Too complicated to apply a meta-op to. See operator.
A handle is a data structure used to store information about some input/output operation such as file or socket reading or writing. Perl 6 uses IO::Handle as a base class for filehandles, and IO::Socket for sockets.
With reference to Huffman coding, "huffmanizing" is making things that are commonly used easier, and often shorter, to type. With things that are used less frequently it's both less of a bother to type longer pieces of code and often longer, more descriptive naming is necessary to easily be reminded of what the rarely-used feature does.
For example, printing output is a common task, while performing thread-safe atomic addition on native atomicity-safe integers is much less so. There's a need to "huffmanize" the task printing and that's why you can do it by just typing three letters put. But there's no need to "huffmanize" the rarely-needed atomic operators, which is why you type the lengthier names, such as atomic-inc-fetch. The name put is a bit vague, but because it's commonly used, it's easy to learn what it does. On the other hand, the name atomic-inc-fetch is rarer, and the more descriptive name helps recall its purpose better.
Often used as a boolean value. See operator. Made via the use keyword.
Include functions from a module in the current namespace.
An instance of a class is also called an object in some other programming languages. It has storage for attributes and is often the return value of a call to a method called new, or a literal.
Instances of most types are defined to be True e.g., defined($instance) is True.
my Str $str = "hello"; ## this is with builtin types, e.g. Str if defined($str) { say "Oh, yeah. I'm defined."; } else { say "No. Something off? "; } ## if you wanted objects... class A { # nothing here for now. } my $an_instance = A.new; say $an_instance.defined.perl;# defined($an_instance) works too.
To put things another way, a class contains the blueprints of methods and attributes, and an instance carries it into the real world.
An interface is an abstract class.
Caller, the one who calls or invokes. The invocant of a method would be the object on which that method is being called, or, in some cases, the class itself. Invocant is used instead of caller because the latter refers to the scope.
Internet Relay Chat. Perl 6 developers and users usually hang out on the #perl6 channel of irc.freenode.org. This channel is also populated by a host of friendly bots that allow you to interact with Perl 6 and its codebase, as well as send delayed messages and other goodies. Check the full list in the community page of perl6.org.
The following terms are often used on the Perl 6 related #IRC channels:
As Late As Possible
A self-referencing pun, e.g. "Are you ignorant or apathetic?" - "I don't know, and I don't care."
That part of a discussion on an #IRC channel that you've missed. If it is not or no longer available in your IRC client, you can go to sites such as http://colabti.org/irclogger/irclogger_logs/perl6 to see what has been logged for you.
A program that does automatic tasks on one or more #IRC channels by acting like a regular user (as far as the IRC server is concerned) and performing some tasks that may involve answering to users requests. Examples are #camelia, #dalek and #yoleaux.
A compunit is a piece of Perl 6 code that is analyzed and compiled as a single unit. Typically, this piece of code will be contained in a single file, but code inside an EVAL is also considered a compunit.
Do What I Mean. A programming language designer motto. The opposite of a DWIM is a #WAT.
Sometimes a test will fail under some conditions, but not others; when this test passes in some test runs and fails in others, it's called flapping.
Something in a generally current document that is no longer true but which has not yet been fixed by correcting or removing it.
For Some Value Of...
Fixed That For You
You don't have to specify types of variables and parameters, but if you do, it helps in early determination of impossible dispatches and better optimization. See also https://en.wikipedia.org/wiki/Gradual_typing.
If I Read (or Remember) Correctly.
In My Humble Opinion.
It Would Be Nice
Low Hanging Fruit. Usually used in the context of a (relatively) simple task to be performed by a (relative) newbie.
Looks Good To Me
Less Than Awesome. Usually used in the context of an error message that is rather non-descriptive or unrelated to the actual error.
No Such Thing
Short for "optimization", usually in either the context of spesh or JIT.
Short for "problem". As in "that's not the pb".
See #Pull Request.
Perl 5
Perl 6
Real Soon Now.
Request Tracker (https://rt.perl.org/). The place where all the bugs related to #Rakudo used to live. Nowadays, the Github issue tracker of the rakudo/rakudo repository is used for that.
An alternative form of #TMTOWTDI, explicitly including the "is" from the contraction "There's".
Too Much Information.
"There's More Than One Way To Do It", the Perl motto.
"Universal Greeting Time" - i.e., it's always "morning".
Works For Me
Work In Progress
Wikipedia
Short for wrong window. When on #IRC, someone types something in a channel that was intended for another channel, or for a private message.
Perl's benevolent dictator for life, among many other things. See also https://en.wikipedia.org/wiki/Larry_Wall.
Performing lexical analysis, a step which usually precedes parsing.
A literal is a piece of code that directly stands for an (often built-in) object and also refers to the object itself.
my $x = 2; # the 2 is a literal say $x; # $x is not a literal, but a variable my $s = "Foo"; # the "Foo" is a literal, the $s is a variable
Different types of literals are described in the syntax document.
As an acronym left-hand side, it usually refers to the left hand side of an expression, and more specifically to the left-hand side of expressions such as $lhs = "this would be the right-hand side". Since the left hand side of these expressions modify their value, when something behaves as a LHS it means that it can be read and written to.
An lvalue, or a left value, is anything that can appear on the left-hand side of the assignment operator =. It is anything you can assign to.
Typical lvalues are variables, private and is rw attributes, lists of variables and lvalue subroutines.
Examples of lvalues:
Declaration | lvalue | Comments |
---|---|---|
my $x; | $x | |
my ($a, $b); | ($a, $b) | |
has $!attribute; | $!attribute | Only inside classes |
has $.attrib is rw; | $.attrib | |
sub a is rw { $x }; | a() |
Examples of things that are not lvalues:
3 | literals |
constant x = 3; | constants |
has $.attrib; | attributes; you can only assign to $!attrib |
sub f { }; f(); | "normal" subs are not writable |
sub f($x) { $x = 3 }; | error - parameters are read-only by default |
These are typically called rvalues.
The mainline is the program text that is not part of any kind of block.
use v6.c; # mainline sub f { # not in mainline, in sub f } f(); # in mainline again
You can also have the mainline of any package-like declarator, such as class, module, grammar, etc. These are typically run just after the class/module/grammar have been compiled (or when loaded from a precompiled file).
Stands for "Maybe Specification". Usually refers to existing tests in the language specification. The speaker is indicating they did not check whether the test is a spectest or a propspec test; i.e. whether the test is included in a released language specification or is a new test, proposed for the next version of the spec.
MoarVM is short for Metamodel On A Runtime Virtual Machine. It's a virtual machine designed specifically for #NQP and its MOP: #6model. A document about the purpose of MoarVM. MoarVM has some similarities with the Hotspot VM so you may peruse its glossary for entries missing from the present one.
The process of picking a candidate for calling of a set of methods or subs that come by the same name but with different arguments. The most narrow candidate wins. In case of an ambiguity, a routine with is default trait will be chosen if one exists, otherwise an exception is thrown.
A method that has multiple candidates going by the same name and are subject to Multi-Dispatch.
Normal Form Grapheme is the way Perl 6 implements graphemes, using a normal form in which strings with the same graphemes can be easily compared in constant time. More on that on this article in 6guts and an explanation of how NFG works in this IRC log.
An implementation of Perl 6 targeting the .NET platform. No longer actively maintained.
See #NQP.
NQP is a primitive language for writing subroutines and methods using a subset of the Perl 6 syntax. It's not intended to be a full-fledged programming language, nor does it provide a runtime environment beyond the basic VM primitives. Compilers (such as #Rakudo) typically use NQP to compile action methods that convert a parse tree into its equivalent abstract syntax tree representation.
Not Yet Implemented
An opcode, or operation code, is a bytecode operation, that is, a command of the language actually used on the virtual machine. They are not usually intended for human consumption, but they are usually specified somewhere, like this document for MoarVM.
An expression is made of operators and operands. More precisely it is made of an operator and operands that can be subexpressions or #values. Operators are an alternative syntax for a #multi-method. With that syntax, what would be the arguments of the function are named operands instead. Operators are classified into categories of categories. A category has a precedence, an arity, and can be #fiddly, #iffy, #diffy. Perl 6 is very creative as to what is an operator, so there are many categories. Operators are made of many tokens, possibly with a subexpression. For example, @a[0] belongs to the postcircumfix category, is broken into the operand @a and the postcircumfix operator [0] where 0 is the postcircumfixed subexpression.
The <O(I<...>)> construction gives information about an operator that completes the information provided by its category. Below %conditional is the category, :reducecheck<ternary> , which specifies calling .ternary to post-process the parse subtree and :pasttype<if> specifies the NQP #opcode generated in the AST from the parse subtree.
<O('%conditional, :reducecheck<ternary>, :pasttype<if>')>
A parse tree represents the structure of a string or sentence according to a grammar. Grammars in Perl 6 output parse trees when they successfully match a string.
Parameter is a class to define parameters to subroutines, method and a callable blocks. As opposed to the arguments you specify when calling a subroutine/method/callable block.
sub foo($bar) { say $bar } # $bar is a parameter foo(42); # 42 is an argument
A virtual machine designed to run Perl 6 and other dynamic languages. No longer actively maintained.
#Parrot AST.
The Perl programming language in its many forms.
A way to describe Perl as a language, considered to be improper by many in the Perl Community.
Plain Ol' Documentation, a documentation format understood by Perl 6. See here for further information.
Stands for "Proof Of Viability". To be included in the language specification, a "proof of viability" implementation of the feature must exist in at least one mostly-compliant Perl 6 compiler.
Stands for "Proposed Specification". Usually refers to existing tests in the language specification that are proposed for inclusion in the next release.
A feature of GitHub and other git hosts like GitLab that allows you to make patches to be easily applied using the GitHub web user interface. It means you request someone to do a git pull from your repository to hers. PR is its usual acronym.
In this context, it either refers to an object property, which is the value of an instance variable, or an Unicode property which are codepoint features that allow programs to identify what kind of entity they represent, that is, if they are a letter, or a number, or something completely different like a control character.
pugs was one of the first interpreters/compilers written for Perl 6. It was written in Haskell by Audrey Tang.
Retronym for the "Perl 6 way" of doing things, as in idiomatic expressions or definitions. First known use with this meaning by sorear in the #perl6 IRC channel in 2010.
Successor to #PAST ('Q' being the next letter after 'P').
Raku is an alternative name for Perl 6 language and can be used interchangeably.
Rakudo is the name of a Perl 6 implementation that runs on #MoarVM and the JVM. It is an abbreviation of Rakuda-do, which, when translated from Japanese, means "The Way of the Camel". Also, in Japanese, "Rakudo" means "Paradise."
In the English language, reify means "to convert into or regard as a concrete thing." Its meaning in Perl 6 is very similar, in that conceptual things, like "elements of an infinite list", get reified when you try to operate on some of them. In general, reification means turning a potential element (be it an element in a lazy list that has not been computed yet or a element in a container that has not been extracted) into its actual value.
A filesystem under control of a source control management application, usually git, that holds the sources for a project, library or application. This file, for instance, is in a GitHub repository. Repositories store not only files, but also history of changes and can be used by the developing or writing team for interaction through issues or comments to code.
In Perl 6 context, however, a repository is also a short name for compilation unit repository and constitutes a system that locates and loads modules, managing their installation and precompilation. They are structured as linked lists, including chain of repositories ending in the default Compunit::Repository::Installation.
Acronym for Right-Hand Side, usually refers to the right-hand side of assignment expressions such as my $bound := $rhs.
The Perl 6 specification tests, which live here: https://github.com/perl6/roast/. Originally developed for #pugs, it now serves all Perl 6 implementations. Why roast? It's the repository of all spec tests.
Roles, mix-ins or traits define interfaces and/or implementation of those interfaces as well as instance variables using them, and are mixed-in when declaring classes that follow that interface. Abstract classes are particular examples of Roles where the actual implementation is deferred to the class that uses that Role.
Roles are part of Perl 6's object system, and are declared using the role keyword and used in class declaration via does.
(Used in regular expressions)
A value that can be used on the right-hand side of an assignment. See also #lvalue.
Stands for "Specification APpendices". The SAP includes optional tests that implementations may choose to follow, but don't necessarily have to.
Can be used as a verb. To SAP something is to place it into Specification Appendices.
A semilist is a semicolon-separated list like this one: 1;3;5, and is actually a list of lists, with each component of the semilist being a slice of a particular dimension. @array[1;3;5] would be equivalent to @array[1][3][5].
In Perl, the sigil is the first character of a variable name. It must be either $, @, %, or & respectively for a scalar, array, hash, or code variable. See also Twigil and role. Also sigiled variables allow short conventions for variable interpolation in a double quoted string, or even postcircumfix expressions starting with such a variable.
Sigilless variables are actually aliases to the value it is assigned to them, since they are not containers. Once you assign a sigilless variable (using the escape \), its value cannot be changed.
A functionality of the #MoarVM platform that uses runtime gathered data to improve commonly used pieces of #bytecode. It is much like a JIT compiler, except that those usually output machine code rather than bytecode.
STD.pm is the "standard" Perl 6 grammar definition (see https://github.com/perl6/std/) that was used to implement Perl 6. STD.pm is no longer really a "specification" in a proscriptive sense: it's more of a guideline or model for Perl 6 implementations to follow.
Stubs define name and signature of methods whose implementation is deferred to other classes.
role Canine { method bark { ... } # the ... indicates a stub }
Classes with stubs are Abstract classes.
Fancy alternative way to denote a name. Generally used in the context of modules linking, be it in the OS level, or at the Perl 6 #Virtual_machine level for modules generated from languages targeting these VMs. The set of imported or exported symbols is called the symbol table.
The current human-readable description of the Perl 6 language. Still in development. Much more a community effort than the Apocalypses and Exegeses were. The current state of the language is reflected by #roast, its #test suite, not the synopses where speculative material is not always so flagged or more recent additions have not been documented. This is even more true of material that has not been yet implemented.
A syntax or syntactic analysis is equivalent to parsing a string to generate its parse tree.
The Perl 6 test suite is #roast.
#IRC screen name for #Damian Conway, writer of the original Exegeses.
#IRC screen name for #Larry Wall, creator of Perl. The name comes from the pronunciation of #TIMTOWTDI as a word.
In this context, a token is a regex that does not backtrack. In general, tokens are extracted from the source program while lexing.
A piece of code that isn't immediately executed, but doesn't have an independent scope.
In this context, tight or tighter refers to precedence rules and is the opposite of looser. Precedence rules for new terms are always expressed in relationship with other terms, so is tighter implies that operands with that operator will be grouped before operands with the looser operator. Operators with tight precedence are grouped with priority to others and are generally tighter than most others; loose exactly the opposite, so it is always convenient to be aware of the exact precedence of all operators used in an expression.
A data structure used to hold a POD string with embedded formatting codes. For example:
=begin pod C<foo> =end pod say $=pod[0].contents[0].contents.perl;
The output will be:
["", Pod::FormattingCode.new(type => "C", meta => [], config => {}, contents => ["foo"]),""]
A type object is an object that is used to represent a type or a class. Since in object oriented programming everything is an object, classes are objects too, and they inherit from Mu.
A value is what is actually contained in a container such as a variable. Used in expressions such as lvalue, to indicate that that particular container can be assigned to.
Stands for "Undefined Behavior". In other words, it is something that is not explicitly specified by the language specification.
A type is known as a value type if it is immutable and any instance of that type is interchangeable with any other instance "of the same value"—that is, any instance constructed in the same way. An instance of a value type is often called a value (but should not be confused with #lvalues or #rvalues).
For example, numbers are value types, so a number constructed one place in your program with, for instance, the literal 3 can't be changed in any way—it simply is 3—and any later use of the literal 3 can safely be pointed at the same place in memory as the first with no ill consequences.
Classes doing the roles Numeric and Stringy are among a few examples of built-in value types.
A value type is created by ensuring that an instance of the value type is immutable (i.e., its attributes cannot be modified after construction) and that its WHICH method returns the same thing every time an instance with the same value is constructed (and conversely returns a different thing every time an instance with a different value is constructed).
The language is free to optimize based on the assumption that equivalent instances of value types are interchangeable, but you should not depend on any such optimization. For instance, if you want clone to return an instance of self, or you want instance construction to be memoized so that re-construction of a previously-constructed value always returns the same instance, you currently must override this behavior yourself.
(The same would hold true of object finalization, but if your instances need special destruction behavior, you almost certainly do not actually have a value type. Values should be thought of as "timeless" and existing in some ideal form outside of your program's memory, like natural values are.)
A variable is a name for a container.
The value of variables is interpolated into strings by simply inserting that variable into the string:
my $polation="polation"; say "inter$polation"; # OUTPUT: «interpolation»
This might need curly braces in case it precedes some alphanumeric characters
my $inter="inter"; say "{$inter}polation"; # OUTPUT: «interpolation»
Interpolation occurs in string context, so a valid stringification method must exist for the class. More general interpolation can be achieved using the double q quoting constructs.
A virtual machine is the Perl compiler entity that executes the bytecode. It can optimize the bytecode or generate machine code Just in Time. Examples are #MoarVM, #Parrot (who are intended to run Perl 6) and more generic virtual machines such as JVM and Javascript.
The opposite of a #DWIM; counter-intuitive behavior. It is said that to every DWIM there is a corresponding WAT. See also https://www.destroyallsoftware.com/talks/wat.
A character or group of blank characters, used to separate words. An example is the space character « ».
6model is used in the MoarVM, and provides primitives used to create an object system. It is described in this presentation by Jonathan Worthington and implemented here in MoarVM.
An easy-to-use markup language for documenting Perl modules and programs
Pod6 is an easy-to-use markup language. It can be used for writing language documentation, for documenting programs and modules, as well as for other types of document composition.
Every Pod6 document has to begin with =begin pod and end with =end pod. Everything between these two delimiters will be processed and used to generate documentation.
=begin pod A very simple Pod6 document =end pod
A Pod6 document may consist of multiple Pod6 blocks. There are four ways to define a block: delimited, paragraph, abbreviated, and declarator; the first three yield the same result but the fourth differs. You can use whichever form is most convenient for your particular documentation task.
Delimited blocks are bounded by =begin and =end markers, both of which are followed by a valid Perl 6 identifier, which is the typename of the block. Typenames that are entirely lowercase (for example: =begin head1) or entirely uppercase (for example: =begin SYNOPSIS) are reserved.
=begin head1 Top Level Heading =end head1
After the typename, the rest of the =begin marker line is treated as configuration information for the block. This information is used in different ways by different types of blocks, but is always specified using Perl6-ish option pairs. That is, any of:
Value is... | Specify with... | Or with... | Or with... |
---|---|---|---|
List | :key[$e1, $e2, ...] | :key($e1, $e2, ...) | :key<$e1 $e2 ...> |
Hash | :key{$k1=>$v1, $k2=>$v2} | ||
Boolean (true) | :key | :key(True) | :key[True] |
Boolean (false) | :!key | :key(False) | :key[False] |
String | :key<str> | :key('str') | :key("str") |
Int | :key(42) | :key[42] | :42key |
Number | :key(2.3) | :key[2.3] |
Where '$e1, $e2, ...' are list elements of type String, Int, Number, or Boolean. Lists may have mixed element types. Note that one-element lists are converted to the type of their element (String, Int, Number, or Boolean). Also note that "bigints" can be used if required.
For hashes, '$k1, $k2, ...' are keys of type Str and '$v1, $v2, ...' are values of type String, Int, Number, or Boolean.
Strings are delimited by single or double quotes. Whitespace is not significant outside of strings. Hash keys need not be quote-delimited unless they contain significant whitespace. Strings entered inside angle brackets become lists if any whitespace is used inside the angle brackets.
All option keys and values must, of course, be constants since Pod6 is a specification language, not a programming language. Specifically, option values cannot be closures. See Synopsis 2 for details of the various Perl 6 pair notations.
The configuration section may be extended over subsequent lines by starting those lines with an = in the first (virtual) column followed by a whitespace character.
Paragraph blocks begin by a =for marker and end by the next Pod6 directive or the first blank line. The =for marker is followed by the typename of the block plus, optionally, any configuration data as in the delimited blocks described above.
=for head1 Top Level Heading
Abbreviated blocks begin by an '=' sign, which is followed immediately by the typename of the block. All following data are part of the contents of the block, thus configuration data cannot be specified for an abbreviated block. The block ends at the next Pod6 directive or the first blank line.
=head1 Top level heading
Declarator blocks differ from the others by not having a specific type, instead they are attached to some source code.
Declarator blocks are introduced by a special comment: either #| or #=, which must be immediately followed by either a space or an opening curly brace. If followed by a space, the block is terminated by the end of line; if followed by one or more opening curly braces, the block is terminated by the matching sequence of closing curly braces.
Blocks starting with #| are attached to the code after them, and blocks starting with #= are attached to the code before them.
Since declarator blocks are attached to source code, they can be used to document classes, roles, subroutines and in general any statement or block.
The WHY method can be used on these classes, roles, subroutines etc. to return the attached Pod6 value.
#| Base class for magicians class Magician { has Int $.level; has Str @.spells; } #| Fight mechanics sub duel(Magician $a, Magician $b) { } #= Magicians only, no mortals. say Magician.WHY; # OUTPUT: «Base class for magicians» say &duel.WHY.leading; # OUTPUT: «Fight mechanics» say &duel.WHY.trailing; # OUTPUT: «Magicians only, no mortals.»
These declarations can extend multiple blocks:
#|( This is an example of stringification: * Numbers turn into strings * Regexes operate on said strings * C<with> topicalizes and places result into $_ ) sub search-in-seq( Int $end, Int $number ) { with (^$end).grep( /^$number/ ) { .say for $_<>; } } #=« Uses * topic * decont operator »
By using a matched pair of parenthesis constructs such as () or «» the comments can extend multiple lines. This format, however, will not translate to a multi-line display by perl6 -doc.
Pod6 offers a wide range of standard block types.
Headings can be defined using =headN, where N is greater than zero (e.g., =head1, =head2, …).
=head1 A top level heading =head2 A second level heading =head3 A third level heading
An ordinary paragraph consists of text that is to be formatted into a document at the current level of nesting, with whitespace squeezed, lines filled, and any special inline mark-up applied.
Ordinary paragraphs consist of one or more consecutive lines of text, each of which starts with a non-whitespace character. The paragraph is terminated by the first blank line or block directive.
For example:
=head1 This is a heading block This is an ordinary paragraph. Its text will be squeezed and short lines filled. It is terminated by the first blank line. This is another ordinary paragraph. Its text will also be squeezed and short lines filled. It is terminated by the trailing directive on the next line. =head2 This is another heading block This is yet another ordinary paragraph, at the first virtual column set by the previous directive
Ordinary paragraphs do not require an explicit marker or delimiters.
Alternatively, there is also an explicit =para marker that can be used to explicitly mark a paragraph.
=para This is an ordinary paragraph. Its text will be squeezed and short lines filled.
In addition, the longer =begin para and =end para form can be used.
For example:
=begin para This is an ordinary paragraph. Its text will be squeezed and short lines filled. This is still part of the same paragraph, which continues until an... =end para
As demonstrated by the previous example, within a delimited =begin para and =end para block, any blank lines are preserved.
Code blocks are used to specify source code, which should be rendered without re-justification, without whitespace-squeezing, and without recognizing any inline formatting codes. Typically these blocks are used to show examples of code, mark-up, or other textual specifications, and are rendered using a fixed-width font.
A code block may be implicitly specified as one or more lines of text, each of which starts with a whitespace character. The implicit code block is then terminated by a blank line.
For example:
This ordinary paragraph introduces a code block: my $name = 'John Doe'; say $name;
Code blocks can also be explicitly defined by enclosing them in =begin code and =end code
=begin code my $name = 'John Doe'; say $name; =end code
Pod6 provides blocks for specifying the input and output of programs.
The =input block is used to specify pre-formatted keyboard input, which should be rendered without re-justification or squeezing of whitespace.
The =output block is used to specify pre-formatted terminal or file output, which should also be rendered without re-justification or whitespace-squeezing.
Lists in Pod6 are specified as a series of =item blocks.
For example:
The three suspects are: =item Happy =item Sleepy =item Grumpy
The three suspects are:
Happy
Sleepy
Grumpy
Lists that define terms or commands use =defn, equivalent to the DL lists in HTML
=defn Happy When you're not blue. =defn Blue When you're not happy.
will be rendered as
When you're not blue.
When you're not happy.
Lists may be multi-level, with items at each level specified using the =item1, =item2, =item3, etc. blocks.
Note that =item is just an abbreviation for =item1.
For example:
=item1 Animal =item2 Vertebrate =item2 Invertebrate =item1 Phase =item2 Solid =item2 Liquid =item2 Gas
Animal
Vertebrate
Invertebrate
Phase
Solid
Liquid
Gas
Using the delimited form of the =item block (=begin item and =end item), we can specify items that contain multiple paragraphs.
For example:
Let's consider two common proverbs: =begin item I<The rain in Spain falls mainly on the plain.> This is a common myth and an unconscionable slur on the Spanish people, the majority of whom are extremely attractive. =end item =begin item I<The early bird gets the worm.> In deciding whether to become an early riser, it is worth considering whether you would actually enjoy annelids for breakfast. =end item As you can see, folk wisdom is often of dubious value.
Let's consider two common proverbs:
The rain in Spain falls mainly on the plain.
This is a common myth and an unconscionable slur on the Spanish people, the majority of whom are extremely attractive.
The early bird gets the worm.
In deciding whether to become an early riser, it is worth considering whether you would actually enjoy annelids for breakfast.
As you can see, folk wisdom is often of dubious value.
Check out this page for documentation related to Tables
Pod6 comments are comments that Pod6 renderers ignore.
Comments are useful for meta-documentation (documenting the documentation). Single-line comments use the =comment marker:
=comment Add more here about the algorithm
For multi-line comments, use a delimited comment block:
=begin comment This comment is multi-line. =end comment
All uppercase block typenames are reserved for specifying standard documentation, publishing, source components, or meta-information.
=NAME =AUTHOR =VERSION =TITLE =SUBTITLE
Formatting codes provide a way to add inline mark-up to a piece of text.
All Pod6 formatting codes consist of a single capital letter followed immediately by a set of single or double angle brackets; Unicode double angle brackets may be used.
Formatting codes may nest other formatting codes.
The following codes are available: B, C, E, I, K, L, N, P, R, T, U, V, X, and Z.
To format a text in bold enclose it in B< >
Perl 6 is B<awesome>
Perl 6 is awesome
To format a text in italic enclose it in I< >
Perl 6 is I<awesome>
Perl 6 is awesome
To underline a text enclose it in U< >
Perl 6 is U<awesome>
To flag text as code and treat it verbatim enclose it in C< >
C<my $var = 1; say $var;>
my $var = 1; say $var;
To create a link enclose it in L< >
A vertical bar (optional) separates label and target.
The target location can be an URL (first example) or a local Pod6 document (second example). Local file names are relative to the base of the project, not the current document.
Perl 6 homepage L<https://perl6.org> L<Perl 6 homepage|https://perl6.org>
Perl 6 homepage https://perl6.org
Structure L</language/about#Structure|/language/about#Structure> L<Structure|/language/about#Structure>
Structure /language/about#Structure
To create a link to a section in the same document:
Comments L<#Comments> L<Comments|#Comments>
Comments #Comments
This code is not implemented in Pod::To::HTML, but is partially implemented in Pod::To::BigPage.
A second kind of link — the P<> or placement link — works in the opposite direction. Instead of directing focus out to another document, it allows you to assimilate the contents of another document into your own.
In other words, the P<> formatting code takes a URI and (where possible) inserts the contents of the corresponding document inline in place of the code itself.
P<> codes are handy for breaking out standard elements of your documentation set into reusable components that can then be incorporated directly into multiple documents. For example:
=COPYRIGHT P<file:/shared/docs/std_copyright.pod> =DISCLAIMER P<http://www.MegaGigaTeraPetaCorp.com/std/disclaimer.txt>
might produce:
Copyright
This document is copyright (c) MegaGigaTeraPetaCorp, 2006. All rights reserved.
Disclaimer
ABSOLUTELY NO WARRANTY IS IMPLIED. NOT EVEN OF ANY KIND. WE HAVE SOLD YOU THIS SOFTWARE WITH NO HINT OF A SUGGESTION THAT IT IS EITHER USEFUL OR USABLE. AS FOR GUARANTEES OF CORRECTNESS...DON'T MAKE US LAUGH! AT SOME TIME IN THE FUTURE WE MIGHT DEIGN TO SELL YOU UPGRADES THAT PURPORT TO ADDRESS SOME OF THE APPLICATION'S MANY DEFICIENCIES, BUT NO PROMISES THERE EITHER. WE HAVE MORE LAWYERS ON STAFF THAN YOU HAVE TOTAL EMPLOYEES, SO DON'T EVEN *THINK* ABOUT SUING US. HAVE A NICE DAY.
If a renderer cannot find or access the external data source for a placement link, it must issue a warning and render the URI directly in some form, possibly as an outwards link. For example:
Copyright
See: file:/shared/docs/std_copyright.pod
Disclaimer
See: http://www.MegaGigaTeraPetaCorp.com/std/disclaimer.txt
You can use any of the following URI forms (see #Links) in a placement link.
A comment is text that is never rendered.
To create a comment enclose it in Z< >
Perl 6 is awesome Z<Of course it is!>
Perl 6 is awesome
Notes are rendered as footnotes.
To create a note enclose it in N< >
Perl 6 is multi-paradigmatic N<Supporting Procedural, Object Oriented, and Functional programming>
To flag text as keyboard input enclose it in K< >
Enter your name K<John Doe>
The R<> formatting code specifies that the contained text is a replaceable item, a placeholder, or a metasyntactic variable. It is used to indicate a component of a syntax or specification that should eventually be replaced by an actual value. For example:
The basic ln command is: ln source_file target_file
or:
Then enter your details at the prompt: =for input Name: your surname ID: your employee number Pass: your 36-letter password
To flag text as terminal output enclose it in T< >
Hello T<John Doe>
To include Unicode code points or HTML5 character references in a Pod6 document, enclose them in E< >
E< > can enclose a number, which is treated as the decimal Unicode value for the desired code point. It can also enclose explicit binary, octal, decimal, or hexadecimal numbers using the Perl 6 notations for explicitly based numbers.
Perl 6 makes considerable use of the E<171> and E<187> characters. Perl 6 makes considerable use of the E<laquo> and E<raquo> characters. Perl 6 makes considerable use of the E<0b10101011> and E<0b10111011> characters. Perl 6 makes considerable use of the E<0o253> and E<0o273> characters. Perl 6 makes considerable use of the E<0d171> and E<0d187> characters. Perl 6 makes considerable use of the E<0xAB> and E<0xBB> characters.
Perl 6 makes considerable use of the « and » characters.
This code is not implemented by Pod::To::HTML, but is implemented in Pod::To::BigPage.
The V<> formatting code treats its entire contents as being verbatim, disregarding every apparent formatting code within it. For example:
The B<V< V<> >> formatting code disarms other codes such as V< I<>, C<>, B<>, and M<> >.
Note, however that the V<> code only changes the way its contents are parsed, not the way they are rendered. That is, the contents are still wrapped and formatted like plain text, and the effects of any formatting codes surrounding the V<> code are still applied to its contents. For example the previous example is rendered as:
The V<> formatting code disarms other codes such as I<>, C<>, B<>, and M<> .
Anything enclosed in an X<> code is an index entry. The contents of the code are both formatted into the document and used as the (case-insensitive) index entry:
An X<array> is an ordered list of scalars indexed by number, starting with 0. A X<hash> is an unordered collection of scalar values indexed by their associated string key.
You can specify an index entry in which the indexed text and the index entry are different, by separating the two with a vertical bar:
An X<array|arrays> is an ordered list of scalars indexed by number, starting with 0. A X<hash|hashes> is an unordered collection of scalar values indexed by their associated string key.
In the two-part form, the index entry comes after the bar and is case-sensitive.
You can specify hierarchical index entries by separating indexing levels with commas:
An X<array| arrays, definition of > is an ordered list of scalars indexed by number, starting with 0. A X<hash| hashes, definition of > is an unordered collection of scalar values indexed by their associated string key.
You can specify two or more entries for a single indexed text, by separating the entries with semicolons:
A X<hash| hashes, definition of; associative arrays > is an unordered collection of scalar values indexed by their associated string key.
The indexed text can be empty, creating a "zero-width" index entry:
X<|puns, deliberate> This is called the "Orcish Maneuver" because you "OR" the "cache".
In order to generate HTML from Pod, you need the Pod::To::HTML module.
If it is not already installed, install it by running the following command: zef install Pod::To::HTML
Once installed, run the following command in the terminal:
perl6 --doc=HTML input.pod6 > output.html
In order to generate Markdown from Pod, you need the Pod::To::Markdown module.
If it is not already installed, install it by running the following command: zef install Pod::To::Markdown
Once installed, run the following command in the terminal:
perl6 --doc=Markdown input.pod6 > output.md
In order to generate Text from Pod, you can use the default Pod::To::Text module.
Using the terminal, run the following command:
perl6 --doc=Text input.pod6 > output.txt
You can omit the =Text portion:
perl6 --doc input.pod6 > output.txt
You can even embed Pod6 directly in your program and add the traditional Unix command line "--man" option to your program with a multi MAIN subroutine like this:
multi MAIN(Bool :$man) { run $*EXECUTABLE, '--doc', $*PROGRAM; }
Now myprogram --man will output your Pod6 rendered as a man page.
In order to access Pod6 documentation from within a Perl 6 program the special = twigil, as documented in the variables section, must be used.
The = twigil provides the introspection over the Pod6 structure, providing a Pod::Block tree root from which it is possible to access the whole structure of the Pod6 document.
As an example, the following piece of code introspects its own Pod6 documentation:
=begin pod =head1 This is a head1 title This is a paragraph. =head2 Subsection Here some text for the subsection. =end pod for $=pod -> $pod-item { for $pod-item.contents -> $pod-block { $pod-block.perl.say; } }
producing the following output:
Pod::Heading.new(level => 1, config => {}, contents => [Pod::Block::Para.new(config => {}, contents => ["This is a head1 title"])]); Pod::Block::Para.new(config => {}, contents => ["This is a paragraph."]); Pod::Heading.new(level => 2, config => {}, contents => [Pod::Block::Para.new(config => {}, contents => ["Subsection"])]); Pod::Block::Para.new(config => {}, contents => ["Here some text for the subsection."]);
The good, the bad and the ugly
The official specification for Perl 6 POD tables is located in the Documentation specification here: Tables. Although Pod 6 specifications are not completely handled properly yet, several projects are ongoing to correct the situation; one such project is ensuring the proper handling of Pod 6 tables.
As part of that effort, this document explains the current state of Pod 6 tables by example: valid tables, invalid tables, and ugly tables (i.e., valid tables that, because of sloppy construction, may result in something different than the user expects).
1. The only valid column separators are either visible (' | ' or ' + ') (note at least one space is required before and after the visible column separators) or invisible [two or more contiguous whitespace (WS) characters (e.g., ' ')]. Column separators are not normally recognized as such at the left or right side of a table, but one on the right side may result in one or more empty cells depending upon the number of the cells in other rows. (Note that a pipe or plus character meant as part of cell data will result in an unintended extra column unless the character is escaped with a backslash, e.g., '\|' or '\+'.)
2. Mixing visible and invisible column separators in the same table is illegal.
3. The only valid row separator characters are '_', '-', '+', ' ', '|', and '='.
4. Consecutive interior row-separator lines are illegal.
5. Leading and trailing row-separator lines generate a warning.
6. Formatting blocks in table cells currently are ignored and treated as plain text.
HINT: During development, use of the environment variable RAKUDO_POD6_TABLE_DEBUG will show you how Rakudo interprets your pod tables before they are passed to renderers such as Pod::To::HTML, Pod::To::Text, and Pod::To::Markdown.
HINT: Not adhering to the following best practices may require more table processing due to additional looping over table rows.
1. Use of WS for column separators is fragile, and they should only be used for simple tables. The Ugly Tables section below illustrates the problem.
2. Align table columns and rows carefully. See the examples in later best practices.
3. Don't use visual borders on the table.
4. For tables with a heading and single- or multi-line content, use one or more contiguous equal signs ('=') as the row separator after the heading, and use one or more contiguous hyphens ('-') as the row separator in the content portion of the table. For example,
Heading and single- or multi-line content
=begin table hdr col 0 | hdr col 1 ====================== row 0 | row 0 col 0 | col 1 ---------------------- row 1 | row 1 col 0 | col 1 ---------------------- =end table
Heading and single-line content
=begin table hdr col 0 | hdr col 1 ====================== row 0 col 0 | row 0 col 1 row 1 col 0 | row 1 col 1 =end table
5. For tables with no header and multi-line content, use one or more contiguous hyphens ('-') as the row separator in the content portion of the table. For example,
=begin table row 0 | row 0 col 0 | col 1 ---------------------- row 1 col 0 | row 1 col 1 =end table
6. For tables with many rows and no multi-line content, using no row separators is fine. However, with one or more rows with multi-line content, it is easier to ensure proper results by using a row separator line (visible or invisible) between every content row.
7. Ensure intentionally empty cells have column separators, otherwise expect a warning about short rows being filled with empty cells. (Tables rows will always have the same number of cells as the row with the most cells. Short rows are padded on the right with empty cells and generate a warning.)
8. Adding a caption to a table is possible using the =begin table line as in this example:
=begin table :caption<My Tasks> mow lawn take out trash =end table
Although not a good practice, currently there is in use an alternate method of defining a caption as shown in this example:
=begin table :config{caption => "My Tasks"} mow lawn take out trash =end table
Note the alternative method of putting the caption in the config hash was necessary before the :caption method was implemented, but that method is now considered to be deprecated. The practice will generate a warning in the upcoming version 6.d, and it will raise an exception in version 6.e.
Following are examples of valid (Good) tables (taken from the current Specification Tests).
=begin table The Shoveller Eddie Stevens King Arthur's singing shovel Blue Raja Geoffrey Smith Master of cutlery Mr Furious Roy Orson Ticking time bomb of fury The Bowler Carol Pinnsler Haunted bowling ball =end table
=table Constants 1 Variables 10 Subroutines 33 Everything else 57
=for table mouse | mice horse | horses elephant | elephants
=table Animal | Legs | Eats ======================= Zebra + 4 + Cookies Human + 2 + Pizza Shark + 0 + Fish
=table Superhero | Secret | | Identity | Superpower ==============|=================|================================ The Shoveller | Eddie Stevens | King Arthur's singing shovel
=begin table Secret Superhero Identity Superpower ============= =============== =================== The Shoveller Eddie Stevens King Arthur's singing shovel Blue Raja Geoffrey Smith Master of cutlery Mr Furious Roy Orson Ticking time bomb of fury The Bowler Carol Pinnsler Haunted bowling ball =end table
=table X | O | ---+---+--- | X | O ---+---+--- | | X
=table X O =========== X O =========== X
=begin table foo bar =end table
Following are examples of invalid (Bad) tables, and they should trigger an unhandled exception during parsing.
Mixed column separator types in the same row are not allowed:
=begin table r0c0 + r0c1 | r0c3 =end table
Mixed visual and whitespace column separator types in the same table are not allowed:
=begin table r0c0 + r0c1 | r0c3 r1c0 r0c1 r0c3 =end table
Two consecutive interior row separators are not allowed:
=begin table r0c0 | r0c1 ============ ============ r1c0 | r1c1 =end table
Following are examples of valid tables that are probably intended to be two columns, but the columns are not aligned well so each will parse as a single-column table.
Unaligned columns with WS column separators:
Notice the second row has the two words separated by only one WS character, while it takes at least two adjacent WS characters to define a column separation. This is a valid table but will be parsed as a single-column table.
=begin table r0c0 r0c1 r1c0 r0c1 =end table
Unaligned columns with visual column separators:
Notice the second row has the two words separated by a visible character ('|') but the character is not recognized as a column separator because it doesn't have an adjacent WS character on both sides of it. Although this is a legal table, the result will not be what the user intended because the first row has two columns while the second row has only one column, and it will thus have an empty second column.
=begin table r0c0 | r0c1 r1c0 |r0c1 =end table
Perl 6 terms
Most syntactic constructs in Perl 6 can be categorized in terms and operators.
Here you can find an overview of different kinds of terms.
42 12_300_00 :16<DEAD_BEEF>
Int literals consist of digits and can contain underscores between any two digits.
To specify a base other than ten, use the colonpair form :radix<number> .
12.34 1_200.345_678
Rat literals (rational numbers) contain two integer parts joined by a dot.
Note that trailing dots are not allowed, so you have to write 1.0 instead of 1. (this rule is important because there are infix operators starting with a dot, for example the .. Range operator).
12.3e-32 3e8
Num literals (floating point numbers) consist of Rat or Int literals followed by an e and a (possibly negative) exponent. 3e8 constructs a Num with value 3 * 10**8.
'a string' 'I\'m escaped!' "I don't need to be" "\"But I still can be,\" he said." q|Other delimiters can be used too!|
String literals are most often created with ' or ", however strings are actually a powerful sub-language of Perl 6. See Quoting Constructs.
/ match some text / rx/slurp \s rest (.*) $/
These forms produce regex literals. See quoting constructs.
a => 1 'a' => 'b' :identifier :!identifier :identifier<value> :identifier<value1 value2> :identifier($value) :identifier['val1', 'val2'] :identifier{key1 => 'val1', key2 => 'value2'} :valueidentifier :$item :@array :%hash :&callable
Pair objects can be created either with infix:«=>» (which auto-quotes the left-hand side if it is an identifier), or with the various colon-pair forms. Those almost always start with a colon and then are followed either by an identifier or the name of an already existing variable (whose name without the sigil is used as the key and value of the variable is used as the value of the pair). There is a special form where an integer value is immediately after the colon and the key is immediately after the value.
In the identifier form of a colon-pair, the optional value can be any circumfix. If it is left blank, the value is Bool::True. The value of the :!identifier form is Bool::False.
If used in an argument list, all of these forms count as named arguments, with the exception of 'quoted string' => $value .
() 1, 2, 3 <a b c> «a b c» qw/a b c/
List literals are: the empty pair of parentheses (), a comma-separated list, or several quoting constructs.
Creates an object of type Whatever. See Whatever documentation for more details.
There are built-in identifier terms in Perl 6, which are listed below. In addition one can add new identifier terms with the syntax:
sub term:<forty-two> { 42 }; say forty-two
or as constants:
constant forty-two = 42; say forty-two;
Inside a method, self refers to the invocant (i.e. the object the method was called on). If used in a context where it doesn't make sense, a compile-time exception of type X::Syntax::NoSelf is thrown.
Returns an Instant object representing the current time. It includes leap seconds and as such a few dozen seconds larger than time:
say (now - time).Int; # OUTPUT: «37»
Returns the current POSIX time as an Int. See now for high-resolution timestamp that includes leap seconds.
Returns a pseudo-random Num in the range 0..^1.
Returns the number π at codepoint U+03C0 (GREEK SMALL LETTER PI), i.e. the ratio between circumference and diameter of a circle. The ASCII equivalent of π is pi.
Returns the number π, i.e., the ratio between circumference and diameter of a circle. pi is the ASCII equivalent of π.
Returns the number τ at codepoint U+03C4 (GREEK SMALL LETTER TAU), i.e. the ratio between circumference and radius of a circle. The ASCII equivalent of τ is tau.
Returns the number τ, i.e. the ratio between circumference and radius of a circle. tau is the ASCII equivalent of τ.
Returns Euler's number at codepoint U+1D452 (MATHEMATICAL ITALIC SMALL E). The ASCII equivalent of 𝑒 is e.
Returns Euler's number. e is the ASCII equivalent of 𝑒.
Returns the imaginary unit (for Complex numbers).
Returns set(), aka the empty set, at codepoint U+2205 (EMPTY SET).
Variables are discussed in the variable language docs.
Constants are similar to variables without a container, and thus cannot be rebound. However, their initializers are evaluated at BEGIN time:
constant speed-of-light = 299792458; # m/s constant @foo = 1, 2, 3; constant &talk = &say; talk speed-of-light²; # OUTPUT: «89875517873681764» talk @foo; # OUTPUT: «(1 2 3)»
Compile-time evaluation means you should be careful with using constants inside modules, which get automatically precompiled, and so the value of the constant would not change even between multiple executions of the program:
# Foo.pm6 unit module Foo; constant comp-time = DateTime.now;
# The value of the constant remains the same even though our script # is executed multiple times: $ perl6 -I. -MFoo -e 'say Foo::comp-time' 2018-06-17T18:18:50.021484-04:00 $ perl6 -I. -MFoo -e 'say Foo::comp-time' 2018-06-17T18:18:50.021484-04:00
Constants are declared with keyword constant followed by an identifier with an optional sigil. Constants are our scoped by default.
constant foo = 42; my constant $baz = rand; our constant @foo = 1, 2, 3; constant %bar = %(:42foo, :100bar);
NOTE: if you're using the Rakudo compiler, you need version 2018.08 or newer for type constraints and auto-coercion on constants to be available. Auto-coercion on %-sigiled constants requires 6.d
An optional type constraint can be used, in which case the use of scope declarator is required:
# !!WRONG!! missing scope declarator before type: Int constant bar = 42; # RIGHT: our Int constant bar = 42;
Unlike variables, you cannot parameterize @-, %-, and &-sigiled constants by specifying the parameterization type in the declarator itself:
# !!WRONG!! cannot parameterize @-sigiled constant with Int our Int constant @foo = 42; # OK: parameterized types as values are fine constant @foo = Array[Int].new: 42;
The reason for the restriction is that constants with @ and % sigils default to List and Map types, which cannot be parameterized. To keep things simple and consistent, parameterization was simply disallowed in these constructs.
The @-, %-, and &-sigiled constants specify implied typecheck of the given value for Positional, Associative, and Callable roles respectively. The @-sigiled constants—and as of 6.d language version, the %-sigiled constants as well—perform auto-coercion of the value if it does not pass the implied typecheck. The @-sigiled constants will coerce using method cache and %-sigiled constants coerce using method Map.
constant @foo = 42; @foo.perl.say; # OUTPUT: «(42,)» constant @bar = [<a b c>]; @bar.perl.say; # OUTPUT: «["a", "b", "c"]»
use v6.d.PREVIEW; constant %foo = <foo bar>; %foo.perl.say; # OUTPUT: «Map.new((:foo("bar")))» constant %bar = {:10foo, :72bar}; %bar.perl.say; # OUTPUT: «{:bar(72), :foo(10)}» # Pair is already Associative, so it remains a Pair constant %baz = :72baz; %baz.perl.say; # OUTPUT: «:baz(72)»
For convenience and consistency reasons, you can use the binding operator ( := ) instead of the assignment operator, use backslash before sigilless name of the constant variable (same as with sigilless variables), and even omit the name of the constant entirely to have an anonymous constant. Since you can't refer to anonymous entities, you may be better off using a BEGIN phaser instead, for clarity.
constant %foo := :{:42foo}; constant \foo = 42; constant = 'anon';
Writing and running tests in Perl 6
Testing code is an integral part of software development. Tests provide automated, repeatable verifications of code behavior, and ensures your code works as expected.
In Perl 6, the Test module provides a testing framework, used also by Perl 6's official spectest suite.
The testing functions emit output conforming to the Test Anything Protocol. In general, they are used in sink context:
ok check-name($meta, :$relaxed-name), "name has a hyphen rather than '::'"
but all functions also return as a Boolean if the test has been successful or not, which can be used to print a message if the test fails:
ok check-name($meta, :$relaxed-name), "name has a hyphen rather than '::'" \ or diag "\nTo use hyphen in name, pass :relaxed-name to meta-ok\n";
As with any Perl project, the tests live under the t directory in the project's base directory.
A typical test file looks something like this:
use Test; # a Standard module included with Rakudo use lib 'lib'; plan $num-tests; # .... tests done-testing; # optional with 'plan'
We ensure that we're using Perl 6, via the use v6.c pragma, then we load the Test module and specify where our libraries are. We then specify how many tests we plan to run (such that the testing framework can tell us if more or fewer tests were run than we expected) and when finished with the tests, we use done-testing to tell the framework we are done.
Note that routines in Test module are not thread-safe. This means you should not attempt to use the testing routines in multiple threads simultaneously, as the TAP output might come out of order and confuse the program interpreting it.
There are no current plans to make it thread safe. If threaded-testing is crucial to you, you may find some suitable ecosystem modules to use instead of Test for your testing needs.
Tests can be run individually by specifying the test filename on the command line:
$ perl6 t/test-filename.t
To run all tests in the directory recursively, prove6 application can be used.
You have to install it before using with zef:
$ zef install App::Prove6
You can run prove6 in a distribution directory this way:
$ prove6 --lib t/
The t/ argument specified directory that contains tests and the --lib option is passed to include lib directory into Perl 6 distribution path, it is an equivalent of -Ilib argument of perl6 command.
For more documentation regarding prove6 usage refer to its page.
To abort the test suite upon first failure, set the PERL6_TEST_DIE_ON_FAIL environmental variable:
$ PERL6_TEST_DIE_ON_FAIL=1 perl6 t/test-filename.t
The same variable can be used within the test file. Set it before loading the Test module:
BEGIN %*ENV<PERL6_TEST_DIE_ON_FAIL> = 1; use Test; ...
Tests plans use plan for declaring how many plans are going to be done or, as might be the case, skipped. If no plan is declared, done-testing is used to declare the end of the tests.
The Test module exports various functions that check the return value of a given expression and produce standardized test output.
In practice, the expression will often be a call to a function or method that you want to unit-test. ok and nok will match True and False. However, where possible it's better to use one of the specialized comparison test functions below, because they can print more helpful diagnostics output in case the comparison fails.
is and nok test for equality using the proper operator, depending on the object (or class) it's handled.
is-approx compares numbers with a certain precision, which can be absolute or relative. It can be useful for numeric values whose precision will depend on the internal representation.
Structures can be also compared using is-deeply, which will check that internal structures of the objects compared is the same.
You can use any kind of comparison with cmp-ok, which takes as an argument the function or operator that you want to be used for comparing.
isa-ok tests whether an object is of a certain type.
can-ok is used on objects to check whether they have that particular method.
does-ok checks whether the given variable can do a certain Role.
like and unlike check using regular expressions; in the first case passes if a match exists, in the second case when it does not.
Modules are tentatively loaded with use-ok, which fails if they fail to load.
dies-ok and lives-ok are opposites ways of testing code; the first checks that it throws an exception, the second that it does not; throws-like checks that the code throws the specific exception it gets handed as an argument; fails-like, similarly, checks if the code returns a specific type of Failure. eval-dies-ok and eval-lives-ok work similarly on strings that are evaluated prior to testing.
The result of a group of subtests is only ok if all subtests are ok; they are grouped using subtest.
Sometimes tests just aren't ready to be run, for instance a feature might not yet be implemented, in which case tests can be marked as todo. Or it could be the case that a given feature only works on a particular platform - in which case one would skip the test on other platforms; skip-rest will skip the remaining tests instead of a particular number given as argument; bail-out will simply exit the tests with a message.
If the convenience functionality documented above does not suit your needs, you can use the following functions to manually direct the test harness output; pass will say a test has passed, and diag will print a (possibly) informative message.
Traps to avoid when getting started with Perl 6
When learning a programming language, possibly with the background of being familiar with another programming language, there are always some things that can surprise you and might cost valuable time in debugging and discovery.
This document aims to show common misconceptions in order to avoid them.
During the making of Perl 6 great pains were taken to get rid of warts in the syntax. When you whack one wart, though, sometimes another pops up. So a lot of time was spent finding the minimum number of warts or trying to put them where they would rarely be seen. Because of this, Perl 6's warts are in different places than you may expect them to be when coming from another language.
Constants are computed at compile time, so if you use them in modules keep in mind that their values will be frozen due to precompilation of the module itself:
# WRONG (most likely): unit module Something::Or::Other; constant $config-file = "config.txt".IO.slurp;
The $config-file will be slurped during precompilation and changes to config.txt file won't be re-loaded when you start the script again; only when the module is re-compiled.
Avoid using a container and prefer binding a value to a variable that offers a behavior similar to a constant, but allowing the value to get updated:
# Good; file gets updated from 'config.txt' file on each script run: unit module Something::Or::Other; my $config-file := "config.txt".IO.slurp;
Actually, assigning to Nil reverts the variable to its default value. So:
my @a = 4, 8, 15, 16; @a[2] = Nil; say @a; # OUTPUT: «[4 8 (Any) 16]»
In this case, Any is the default value of an Array element.
You can purposefully assign Nil as a default value:
my %h is default(Nil) = a => Nil; say %h; # OUTPUT: «Hash %h = {:a(Nil)}»
Or bind a value to Nil if that is the result you want:
@a[3] := Nil; say @a; # OUTPUT: «[4 8 (Any) Nil]»
This trap might be hidden in the result of functions, such as matches:
my $result2 = 'abcdef' ~~ / dex /; say "Result2 is { $result2.^name }"; # OUTPUT: «Result2 is Any»
A Match will be Nil if it finds nothing; however it assigning Nil to $result2 above will result in its default value, which is Any as shown.
The programmer intended for the code to count the number of times the routine is called, but the counter is not increasing:
sub count-it { say "Count is {$++}" } count-it; count-it; # OUTPUT: # Count is 0 # Count is 0
When it comes to state variables, the block in which the vars are declared gets cloned —and vars get initialized anew— whenever that block's block is re-entered. This lets constructs like the one below behave appropriately; the state variable inside the loop gets initialized anew each time the sub is called:
sub count-it { for ^3 { state $count = 0; say "Count is $count"; $count++; } } count-it; say "…and again…"; count-it; # OUTPUT: # Count is 0 # Count is 1 # Count is 2 # …and again… # Count is 0 # Count is 1 # Count is 2
The same layout exists in our buggy program. The { } inside a double-quoted string isn't merely an interpolation to execute a piece of code. It's actually its own block, which is just as in the example above gets cloned each time the sub is entered, re-initializing our state variable. To get the right count, we need to get rid of that inner block, using a scalar contextualizer to interpolate our piece of code instead:
sub count-it { say "Count is $($++)" } count-it; count-it; # OUTPUT: # Count is 0 # Count is 1
Alternatively, you can also use the concatenation operator instead:
sub count-it { say "Count is " ~ $++ }
Using (cont), ∋, ∌, (elem), ∈, or ∉ on classes implementing Associative will return False if the value of the key is falsy:
enum Foo «a b»; say Foo.enums ∋ 'a'; # OUTPUT: # False
Instead, use :exists:
enum Foo «a b»; say Foo.enums<a>:exists; # OUTPUT: # True
Curly braces are used to declare blocks. However, empty curly braces will declare a hash.
$ = {say 42;} # Block $ = {;} # Block $ = {…} # Block $ = { } # Hash
You can use the second form if you effectively want to declare an empty block:
my &does-nothing = {;}; say does-nothing(33); # OUTPUT: «Nil»
Newcomers often think that, because attributes with accessors are declared as has $.x, they can assign to $.x inside the class. That's not the case.
For example
class Point { has $.x; has $.y; method double { $.x *= 2; # WRONG $.y *= 2; # WRONG self; } } say Point.new(x => 1, y => -2).double.x # OUTPUT: «Cannot assign to an immutable value»
the first line inside the method double is marked with # WRONG because $.x, short for $( self.x ), is a call to a read-only accessor.
The syntax has $.x is short for something like has $!x; method x() { $!x }, so the actual attribute is called $!x, and a read-only accessor method is automatically generated.
Thus the correct way to write the method double is
method double { $!x *= 2; $!y *= 2; self; }
which operates on the attributes directly.
When you define your own BUILD submethod, you must take care of initializing all attributes by yourself. For example
class A { has $.x; has $.y; submethod BUILD { $!y = 18; } } say A.new(x => 42).x; # OUTPUT: «Any»
leaves $!x uninitialized, because the custom BUILD doesn't initialize it.
Note: Consider using TWEAK instead. Rakudo supports TWEAK method since release 2016.11.
One possible remedy is to explicitly initialize the attribute in BUILD:
submethod BUILD(:$x) { $!y = 18; $!x := $x; }
which can be shortened to:
submethod BUILD(:$!x) { $!y = 18; }
say 'a b' ~~ /a b/; # OUTPUT: «False»
Whitespace in regexes is, by default, considered an optional filler without semantics, just like in the rest of the Perl 6 language.
Ways to match whitespace:
\s to match any one whitespace, \s+ to match at least one
' ' (a blank in quotes) to match a single blank
\t, \n for specific whitespace (tab, newline)
\h, \v for horizontal, vertical whitespace
.ws, a built-in rule for whitespace that oftentimes does what you actually want it to do
with m:s/a b/ or m:sigspace/a b/, the blank in the regexes matches arbitrary whitespace
While some languages will let you get away with removing as much whitespace between tokens as possible, Perl 6 is less forgiving. The overarching mantra is we discourage code golf, so don't scrimp on whitespace (the more serious underlying reason behind these restrictions is single-pass parsing and ability to parse Perl 6 programs with virtually no backtracking).
The common areas you should watch out for are:
# WRONG; trying to hash-slice a Bool: while ($++ > 5){ .say }
# RIGHT: while ($++ > 5) { .say } # EVEN BETTER; Perl 6 does not require parentheses there: while $++ > 5 { .say }
# WRONG; ambiguity with `[<]` meta op: my @a = [[<foo>],];
# RIGHT; reductions cannot have spaces in them, so put one in: my @a = [[ <foo>],]; # No ambiguity here, natural spaces between items suffice to resolve it: my @a = [[<foo bar ber>],];
# WRONG; trying to index 3 associatively: say 3<5>4
# RIGHT; prefer some extra whitespace around infix operators: say 3 < 5 > 4
See the section on operator traps for more information about how the ...^ operator can be mistaken for the ... operator with a ^ operator immediately following it. You must use whitespace correctly to indicate which interpretation will be followed.
Beginners might expect a variable in a Capture to supply its current value when that Capture is later used. For example:
my $a = 2; say join ",", ($a, ++$a); # OUTPUT: «3,3»
Here the Capture contained the container pointed to by $a and the value of the result of the expression ++$a. Since the Capture must be reified before &say can use it, the ++$a may happen before &say looks inside the container in $a (and before the List is created with the two terms) and so it may already be incremented.
Instead, use an expression that produces a value when you want a value.
my $a = 2; say join ",", (+$a, ++$a); # OUTPUT: «2,3»
Or even simpler
my $a = 2; say "$a, {++$a}"; # OUTPUT: «2, 3»
The same happens in this case:
my @arr; my ($a, $b) = (1,1); for ^5 { ($a,$b) = ($b, $a+$b); @arr.push: ($a, $b); say @arr };
Outputs «[(1 2)][(2 3) (2 3)][(3 5) (3 5) (3 5)].... $a and $b are not reified until say is called, the value that they have in that precise moment is the one printed. To avoid that, decontainerize values or take them out of the variable in some way before using them.
my @arr; my ($a, $b) = (1,1); for ^5 { ($a,$b) = ($b, $a+$b); @arr.push: ($a.item, $b.item); say @arr };
With item, the container will be evaluated in item context, its value extracted, and the desired outcome achieved.
Perl 6 includes a Cool class, which provides some of the DWIM behaviors we got used to by coercing arguments when necessary. However, DWIM is never perfect. Especially with Lists, which are Cool, there are many methods that will not do what you probably think they do, including contains, starts-with or index. Please see some examples in the section below.
In Perl 6, strings are not lists of characters. One cannot iterate over them or index into them as you can with lists, despite the name of the .index routine.
List inherits from Cool, which provides access to .index. Because of the way .index coerces a List into a Str, this can sometimes appear to be returning the index of an element in the list, but that is not how the behavior is defined.
my @a = <a b c d>; say @a.index(‘a’); # 0 say @a.index('c'); # 4 -- not 2! say @a.index('b c'); # 2 -- not undefined! say @a.index(<a b>); # 0 -- not undefined!
These same caveats apply to .rindex.
Similarly, .contains does not look for elements in the list.
my @menu = <hamburger fries milkshake>; say @menu.contains('hamburger'); # True say @menu.contains('hot dog'); # False say @menu.contains('milk'); # True! say @menu.contains('er fr'); # True! say @menu.contains(<es mi>); # True!
If you actually want to check for the presence of an element, use the (cont) operator for single elements, and the superset and strict superset), _infix_⊃> operators for multiple elements.
my @menu = <hamburger fries milkshake>; say @menu (cont) 'fries'; # True say @menu (cont) 'milk'; # False say @menu (>) <hamburger fries>; # True say @menu (>) <milkshake fries>; # True (! NB: order doesn't matter)
If you are doing a lot of element testing, you may be better off using a Set.
Experienced programmers will probably not be surprised by this, but Numeric literals will be parsed into their numeric value before being coerced into a string, which may create nonintuitive results.
say 0xff.contains(55); # True say 0xff.contains(0xf); # False say 12_345.contains("23"); # True say 12_345.contains("2_"); # False
A common task is to retrieve one or more random elements from a collection, but List.rand isn't the way to do that. Cool provides rand, but that first coerces the List into the number of items in the list, and returns a random real number between 0 and that value. To get random elements, see pick and roll.
my @colors = <red orange yellow green blue indigo violet>; say @colors.rand; # 2.21921955680514 say @colors.pick; # orange say @colors.roll; # blue say @colors.pick(2); # yellow violet (cannot repeat) say @colors.roll(3); # red green red (can repeat)
You want to check whether a number is divisible by any of a set of numbers:
say 42 %% <11 33 88 55 111 20325>; # OUTPUT: «True»
What? There's no single number 42 should be divisible by. However, that list has 6 elements, and 42 is divisible by 6. That's why the output is true. In this case, you should turn the List into a Junction:
say 42 %% <11 33 88 55 111 20325>.any; # OUTPUT: «any(False, False, False, False, False, False)»
which will clearly reveal the falsehood of the divisiveness of all the numbers in the list, which will be numified separately.
In some languages one could reference the last element of an array by asking for the "-1th" element of the array, e.g.:
my @array = qw{victor alice bob charlie eve}; say @array[-1]; # OUTPUT: «eve»
In Perl 6 it is not possible to use negative subscripts, however the same is achieved by actually using a function, namely *-1. Thus, accessing the last element of an array becomes:
my @array = qw{victor alice bob charlie eve}; say @array[*-1]; # OUTPUT: «eve»
Yet another way is to utilize the array's tail method:
my @array = qw{victor alice bob charlie eve}; say @array.tail; # OUTPUT: «eve» say @array.tail(2); # OUTPUT: «(charlie eve)»
Quite often new users will happen to write something like:
sub foo(Array @a) { ... }
...before they have gotten far enough in the documentation to realize that this is asking for an Array of Arrays. To say that @a should only accept Arrays, use instead:
sub foo(@a where Array) { ... }
It is also common to expect this to work, when it does not:
sub bar(Int @a) { 42.say }; bar([1, 2, 3]); # expected Positional[Int] but got Array
The problem here is that [1, 2, 3] is not an Array[Int], it is a plain old Array that just happens to have Ints in it. To get it to work, the argument must also be an Array[Int].
my Int @b = 1, 2, 3; bar(@b); # OUTPUT: «42» bar(Array[Int].new(1, 2, 3));
This may seem inconvenient, but on the upside it moves the type-check on what is assigned to @b to where the assignment happens, rather than requiring every element to be checked on every call.
This trap can be seen in different varieties. Here are some of them:
my $x = ‘hello’; my $y = ‘foo bar’; my %h = $x => 42, $y => 99; say %h«$x»; # ← WRONG; assumption that $x has no whitespace say %h«$y»; # ← WRONG; splits ‘foo bar’ by whitespace say %h«"$y"»; # ← KINDA OK; it works but there is no good reason to do that say %h{$y}; # ← RIGHT; this is what should be used run «touch $x»; # ← WRONG; assumption that only one file will be created run «touch $y»; # ← WRONG; will touch file ‘foo’ and ‘bar’ run «touch "$y"»; # ← WRONG; better, but has a different issue if $y starts with - run «touch -- "$y"»; # ← KINDA OK; it works but there is no good enough reason to do that run ‘touch’, ‘--’, $y; # ← RIGHT; explicit and *always* correct run <touch -->, $y; # ← RIGHT; < > are OK, this is short and correct
Basically, «» quoting is only safe to use if you remember to always quote your variables. The problem is that it inverts the default behavior to unsafe variant, so just by forgetting some quotes you are risking to introduce either a bug or maybe even a security hole. To stay on the safe side, refrain from using «».
Some problems that might arise when dealing with strings.
Interpolation in string literals can be too clever for your own good.
# "HTML tags" interpreted as associative indexing: "$foo<html></html>" eq "$foo{'html'}{'/html'}"
# Parentheses interpreted as call with argument: "$foo(" ~ @args ~ ")" eq "$foo(' ~ @args ~ ')"
You can avoid those problems using non-interpolating single quotes and switching to more liberal interpolation with \qq[] escape sequence:
my $a = 1; say '\qq[$a]()$b()'; # OUTPUT: «1()$b()»
Another alternative is to use Q:c quoter, and use code blocks {} for all interpolation:
my $a = 1; say Q:c«{$a}()$b()»; # OUTPUT: «1()$b()»
There are methods that Str inherits from Any that work on iterables like lists. Iterators on strings contain one element that is the whole string. To use list-based methods like sort, reverse, you need to convert the string into a list first.
say "cba".sort; # OUTPUT: «(cba)» say "cba".comb.sort.join; # OUTPUT: «abc»
In Perl 6, .chars returns the number of graphemes, or user visible characters. These graphemes could be made up of a letter plus an accent for example. If you need the number of codepoints, you should use .codes. If you need the number of bytes when encoded as UTF8, you should use .encode.bytes to encode the string as UTF8 and then get the number of bytes.
say "\c[LATIN SMALL LETTER J WITH CARON, COMBINING DOT BELOW]"; # OUTPUT: «ǰ̣» say 'ǰ̣'.codes; # OUTPUT: «2» say 'ǰ̣'.chars; # OUTPUT: «1» say 'ǰ̣'.encode.bytes; # OUTPUT: «4»
For more information on how strings work in Perl 6, see the Unicode page.
Perl 6 normalizes all text into Unicode NFC form (Normalization Form Canonical). Filenames are the only text not normalized by default. If you are expecting your strings to maintain a byte for byte representation as the original, you need to use UTF8-C8 when reading or writing to any filehandles.
Str "0" is True, while Numeric is False. So what's the Bool value of allomorph <0>?
In general, allomorphs follow Numeric semantics, so the ones that numerically evaluate to zero are False:
say so <0>; # OUTPUT: «False» say so <0e0>; # OUTPUT: «False» say so <0.0>; # OUTPUT: «False»
To force comparison being done for the Stringy part of the allomorph, use prefix ~ operator or the Str method to coerce the allomorph to Str, or use the chars routine to test whether the allomorph has any length:
say so ~<0>; # OUTPUT: «True» say so <0>.Str; # OUTPUT: «True» say so chars <0>; # OUTPUT: «True»
In order to do case-insensitive comparison, you can use .fc (fold-case). The problem is that people tend to use .lc or .uc, and it does seem to work within the ASCII range, but fails on other characters. This is not just a Perl 6 trap, the same applies to other languages.
say ‘groß’.lc eq ‘GROSS’.lc; # ← WRONG; False say ‘groß’.uc eq ‘GROSS’.uc; # ← WRONG; True, but that's just luck say ‘groß’.fc eq ‘GROSS’.fc; # ← RIGHT; True
If you are working with regexes, then there is no need to use .fc and you can use :i (:ignorecase) adverb instead.
Consider this code:
enum Animals <Dog Cat>; my %h := :{ Dog => 42 }; say %h{Dog}; # OUTPUT: «(Any)»
The :{ … } syntax is used to create object hashes. The intentions of someone who wrote that code were to create a hash with Enum objects as keys (and say %h{Dog} attempts to get a value using the Enum object to perform the lookup). However, that's not how pair notation works.
For example, in Dog => 42 the key will be a Str. That is, it doesn't matter if there is a constant, or an enumeration with the same name. The pair notation will always use the left-hand side as a string literal, as long as it looks like an identifier.
To avoid this, use (Dog) => 42 or ::Dog => 42.
When dealing with Scalar values, the Pair holds the container to the value. This means that it is possible to reflect changes to the Scalar value from outside the Pair:
my $v = 'value A'; my $pair = Pair.new( 'a', $v ); $pair.say; # OUTPUT: a => value A $v = 'value B'; $pair.say; # OUTPUT: a => value B
Use the method freeze to force the removal of the Scalar container from the Pair. For more details see the documentation about Pair.
When iterating over this kind of objects, an order is not defined.
my $set = <a b c>.Set; .say for $set.list; # OUTPUT: «a => Truec => Trueb => True» # OUTPUT: «a => Truec => Trueb => True» # OUTPUT: «c => Trueb => Truea => True»
Every iteration might (and will) yield a different order, so you cannot trust a particular sequence of the elements of a set. If order does not matter, just use them that way. If it does, use sort
my $set = <a b c>.Set; .say for $set.list.sort; # OUTPUT: «a => Trueb => Truec => True»
In general, sets, bags and mixes are unordered, so you should not depend on them having a particular order.
Some operators commonly shared among other languages were repurposed in Perl 6 for other, more common, things:
The ^, |, and & are not bitwise operators, they create Junctions. The corresponding bitwise operators in Perl 6 are: +^, +|, +& for integers and ?^, ?|, ?& for booleans.
Lavish use of whitespace helps readability, but keep in mind infix operators cannot have any whitespace in them. One such operator is the sequence operator that excludes right point: ...^ (or its Unicode equivalent …^).
say 1... ^5; # OUTPUT: «(1 0 1 2 3 4)» say 1...^5; # OUTPUT: «(1 2 3 4)»
If you place whitespace between the ellipsis (…) and the caret (^), it's no longer a single infix operator, but an infix inclusive sequence operator (…) and a prefix Range operator (^). Iterables are valid endpoints for the sequence operator, so the result you'll get might not be what you expected.
In some languages, using strings as range end points, considers the entire string when figuring out what the next string should be; loosely treating the strings as numbers in a large base. Here's Perl 5 version:
say join ", ", "az".."bc"; # OUTPUT: «az, ba, bb, bc»
Such a range in Perl 6 will produce a different result, where each letter will be ranged to a corresponding letter in the end point, producing more complex sequences:
say join ", ", "az".."bc"; #`{ OUTPUT: « az, ay, ax, aw, av, au, at, as, ar, aq, ap, ao, an, am, al, ak, aj, ai, ah, ag, af, ae, ad, ac, bz, by, bx, bw, bv, bu, bt, bs, br, bq, bp, bo, bn, bm, bl, bk, bj, bi, bh, bg, bf, be, bd, bc »}
say join ", ", "r2".."t3"; # OUTPUT: «r2, r3, s2, s3, t2, t3»
To achieve simpler behavior, similar to the Perl 5 example above, use a sequence operator that calls .succ method on the starting string:
say join ", ", ("az", *.succ ... "bc"); # OUTPUT: «az, ba, bb, bc»
The smartmatch operator ~~ and andthen set the topic $_ to their left-hand-side. In conjunction with implicit method calls on the topic this can lead to surprising results.
my &method = { note $_; $_ }; $_ = 'object'; say .&method; # OUTPUT: «objectobject» say 'topic' ~~ .&method; # OUTPUT: «topicTrue»
In many cases flipping the method call to the LHS will work.
my &method = { note $_; $_ }; $_ = 'object'; say .&method; # OUTPUT: «objectobject» say .&method ~~ 'topic'; # OUTPUT: «objectFalse»
The fat arrow operator => will turn words on its left-hand side to Str without checking the scope for constants or \-sigiled variables. Use explicit scoping to get what you mean.
constant V = 'x'; my %h = V => 'oi‽', ::V => 42; say %h.perl # OUTPUT: «{:V("oi‽"), :x(42)}»
Infix operators, both built in and user defined, can be combined with the assignment operator as this addition example demonstrates:
my $x = 10; $x += 20; say $x; # OUTPUT: «30»
For any given infix operator op, L op= R is equivalent to L = L op R (where L and R are the left and right arguments, respectively). This means that the following code may not behave as expected:
my @a = 1, 2, 3; @a += 10; say @a; # OUTPUT: «[13]»
Coming from a language like C++, this might seem odd. It is important to bear in mind that += isn't defined as method on the left hand argument (here the @a array) but is simply shorthand for:
my @a = 1, 2, 3; @a = @a + 10; say @a; # OUTPUT: «[13]»
Here @a is assigned the result of adding @a (which has three elements) and 10; 13 is therefore placed in @a.
Use the hyper form of the assignment operators instead:
my @a = 1, 2, 3; @a »+=» 10; say @a; # OUTPUT: «[11 12 13]»
Perl 6 offers several constructs to generate regexes at runtime through interpolation (see their detailed description here). When a regex generated this way contains only literals, the above constructs behave (pairwise) identically, as if they are equivalent alternatives. As soon as the generated regex contains metacharacters, however, they behave differently, which may come as a confusing surprise.
The first two constructs that may easily be confused with each other are $variable and <$variable>:
my $variable = 'camelia'; say ‘I ♥ camelia’ ~~ / $variable /; # OUTPUT: 「camelia」 say ‘I ♥ camelia’ ~~ / <$variable> /; # OUTPUT: 「camelia」
Here they act the same because the value of $variable consists of literals. But when the variable is changed to comprise regex metacharacters the outputs become different:
my $variable = '#camelia'; say ‘I ♥ #camelia’ ~~ / $variable /; # OUTPUT: 「#camelia」 say ‘I ♥ #camelia’ ~~ / <$variable> /; # !! Error: malformed regex
What happens here is that the string #camelia contains the metacharacter #. In the context of a regex, this character should be quoted to match literally; without quoting, the # is parsed as the start of a comment that runs until the end of the line, which in turn causes the regex not to be terminated, and thus to be malformed.
Two other constructs that must similarly be distinguished from one another are $(code) and <{code}>. Like before, as long as the (stringified) return value of code comprises only literals, there is no distinction between the two:
my $variable = 'ailemac'; say ‘I ♥ camelia’ ~~ / $($variable.flip) /; # OUTPUT: 「camelia」 say ‘I ♥ camelia’ ~~ / <{$variable.flip}> /; # OUTPUT: 「camelia」
But when the return value is changed to comprise regex metacharacters, the outputs diverge:
my $variable = 'ailema.'; say ‘I ♥ camelia’ ~~ / $($variable.flip) /; # OUTPUT: Nil say ‘I ♥ camelia’ ~~ / <{$variable.flip}> /; # OUTPUT: 「camelia」
In this case the return value of the code is the string .amelia, which contains the metacharacter .. The above attempt by $(code) to match the dot literally fails; the attempt by <{code}> to match the dot as a regex wildcard succeeds. Hence the different outputs.
To match one of several possible alternatives, || or | will be used. But they are so different.
When there are multiple matching alternations, for those separated by ||, the first matching alternation wins; for those separated by |, which to win is decided by LTM strategy. See also: documentation on || and documentation on |.
For simple regexes just using || instead of | will get you familiar semantics, but if writing grammars then it's useful to learn about LTM and declarative prefixes and prefer |. And keep yourself away from using them in one regex. When you have to do that, add parentheses and ensure that you know how LTM strategy works to make the code do what you want.
The trap typically arises when you try to mix both | and || in the same regex:
say 42 ~~ / [ 0 || 42 ] | 4/; # OUTPUT: «「4」» say 42 ~~ / [ 42 || 0 ] | 4/; # OUTPUT: «「42」»
The code above may seem like it is producing a wrong result, but the implementation is actually right.
Each time a regular expression is matched against something, the special variable $/ holding the result Match object is changed accordingly to the result of the match (that could also be Nil).
The $/ is changed without any regard to the scope the regular expression is matched within.
For further information and examples please see the related section in the Regular Expressions documentation.
Regexes can contain quoted lists; longest token matching is performed on the list's elements as if a | alternation had been specified (see here for further information).
Within a regex, the following are lists with a single item, 'foo':
say 'foo' ~~ /< foo >/; # OUTPUT: «「foo」» say 'foo' ~~ /< foo>/; # OUTPUT: «「foo」»
but this is a call to the named rule foo:
say 'foo' ~~ /<foo>/; # OUTPUT: «No such method 'foo' for invocant of type 'Match' in block <unit> at <unknown file> line 1»
Be wary of the difference; if you intend to use a quoted list, ensure that whitespace follows the initial <.
Unlike Perl 5, non-capturing and non-global matching in list context doesn't produce any values:
if 'x' ~~ /./ { say 'yes' } # OUTPUT: «yes» for 'x' ~~ /./ { say 'yes' } # NO OUTPUT
This is because its 'list' slot (inherited from Capture class) doesn't get populated with the original Match object:
say ('x' ~~ /./).list # OUTPUT: «()»
To achieve the desired result, use global matching, capturing parentheses or a list with a trailing comma:
for 'x' ~~ m:g/./ { say 'yes' } # OUTPUT: «yes» for 'x' ~~ /(.)/ { say 'yes' } # OUTPUT: «yes» for ('x' ~~ /./,) { say 'yes' } # OUTPUT: «yes»
Adverbs do have a precedence that may not follow the order of operators that is displayed on your screen. If two operators of equal precedence are followed by an adverb it will pick the first operator it finds in the abstract syntax tree. Use parentheses to help Perl 6 understand what you mean or use operators with looser precedence.
my %x = a => 42; say !%x<b>:exists; # dies with X::AdHoc say %x<b>:!exists; # this works say !(%x<b>:exists); # works too say not %x<b>:exists; # works as well say True unless %x<b>:exists; # avoid negation altogether
The loose precedence of .. can lead to some errors. It is usually best to parenthesize ranges when you want to operate on the entire range.
1..3.say; # says "3" (and warns about useless "..") (1..3).say; # says "1..3"
The precedence of and, or, etc. is looser than routine calls. This can have surprising results for calls to routines that would be operators or statements in other languages like return, last and many others.
sub f { return True and False; # this is actually # (return True) and False; } say f; # OUTPUT: «True»
say -1²; # OUTPUT: «-1» say -1**2; # OUTPUT: «-1»
When performing a regular mathematical calculation, the power takes precedence over the minus; so -1² can be written as -(1²). Perl 6 matches these rules of mathematics and the precedence of ** operator is tighter than that of the prefix -. If you wish to raise a negative number to a power, use parentheses:
say (-1)²; # OUTPUT: «1» say (-1)**2; # OUTPUT: «1»
Prefix minus binds looser than dotty method op calls. The prefix minus will be applied to the return value from the method. To ensure the minus gets passed as part of the argument, enclose in parenthesis.
say -1.abs; # OUTPUT: «-1» say (-1).abs; # OUTPUT: «1»
Subroutine and method calls can be made using one of two forms:
foo(...); # function call form, where ... represent the required arguments foo ...; # list op form, where ... represent the required arguments
The function call form can cause problems for the unwary when whitespace is added after the function or method name and before the opening parenthesis.
First we consider functions with zero or one parameter:
sub foo() { say 'no arg' } sub bar($a) { say "one arg: $a" }
Then execute each with and without a space after the name:
foo(); # okay: no arg foo (); # FAIL: Too many positionals passed; expected 0 arguments but got 1 bar($a); # okay: one arg: 1 bar ($a); # okay: one arg: 1
Now declare a function of two parameters:
sub foo($a, $b) { say "two args: $a, $b" }
Execute it with and without the space after the name:
foo($a, $b); # okay: two args: 1, 2 foo ($a, $b); # FAIL: Too few positionals passed; expected 2 arguments but got 1
The lesson is: "be careful with spaces following sub and method names when using the function call format." As a general rule, good practice might be to avoid the space after a function name when using the function call format.
Note that there are clever ways to eliminate the error with the function call format and the space, but that is bordering on hackery and will not be mentioned here. For more information, consult Functions.
Finally, note that, currently, when declaring the functions whitespace may be used between a function or method name and the parentheses surrounding the parameter list without problems.
Many built-in subroutines and method calls accept named parameters and your own code may accept them as well, but be sure the arguments you pass when calling your routines are actually named parameters:
sub foo($a, :$b) { ... } foo(1, 'b' => 2); # FAIL: Too many positionals passed; expected 1 argument but got 2
What happened? That second argument is not a named parameter argument, but a Pair passed as a positional argument. If you want a named parameter it has to look like a name to Perl:
foo(1, b => 2); # okay foo(1, :b(2)); # okay foo(1, :b<it>); # okay my $b = 2; foo(1, :b($b)); # okay, but redundant foo(1, :$b); # okay # Or even... my %arg = 'b' => 2; foo(1, |%arg); # okay too
That last one may be confusing, but since it uses the | prefix on a Hash, which is a special compiler construct indicating you want to use the contents of the variable as arguments, which for hashes means to treat them as named arguments.
If you really do want to pass them as pairs you should use a List or Capture instead:
my $list = ('b' => 2),; # this is a List containing a single Pair foo(|$list, :$b); # okay: we passed the pair 'b' => 2 to the first argument foo(1, |$list); # FAIL: Too many positionals passed; expected 1 argument but got 2 foo(1, |$list.Capture); # OK: .Capture call converts all Pair objects to named args in a Capture
my $cap = \('b' => 2); # a Capture with a single positional value foo(|$cap, :$b); # okay: we passed the pair 'b' => 2 to the first argument foo(1, |$cap); # FAIL: Too many positionals passed; expected 1 argument but got 2
A Capture is usually the best option for this as it works exactly like the usual capturing of routine arguments during a regular call.
The nice thing about the distinction here is that it gives the developer the option of passing pairs as either named or positional arguments, which can be handy in various instances.
While it is typically unnoticeable, there is a backend-dependent argument count limit. Any code that does flattening of arbitrarily sized arrays into arguments won't work if there are too many elements.
my @a = 1 xx 9999; my @b; @b.push: |@a; say @b.elems # OUTPUT: «9999»
my @a = 1 xx 999999; my @b; @b.push: |@a; # OUTPUT: «Too many arguments in flattening array. in block <unit> at <tmp> line 1»
Avoid this trap by rewriting the code so that there is no flattening. In the example above, you can replace push with append. This way, no flattening is required because the array can be passed as is.
my @a = 1 xx 999999; my @b; @b.append: @a; say @b.elems # OUTPUT: «999999»
sub returns-ret () { CATCH { default {} } "ret"; } sub doesn't-return-ret () { "ret"; CATCH { default {} } } say returns-ret; # OUTPUT: «ret» say doesn't-return-ret; # BAD: outputs «Nil» and a warning «Useless use of constant string "ret" in sink context (line 13)»
Code for returns-ret and doesn't-return-ret might look exactly the same, since in principle it does not matter where the CATCH block goes. However, a block is an object and the last object in a sub will be returned, so the doesn't-return-ret will return Nil, and, besides, since "ret" will be now in sink context, it will issue a warning. In case you want to place phasers last for conventional reasons, use the explicit form of return.
sub explicitly-return-ret () { return "ret"; CATCH { default {} } }
Unlike some other languages, Perl 6 does not use reference counting, and so the filehandles are NOT closed when they go out of scope. You have to explicitly close them either by using close routine or using the :close argument several of IO::Handle's methods accept. See IO::Handle.close for details.
The same rules apply to IO::Handle's subclass IO::Pipe, which is what you operate on when reading from a Proc you get with routines run and shell.
The caveat applies to IO::CatHandle type as well, though not as severely. See IO::CatHandle.close for details.
Partly for historical reasons and partly by design, an IO::Path object stringifies without considering its CWD attribute, which means if you chdir and then stringify an IO::Path, or stringify an IO::Path with custom $!CWD attribute, the resultant string won't reference the original filesystem object:
with 'foo'.IO { .Str.say; # OUTPUT: «foo» .relative.say; # OUTPUT: «foo» chdir "/tmp"; .Str.say; # OUTPUT: «foo» .relative.say # OUTPUT: «../home/camelia/foo» } # Deletes ./foo, not /bar/foo unlink IO::Path.new("foo", :CWD</bar>).Str
The easy way to avoid this issue is to not stringify an IO::Path object at all. Core routines that work with paths can take an IO::Path object, so you don't need to stringify the paths.
If you do have a case where you need a stringified version of an IO::Path, use absolute or relative methods to stringify it into an absolute or relative path, respectively.
If you are facing this issue because you use chdir in your code, consider rewriting it in a way that does not involve changing the current directory. For example, you can pass cwd named argument to run without having to use chdir around it.
There is a difference between using .lines on IO::Handle and on a Str. The trap arises if you start assuming that both split data the same way.
say $_.perl for $*IN.lines # .lines called on IO::Handle # OUTPUT: # "foox" # "fooy\rbar" # "fooz"
As you can see in the example above, there was a line which contained \r (“carriage return” control character). However, the input is split strictly by \n, so \r was kept as part of the string.
On the other hand, Str.lines attempts to be “smart” about processing data from different operating systems. Therefore, it will split by all possible variations of a newline.
say $_.perl for $*IN.slurp(:bin).decode.lines # .lines called on a Str # OUTPUT: # "foox" # "fooy" # "bar" # "fooz"
The rule is quite simple: use IO::Handle.lines when working with programmatically generated output, and Str.lines when working with user-written texts.
Use $data.split(“\n”) in cases where you need the behavior of IO::Handle.lines but the original IO::Handle is not available.
RT#132154Note that if you really want to slurp the data first, then you will have to use .IO.slurp(:bin).decode.split(“\n”). Notice how we use :bin to prevent it from doing the decoding, only to call .decode later anyway. All that is needed because .slurp is assuming that you are working with text and therefore it attempts to be smart about newlines.
RT#131923If you are using Proc::Async, then there is currently no easy way to make it split data the right way. You can try reading the whole output and then using Str.split (not viable if you are dealing with large data) or writing your own logic to split the incoming data the way you need. Same applies if your data is null-separated.
When using Proc::Async you should not assume that .print (or any other similar method) is synchronous. The biggest issue of this trap is that you will likely not notice the problem by running the code once, so it may cause a hard-to-detect intermittent fail.
Here is an example that demonstrates the issue:
loop { my $proc = Proc::Async.new: :w, ‘head’, ‘-n’, ‘1’; my $got-something; react { whenever $proc.stdout.lines { $got-something = True } whenever $proc.start { die ‘FAIL!’ unless $got-something } $proc.print: “one\ntwo\nthree\nfour”; $proc.close-stdin; } say $++; }
And the output it may produce:
0 1 2 3 An operation first awaited: in block <unit> at print.p6 line 4 Died with the exception: FAIL! in block at print.p6 line 6
Resolving this is easy because .print returns a promise that you can await on. The solution is even more beautiful if you are working in a react block:
whenever $proc.print: “one\ntwo\nthree\nfour” { $proc.close-stdin; }
Method .stdout of Proc::Async returns a supply that emits chunks of data, not lines. The trap is that sometimes people assume it to give lines right away.
my $proc = Proc::Async.new(‘cat’, ‘/usr/share/dict/words’); react { whenever $proc.stdout.head(1) { .say } # ← WRONG (most likely) whenever $proc.start { } }
The output is clearly not just 1 line:
A A's AMD AMD's AOL AOL's Aachen Aachen's Aaliyah Aaliyah's Aaron Aaron's Abbas Abbas's Abbasid Abbasid's Abbott Abbott's Abby
If you want to work with lines, then use $proc.stdout.lines. If you're after the whole output, then something like this should do the trick: whenever $proc.stdout { $out ~= $_ }.
Some methods return a Proc object. If it represents a failed process, Proc itself won't be exception-like, but sinking it will cause an X::Proc::Unsuccessful exception to be thrown. That means this construct will throw, despite the try in place:
try run("perl6", "-e", "exit 42"); say "still alive"; # OUTPUT: «The spawned process exited unsuccessfully (exit code: 42)»
This is because try receives a Proc and returns it, at which point it sinks and throws. Explicitly sinking it inside the try avoids the issue and ensures the exception is thrown inside the try:
try sink run("perl6", "-e", "exit 42"); say "still alive"; # OUTPUT: «still alive»
If you're not interested in catching any exceptions, then use an anonymous variable to keep the returned Proc in; this way it'll never sink:
$ = run("perl6", "-e", "exit 42"); say "still alive"; # OUTPUT: «still alive»
Using the ^ twigil can save a fair amount of time and space when writing out small blocks of code. As an example:
for 1..8 -> $a, $b { say $a + $b; }
can be shortened to just
for 1..8 { say $^a + $^b; }
The trouble arises when a person wants to use more complex names for the variables, instead of just one letter. The ^ twigil is able to have the positional variables be out of order and named whatever you want, but assigns values based on the variable's Unicode ordering. In the above example, we can have $^a and $^b switch places, and those variables will keep their positional values. This is because the Unicode character 'a' comes before the character 'b'. For example:
# In order sub f1 { say "$^first $^second"; } f1 "Hello", "there"; # OUTPUT: «Hello there»
# Out of order sub f2 { say "$^second $^first"; } f2 "Hello", "there"; # OUTPUT: «there Hello»
Due to the variables allowed to be called anything, this can cause some problems if you are not accustomed to how Perl 6 handles these variables.
# BAD NAMING: alphabetically `four` comes first and gets value `1` in it: for 1..4 { say "$^one $^two $^three $^four"; } # OUTPUT: «2 4 3 1» # GOOD NAMING: variables' naming makes it clear how they sort alphabetically: for 1..4 { say "$^a $^b $^c $^d"; } # OUTPUT: «1 2 3 4»
While » may look like a shorter way to write map, they differ in some key aspects.
First, the » includes a hint to the compiler that it may autothread the execution, thus if you're using it to call a routine that produces side effects, those side effects may be produced out of order (the result of the operator is kept in order, however). Also if the routine being invoked accesses a resource, there's the possibility of a race condition, as multiple invocations may happen simultaneously, from different threads.
This is an actual output from Rakudo 2015.09<a b c d>».say # OUTPUT: «dbca»
Second, » checks the nodality of the routine being invoked and based on that will use either deepmap or nodemap to map over the list, which can be different from how a map call would map over it:
say ((1, 2, 3), [^4], '5')».Numeric; # OUTPUT: «((1 2 3) [0 1 2 3] 5)» say ((1, 2, 3), [^4], '5').map: *.Numeric; # OUTPUT: «(3 4 5)»
The bottom line is that map and » are not interchangeable, but using one instead of the other is OK as long as you understand the differences.
Keep in mind that « » performs word splitting similarly to how shells do it, so many shell pitfalls apply here as well (especially when using in combination with run):
my $file = ‘--my arbitrary filename’; run ‘touch’, ‘--’, $file; # RIGHT run <touch -->, $file; # RIGHT run «touch -- "$file"»; # RIGHT but WRONG if you forget quotes run «touch -- $file»; # WRONG; touches ‘--my’, ‘arbitrary’ and ‘filename’ run ‘touch’, $file; # WRONG; error from `touch` run «touch "$file"»; # WRONG; error from `touch`
Note that -- is required for many programs to disambiguate between command-line arguments and filenames that begin with hyphens.
The once block is a block of code that will only run once when its parent block is run. As an example:
my $var = 0; for 1..10 { once { $var++; } } say "Variable = $var"; # OUTPUT: «Variable = 1»
This functionality also applies to other code blocks like sub and while, not just for loops. Problems arise though, when trying to nest once blocks inside of other code blocks:
my $var = 0; for 1..10 { do { once { $var++; } } } say "Variable = $var"; # OUTPUT: «Variable = 10»
In the above example, the once block was nested inside of a code block which was inside of a for loop code block. This causes the once block to run multiple times, because the once block uses state variables to determine whether it has run previously. This means that if the parent code block goes out of scope, then the state variable the once block uses to keep track of if it has run previously, goes out of scope as well. This is why once blocks and state variables can cause some unwanted behavior when buried within more than one code block.
If you want to have something that will emulate the functionality of a once block, but still work when buried a few code blocks deep, we can manually build the functionality of a once block. Using the above example, we can change it so that it will only run once, even when inside the do block by changing the scope of the state variable.
my $var = 0; for 1..10 { state $run-code = True; do { if ($run-code) { $run-code = False; $var++; } } } say "Variable = $var"; # OUTPUT: «Variable = 1»
In this example, we essentially manually build a once block by making a state variable called $run-code at the highest level that will be run more than once, then checking to see if $run-code is True using a regular if. If the variable $run-code is True, then make the variable False and continue with the code that should only be completed once.
The main difference between using a state variable like the above example and using a regular once block is what scope the state variable is in. The scope for the state variable created by the once block, is the same as where you put the block (imagine that the word 'once' is replaced with a state variable and an if to look at the variable). The example above using state variables works because the variable is at the highest scope that will be repeated; whereas the example that has a once block inside of a do, made the variable within the do block which is not the highest scope that is repeated.
Using a once block inside a class method will cause the once state to carry across all instances of that class. For example:
class A { method sayit() { once say 'hi' } } my $a = A.new; $a.sayit; # OUTPUT: «hi» my $b = A.new; $b.sayit; # nothing
Using LEAVE phaser to perform graceful resource termination is a common pattern, but it does not cover the case when the program is stopped with exit.
The following nondeterministic example should demonstrate the complications of this trap:
my $x = say ‘Opened some resource’; LEAVE say ‘Closing the resource gracefully’ with $x; exit 42 if rand < ⅓; # ① 「exit」 is bad die ‘Dying because of unhandled exception’ if rand < ½; # ② 「die」 is ok # fallthru ③
There are three possible results:
① Opened some resource ② Opened some resource Closing the resource gracefully Dying because of unhandled exception in block <unit> at print.p6 line 5 ③ Opened some resource Closing the resource gracefully
A call to exit is part of normal operation for many programs, so beware unintentional combination of LEAVE phasers and exit calls.
Parameter binding is executed when we're "inside" the routine's block, which means LEAVE phaser would run when we leave that block if parameter binding fails when wrong arguments are given:
sub foo(Int) { my $x = 42; LEAVE say $x.Int; # ← WRONG; assumes that $x is set } say foo rand; # OUTPUT: «No such method 'Int' for invocant of type 'Any'»
A simple way to avoid this issue is to declare your sub or method a multi, so the candidate is eliminated during dispatch and the code never gets to binding anything inside the sub, thus never entering the routine's body:
multi foo(Int) { my $x = 42; LEAVE say $x.Int; } say foo rand; # OUTPUT: «Cannot resolve caller foo(Num); none of these signatures match: (Int)»
Another alternative is placing the LEAVE into another block (assuming it's appropriate for it to be executed when that block is left, not the routine's body:
sub foo(Int) { my $x = 42; { LEAVE say $x.Int; } } say foo rand; # OUTPUT: «Type check failed in binding to parameter '<anon>'; expected Int but got Num (0.7289418947969465e0)»
You can also ensure LEAVE can be executed even if the routine is left due to failed argument binding. In our example, we check $x is defined before doing anything with it.
sub foo(Int) { my $x = 42; LEAVE $x andthen .Int.say; } say foo rand; # OUTPUT: «Type check failed in binding to parameter '<anon>'; expected Int but got Num (0.8517160389079508e0)»
grammar will-fail { token TOP {^ <word> $} token word { \w+ } } class will-fail-actions { method TOP ($/) { my $foo = ~$/; say $foo ~~ /foo/; } }
Will fail with Cannot assign to a readonly variable ($/) or a value on method TOP. The problem here is that regular expressions also affect $/. Since it is in TOP's signature, it is a read-only variable, which is what produces the error. You can safely either use another variable in the signature or add is copy, this way:
method TOP ($/ is copy) { my $foo = ~$/; my $v = $foo ~~ /foo/; }
Grammars are actually a type of classes.
grammar G {}; say G.^mro; # OUTPUT: «((G) (Grammar) (Match) (Capture) (Cool) (Any) (Mu))»
^mro prints the class hierarchy of this empty grammar, showing all the superclasses. And these superclasses have their very own methods. Defining a method in that grammar might clash with the ones inhabiting the class hierarchy:
grammar g { token TOP { <item> }; token item { 'defined' } }; say g.parse('defined'); # OUTPUT: «Too many positionals passed; expected 1 argument but got 2 in regex item at /tmp/grammar-clash.p6 line 3 in regex TOP at /tmp/grammar-clash.p6 line 2 in block <unit> at /tmp/grammar-clash.p6 line 5»
item seems innocuous enough, but it is a sub defined in class Mu. The message is a bit cryptic and totally unrelated to that fact, but that is why this is listed as a trap. In general, all subs defined in any part of the hierarchy are going to cause problems; some methods will too. For instance, CREATE, take and defined (which are defined in Mu). In general, multi methods and simple methods will not have any problem, but it might not be a good practice to use them as rule names.
Also avoid phasers for rule/token/regex names: TWEAK, BUILD, BUILD-ALL will throw another kind of exception if you do that: Cannot find method 'match': no method cache and no .^find_method, once again only slightly related to what is actually going on.
Let's say you have a hash and you want to use :exists on more than one element:
my %h = a => 1, b => 2; say ‘a exists’ if %h<a>:exists; # ← OK; True say ‘y exists’ if %h<y>:exists; # ← OK; False say ‘Huh‽’ if %h<x y>:exists; # ← WRONG; returns a 2-item list
Did you mean “if any of them exists”, or did you mean that all of them should exist? Use any or all Junction to clarify:
my %h = a => 1, b => 2; say ‘x or y’ if any %h<x y>:exists; # ← RIGHT (any); False say ‘a, x or y’ if any %h<a x y>:exists; # ← RIGHT (any); True say ‘a, x and y’ if all %h<a x y>:exists; # ← RIGHT (all); False say ‘a and b’ if all %h<a b>:exists; # ← RIGHT (all); True
The reason why it is always True (without using a junction) is that it returns a list with Bool values for each requested lookup. Non-empty lists always give True when you Boolify them, so the check always succeeds no matter what keys you give it.
Every now and then, someone gets the idea that they can use [Z] to create the transpose of a list-of-lists:
my @matrix = <X Y>, <a b>, <1 2>; my @transpose = [Z] @matrix; # ← WRONG; but so far so good ↙ say @transpose; # [(X a 1) (Y b 2)]
And everything works fine, until you get an input @matrix with exactly one row (child list):
my @matrix = <X Y>,; my @transpose = [Z] @matrix; # ← WRONG; ↙ say @transpose; # [(X Y)] – not the expected transpose [(X) (Y)]
This happens partly because of the single argument rule, and there are other cases when this kind of a generalization may not work.
The ~ infix operator can be used to concatenate Strs or Blobs. However, an empty list will always be reduced to an empty Str. This is due to the fact that, in the presence of a list with no elements, the reduction metaoperator returns the identity element for the given operator. Identity element for ~ is an empty string, regardless of the kind of elements the list could be populated with.
my Blob @chunks; say ([~] @chunks).perl; # OUTPUT: «""»
This might cause a problem if you attempt to use the result while assuming that it is a Blob:
my Blob @chunks; say ([~] @chunks).decode; # OUTPUT: «No such method 'decode' for invocant of type 'Str'. Did you mean 'encode'?…»
There are many ways to cover that case. You can avoid [ ] metaoperator altogether:
my @chunks; # … say Blob.new: |«@chunks; # OUTPUT: «Blob:0x<>»
Alternatively, you can initialize the array with an empty Blob:
my @chunks = Blob.new; # … say [~] @chunks; # OUTPUT: «Blob:0x<>»
Or you can utilize || operator to make it use an empty Blob in case the list is empty:
my @chunks; # … say [~] @chunks || Blob.new; # OUTPUT: «Blob:0x<>»
Please note that a similar issue may arise when reducing lists with other operators.
Maps apply an expression to every element of a List and return a Seq:
say <þor oðin loki>.map: *.codes; # OUTPUT: «(3 4 4)»
Maps are often used as a compact substitute for a loop, performing some kind of action in the map code block:
<þor oðin loki>.map: *.codes.say; # OUTPUT: «344»
The problem might arise when maps are nested and in a sink context.
<foo bar ber>.map: { $^a.comb.map: { $^b.say}}; # OUTPUT: «»
You might expect the innermost map to bubble the result up to the outermost map, but it simply does nothing. Maps return Seqs, and in sink context the innermost map will iterate and discard the produced values, which is why it yields nothing.
Simply using say at the beginning of the sentence will save the result from sink context:
say <foo bar ber>.map: *.comb.map: *.say ; # OUTPUT: «foobarber((True True True) (True True True) (True True True))»
However, it will not be working as intended; the first foobarber is the result of the innermost say, but then say returns a Bool, True in this case. Those Trues are what get printed by the outermost say, one for every letter. A much better option would be to flatten the outermost sequence:
<foo bar ber>.map({ $^a.comb.map: { $^b.say}}).flat # OUTPUT: «foobarber»
Of course, saving say for the result will also produce the intended result, as it will be saving the two nested sequences from void context:
say <foo bar ber>.map: { $^þ.comb }; # OUTPUT: « ((f o o) (b a r) (b e r))»
The smartmatch operator shortcuts to the right hand side accepting the left hand side. This may cause some confusion.
Using WhateverCode in the left hand side of a smartmatch does not work as expected, or at all:
my @a = <1 2 3>; say @a.grep( *.Int ~~ 2 ); # OUTPUT: «Cannot use Bool as Matcher with '.grep'. Did you mean to # use $_ inside a block?»
The error message does not make a lot of sense. It does, however, if you put it in terms of the ACCEPTS method: that code is equivalent to 2.ACCEPTS( *.Int ), but *.Int cannot be coerced to Numeric, being as it is a Block.
Solution: don't use WhateverCode in the left hand side of a smartmatch:
my @a = <1 2 3>; say @a.grep( 2 ~~ *.Int ); # OUTPUT: «(2)»
A low-level explanation of Perl 6 containers
This section explains the levels of indirection involved in dealing with variables and container elements. The different types of containers used in Perl 6 are explained and the actions applicable to them like assigning, binding and flattening. More advanced topics like self-referential data, type constraints and custom containers are discussed at the end.
Some people like to say "everything is an object", but in fact a variable is not a user-exposed object in Perl 6.
When the compiler encounters a variable declaration like my $x, it registers it in some internal symbol table. This internal symbol table is used to detect undeclared variables and to tie the code generation for the variable to the correct scope.
At runtime, a variable appears as an entry in a lexical pad, or lexpad for short. This is a per-scope data structure that stores a pointer for each variable.
In the case of my $x, the lexpad entry for the variable $x is a pointer to an object of type Scalar, usually just called the container.
Although objects of type Scalar are everywhere in Perl 6, you rarely see them directly as objects, because most operations decontainerize, which means they act on the Scalar container's contents instead of the container itself.
In code like
my $x = 42; say $x;
the assignment $x = 42 stores a pointer to the Int object 42 in the scalar container to which the lexpad entry for $x points.
The assignment operator asks the container on the left to store the value on its right. What exactly that means is up to the container type. For Scalar it means "replace the previously stored value with the new one".
Note that subroutine signatures allow passing around of containers:
sub f($a is rw) { $a = 23; } my $x = 42; f($x); say $x; # OUTPUT: «23»
Inside the subroutine, the lexpad entry for $a points to the same container that $x points to outside the subroutine. Which is why assignment to $a also modifies the contents of $x.
Likewise a routine can return a container if it is marked as is rw:
my $x = 23; sub f() is rw { $x }; f() = 42; say $x; # OUTPUT: «42»
For explicit returns, return-rw instead of return must be used.
Returning a container is how is rw attribute accessors work. So
class A { has $.attr is rw; }
is equivalent to
class A { has $!attr; method attr() is rw { $!attr } }
Scalar containers are transparent to type checks and most kinds of read-only accesses. A .VAR makes them visible:
my $x = 42; say $x.^name; # OUTPUT: «Int» say $x.VAR.^name; # OUTPUT: «Scalar»
And is rw on a parameter requires the presence of a writable Scalar container:
sub f($x is rw) { say $x }; f 42; CATCH { default { say .^name, ': ', .Str } }; # OUTPUT: «X::Parameter::RW: Parameter '$x' expected a writable container, but got Int value»
Callable containers provide a bridge between the syntax of a Routine call and the actual call of the method CALL-ME of the object that is stored in the container. The sigil & is required when declaring the container and has to be omitted when executing the Callable. The default type constraint is Callable.
my &callable = -> $ν { say "$ν is", $ν ~~ Int??" whole"!!" not whole" } callable(⅓); callable(3);
The sigil has to be provided when referring to the value stored in the container. This in turn allows Routines to be used as arguments to calls.
sub f() {} my &g = sub {} sub caller(&c1, &c2){ c1, c2 } caller(&f, &g);
Next to assignment, Perl 6 also supports binding with the := operator. When binding a value or a container to a variable, the lexpad entry of the variable is modified (and not just the container it points to). If you write
my $x := 42;
then the lexpad entry for $x directly points to the Int 42. Which means that you cannot assign to it anymore:
my $x := 42; $x = 23; CATCH { default { say .^name, ': ', .Str } }; # OUTPUT: «X::AdHoc: Cannot assign to an immutable value»
You can also bind variables to other variables:
my $a = 0; my $b = 0; $a := $b; $b = 42; say $a; # OUTPUT: «42»
Here, after the initial binding, the lexpad entries for $a and $b both point to the same scalar container, so assigning to one variable also changes the contents of the other.
You've seen this situation before: it is exactly what happened with the signature parameter marked as is rw.
Sigilless variables and parameters with the trait is raw always bind (whether = or := is used):
my $a = 42; my \b = $a; b++; say $a; # OUTPUT: «43» sub f($c is raw) { $c++ } f($a); say $a; # OUTPUT: «44»
There are a number of positional container types with slightly different semantics in Perl 6. The most basic one is List, which is created by the comma operator.
say (1, 2, 3).^name; # OUTPUT: «List»
A list is immutable, which means you cannot change the number of elements in a list. But if one of the elements happens to be a scalar container, you can still assign to it:
my $x = 42; ($x, 1, 2)[0] = 23; say $x; # OUTPUT: «23» ($x, 1, 2)[1] = 23; # Cannot modify an immutable value CATCH { default { say .^name, ': ', .Str } }; # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Int»
So the list doesn't care about whether its elements are values or containers, they just store and retrieve whatever was given to them.
Lists can also be lazy; in that case, elements at the end are generated on demand from an iterator.
An Array is just like a list, except that it forces all its elements to be containers, which means that you can always assign to elements:
my @a = 1, 2, 3; @a[0] = 42; say @a; # OUTPUT: «[42 2 3]»
@a actually stores three scalar containers. @a[0] returns one of them, and the assignment operator replaces the integer value stored in that container with the new one, 42.
Assignment to a scalar variable and to an array variable both do the same thing: discard the old value(s), and enter some new value(s).
Nevertheless, it's easy to observe how different they are:
my $x = 42; say $x.^name; # OUTPUT: «Int» my @a = 42; say @a.^name; # OUTPUT: «Array»
This is because the Scalar container type hides itself well, but Array makes no such effort. Also assignment to an array variable is coercive, so you can assign a non-array value to an array variable.
To place a non-Array into an array variable, binding works:
my @a := (1, 2, 3); say @a.^name; # OUTPUT: «List»
As a curious side note, Perl 6 supports binding to array elements:
my @a = (1, 2, 3); @a[0] := my $x; $x = 42; say @a; # OUTPUT: «[42 2 3]»
If you've read and understood the previous explanations, it is now time to wonder how this can possibly work. After all, binding to a variable requires a lexpad entry for that variable, and while there is one for an array, there aren't lexpad entries for each array element, because you cannot expand the lexpad at runtime.
The answer is that binding to array elements is recognized at the syntax level and instead of emitting code for a normal binding operation, a special method (called BIND-KEY) is called on the array. This method handles binding to array elements.
Note that, while supported, one should generally avoid directly binding uncontainerized things into array elements. Doing so may produce counter-intuitive results when the array is used later.
my @a = (1, 2, 3); @a[0] := 42; # This is not recommended, use assignment instead. my $b := 42; @a[1] := $b; # Nor is this. @a[2] = $b; # ...but this is fine. @a[1, 2] := 1, 2; # runtime error: X::Bind::Slice CATCH { default { say .^name, ': ', .Str } }; # OUTPUT: «X::Bind::Slice: Cannot bind to Array slice»
Operations that mix Lists and Arrays generally protect against such a thing happening accidentally.
The % and @ sigils in Perl 6 generally indicate multiple values to an iteration construct, whereas the $ sigil indicates only one value.
my @a = 1, 2, 3; for @a { }; # 3 iterations my $a = (1, 2, 3); for $a { }; # 1 iteration
@-sigiled variables do not flatten in list context:
my @a = 1, 2, 3; my @b = @a, 4, 5; say @b.elems; # OUTPUT: «3»
There are operations that flatten out sublists that are not inside a scalar container: slurpy parameters (*@a) and explicit calls to flat:
my @a = 1, 2, 3; say (flat @a, 4, 5).elems; # OUTPUT: «5» sub f(*@x) { @x.elems }; say f @a, 4, 5; # OUTPUT: «5»
You can also use | to create a Slip, introducing a list into the other.
my @l := 1, 2, (3, 4, (5, 6)), [7, 8, (9, 10)]; say (|@l, 11, 12); # OUTPUT: «(1 2 (3 4 (5 6)) [7 8 (9 10)] 11 12)» say (flat @l, 11, 12) # OUTPUT: «(1 2 3 4 5 6 7 8 (9 10) 11 12)»
In the first case, every element of @l is slipped as the corresponding elements of the resulting list. flat, in the other hand, flattens all elements including the elements of the included array, except for (9 10).
As hinted above, scalar containers prevent that flattening:
sub f(*@x) { @x.elems }; my @a = 1, 2, 3; say f $@a, 4, 5; # OUTPUT: «3»
The @ character can also be used as a prefix to coerce the argument to a list, thus removing a scalar container:
my $x = (1, 2, 3); .say for @$x; # 3 iterations
However, the decont operator <> is more appropriate to decontainerize items that aren't lists:
my $x = ^Inf .grep: *.is-prime; say "$_ is prime" for @$x; # WRONG! List keeps values, thus leaking memory say "$_ is prime" for $x<>; # RIGHT. Simply decontainerize the Seq my $y := ^Inf .grep: *.is-prime; # Even better; no Scalars involved at all
Methods generally don't care whether their invocant is in a scalar, so
my $x = (1, 2, 3); $x.map(*.say); # 3 iterations
maps over a list of three elements, not of one.
Container types, including Array and Hash, allow you to create self-referential structures.
my @a; @a[0] = @a; put @a.perl; # OUTPUT: «((my @Array_75093712) = [@Array_75093712,])»
Although Perl 6 does not prevent you from creating and using self-referential data, by doing so you may end up in a loop trying to dump the data. As a last resort, you can use Promises to handle timeouts.
Any container can have a type constraint in the form of a type object or a subset. Both can be placed between a declarator and the variable name or after the trait of. The constraint is a property of the variable, not the container.
subset Three-letter of Str where .chars == 3; my Three-letter $acronym = "ÞFL";
In this case, the type constraint is the (compile-type defined) subset Three-letter.
Variables may have no container in them, yet still offer the ability to re-bind and typecheck that rebind. The reason for that is in such cases the binding operator := performs the typecheck:
my Int \z = 42; z := 100; # OK z := "x"; # Typecheck failure
The same isn't the case when, say, binding to a Hash key, as the binding is then handled by a method call (even though the syntax remains the same, using := operator).
The default type constraint of a Scalar container is Mu. Introspection of type constraints on containers is provided by .VAR.of method, which for @ and % sigiled variables gives the constraint for values:
my Str $x; say $x.VAR.of; # OUTPUT: «(Str)» my Num @a; say @a.VAR.of; # OUTPUT: «(Num)» my Int %h; say %h.VAR.of; # OUTPUT: «(Int)»
A container can also enforce a variable to be defined. Put a smiley in the declaration:
my Int:D $def = 3; say $def; # OUTPUT: «3» $def = Int; # Typecheck failure
You'll also need to initialize the variable in the declaration, it can't be left undefined after all.
It's also possible to have this constraint enforced in all variables declared in a scope with the default defined variables pragma. People coming from other languages where variables are always defined will want to have a look.
To provide custom containers Perl 6 provides the class Proxy. It takes two methods that are called when values are stored or fetched from the container. Type checks are not done by the container itself and other restrictions like readonlyness can be broken. The returned value must therefore be of the same type as the type of the variable it is bound to. We can use type captures to work with types in Perl 6.
sub lucky(::T $type) { my T $c-value; # closure variable return Proxy.new( FETCH => method () { $c-value }, STORE => method (T $new-value) { X::OutOfRange.new(what => 'number', got => '13', range => '-∞..12, 14..∞').throw if $new-value == 13; $c-value = $new-value; } ); } my Int $a := lucky(Int); say $a = 12; # OUTPUT: «12» say $a = 'FOO'; # X::TypeCheck::Binding say $a = 13; # X::OutOfRange CATCH { default { say .^name, ': ', .Str } };
What are contexts and how to switch into them
A context is needed, in many occasions, to interpret the value of a container. In Perl 6, we will use context to coerce the value of a container into some type or class, or in general decide what to do with it, as in the case of the sink context. In general, recognizing an object that is in a certain context will force an implicit coercion by calling a specific method on it.
The sink context is equivalent to what in other languages is called void context, that is, a context in which we throw (down the sink, as it were) the result of an operation or the return value from a block. In general, this context will be invoked in warnings and errors when a statement does not know what to do with that value.
my $sub = -> $a { return $a² }; $sub; # OUTPUT: «WARNINGS:Useless use of $sub in sink context (line 1)»
You can force that sink context on Iterators, by using the sink-all method. Procs can also be sunk via the sink method, forcing them to raise an exception and not returning anything.
In general, blocks will warn if evaluated in sink context; however, gather/take blocks are explicitly evaluated in sink context, with values returned explicitly using take; however, sinking will explicitly throw away those values, so use sink only if you want to run a gather statement for the side effects.
In sink context, an object will call its sink method if present:
sub foo { return [<a b c>] does role { method sink { say "sink called" } } } foo; # OUTPUT: sink called
This context, and probably all other contexts except sink above, are conversion or interpretation contexts in the sense that they take an untyped or typed variable and duck-type it to whatever is needed to perform the operation. In some cases that will imply a conversion (from Str to Numeric, for instance); in other cases simply an interpretation (IntStr will be interpreted as Int or as Str).
Number context is called whenever we need to apply a numerical operation on a variable.
my $not-a-string = "1 "; my $neither-a-string = "3 "; say $not-a-string + $neither-a-string; # OUTPUT: «4»
In the code above, strings will be interpreted in numeric context as long as there are only a few digits and no other characters. It can have any number of leading or trailing whitespace, however.
Numeric context can be forced by using arithmetic operators such as + or -. In that context, the Numeric method will be called if available and the value returned used as the numeric value of the object.
my $t = True; my $f = False; say $t + $f; # OUTPUT: «1» say $t.Numeric; # OUTPUT: «1» say $f.Numeric; # OUTPUT: «0» my $list= <a b c>; say True + $list; # OUTPUT: «4»
In the case of listy things, the numeric value will be in general equivalent to .elems; in some cases, like Thread it will return an unique thread identifier.
In a string context, values can be manipulated as strings. This context is used, for instance, for coercing non-string values so that they can be printed to standard output.
put $very-complicated-and-hairy-object; # OUTPUT: something meaningful
Or when smartmatching to a regular expression:
put 333444777 ~~ /(3+)/; # OUTPUT: «「333」 0 => 「333」»
In general, the Str routine will be called on a variable to contextualize it; since this method is inherited from Mu, it is always present, but it is not always guaranteed to work. In some core classes it will issue a warning.
~ is the (unary) string contextualizer. As an operator, it concatenates strings, but as a prefix operator it becomes the string context operator.
my @array = [ [1,2,3], [4,5,6]]; say ~@array; # OUTPUT: «1 2 3 4 5 6»
This will happen also in a reduction context, when [~] is applied to a list
say [~] [ 3, 5+6i, Set(<a b c>), [1,2,3] ]; # OUTPUT: «35+6ic a b1 2 3»
In that sense, empty lists or other containers will stringify to an empty string:
say [~] [] ; # OUTPUT: «»
Since ~ acts also as buffer concatenation operator, it will have to check that every element is not empty, since a single empty buffer in string context will behave as a string, thus yielding an error.
say [~] Buf.new(0x3,0x33), Buf.new(0x2,0x22); # OUTPUT: «Buf:0x<03 33 02 22>»
However,
my $non-empty = Buf.new(0x3, 0x33); my $empty = []; my $non-empty-also = Buf.new(0x2,0x22); say [~] $non-empty, $empty, $non-empty-also; # OUTPUT: «Cannot use a Buf as a string, but you called the Stringy method on it
Since ~ is putting in string context the second element of this list, ~ is going to be using the second form that applies to strings, thus yielding the shown error. Simply making sure that everything you concatenate is a buffer will avoid this problem.
my $non-empty = Buf.new(0x3, 0x33); my $empty = Buf.new(); my $non-empty-also = Buf.new(0x2,0x22); say [~] $non-empty, $empty, $non-empty-also; # OUTPUT: «Buf:0x<03 33 02 22>»
In general, a context will coerce a variable to a particular type by calling the contextualizer; in the case of mixins, if the context class is mixed in, it will behave in that way.
my $described-number = 1i but 'Unity in complex plane'; put $described-number; # OUTPUT: «Unity in complex plane»
but creates a mixin, which endows the complex number with a Str method. put contextualizes it into a string, that is, it calls Str, the string contextualizer, with the result shown above.
This context will force a variable to be interpreted as True or False.
say "Hey" if 7; # OUTPUT: «Hey» say "Ahoy" if "";
This context appears in expressions such as if or while, and is equivalent to calling so on these values.
say "Hey" if 7.so; # OUTPUT: «Hey» say "Ahoy" if not set().so; # OUTPUT: «Ahoy»
In general, non-zero, non-empty will be converted to True; zero or empty will be equivalent to False. But .so can be defined to return any Boolean value we want, so this is just a rule of thumb.
? and ! are the Boolean context operator and its negation respectively. They will force this context on an object.
say ? 0i; # OUTPUT: «False» say ! :true; # OUTPUT: «False»
There are actually several different list contexts, which are better explained in that page. In general, the list contextualizer is the comma ,
say (3,).^name; # OUTPUT: «List»
and the method called in that case is also .list
Any.list.^name; # OUTPUT: «List» say 3.list.^name; # OUTPUT: «List» say (^3).list; # OUTPUT: «(0 1 2)»
Statements used to control the flow of execution
Perl 6 programs consist of one or more statements. Simple statements are separated by semicolons. The following program will say "Hello" and then say "World" on the next line.
say "Hello"; say "World";
In most places where spaces appear in a statement, and before the semicolon, it may be split up over many lines. Also, multiple statements may appear on the same line. It would be awkward, but the above example could also be written as:
say "Hello"; say "World";
Like many other languages, Perl 6 uses blocks enclosed by { and } to turn a sequence of statements into a single one. It is OK to skip the semicolon between the last statement in a block and the closing }.
{ say "Hello"; say "World" }
When a block stands alone as a statement, it will be entered immediately after the previous statement finishes, and the statements inside it will be executed.
say 1; # OUTPUT: «1» { say 2; say 3 }; # OUTPUT: «23» say 4; # OUTPUT: «4»
Unless it stands alone as a statement, a block simply creates a closure. The statements inside are not executed immediately. Closures are another topic and how they are used is explained elsewhere. For now it is just important to understand when blocks run and when they do not:
say "We get here"; { say "then here." }; { say "not here"; 0; } or die;
In the above example, after running the first statement, the first block stands alone as a second statement, so we run the statement inside it. The second block is a closure, so instead, it makes an object of type Block but does not run it. Object instances are usually considered to be true, so the code does not die, even though that block would evaluate to 0, were it to be executed. The example does not say what to do with the Block object, so it just gets thrown away.
Most of the flow control constructs covered below are just ways to tell Perl 6 when, how, and how many times, to enter blocks like that second block.
Before we go into those, an important side-note on syntax: If there is nothing (or nothing but comments) on a line after a closing curly brace where you would normally put semicolon, then you do not need the semicolon:
# All three of these lines can appear as a group, as is, in a program { 42.say } # OUTPUT: «42» { 43.say } # OUTPUT: «43» { 42.say }; { 43.say } # OUTPUT: «4243»
...but:
{ 42.say } { 43.say } # Syntax error { 42.say; } { 43.say } # Also a syntax error, of course
So, be careful when you backspace in a line-wrapping editor:
{ "Without semicolons line-wrapping can be a bit treacherous.".say } \ { 43.say } # Syntax error
You have to watch out for this in most languages anyway to prevent things from getting accidentally commented out. Many of the examples below may have unnecessary semicolons for clarity.
Class bodies behave like simple blocks for any top level expression; same goes to roles and other packages, like grammars (which are actually classes) or modules.
class C { say "I live"; die "I will never live!" }; my $c = C.new; │ # OUTPUT: Fails and writes «I liveI will never live!
This block will first run the first statement, and then die printing the second statement. $c will never get a value.
Blocks may have phasers: special labeled blocks that break their execution into phases that run in particular phases. See the page phasers for the details.
The simplest way to run a block where it cannot be a stand-alone statement is by writing do before it:
# This dies half of the time do { say "Heads I win, tails I die."; Bool.pick } or die; say "I win.";
Note that you need a space between the do and the block.
The whole do {...} evaluates to the final value of the block. The block will be run when that value is needed in order to evaluate the rest of the expression. So:
False and do { 42.say };
...will not say 42. However, the block is only evaluated once each time the expression it is contained in is evaluated:
# This says "(..1 ..2 ..3)" not "(..1 ...2 ....3)" my $f = "."; say do { $f ~= "." } X~ 1, 2, 3;
In other words, it follows the same reification rules as everything else.
Technically, do is a loop which runs exactly one iteration.
A do may also be used on a bare statement (without curly braces) but this is mainly just useful for avoiding the syntactical need to parenthesize a statement if it is the last thing in an expression:
3, do if 1 { 2 } ; # OUTPUT: «(3, 2)» 3, (if 1 { 2 }) ; # OUTPUT: «(3, 2)»
3, if 1 { 2 } ; # Syntax error
The simplest way to run a block asynchronously is by writing start before it:
start { sleep 1; say "done" } say "working"; # working, done
Note that you need a space between the start and the block. In the example above, the start block is in sink context, since it's not assigned to a variable. From version 6.d, these kind of blocks have an exception handler attached:
start { die "We're dead"; } say "working"; sleep 10;
This code will print Unhandled exception in code scheduled on thread 4 We're dead in version 6.d, while it will simply get out after waiting for 10 seconds in version 6.c.
The start {...} immediately returns a Promise that can be safely ignored if you are not interested in the result of the block. If you are interested in the final value of the block, you can call the .result method on the returned promise. So:
my $promise = start { sleep 10; 42 } # ... do other stuff say "The result is $promise.result()";
If the code inside the block has not finished, the call to .result will wait until it is done.
A start may also be used on a bare statement (without curly braces). This is mainly useful when calling a subroutine / method on an object is the only thing to do asynchronously.
sub get42 { 42 } my $promise = start get42; say $promise.result; # OUTPUT: «42»
Note that code executed this way does not have access to the special variables $! and $/ of its outer block, but receives new ones, so every asynchronous task has its per-task state.
Thus, try expressions and regex matches executed in the asynchronous task have their per-task state.
'a' ~~ /a/; # $/ is set to 「a」 try die; # $! is defined now with an anonymous AdHoc exception # as a code block await start { say $! }; # OUTPUT: «Nil» await start { say $/ }; # OUTPUT: «Nil» # as a single statement await start $!.say; # OUTPUT: «Nil» await start $/.say; # OUTPUT: «Nil»
To conditionally run a block of code, use an if followed by a condition. The condition, an expression, will be evaluated immediately after the statement before the if finishes. The block attached to the condition will only be evaluated if the condition means True when coerced to Bool. Unlike some languages the condition does not have to be parenthesized, instead the { and } around the block are mandatory:
if 1 { "1 is true".say } ; # says "1 is true"
if 1 "1 is true".say ; # syntax error, missing block
if 0 { "0 is true".say } ; # does not say anything, because 0 is false
if 42.say and 0 { 43.say }; # says "42" but does not say "43"
There is also a form of if called a "statement modifier" form. In this case, the if and then the condition come after the code you want to run conditionally. Do note that the condition is still always evaluated first:
43.say if 42.say and 0; # says "42" but does not say "43" 43.say if 42.say and 1; # says "42" and then says "43" say "It is easier to read code when 'if's are kept on left of screen" if True; # says the above, because it is true { 43.say } if True; # says "43" as well
The statement modifier form is probably best used sparingly.
The if statement itself will either slip us an empty list, if it does not run the block, or it will return the value which the block produces:
my $d = 0; say (1, (if 0 { $d += 42; 2; }), 3, $d); # says "(1 3 0)" my $c = 0; say (1, (if 1 { $c += 42; 2; }), 3, $c); # says "(1 2 3 42)" say (1, (if 1 { 2, 2 }), 3); # does not slip, says "(1 (2 2) 3)"
For the statement modifier it is the same, except you have the value of the statement instead of a block:
say (1, (42 if True) , 2); # says "(1 42 2)" say (1, (42 if False), 2); # says "(1 2)" say (1, 42 if False , 2); # says "(1 42)" because "if False, 2" is true
The if does not change the topic ($_) by default. In order to access the value which the conditional expression produced, you have to ask for it more strongly:
$_ = 1; if 42 { $_.say } ; # says "1" $_ = 1; if 42 -> $_ { $_.say } ; # says "42" $_ = 1; if 42 -> $a { $_.say; $a.say } ; # says "1" then says "42" $_ = 1; if 42 { $_.say; $^a.say } ; # says "1" then says "42"
A compound conditional may be produced by following an if conditional with else to provide an alternative block to run when the conditional expression is false:
if 0 { say "no" } else { say "yes" } ; # says "yes" if 0 { say "no" } else{ say "yes" } ; # says "yes", space is not required
The else cannot be separated from the conditional statement by a semicolon, but as a special case, it is OK to have a newline.
if 0 { say "no" }; else { say "yes" } ; # syntax error
if 0 { say "no" } else { say "yes" } ; # says "yes"
Additional conditions may be sandwiched between the if and the else using elsif. An extra condition will only be evaluated if all the conditions before it were false, and only the block next to the first true condition will be run. You can end with an elsif instead of an else if you want.
if 0 { say "no" } elsif False { say "NO" } else { say "yes" } # says "yes" if 0 { say "no" } elsif True { say "YES" } else { say "yes" } # says "YES" if 0 { say "no" } elsif False { say "NO" } # does not say anything sub right { "Right!".say; True } sub wrong { "Wrong!".say; False } if wrong() { say "no" } elsif right() { say "yes" } else { say "maybe" } # The above says "Wrong!" then says "Right!" then says "yes"
You cannot use the statement modifier form with else or elsif:
42.say if 0 else { 43.say } # syntax error
All the same rules for semicolons and newlines apply, consistently
if 0 { say 0 }; elsif 1 { say 1 } else { say "how?" } ; # syntax error if 0 { say 0 } elsif 1 { say 1 }; else { say "how?" } ; # syntax error
if 0 { say 0 } elsif 1 { say 1 } else { say "how?" } ; # says "1"
if 0 { say 0 } elsif 1 { say 1 } else { say "how?" } ; # says "1" if 0 { say 0 } elsif 1 { say 1 } else { say "how?" } ; # says "1" if 0 { say "no" } elsif False { say "NO" } else { say "yes" } ; # says "yes"
The whole thing either slips us an empty list (if no blocks were run) or returns the value produced by the block that did run:
my $d = 0; say (1, (if 0 { $d += 42; "two"; } elsif False { $d += 43; 2; }), 3, $d); # says "(1 3 0)" my $c = 0; say (1, (if 0 { $c += 42; "two"; } else { $c += 43; 2; }), 3, $c); # says "(1 2 3 43)"
It's possible to obtain the value of the previous expression inside an else, which could be from if or the last elsif if any are present:
$_ = 1; if 0 { } else -> $a { "$_ $a".say } ; # says "1 0" $_ = 1; if False { } else -> $a { "$_ $a".say } ; # says "1 False" if False { } elsif 0 { } else -> $a { $a.say } ; # says "0"
When you get sick of typing "if not (X)" you may use unless to invert the sense of a conditional statement. You cannot use else or elsif with unless because that ends up getting confusing. Other than those two differences unless works the same as #if:
unless 1 { "1 is false".say } ; # does not say anything, since 1 is true
unless 1 "1 is false".say ; # syntax error, missing block
unless 0 { "0 is false".say } ; # says "0 is false"
unless 42.say and 1 { 43.say } ; # says "42" but does not say "43" 43.say unless 42.say and 0; # says "42" and then says "43" 43.say unless 42.say and 1; # says "42" but does not say "43" $_ = 1; unless 0 { $_.say } ; # says "1" $_ = 1; unless 0 -> $_ { $_.say } ; # says "0" $_ = 1; unless False -> $a { $a.say } ; # says "False" my $c = 0; say (1, (unless 0 { $c += 42; 2; }), 3, $c); # says "(1 2 3 42)" my $d = 0; say (1, (unless 1 { $d += 42; 2; }), 3, $d); # says "(1 3 0)"
The with statement is like if, but tests for definedness rather than truth, and it topicalizes on the condition, much like given:
with "abc".index("a") { .say } # prints 0
Similarly to elsif, orwith may be used to chain definedness tests:
# The below code says "Found a at 0" my $s = "abc"; with $s.index("a") { say "Found a at $_" } orwith $s.index("b") { say "Found b at $_" } orwith $s.index("c") { say "Found c at $_" } else { say "Didn't find a, b or c" }
You may intermix if-based and with-based clauses.
# This says "Yes" if 0 { say "No" } orwith Nil { say "No" } orwith 0 { say "Yes" };
As with unless, you may use without to check for undefinedness, but you may not add an else clause:
my $answer = Any; without $answer { warn "Got: {$_.perl}" }
There are also with and without statement modifiers:
my $answer = (Any, True).roll; say 42 with $answer; warn "undefined answer" without $answer;
As with the other chainable constructs, an else completing a with/if..orwith/elsif chain will itself topicalize to the value of the prior (failed) condition's topic (either the topic of with or the final orwith or elsif).
In the case of an else following a with or orwith, topicalizing a value guaranteed to be undefined may seem useless. But it makes for a useful idiom when used in conjunction with operations that may fail, because Failure values are always undefined:
sub may_fail( --> Numeric:D ) { my $value = (^10).pick || fail "Zero is unacceptable"; fail "Odd is also not okay" if $value % 2; return $value; } with may_fail() -> $value { # defined, so didn't fail say "I know $value isn't zero or odd." } else { # undefined, so failed, and the Failure is the topic say "Uh-oh: {.exception.message}." }
Note that while topicalizing a Failure marks it handled—so you can use the with/else to proceed safely with execution—it doesn't make the Failure value itself safe. Even within the else clause, if you try to use the value directly, it will result in your else clause itself failing (or, in Rakudo, "promoting" the Failure into a thrown exception).
But as seen above, you can use the methods of a handled Failure object the else topicalizes, such as exception, if you wish to provide diagnostics or interrogate the underlying Exception.
The when block is similar to an if block and either or both can be used in an outer block; they also both have a "statement modifier" form. But there is a difference in how following code in the same, outer block is handled: When the when block is executed, control is passed to the enclosing block and following statements are ignored; but when the if block is executed, following statements are executed.
{ if X {...} # if X is true in boolean context, block is executed # following statements are executed regardless } { when X {...} # if X is true in boolean context, block is executed # and control passes to the outer block # following statements are NOT executed }
Should the if and when blocks above appear at file scope, following statements would be executed in each case.
There is one other feature when has that if doesn't: the when's boolean context test defaults to $_ ~~ while the if's does not. That has an effect on how one uses the X in the when block without a value for $_ (it's Any in that case and Any smartmatches on True: Any ~~ True yields True). Consider the following:
{ my $a = 1; my $b = True; when $a { say 'a' }; # no output when so $a { say 'a' } # a (in "so $a" 'so' coerces $a to Boolean context True # which matches with Any) when $b { say 'b' }; # no output (this statement won't be run) }
Finally, when's statement modifier form does not affect execution of following statements either inside or outside of another block:
say "foo" when X; # if X is true statement is executed # following statements are not affected
Since a successful match will exit the block, the behavior of this piece of code:
$_ = True; my $a; { $a = do when .so { "foo" } }; say $a; # OUTPUT: «(Any)»
is explained since the do block is abandoned before any value is stored or processed. However, in this case:
$_ = False; my $a; { $a = do when .so { "foo" } }; say $a; # OUTPUT: «False»
the block is not abandoned since the comparison is false, so $a will actually get a value.
The for loop iterates over a list, running the statements inside a block once on each iteration. If the block takes parameters, the elements of the list are provided as arguments.
my @foo = 1..3; for @foo { $_.print } # prints each value contained in @foo for @foo { .print } # same thing, because .print implies a $_ argument for @foo { 42.print } # prints 42 as many times as @foo has elements
Pointy block syntax or a placeholder may be used to name the parameter, of course.
my @foo = 1..3; for @foo -> $item { print $item } for @foo { print $^item } # same thing
Multiple parameters can be declared, in which case the iterator takes as many elements from the list as needed before running the block.
my @foo = 1..3; for @foo.kv -> $idx, $val { say "$idx: $val" } my %hash = <a b c> Z=> 1,2,3; for %hash.kv -> $key, $val { say "$key => $val" } for 1, 1.1, 2, 2.1 { say "$^x < $^y" } # says "1 < 1.1" then says "2 < 2.1"
Parameters of a pointy block can have default values, allowing to handle lists with missing elements.
my @list = 1,2,3,4; for @list -> $a, $b = 'N/A', $c = 'N/A' { say "$a $b $c" } # OUTPUT: «1 2 34 N/A N/A»
If the postfix form of for is used, a block is not required and the topic is set for the statement list.
say „I $_ butterflies!“ for <♥ ♥ ♥>; # OUTPUT«I ♥ butterflies!I ♥ butterflies!I ♥ butterflies!»
A for may be used on lazy lists – it will only take elements from the list when they are needed, so to read a file line by line, you could use:
for $*IN.lines -> $line { .say }
Iteration variables are always lexical, so you don't need to use my to give them the appropriate scope. Also, they are read-only aliases. If you need them to be read-write, use <-> instead of ->. If you need to make $_ read-write in a for loop, do so explicitly.
my @foo = 1..3; for @foo <-> $_ { $_++ }
A for loop can produce a List of the values produced by each run of the attached block. To capture these values, put the for loop in parenthesis or assign them to an array:
(for 1, 2, 3 { $_ * 2 }).say; # OUTPUT «(2 4 6)» my @a = do for 1, 2, 3 { $_ * 2 }; @a.say; # OUTPUT «[2 4 6]» my @b = (for 1, 2, 3 { $_ * 2 }); @b.say; # OUTPUT: «[2 4 6]»
The Empty constant will act as a no-op for a loop:
say "Not here" for Empty;
Will not do anything. This constant is equivalent to a empty Slip or List.
Undefined values will behave in the same way:
my @array := Empty; .say for @array; say @array; # OUTPUT: «()»
Assigning Empty will effectively undefine an Array, using for over an undefined array will not even enter the loop, as shown, effectively behaving in the same way as above when Empty was used directly.
With hyper and race, the for loop is potentially iterated in parallel. See also the documentation for hyper and race in class Map.
my $primes_h = hyper for ^10_000 -> $number { $number if $number.is-prime }; say $primes_h.elems; # OUTPUT: «1229» say $primes_h.tail: 5; # OUTPUT: «(9931 9941 9949 9967 9973)»
with hyper the order of elements is preserved.
my $primes_r = race for ^10_000 -> $number { $number if $number.is-prime }; say $primes_r.elems; # OUTPUT: «1229»
Unlike hyper, race does not preserve the order of elements.
gather is a statement or block prefix that returns a sequence of values. The values come from calls to take in the dynamic scope of the gather block.
my @a = gather { take 1; take 5; take 42; } say join ', ', @a; # OUTPUT: «1, 5, 42»
gather/take can generate values lazily, depending on context. If you want to force lazy evaluation use the lazy subroutine or method. Binding to a scalar or sigilless container will also force laziness.
For example
my @vals = lazy gather { take 1; say "Produced a value"; take 2; } say @vals[0]; say 'between consumption of two values'; say @vals[1]; # OUTPUT: # 1 # between consumption of two values # Produced a value # 2
gather/take is scoped dynamically, so you can call take from subs or methods that are called from within gather:
sub weird(@elems, :$direction = 'forward') { my %direction = ( forward => sub { take $_ for @elems }, backward => sub { take $_ for @elems.reverse }, random => sub { take $_ for @elems.pick(*) }, ); return gather %direction{$direction}(); } say weird(<a b c>, :direction<backward> ); # OUTPUT: «(c b a)»
If values need to be mutable on the caller side, use take-rw.
Note that gather/take also work for hashes. The return value is still a Seq but the assignment to a hash in the following example makes it a hash.
my %h = gather { take "foo" => 1; take "bar" => 2}; say %h; # OUTPUT: «{bar => 2, foo => 1}»
Emits the invocant into the enclosing supply:
my $supply = supply { emit $_ for "foo", 42, .5; } $supply.tap: { say "received {.^name} ($_)"; } # OUTPUT: # received Str (foo) # received Int (42) # received Rat (0.5)
The given statement is Perl 6's topicalizing keyword in a similar way that switch topicalizes in languages such as C. In other words, given sets $_ inside the following block. The keywords for individual cases are when and default. The usual idiom looks like this:
my $var = (Any, 21, any <answer lie>).pick; given $var { when 21 { say $_ * 2 } when 'lie' { .say } default { say 'default' } }
The given statement is often used alone:
given 42 { .say; .Numeric; }
This is a lot more understandable than:
{ .say; .Numeric; }(42)
A block containing a default statement will be left immediately when the sub-block after the default statement is left. It is as though the rest of the statements in the block are skipped.
given 42 { "This says".say; $_ == 42 and ( default { "This says, too".say; 43; } ); "This never says".say; } # The above block evaluates to 43
A when statement will also do this (but a when statement modifier will not.)
In addition, when statements smartmatch the topic ($_) against a supplied expression such that it is possible to check against values, regular expressions, and types when specifying a match.
for 42, 43, "foo", 44, "bar" { when Int { .say } when /:i ^Bar/ { .say } default { say "Not an Int or a Bar" } } # OUTPUT: «4243Not an Int or a Bar44Bar»
In this form, the given/when construct acts much like a set of if/elsif/else statements. Be careful with the order of the when statements. The following code says "Int" not 42.
given 42 { when Int { say "Int" } when 42 { say 42 } default { say "huh?" } } # OUTPUT: «Int»
When a when statement or default statement causes the outer block to return, nesting when or default blocks do not count as the outer block, so you can nest these statements and still be in the same "switch" just so long as you do not open a new block:
given 42 { when Int { when 42 { say 42 } say "Int" } default { say "huh?" } } # OUTPUT: «42»
when statements can smartmatch against Signatures.
Both proceed and succeed are meant to be used only from inside when or default blocks.
The proceed statement will immediately leave the when or default block, skipping the rest of the statements, and resuming after the block. This prevents the when or default from exiting the outer block.
given * { default { proceed; "This never says".say } } "This says".say;
This is most often used to enter multiple when blocks. proceed will resume matching after a successful match, like so:
given 42 { when Int { say "Int"; proceed } when 42 { say 42 } when 40..* { say "greater than 40" } default { say "huh?" } } # OUTPUT: «Int» # OUTPUT: «42»
Note that the when 40..* match didn't occur. For this to match such cases as well, one would need a proceed in the when 42 block.
This is not like a C switch statement, because the proceed does not merely enter the directly following block, it attempts to match the given value once more, consider this code:
given 42 { when Int { "Int".say; proceed } when 43 { 43.say } when 42 { 42.say } default { "got change for an existential answer?".say } } # OUTPUT: «Int» # OUTPUT: «42»
...which matches the Int, skips 43 since the value doesn't match, matches 42 since this is the next positive match, but doesn't enter the default block since the when 42 block doesn't contain a proceed.
By contrast, the succeed keyword short-circuits execution and exits the entire given block at that point. It may also take an argument to specify a final value for the block.
given 42 { when Int { say "Int"; succeed "Found"; say "never this!"; } when 42 { say 42 } default { say "dunno?" } } # OUTPUT: «Int»
If you are not inside a when or default block, it is an error to try to use proceed or succeed.Also remember, the when statement modifier form does not cause any blocks to be left, and any succeed or proceed in such a statement applies to the surrounding clause, if there is one:
given 42 { { say "This says" } when Int; "This says too".say; when * > 41 { { "And this says".say; proceed } when * > 41; "This never says".say; } "This also says".say; }
given can follow a statement to set the topic in the statement it follows.
.say given "foo"; # OUTPUT: «foo» printf "%s %02i.%02i.%i", <Mo Tu We Th Fr Sa Su>[.day-of-week - 1], .day, .month, .year given DateTime.now; # OUTPUT: «Sa 03.06.2016»
The loop statement takes three statements in parentheses separated by ; that take the role of initializer, conditional and incrementer. The initializer is executed once and any variable declaration will spill into the surrounding block. The conditional is executed once per iteration and coerced to Bool, if False the loop is stopped. The incrementer is executed once per iteration.
loop (my $i = 0; $i < 10; $i++) { say $i; }
The infinite loop does not require parentheses.
loop { say 'forever' }
The loop statement may be used to produce values from the result of each run of the attached block if it appears in lists:
(loop ( my $i = 0; $i++ < 3;) { $i * 2 }).say; # OUTPUT: «(2 4 6)» my @a = (loop ( my $j = 0; $j++ < 3;) { $j * 2 }); @a.say; # OUTPUT: «[2 4 6]» my @b = do loop ( my $k = 0; $k++ < 3;) { $k * 2 }; @b.say; # same thing
Unlike a for loop, one should not rely on whether returned values are produced lazily. It would probably be best to use eager to guarantee that a loop whose return value may be used actually runs:
sub heads-in-a-row { (eager loop (; 2.rand < 1;) { "heads".say }) }
The while statement executes the block as long as its condition is true. So
my $x = 1; while $x < 4 { print $x++; } print "\n"; # OUTPUT: «123»
Similarly, the until statement executes the block as long as the expression is false.
my $x = 1; until $x > 3 { print $x++; } print "\n"; # OUTPUT: «123»
The condition for while or until can be parenthesized, but there must be a space between the keyword and the opening parenthesis of the condition.
Both while and until can be used as statement modifiers. E. g.
my $x = 42; $x-- while $x > 12
Also see repeat/while and repeat/until below.
All these forms may produce a return value the same way loop does.
Executes the block at least once and, if the condition allows, repeats that execution. This differs from while/until in that the condition is evaluated at the end of the loop, even if it appears at the front.
my $x = -42; repeat { $x++; } while $x < 5; $x.say; # OUTPUT: «5» repeat { $x++; } while $x < 5; $x.say; # OUTPUT: «6» repeat while $x < 10 { $x++; } $x.say; # OUTPUT: «10» repeat while $x < 10 { $x++; } $x.say; # OUTPUT: «11» repeat { $x++; } until $x >= 15; $x.say; # OUTPUT: «15» repeat { $x++; } until $x >= 15; $x.say; # OUTPUT: «16» repeat until $x >= 20 { $x++; } $x.say; # OUTPUT: «20» repeat until $x >= 20 { $x++; } $x.say; # OUTPUT: «21»
All these forms may produce a return value the same way loop does.
The sub return will stop execution of a subroutine or method, run all relevant phasers and provide the given return value to the caller. The default return value is Nil. If a return type constraint is provided it will be checked unless the return value is Nil. If the type check fails the exception X::TypeCheck::Return is thrown. If it passes a control exception is raised and can be caught with CONTROL.
Any return in a block is tied to the first Routine in the outer lexical scope of that block, no matter how deeply nested. Please note that a return in the root of a package will fail at runtime. A return in a block that is evaluated lazily (e.g. inside map) may find the outer lexical routine gone by the time the block is executed. In almost any case last is the better alternative. Please check the functions documentation for more information on how return values are handled and produced.
The sub return will return values, not containers. Those are immutable and will lead to runtime errors when attempted to be mutated.
sub s(){ my $a = 41; return $a }; say ++s(); CATCH { default { say .^name, ': ', .Str } }; # OUTPUT: «X::Multi::NoMatch.new(dispatcher …
To return a mutable container, use return-rw.
sub s(){ my $a = 41; return-rw $a }; say ++s(); # OUTPUT: «42»
The same rules as for return regarding phasers and control exceptions apply.
Leaves the current routine and returns the provided Exception or Str wrapped inside a Failure, after all relevant phasers are executed. If the caller activated fatal exceptions via the pragma use fatal;, the exception is thrown instead of being returned as a Failure.
sub f { fail "WELP!" }; say f; CATCH { default { say .^name, ': ', .Str } } # OUTPUT: «X::AdHoc: WELP!»
A block prefix with once will be executed exactly once, even if placed inside a loop or a recursive routine.
my $guard = 3; loop { last if $guard-- <= 0; once { put 'once' }; print 'many' } # OUTPUT: «oncemanymanymany»
This works per "clone" of the containing code object, so:
({ once 42.say } xx 3).map: {$_(), $_()}; # says 42 thrice
Note that this is not a thread-safe construct when the same clone of the same block is run by multiple threads. Also remember that methods only have one clone per class, not per object.
A quietly block will suppress all warnings generated in it.
quietly { warn 'kaput!' }; warn 'still kaput!'; # OUTPUT: «still kaput! [...]»
Any warning generated from any routine called from within the block will also be suppressed:
sub told-you { warn 'hey...' }; quietly { told-you; warn 'kaput!' }; warn 'Only telling you now!' # OUTPUT: «Only telling you now! [...] »
while, until, loop and for loops can all take a label, which can be used to identify them for next, last, and redo. Nested loops are supported, for instance:
OUTAHERE: while True { for 1,2,3 -> $n { last OUTAHERE if $n == 2; } }
Labels can be used also within nested loops to name each loop, for instance:
OUTAHERE: loop ( my $i = 1; True; $i++ ) { OUTFOR: for 1,2,3 -> $n { # exits the for loop before its natural end last OUTFOR if $n == 2; } # exits the infinite loop last OUTAHERE if $i >= 2; }
The next command starts the next iteration of the loop. So the code
my @x = 1, 2, 3, 4, 5; for @x -> $x { next if $x == 3; print $x; }
prints "1245".
If the NEXT phaser is present, it runs before the next iteration:
my Int $i = 0; while ($i < 10) { if ($i % 2 == 0) { next; } say "$i is odd."; NEXT { $i++; } } # OUTPUT: «1 is odd.3 is odd.5 is odd.7 is odd.9 is odd.»
In a whenever block, next immediately exits the block for the current value:
react { whenever Supply.interval(1) { next if .is-prime; say $_; done if $_ == 4; } }
prints "0", "1" and "4" - integers from 0 to 4 with primes skipped.
*Since version 6.d, the next command in a loop that collects its last statement values returns Empty for the iterations they run on.*
The last command immediately exits the loop in question.
my @x = 1, 2, 3, 4, 5; for @x -> $x { last if $x == 3; print $x; }
prints "12".
If the LAST phaser is present, it runs before exiting the loop:
my Int $i = 1; while ($i < 10) { if ($i % 5 == 0) { last; } LAST { say "The last number was $i."; } NEXT { $i++; } } # OUTPUT: «The last number was 5.»
*Since version 6.d, the last command in a loop that collects its last statement values returns Empty for the iterations they run on.*
The redo command restarts the loop block without evaluating the conditional again.
loop { my $x = prompt("Enter a number"); redo unless $x ~~ /\d+/; last; }
How Perl 6 deals with data structures and what we can expect from them
Some classes do not have any internal structure and to access parts of them, specific methods have to be used. Numbers, strings, and some other monolithic classes are included in that class. They use the $ sigil, although complex data structures can also use it.
my $just-a-number = 7; my $just-a-string = "8";
There is a Scalar class, which is used internally to assign a default value to variables declared with the $ sigil.
my $just-a-number = 333; say $just-a-number.VAR.^name; # OUTPUT: «Scalar»
Any complex data structure can be scalarized by using the item contextualizer $:
(1, 2, 3, $(4, 5))[3].VAR.^name.say; # OUTPUT: «Scalar»
However, this means that it will be treated as such in the context they are. You can still access its internal structure.
(1, 2, 3, $(4, 5))[3][0].say; # OUTPUT: «4»
An interesting side effect, or maybe intended feature, is that scalarization conserves identity of complex structures.
for ^2 { my @list = (1, 1); say @list.WHICH; } # OUTPUT: «Array|93947995146096Array|93947995700032»
Every time (1, 1) is assigned, the variable created is going to be different in the sense that === will say it is; as it is shown, different values of the internal pointer representation are printed. However
for ^2 { my $list = (1, 1); say $list.WHICH } # OUTPUT: «List|94674814008432List|94674814008432»
In this case, $list is using the Scalar sigil and thus will be a Scalar. Any scalar with the same value will be exactly the same, as shown when printing the pointers.
Complex data structures fall in two different broad categories: Positional, or list-like and Associative, or key-value pair like, according to how you access its first-level elements. In general, complex data structures, including objects, will be a combination of both, with object properties assimilated to key-value pairs. While all objects subclass Mu, in general complex objects are instances of subclasses of Any. While it is theoretically possible to mix in Positional or Associative without doing so, most methods applicable to complex data structures are implemented in Any.
Navigating these complex data structures is a challenge, but Perl 6 provides a couple of functions that can be used on them: deepmap and duckmap. While the former will go to every single element, in order, and do whatever the block passed requires,
say [[1, 2, [3, 4]],[[5, 6, [7, 8]]]].deepmap( *.elems ); # OUTPUT: «[[1 1 [1 1]] [1 1 [1 1]]]»
which returns 1 because it goes to the deeper level and applies elems to them, deepmap can perform more complicated operations:
say [[1, 2, [3, 4]], [[5, 6, [7, 8]]]].duckmap: -> $array where .elems == 2 { $array.elems }; # OUTPUT: «[[1 2 2] [5 6 2]]»
In this case, it dives into the structure, but returns the element itself if it does not meet the condition in the block (1, 2), returning the number of elements of the array if it does (the two 2s at the end of each subarray).
Since deepmap and duckmap are Any methods, they also apply to Associative arrays:
say %( first => [1, 2], second => [3,4] ).deepmap( *.elems ); # OUTPUT: «{first => [1 1], second => [1 1]}»
Only in this case, they will be applied to every list or array that is a value, leaving the keys alone.
Positional and Associative can be turned into each other.
say %( first => [1, 2], second => [3,4] ).list[0]; # OUTPUT: «second => [3 4]»
However, in this case, and for Rakudo >= 2018.05, it will return a different value every time it runs. A hash will be turned into a list of the key-value pairs, but it is guaranteed to be disordered. You can also do the operation in the opposite direction, as long as the list has an even number of elements (odd number will result in an error):
say <a b c d>.Hash # OUTPUT: «{a => b, c => d}»
But
say <a b c d>.Hash.kv # OUTPUT: «(c d a b)»
will obtain a different value every time you run it; kv turns every Pair into a list.
Complex data structures are also generally Iterable. Generating an iterator out of them will allow the program to visit the first level of the structure, one by one:
.say for 'א'..'ס'; # OUTPUT: «אבגדהוזחטיךכלםמןנס»
'א'..'ס' is a Range, a complex data structure, and with for in front it will iterate until the list is exhausted. You can use for on your complex data structures by overriding the iterator method (from role Iterable):
class SortedArray is Array { method iterator() { self.sort.iterator } }; my @thing := SortedArray.new([3,2,1,4]); .say for @thing; # OUTPUT: «1234»
for calls directly the iterator method on @thing making it return the elements of the array in order. Much more on iterating on the page devoted to it.
Perl 6 is a functional language and, as such, functions are first-class data structures. Functions follow the Callable role, which is the 4th element in the quartet of fundamental roles. Callable goes with the & sigil, although in most cases it is elided for the sake of simplicity; this sigil elimination is always allowed in the case of Callables.
my &a-func= { (^($^þ)).Seq }; say a-func(3), a-func(7); # OUTPUT: «(0 1 2)(0 1 2 3 4 5 6)»
Blocks are the simplest callable structures, since Callables cannot be instantiated. In this case we implement a block that logs events and can retrieve them:
my $logger = -> $event, $key = Nil { state %store; if ( $event ) { %store{ DateTime.new( now ) } = $event; } else { %store.keys.grep( /$key/ ) } } $logger( "Stuff" ); $logger( "More stuff" ); say $logger( Nil, "2018-05-28" ); # OUTPUT: «(Stuff More stuff)»
A Block has a Signature, in this case two arguments, the first of which is the event that is going to be logged, and the second is the key to retrieve the events. They will be used in an independent way, but its intention is to showcase the use of a state variable that is kept from every invocation to the next. This state variable is encapsulated within the block, and cannot be accessed from outside except by using the simple API the block provides: calling the block with a second argument. The two first invocations log two events, the third invocation at the bottom of the example use this second type of call to retrieve the stored values. Blocks can be cloned:
my $clogger = $logger.clone; $clogger( "Clone stuff" ); $clogger( "More clone stuff" ); say $clogger( Nil, "2018-05-28" ); # OUTPUT: «(Clone stuff More clone stuff)»
And cloning will reset the state variable; instead of cloning, we can create façades that change the API. For instance, eliminate the need to use Nil as first argument to retrieve the log for a certain date:
my $gets-logs = $logger.assuming( Nil, * ); $logger( %(changing => "Logs") ); say $gets-logs( "2018-05-28" ); # OUTPUT: «({changing => Logs} Stuff More stuff)»
assuming wraps around a block call, giving a value (in this case, Nil) to the arguments we need, and passing on the arguments to the other arguments we represent using *. In fact, this corresponds to the natural language statement "We are calling $logger assuming the first argument is Nil". We can slightly change the appearance of these two Blocks to clarify they are actually acting on the same block:
my $Logger = $logger.clone; my $Logger::logs = $Logger.assuming( *, Nil ); my $Logger::get = $Logger.assuming( Nil, * ); $Logger::logs( <an array> ); $Logger::logs( %(key => 42) ); say $Logger::get( "2018-05-28" );
Although :: is generally used for invocation of class methods, it is actually a valid part of the name of a variable. In this case we use them conventionally to simply indicate $Logger::logs and $Logger::get are actually calling $Logger, which we have capitalized to use a class-like appearance. The point of this tutorial is that using functions as first-class citizens, together with the use of state variables, allows the use of certain interesting design patterns such as this one.
As such first class data structures, callables can be used anywhere another type of data can.
my @regex-check = ( /<alnum>/, /<alpha>/, /<punct>/ ); say @regex-check.map: "33af" ~~ *; # OUTPUT: «(「3」 alnum => 「3」 「a」 alpha => 「a」 Nil)»
Regexes are actually a type of callable:
say /regex/.does( Callable ); # OUTPUT: «True»
And in the example above we are calling regexes stored in an array, and applying them to a string literal.
Callables are composed by using the function composition operator ∘:
my $typer = -> $thing { $thing.^name ~ ' → ' ~ $thing }; my $Logger::withtype = $Logger::logs ∘ $typer; $Logger::withtype( Pair.new( 'left', 'right' ) ); $Logger::withtype( ¾ ); say $Logger::get( "2018-05-28" ); # OUTPUT: «(Pair → left right Rat → 0.75)»
We are composing $typer with the $Logger::logs function defined above, obtaining a function that logs an object preceded by its type, which can be useful for filtering, for instance. $Logger::withtype is, in fact, a complex data structure composed of two functions which are applied in a serial way, but every one of the callables composed can keep state, thus creating complex transformative callables, in a design pattern that is similar to object composition in the object oriented realm. You will have to choose, in every particular case, what is the programming style which is most suitable for your problem.
Perl 6 has different ways of defining data structures, but also many ways to constrain them so that you can create the most adequate data structure for every problem domain. but, for example, mixes roles or values into a value or a variable:
my %not-scalar := %(2 => 3) but Associative[Int, Int]; say %not-scalar.^name; # OUTPUT: «Hash+{Associative[Int, Int]}» say %not-scalar.of; # OUTPUT: «Associative[Int, Int]» %not-scalar{3} = 4; %not-scalar<thing> = 3; say %not-scalar; # OUTPUT: «{2 => 3, 3 => 4, thing => 3}»
In this case, but is mixing in the Associative[Int, Int] role; please note that we are using binding so that the type of the variable is the one defined, and not the one imposed by the % sigil; this mixed-in role shows in the name surrounded by curly braces. What does that really mean? That role includes two methods, of and keyof; by mixing the role in, the new of will be called (the old of would return Mu, which is the default value type for Hashes). However, that is all it does. It is not really changing the type of the variable, as you can see since we are using any kind of key and values in the next few statements.
However, we can provide new functionality to a variable using this type of mixin:
role Lastable { method last() { self.sort.reverse[0] } } my %hash-plus := %( 3 => 33, 4 => 44) but Lastable; say %hash-plus.sort[0]; # OUTPUT: «3 => 33» say %hash-plus.last; # OUTPUT: «4 => 44»
In Lastable we use the universal self variable to refer to whatever object this particular role is mixed in; in this case it will contain the hash it is mixed in with; it will contain something else (and possibly work some other way) in other case. This role will provide the last method to any variable it's mixed with, providing new, attachable, functionalities to regular variables. Roles can even be added to existing variables using the does keyword.
Subsets can also be used to constrain the possible values a variable might hold; they are Perl 6 attempt at gradual typing; it is not a full attempt, because subsets are not really types in a strict sense, but they allow runtime type checking. It adds type-checking functionality to regular types, so it helps create a richer type system, allowing things like the one shown in this code:
subset OneOver where (1/$_).Int == 1/$_; my OneOver $one-fraction = ⅓; say $one-fraction; # OUTPUT: «0.333333»
On the other hand, my OneOver $ = ⅔; will cause a type-check error. Subsets can use Whatever, that is, *, to refer to the argument; but this will be instantiated every time you use it to a different argument, so if we use it twice in the definition we would get an error. In this case we are using the topic single variable, $_, to check the instantiation. Subsetting can be done directly, without the need of declaring it, in signatures.
It might be assumed that all the data contained in a data structure is actually there. That is not necessarily the case: in many cases, for efficiency reasons or simply because it is not possible, the elements contained in a data structure only jump into existence when they are actually needed. This computation of items as they are needed is called reification or vivification.
# A list containing infinite number of un-reified Fibonacci numbers: my @fibonacci = 1, 1, * + * … ∞; # We reify 10 of them, looking up the first 10 of them with array index: say @fibonacci[^10]; # OUTPUT: «(1 1 2 3 5 8 13 21 34 55)» # We reify 5 more: 10 we already reified on previous line, and we need to # reify 5 more to get the 15th element at index 14. Even though we need only # the 15th element, the original Seq still has to reify all previous elements: say @fibonacci[14]; # OUTPUT: «987»
Above we were reifying a Seq we created with the sequence operator, but other data structures use the concept as well. For example, an un-reified Range is just the two end points. In some languages, calculating the sum of a huge range is a lengthy and memory-consuming process, but Perl 6 calculates it instantly:
say sum 1 .. 9_999_999_999_999; # OUTPUT: «49999999999995000000000000»
Why? Because the sum can be calculated without vivifying the Range; that is, without figuring out all the elements it contains. This is why this feature exists. You can even make your own things reify-on-demand, using gather and take:
my $seq = gather { say "About to make 1st element"; take 1; say "About to make 2nd element"; take 2; } say "Let's reify an element!"; say $seq[0]; say "Let's reify more!"; say $seq[1]; say "Both are reified now!"; say $seq[^2]; # OUTPUT: # Let's reify an element! # About to make 1st element # 1 # Let's reify more! # About to make 2nd element # 2 # Both are reified now! # (1 2)
Following the output above, you can see the print statements inside the gather got executed only when we reified the individual elements while looking up an element. Also note that the elements got reified just once. When we printed the same elements again on the last line of the example, the messages inside gather was no longer printed. This is because the construct used already-reified elements from the Seq's cache.
Note that above we assigned the gather to a Scalar container (the $ sigil), not the Positional one (the @ sigil). The reason is that the @-sigiled variables are mostly eager. What this means is they reify the stuff assigned to them right away most of the time. The only time they don't do it is when the items are known to be is-lazy, like our sequence generated with infinity as the end point. Were we to assign the gather to a @-variable, the say statements inside of it would've been printed right away.
Another way to vivify the list fully is by calling .elems on it. This is the reason why checking whether a list contains any items is best done by using .Bool method (or just using if @array { … }), since you don't need to reify all the elements to find out if there are any of them.
There are times where you do want to fully-reify a list before doing something. For example, the IO::Handle.lines returns a Seq. The following code contains a bug; keeping reification in mind, try to spot it:
my $fh = "/tmp/bar".IO.open; my $lines = $fh.lines; close $fh; say $lines[0];
We open a filehandle, then assign return of .lines to a Scalar variable, so the returned Seq does not get reified right away. We then close the filehandle, and try to print an element from $lines.
The bug in the code is by the time we reify the $lines Seq on the last line, we've already closed the filehandle. When the Seq's iterator tries to generate the item we've requested, it results in the error about attempting to read from a closed handle. So, to fix the bug we can either assign to a @-sigiled variable or call .elems on $lines before closing the handle:
my $fh = "/tmp/bar".IO.open; my @lines = $fh.lines; close $fh; say @lines[0]; # no problem!
We can also use any function whose side effect is reification, like .elems mentioned above:
my $fh = "/tmp/bar".IO.open; my $lines = $fh.lines; say "Read $lines.elems() lines"; # reifying before closing handle close $fh; say $lines[0]; # no problem!
Using eager will also reify the whole sequence:
my $fh = "/tmp/bar".IO.open; my $lines = eager $fh.lines; # Uses eager for reification. close $fh; say $lines[0];
Languages that allow introspection like Perl 6 have functionalities attached to the type system that let the developer access container and value metadata. This metadata can be used in a program to carry out different actions depending on their value. As it is obvious from the name, metadata are extracted from a value or container via the metaclass.
my $any-object = "random object"; my $metadata = $any-object.HOW; say $metadata.^mro; # OUTPUT: «((ClassHOW) (Any) (Mu))» say $metadata.can( $metadata, "uc" ); # OUTPUT: «(uc uc)»
With the first say we show the class hierarchy of the metamodel class, which in this case is Metamodel::ClassHOW. It inherits directly from Any, meaning any method there can be used; it also mixes in several roles which can give you information about the class structure and functions. But one of the methods of that particular class is can, which we can use to look up whether the object can use the uc (uppercase) method, which it obviously can. However, it might not be so obvious in some other cases, when roles are mixed in directly into a variable. For instance, in the case of %hash-plus defined above:
say %hash-plus.^can("last"); # OUTPUT: «(last)»
In this case we are using the syntactic sugar for HOW.method, ^method, to check if your data structure responds to that method; the output, which shows the name of the methods that match, certifies that we can use it.
See also this article on class introspection on how to access class properties and methods, and use it to generate test data for a class; this Advent Calendar article describes the meta-object protocol extensively.
Processing date and time in Perl 6
Perl 6 includes several classes that deal with temporal information: Date, DateTime, Instant and Duration. The three first are dateish, so they mix in the Dateish role, which defines all methods and properties that classes that deal with date should assume. It also includes a class hierarchy of exceptions rooted in X::Temporal.
We will try to illustrate these classes in the next (somewhat extended) example, which can be used to process all files in a directory (by default .) with a particular extension (by default .p6) in a directory, sort them according to their age, and compute how many files have been created per month and how many were modified in certain periods expressed in ranges of months:
sub MAIN( $path = ".", $extension = "p6" ) { my DateTime $right = DateTime.now; my %metadata; my %files-month; my %files-period; for dir($path).grep( / \.$extension $/ ) -> $file { CATCH { when X::Temporal { say "Date-related problem", .payload } when X::IO { say "File-related problem", .payload } default { .payload.say } } my Instant $modified = $file.modified; my Instant $accessed = $file.accessed; my Duration $duration = $accessed - $modified; my $age = $right - DateTime($accessed); my $time-of-day = $file.changed.DateTime.hh-mm-ss but Dateish; my $file-changed-date = $file.changed.Date; %metadata{$file} = %( modified => $modified, accessed => $accessed, age => $age, difference => $duration, changed-tod => $time-of-day, changed-date => $file-changed-date); %files-month{$file-changed-date.month}++; given $file-changed-date { when Date.new("2018-01-01")..^Date.new("2018-04-01") { %files-period<pre-grant>++} when Date.new("2018-04-01")..Date.new("2018-05-31") { %files-period<grant>++} default { %files-period<post-grant>++}; } } %metadata.sort( { $^a.value<age> <=> $^b.value<age> } ).map: { say $^x.key, ", ", $^x.value<accessed modified age difference changed-tod changed-date>.join(", "); }; %files-month.keys.sort.map: { say "Month $^x → %files-month{$^x}" }; %files-period.keys.map: { say "Period $^x → %files-period{$^x}" }; }
DateTime is used in line 6 to contain the current date and time returned by now.
A CATCH phaser is declared in lines 11 to 15. Its main mission is to distinguish between DateTime-related exceptions and other types. These kind of exception can arise from invalid formats or timezone clashes. Barring some corruption of the file attributes, both are impossible, but in any case they should be caught and separated from other types of exceptions.
We use Instants in lines 16-17 to represent the moment in which the files where accessed and modified. An Instant is measured in atomic seconds, and is a very low-level description of a time event; however, the Duration declared in line 18 represent the time transcurred among two different Instants, and we will be using it to represent the age.
For some variables we might be interested in dealing with them with some dateish traits. $time-of-day contains the time of the day the file was changed; changed will return an Instant, but it is converted into a Date (which is Dateish while Instant is not) and then the time of day is extracted from that. $time-of-day will have «Str+{Dateish}» type.
We will use the date in this variable to find out the period when the files were changed.
Date.new("2018-01-01")..^Date.new("2018-04-01")
creates a date Range and $file-changed-date is smartmatched against it. Dates can be used this way; in this case it creates a Range that excludes its last element.
This very variable is also used to compute the month of the year when the file was modified. Date is obviously Dateish and then has the month method to extract that property from it.
Duration objects can be compared. This is used in
%metadata.sort({ $^a.value<age> <=> $^b.value<age> });
to sort the files by age.
An example using the enum type
The enum type is much more complex in Perl 6 than in some other languages, and the details are found in its type description.
This short document will give a simple example of its use as is the usual practice in C-like languages.
Say we have a program that needs to write to various directories; we want a function that, given a directory name, tests it for (1) its existence and (2) whether it can be written to by the user of the program; this implies that there are three possible states from the user perspective: either you can write (CanWrite), or there is no directory (NoDir) or the directory exists, but you cannot write (NoWrite). The results of the test will determine what actions the program takes next.
enum DirStat <CanWrite NoDir NoWrite>; sub check-dir-status($dir --> DirStat) { if $dir.IO.d { # dir exists, can the program user write to it? my $f = "$dir/.tmp"; spurt $f, "some text"; CATCH { # unable to write for some reason return NoWrite; } # if we get here we must have successfully written to the dir unlink $f; return CanWrite; } # if we get here the dir must not exist return NoDir; } # test each of three directories by a non-root user my $dirs = '/tmp', # normally writable by any user '/', # writable only by root '~/tmp'; # a non-existent dir in the user's home dir for $dirs -> $dir { my $stat = check-dir-status $dir; say "status of dir '$dir': $stat"; if $stat ~~ CanWrite { say " user can write to dir: $dir"; } } # output # status of dir '/tmp': CanWrite # user can write to dir: /tmp # status of dir '/': NoWrite # status of dir '~/tmp': NoDir
Using exceptions in Perl 6
Exceptions in Perl 6 are objects that hold information about errors. An error can be, for example, the unexpected receiving of data or a network connection no longer available, or a missing file. The information that an exception object stores is, for instance, a human-readable message about the error condition, the backtrace of the raising of the error, and so on.
All built-in exceptions inherit from Exception, which provides some basic behavior, including the storage of a backtrace and an interface for the backtrace printer.
Ad hoc exceptions can be used by calling die with a description of the error:
die "oops, something went wrong"; # RESULT: «oops, something went wrong in block <unit> at my-script.p6:1»
It is worth noting that die prints the error message to the standard error $*ERR.
Typed exceptions provide more information about the error stored within an exception object.
For example, if while executing .zombie copy on an object, a needed path foo/bar becomes unavailable, then an X::IO::DoesNotExist exception can be raised:
die X::IO::DoesNotExist.new(:path("foo/bar"), :trying("zombie copy")) # RESULT: «Failed to find 'foo/bar' while trying to do '.zombie copy' # in block <unit> at my-script.p6:1»
Note how the object has provided the backtrace with information about what went wrong. A user of the code can now more easily find and correct the problem.
It's possible to handle exceptional circumstances by supplying a CATCH block:
die X::IO::DoesNotExist.new(:path("foo/bar"), :trying("zombie copy")); CATCH { when X::IO { $*ERR.say: "some kind of IO exception was caught!" } } # OUTPUT: «some kind of IO exception was caught!»
Here, we are saying that if any exception of type X::IO occurs, then the message some kind of IO exception was caught! will be sent to stderr, which is what $*ERR.say does, getting displayed on whatever constitutes the standard error device in that moment, which will probably be the console by default.
A CATCH block uses smartmatching similar to how given/when smartmatches on options, thus it's possible to catch and handle various categories of exceptions inside a when block.
To handle all exceptions, use a default statement. This example prints out almost the same information as the normal backtrace printer.
CATCH { default { $*ERR.say: .message; for .backtrace.reverse { next if .file.starts-with('SETTING::'); next unless .subname; $*ERR.say: " in block {.subname} at {.file} line {.line}"; } } }
Note that the match target is a role. To allow user defined exceptions to match in the same manner, they must implement the given role. Just existing in the same namespace will look alike but won't match in a CATCH block.
After a CATCH has handled the exception, the block enclosing the CATCH block is exited.
In other words, even when the exception is handled successfully, the rest of the code in the enclosing block will never be executed.
die "something went wrong ..."; CATCH { # will definitely catch all the exception default { .Str.say; } } say "This won't be said."; # but this line will be never reached since # the enclosing block will be exited immediately # OUTPUT: «something went wrong ...»
Compare with this:
CATCH { CATCH { default { .Str.say; } } die "something went wrong ..."; } say "Hi! I am at the outer block!"; # OUTPUT: «Hi! I am at the outer block!»
See Resuming of exceptions, for how to return control back to where the exception originated.
A try block is a normal block which implicitly turns on the use fatal pragma and includes an implicit CATCH block that drops the exception, which means you can use it to contain them. Caught exceptions are stored inside the $! variable, which holds a value of type Exception.
A normal block like this one will simply fail:
{ my $x = +"a"; say $x.^name; } # OUTPUT: «Failure»
However, a try block will contain the exception and put it into the $! variable:
try { my $x = +"a"; say $x.^name; } if $! { say "Something failed!" } # OUTPUT: «Something failed!» say $!.^name; # OUTPUT: «X::Str::Numeric»
Any exception that is thrown in such a block will be caught by a CATCH block, either implicit or provided by the user. In the latter case, any unhandled exception will be rethrown. If you choose not to handle the exception, they will be contained by the block.
try { die "Tough luck"; say "Not gonna happen"; } try { fail "FUBAR"; }
In both try blocks above, exceptions will be contained within the block, but the say statement will not be run. We can handle them, though:
class E is Exception { method message() { "Just stop already!" } } try { E.new.throw; # this will be local say "This won't be said."; } say "I'm alive!"; try { CATCH { when X::AdHoc { .Str.say; .resume } } die "No, I expect you to DIE Mr. Bond!"; say "I'm immortal."; E.new.throw; say "No, you don't!"; }
Which would output:
I'm alive! No, I expect you to DIE Mr. Bond! I'm immortal. Just stop already! in block <unit> at exception.p6 line 21
Since the CATCH block is handling just the X::AdHoc exception thrown by the die statement, but not the E exception. In the absence of a CATCH block, all exceptions will be contained and dropped, as indicated above. resume will resume execution right after the exception has been thrown; in this case, in the die statement. Please consult the section on resuming of exceptions for more information on this.
A try-block is a normal block and as such treats its last statement as the return value of itself. We can therefore use it as a right-hand side.
say try { +"99999" } // "oh no"; # OUTPUT: «99999» say try { +"hello" } // "oh no"; # OUTPUT: «oh no»
Try blocks support else blocks indirectly by returning the return value of the expression or Nil if an exception was thrown.
with try +"♥" { say "this is my number: $_" } else { say "not my number!" } # OUTPUT: «not my number!»
try can also be used with a statement instead of a block, that is, as a statement prefix:
say try "some-filename.txt".IO.slurp // "sane default"; # OUTPUT: «sane default»
What try actually causes is, via the use fatal pragma, an immediate throw of the exceptions that happen within its scope, but by doing so the CATCH block is invoked from the point where the exception is thrown, which defines its scope.
my $error-code = "333"; sub bad-sub { die "Something bad happened"; } try { my $error-code = "111"; bad-sub; CATCH { default { say "Error $error-code ", .^name, ': ',.Str } } } # OUTPUT: «Error 111 X::AdHoc: Something bad happened»
Exceptions can be thrown explicitly with the .throw method of an Exception object.
This example throws an AdHoc exception, catches it and allows the code to continue from the point of the exception by calling the .resume method.
{ X::AdHoc.new(:payload<foo>).throw; "OHAI".say; CATCH { when X::AdHoc { .resume } } } "OBAI".say; # OUTPUT: «OHAIOBAI»
If the CATCH block doesn't match the exception thrown, then the exception's payload is passed on to the backtrace printing mechanism.
{ X::AdHoc.new(:payload<foo>).throw; "OHAI".say; CATCH { } } "OBAI".say; # RESULT: «foo # in block <unit> at my-script.p6:1»
This next example doesn't resume from the point of the exception. Instead, it continues after the enclosing block, since the exception is caught, and then control continues after the CATCH block.
{ X::AdHoc.new(:payload<foo>).throw; "OHAI".say; CATCH { when X::AdHoc { } } } "OBAI".say; # OUTPUT: «OBAI»
throw can be viewed as the method form of die, just that in this particular case, the sub and method forms of the routine have different names.
Exceptions interrupt control flow and divert it away from the statement following the statement that threw it. Any exception handled by the user can be resumed and control flow will continue with the statement following the statement that threw the exception. To do so, call the method .resume on the exception object.
CATCH { when X::AdHoc { .resume } } # this is step 2 die "We leave control after this."; # this is step 1 say "We have continued with control flow."; # this is step 3
Resuming will occur right after the statement that has caused the exception, and in the innermost call frame:
sub bad-sub { die "Something bad happened"; return "not returning"; } { my $return = bad-sub; say "Returned $return"; CATCH { default { say "Error ", .^name, ': ',.Str; $return = '0'; .resume; } } } # OUTPUT: # Error X::AdHoc: Something bad happened # Returned not returning
In this case, .resume is getting to the return statement that happens right after the die statement. Please note that the assignment to $return is taking no effect, since the CATCH statement is happening inside the call to bad-sub, which, via the return statement, assigns the not returning value to it.
If an exception is thrown and not caught, it causes the program to exit with a non-zero status code, and typically prints a message to the standard error stream of the program. This message is obtained by calling the gist method on the exception object. You can use this to suppress the default behavior of printing a backtrace along with the message:
class X::WithoutLineNumber is X::AdHoc { multi method gist(X::WithoutLineNumber:D:) { $.payload } } die X::WithoutLineNumber.new(payload => "message") # prints "message\n" to $*ERR and exits, no backtrace
Control exceptions are raised when throwing an Exception which does the X::Control role (since Rakudo 2019.03). They are usually thrown by certain keywords and are handled either automatically or by the appropriate phaser. Any unhandled control exception is converted to a normal exception.
{ return; CATCH { default { $*ERR.say: .^name, ': ', .Str } } } # OUTPUT: «X::ControlFlow::Return: Attempt to return outside of any Routine» # was CX::Return
Functions and functional programming in Perl 6
Routines are one of the means Perl 6 has to reuse code. They come in several forms, most notably methods, which belong in classes and roles and are associated with an object; and functions (also called subroutines or subs, for short), which can be called independently of objects.
Subroutines default to lexical (my) scoping, and calls to them are generally resolved at compile time.
Subroutines can have a signature, also called parameter list, which specifies which, if any, arguments the signature expects. It can specify (or leave open) both the number and types of arguments, and the return value.
Introspection on subroutines is provided via Routine.
The basic way to create a subroutine is to use the sub declarator followed by an optional identifier:
sub my-func { say "Look ma, no args!" } my-func;
The sub declarator returns a value of type Sub that can be stored in any container:
my &c = sub { say "Look ma, no name!" } c; # OUTPUT: «Look ma, no name!» my Any:D $f = sub { say 'Still nameless...' } $f(); # OUTPUT: «Still nameless...» my Code \a = sub { say ‚raw containers don't implement postcircumfix:<( )>‘ }; a.(); # OUTPUT: «raw containers don't implement postcircumfix:<( )>»
The declarator sub will declare a new name in the current scope at compile time. As such, any indirection has to be resolved at compile time:
constant aname = 'foo'; sub ::(aname) { say 'oi‽' }; foo;
This will become more useful once macros are added to Perl 6.
To have the subroutine take arguments, a signature goes between the subroutine's name and its body, in parentheses:
sub exclaim ($phrase) { say $phrase ~ "!!!!" } exclaim "Howdy, World";
By default, subroutines are lexically scoped. That is, sub foo {...} is the same as my sub foo {...} and is only defined within the current scope.
sub escape($str) { # Puts a slash before non-alphanumeric characters S:g[<-alpha -digit>] = "\\$/" given $str } say escape 'foo#bar?'; # OUTPUT: «foo\#bar\?» { sub escape($str) { # Writes each non-alphanumeric character in its hexadecimal escape S:g[<-alpha -digit>] = "\\x[{ $/.ord.base(16) }]" given $str } say escape 'foo#bar?' # OUTPUT: «foo\x[23]bar\x[3F]» } # Back to original escape function say escape 'foo#bar?'; # OUTPUT: «foo\#bar\?»
Subroutines don't have to be named. If unnamed, they're called anonymous subroutines.
say sub ($a, $b) { $a ** 2 + $b ** 2 }(3, 4) # OUTPUT: «25»
But in this case, it's often desirable to use the more succinct block syntax. Subroutines and blocks can be called in place, as in the example above.
say -> $a, $b { $a ** 2 + $b ** 2 }(3, 4) # OUTPUT: «25»
Or even
say { $^a ** 2 + $^b ** 2 }(3, 4) # OUTPUT: «25»
Whenever you see something like { $_ + 42 }, -> $a, $b { $a ** $b }, or { $^text.indent($:spaces) }, that's Block syntax; the -> is considered also part of the block. Statements such as if, for, while are followed by these kind of blocks.
for 1, 2, 3, 4 -> $a, $b { say $a ~ $b; } # OUTPUT: «1234»
They can also be used on their own as anonymous blocks of code.
say { $^a ** 2 + $^b ** 2}(3, 4) # OUTPUT: «25»
Please note that this implies that, despite the fact that statements such as if do not define a topic variable, they actually can:
my $foo = 33; if $foo ** 33 -> $a { say "$a is not null"; # } # OUTPUT: «129110040087761027839616029934664535539337183380513 is not null»
For block syntax details, see the documentation for the Block type.
The parameters that a function accepts are described in its signature.
sub format (Str $s) { ... } -> $a, $b { ... }
Details about the syntax and use of signatures can be found in the documentation on the Signature class.
If no signature is provided but either of the two automatic variables @_ or %_ are used in the function body, a signature with *@_ or *%_ will be generated. Both automatic variables can be used at the same time.
sub s { say @_, %_ }; say &s.signature # OUTPUT: «(*@_, *%_)»
Arguments are supplied as a comma separated list. To disambiguate nested calls, use parentheses:
sub f(&c){ c() * 2 }; # call the function reference c with empty parameter list sub g($p){ $p - 2 }; say(g(42), 45); # pass only 42 to g()
When calling a function, positional arguments should be supplied in the same order as the function's signature. Named arguments may be supplied in any order, but it's considered good form to place named arguments after positional arguments. Inside the argument list of a function call, some special syntax is supported:
sub f(|c){}; f :named(35); # A named argument (in "adverb" form) f named => 35; # Also a named argument f :35named; # A named argument using abbreviated adverb form f 'named' => 35; # Not a named argument, a Pair in a positional argument my \c = <a b c>.Capture; f |c; # Merge the contents of Capture $c as if they were supplied
Arguments passed to a function are conceptually first collected in a Capture container. Details about the syntax and use of these containers can be found in the documentation on the Capture class.
When using named arguments, note that normal List "pair-chaining" allows one to skip commas between named arguments.
sub f(|c){}; f :dest</tmp/foo> :src</tmp/bar> :lines(512); f :32x :50y :110z; # This flavor of "adverb" works, too f :a:b:c; # The spaces are also optional.
Any Block or Routine will provide the value of its last expression as a return value to the caller. If either return or return-rw is called, then its parameter, if any, will become the return value. The default return value is Nil.
sub a { 42 }; sub b { say a }; sub c { }; b; # OUTPUT: «42» say c; # OUTPUT: «Nil»
Multiple return values are returned as a list or by creating a Capture. Destructuring can be used to untangle multiple return values.
sub a { 42, 'answer' }; put a.perl; # OUTPUT: «(42, "answer")» my ($n, $s) = a; put [$s, $n]; # OUTPUT: «answer 42» sub b { <a b c>.Capture }; put b.perl; # OUTPUT: «\("a", "b", "c")»
Perl 6 has many ways to specify a function's return type:
sub foo(--> Int) {}; say &foo.returns; # OUTPUT: «(Int)»
sub foo() returns Int {}; say &foo.returns; # OUTPUT: «(Int)»
sub foo() of Int {}; say &foo.returns; # OUTPUT: «(Int)»
my Int sub foo() {}; say &foo.returns; # OUTPUT: «(Int)»
Attempting to return values of another type will cause a compilation error.
sub foo() returns Int { "a"; }; foo; # Type check fails
returns and of are equivalent, and both take only a Type since they are declaring a trait of the Callable. The last declaration is, in fact, a type declaration, which obviously can take only a type. In the other hand, --> can take either undefined or definite values.
Note that Nil and Failure are exempt from return type constraints and can be returned from any routine, regardless of its constraint:
sub foo() returns Int { fail }; foo; # Failure returned sub bar() returns Int { return }; bar; # Nil returned
Perl 6 allows for writing several routines with the same name but different signatures. When the routine is called by name, the runtime environment determines the proper candidate and invokes it.
Each candidate is declared with the multi keyword. Dispatch happens depending on the number (arity), type and name of arguments. Consider the following example:
# version 1 multi happy-birthday( $name ) { say "Happy Birthday $name !"; } # version 2 multi happy-birthday( $name, $age ) { say "Happy {$age}th Birthday $name !"; } # version 3 multi happy-birthday( :$name, :$age, :$title = 'Mr' ) { say "Happy {$age}th Birthday $title $name !"; } # calls version 1 (arity) happy-birthday 'Larry'; # OUTPUT: «Happy Birthday Larry !» # calls version 2 (arity) happy-birthday 'Luca', 40; # OUTPUT: «Happy 40th Birthday Luca !» # calls version 3 # (named arguments win against arity) happy-birthday( age => '50', name => 'John' ); # OUTPUT: «Happy 50th Birthday Mr John !» # calls version 2 (arity) happy-birthday( 'Jack', 25 ); # OUTPUT: «Happy 25th Birthday Jack !»
The first two versions of the happy-birthday sub differs only in the arity (number of arguments), while the third version uses named arguments and is chosen only when named arguments are used, even if the arity is the same of another multi candidate.
When two sub have the same arity, the type of the arguments drive the dispatch; when there are named arguments they drive the dispatch even when their type is the same as another candidate:
multi happy-birthday( Str $name, Int $age ) { say "Happy {$age}th Birthday $name !"; } multi happy-birthday( Str $name, Str $title ) { say "Happy Birthday $title $name !"; } multi happy-birthday( Str :$name, Int :$age ) { say "Happy Birthday $name, you turned $age !"; } happy-birthday 'Luca', 40; # OUTPUT: «Happy 40th Birthday Luca !» happy-birthday 'Luca', 'Mr'; # OUTPUT: «Happy Birthday Mr Luca !» happy-birthday age => 40, name => 'Luca'; # OUTPUT: «Happy Birthday Luca, you turned 40 !»
Named parameters participate in the dispatch even if they are not provided in the call. Therefore a multi candidate with named parameters will be given precedence.
For more information about type constraints see the documentation for the Signature class.
multi as-json(Bool $d) { $d ?? 'true' !! 'false'; } multi as-json(Real $d) { ~$d } multi as-json(@d) { sprintf '[%s]', @d.map(&as-json).join(', ') } say as-json( True ); # OUTPUT: «true» say as-json( 10.3 ); # OUTPUT: «10.3» say as-json( [ True, 10.3, False, 24 ] ); # OUTPUT: «[true, 10.3, false, 24]»
multi without any specific routine type always defaults to a sub, but you can use it on methods as well. The candidates are all the multi methods of the object:
class Congrats { multi method congratulate($reason, $name) { say "Hooray for your $reason, $name"; } } role BirthdayCongrats { multi method congratulate('birthday', $name) { say "Happy birthday, $name"; } multi method congratulate('birthday', $name, $age) { say "Happy {$age}th birthday, $name"; } } my $congrats = Congrats.new does BirthdayCongrats; $congrats.congratulate('promotion','Cindy'); # OUTPUT: «Hooray for your promotion, Cindy» $congrats.congratulate('birthday','Bob'); # OUTPUT: «Happy birthday, Bob»
Unlike sub, if you use named parameters with multi methods, the parameters must be required parameters to behave as expected.
Please note that a non-multi sub or operator will hide multi candidates of the same name in any parent scope or child scope. The same is true for imported non-multi candidates.
proto is a way to formally declare commonalities between multi candidates. It acts as a wrapper that can validate but not modify arguments. Consider this basic example:
proto congratulate(Str $reason, Str $name, |) {*} multi congratulate($reason, $name) { say "Hooray for your $reason, $name"; } multi congratulate($reason, $name, Int $rank) { say "Hooray for your $reason, $name -- got rank $rank!"; } congratulate('being a cool number', 'Fred'); # OK congratulate('being a cool number', 'Fred', 42); # OK
congratulate('being a cool number', 42); # Proto match error
The proto insists that all multi congratulate subs conform to the basic signature of two strings, optionally followed by further parameters. The | is an un-named Capture parameter, and allows a multi to take additional arguments. The first two calls succeed, but the third fails (at compile time) because 42 doesn't match Str.
say &congratulate.signature # OUTPUT: «(Str $reason, Str $name, | is raw)»
You can give the proto a function body, and place the {*} where you want the dispatch to be done.
# attempts to notify someone -- False if unsuccessful proto notify(Str $user, Str $msg) { my \hour = DateTime.now.hour; if hour > 8 or hour < 22 { return {*}; } else { # we can't notify someone when they might be sleeping return False; } }
{*} always dispatches to candidates with the parameters it's called with. Parameter defaults and type coercions will work but are not passed on.
proto mistake-proto(Str() $str, Int $number = 42) {*} multi mistake-proto($str, $number) { say $str.^name } mistake-proto(7, 42); # OUTPUT: «Int» -- not passed on
mistake-proto('test'); # fails -- not passed on
The only keyword preceding sub or method indicates that it will be the only function with that name that inhabits a given namespace.
only sub you () {"Can make all the world seem right"};
This will make other declarations in the same namespace, such as
sub you ( $can ) { "Make the darkness bright" }
fail with an exception of type X::Redeclaration. only is the default value for all subs; in the case above, not declaring the first subroutine as only will yield exactly the same error; however, nothing prevents future developers from declaring a proto and preceding the names with multi. Using only before a routine is a defensive programming feature that declares the intention of not having routines with the same name declared in the same namespace in the future.
(exit code 1) ===SORRY!=== Error while compiling /tmp/only-redeclaration.p6 Redeclaration of routine 'you' (did you mean to declare a multi-sub?) at /tmp/only-redeclaration.p6:3 ------> <BOL>⏏<EOL>
Anonymous sub cannot be declared only. only sub {}' will throw an error of type, surprisingly, X::Anon::Multi.
While the dispatch system described above provides a lot of flexibility, there are some conventions that most internal functions, and those in many modules, will follow.
Perhaps the most important one of these conventions is the way slurpy list arguments are handled. Most of the time, functions will not automatically flatten slurpy lists. The rare exceptions are those functions that don't have a reasonable behavior on lists of lists (e.g., chrs) or where there is a conflict with an established idiom (e.g., pop being the inverse of push).
If you wish to match this look and feel, any Iterable argument must be broken out element-by-element using a **@ slurpy, with two nuances:
An Iterable inside a Scalar container doesn't count.
This can be achieved by using a slurpy with a + or +@ instead of **:
sub grab(+@a) { "grab $_".say for @a }
which is shorthand for something very close to:
multi sub grab(**@a) { "grab $_".say for @a } multi sub grab(\a) { a ~~ Iterable and a.VAR !~~ Scalar ?? nextwith(|a) !! nextwith(a,) }
This results in the following behavior, which is known as the "single argument rule" and is important to understand when invoking slurpy functions:
grab(1, 2); # OUTPUT: «grab 1grab 2» grab((1, 2)); # OUTPUT: «grab 1grab 2» grab($(1, 2)); # OUTPUT: «grab 1 2» grab((1, 2), 3); # OUTPUT: «grab 1 2grab 3»
This also makes user-requested flattening feel consistent whether there is one sublist, or many:
grab(flat (1, 2), (3, 4)); # OUTPUT: «grab 1grab 2grab 3grab 4» grab(flat $(1, 2), $(3, 4)); # OUTPUT: «grab 1 2grab 3 4» grab(flat (1, 2)); # OUTPUT: «grab 1grab 2» grab(flat $(1, 2)); # OUTPUT: «grab 1grab 2»
It's worth noting that mixing binding and sigilless variables in these cases requires a bit of finesse, because there is no Scalar intermediary used during binding.
my $a = (1, 2); # Normal assignment, equivalent to $(1, 2) grab($a); # OUTPUT: «grab 1 2» my $b := (1, 2); # Binding, $b links directly to a bare (1, 2) grab($b); # OUTPUT: «grab 1grab 2» my \c = (1, 2); # Sigilless variables always bind, even with '=' grab(c); # OUTPUT: «grab 1grab 2»
Functions and other code objects can be passed around as values, just like any other object.
There are several ways to get hold of a code object. You can assign it to a variable at the point of declaration:
my $square = sub (Numeric $x) { $x * $x } # and then use it: say $square(6); # OUTPUT: «36»
Or you can reference an existing named function by using the &-sigil in front of it.
sub square($x) { $x * $x }; # get hold of a reference to the function: my $func = &square
This is very useful for higher order functions, that is, functions that take other functions as input. A simple one is map, which applies a function to each input element:
sub square($x) { $x * $x }; my @squared = map &square, 1..5; say join ', ', @squared; # OUTPUT: «1, 4, 9, 16, 25»
To call a subroutine with 2 arguments like an infix operator, use a subroutine reference surrounded by [ and ].
sub plus { $^a + $^b }; say 21 [&plus] 21; # OUTPUT: «42»
All code objects in Perl 6 are closures, which means they can reference lexical variables from an outer scope.
sub generate-sub($x) { my $y = 2 * $x; return sub { say $y }; # ^^^^^^^^^^^^^^ inner sub, uses $y } my $generated = generate-sub(21); $generated(); # OUTPUT: «42»
Here, $y is a lexical variable inside generate-sub, and the inner subroutine that is returned uses it. By the time that inner sub is called, generate-sub has already exited. Yet the inner sub can still use $y, because it closed over the variable.
Another closure example is the use of map to multiply a list of numbers:
my $multiply-by = 5; say join ', ', map { $_ * $multiply-by }, 1..5; # OUTPUT: «5, 10, 15, 20, 25»
Here, the block passed to map references the variable $multiply-by from the outer scope, making the block a closure.
Languages without closures cannot easily provide higher-order functions that are as easy to use and powerful as map.
Routines are code objects that conform to type Routine, most notably Sub, Method, Regex and Submethod.
They carry extra functionality in addition to what a Block supplies: they can come as multis, you can wrap them, and exit early with return:
my $keywords = set <if for unless while>; sub has-keyword(*@words) { for @words -> $word { return True if $word (elem) $keywords; } False; } say has-keyword 'not', 'one', 'here'; # OUTPUT: «False» say has-keyword 'but', 'here', 'for'; # OUTPUT: «True»
Here, return doesn't just leave the block inside which it was called, but the whole routine. In general, blocks are transparent to return, they attach to the outermost routine.
Routines can be inlined and as such provide an obstacle for wrapping. Use the pragma use soft; to prevent inlining to allow wrapping at runtime.
sub testee(Int $i, Str $s){ rand.Rat * $i ~ $s; } sub wrap-to-debug(&c){ say "wrapping {&c.name} with arguments {&c.signature.perl}"; &c.wrap: sub (|args){ note "calling {&c.name} with {args.gist}"; my \ret-val := callwith(|args); note "returned from {&c.name} with return value {ret-val.perl}"; ret-val } } my $testee-handler = wrap-to-debug(&testee); # OUTPUT: «wrapping testee with arguments :(Int $i, Str $s)» say testee(10, "ten"); # OUTPUT: «calling testee with \(10, "ten")returned from testee with return value "6.151190ten"6.151190ten» &testee.unwrap($testee-handler); say testee(10, "ten"); # OUTPUT: «6.151190ten»Important ones: candidates, wrap, unwrap, assuming, arity, count
Operators are just subroutines with funny names. The funny names are composed of the category name (infix, prefix, postfix, circumfix, postcircumfix), followed by a colon, and a list of the operator name or names (two components in the case of circumfix and postcircumfix).
This works both for adding multi candidates to existing operators and for defining new ones. In the latter case, the definition of the new subroutine automatically installs the new operator into the grammar, but only in the current lexical scope. Importing an operator via use or import also makes it available.
# adding a multi candidate to an existing operator: multi infix:<+>(Int $x, "same") { 2 * $x }; say 21 + "same"; # OUTPUT: «42» # defining a new operator sub postfix:<!>(Int $x where { $x >= 0 }) { [*] 1..$x }; say 6!; # OUTPUT: «720»
The operator declaration becomes available as soon as possible, so you can recurse into a just-defined operator:
sub postfix:<!>(Int $x where { $x >= 0 }) { $x == 0 ?? 1 !! $x * ($x - 1)! } say 6!; # OUTPUT: «720»
Circumfix and postcircumfix operators are made of two delimiters, one opening and one closing.
sub circumfix:<START END>(*@elems) { "start", @elems, "end" } say START 'a', 'b', 'c' END; # OUTPUT: «(start [a b c] end)»
Postcircumfixes also receive the term after which they are parsed as an argument:
sub postcircumfix:<!! !!>($left, $inside) { "$left -> ( $inside )" } say 42!! 1 !!; # OUTPUT: «42 -> ( 1 )»
Blocks can be assigned directly to operator names. Use a variable declarator and prefix the operator name with a &-sigil.
my &infix:<ieq> = -> |l { [eq] l>>.fc }; say "abc" ieq "Abc"; # OUTPUT: «True»
Operator precedence in Perl 6 is specified relative to existing operators. The traits is tighter, is equiv and is looser can be provided with an operator to indicate how the precedence of the new operator is related to other, existing ones. More than one trait can be applied.
For example, infix:<*> has a tighter precedence than infix:<+>, and squeezing one in between works like this:
sub infix:<!!>($a, $b) is tighter(&infix:<+>) { 2 * ($a + $b) } say 1 + 2 * 3 !! 4; # OUTPUT: «21»
Here, the 1 + 2 * 3 !! 4 is parsed as 1 + ((2 * 3) !! 4), because the precedence of the new !! operator is between that of + and *.
The same effect could have been achieved with:
sub infix:<!!>($a, $b) is looser(&infix:<*>) { ... }
To put a new operator on the same precedence level as an existing operator, use is equiv(&other-operator) instead.
When the same operator appears several times in a row, there are multiple possible interpretations. For example:
1 + 2 + 3
could be parsed as
(1 + 2) + 3 # left associative
or as
1 + (2 + 3) # right associative
For addition of real numbers, the distinction is somewhat moot, because + is mathematically associative.
But for other operators it matters a great deal. For example, for the exponentiation/power operator, infix:<**>:
say 2 ** (2 ** 3); # OUTPUT: «256» say (2 ** 2) ** 3; # OUTPUT: «64»
Perl 6 has the following possible associativity configurations:
A | Assoc | Meaning of $a ! $b ! $c |
---|---|---|
L | left | ($a ! $b) ! $c |
R | right | $a ! ($b ! $c) |
N | non | ILLEGAL |
C | chain | ($a ! $b) and ($b ! $c) |
X | list | infix:<!>($a; $b; $c) |
You can specify the associativity of an operator with the is assoc trait, where left is the default associativity.
sub infix:<§>(*@a) is assoc<list> { '(' ~ @a.join('|') ~ ')'; } say 1 § 2 § 3; # OUTPUT: «(1|2|3)»
Traits are subroutines that run at compile time and modify the behavior of a type, variable, routine, attribute, or other language object.
Examples of traits are:
class ChildClass is ParentClass { ... } # ^^ trait, with argument ParentClass has $.attrib is rw; # ^^^^^ trait with name 'rw' class SomeClass does AnotherRole { ... } # ^^^^ trait has $!another-attribute handles <close>; # ^^^^^^^ trait
... and also is tighter, is looser, is equiv and is assoc from the previous section.
Traits are subs declared in the form trait_mod<VERB>, where VERB stands for the name like is, does or handles. It receives the modified thing as argument, and the name as a named argument. See Sub for details.
multi sub trait_mod:<is>(Routine $r, :$doubles!) { $r.wrap({ 2 * callsame; }); } sub square($x) is doubles { $x * $x; } say square 3; # OUTPUT: «18»
See type Routine for the documentation of built-in routine traits.
There are cases in which a routine might want to call the next method from a chain. This chain could be a list of parent classes in a class hierarchy, or it could be less specific multi candidates from a multi dispatch, or it could be the inner routine from a wrap.
Fortunately, we have a series of re-dispatching tools that help us to make it easy.
callsame calls the next matching candidate with the same arguments that were used for the current candidate and returns that candidate's return value.
proto a(|) {*} multi a(Any $x) { say "Any $x"; return 5; } multi a(Int $x) { say "Int $x"; my $res = callsame; say "Back in Int with $res"; } a 1; # OUTPUT: «Int 1Any 1Back in Int with 5»
callwith calls the next candidate matching the original signature, that is, the next function that could possibly be used with the arguments provided by users and returns that candidate's return value.
proto a(|) {*} multi a(Any $x) { say "Any $x"; return 5; } multi a(Int $x) { say "Int $x"; my $res = callwith($x + 1); say "Back in Int with $res"; } a 1; # OUTPUT: «Int 1Any 2Back in Int with 5»
Here, a 1 calls the most specific Int candidate first, and callwith re-dispatches to the less specific Any candidate. Note that although our parameter $x + 1 is an Int, still we call the next candidate in the chain.
In this case, for example:
proto how-many(|) {*} multi how-many( Associative $a ) { say "Associative $a "; my $calling = callwith( 1 => $a ); return $calling; } multi how-many( Pair $a ) { say "Pair $a "; return "There is $a " } multi how-many( Hash $a ) { say "Hash $a"; return "Hashing $a"; } my $little-piggy = little => 'piggy'; say $little-piggy.^name; # OUTPUT: «Pair» say &how-many.cando( \( $little-piggy )); # OUTPUT: «(sub how-many (Pair $a) { #`(Sub|68970512) ... } sub how-many (Associative $a) { #`(Sub|68970664) ... })» say how-many( $little-piggy ); # OUTPUT: «Pair little piggyThere is little piggy»
the only candidates that take the Pair argument supplied by the user are the two functions defined first. Although a Pair can be easily coerced to a Hash, here is how signatures match:
say :( Pair ) ~~ :( Associative ); # OUTPUT: «True» say :( Pair ) ~~ :( Hash ); # OUTPUT: «False»
The arguments provided by us are a Pair. It does not match a Hash, so the corresponding function is thus not included in the list of candidates, as can be seen by the output of &how-many.cando( \( $little-piggy ));.
nextsame calls the next matching candidate with the same arguments that were used for the current candidate and never returns.
proto a(|) {*} multi a(Any $x) { say "Any $x"; return 5; } multi a(Int $x) { say "Int $x"; nextsame; say "never executed because nextsame doesn't return"; } a 1; # OUTPUT: «Int 1Any 1»
nextwith calls the next matching candidate with arguments provided by users and never returns.
proto a(|) {*} multi a(Any $x) { say "Any $x"; return 5; } multi a(Int $x) { say "Int $x"; nextwith($x + 1); say "never executed because nextsame doesn't return"; } a 1; # OUTPUT: «Int 1Any 2»
samewith calls current candidate again with arguments provided by users and returns return value of the new instance of current candidate.
proto a(|) {*} multi a(Int $x) { return 1 unless $x > 1; return $x * samewith($x-1); } say (a 10); # OUTPUT: «36288002»
Redispatch may be required to call a block that is not the current scope what provides nextsame and friends with the problem to referring to the wrong scope. Use nextcallee to capture the right candidate and call it at the desired time.
proto pick-winner(|) {*} multi pick-winner (Int \s) { my &nextone = nextcallee; Promise.in(π²).then: { nextone s } } multi pick-winner { say "Woot! $^w won" } with pick-winner ^5 .pick -> \result { say "And the winner is..."; await result; } # OUTPUT: # And the winner is... # Woot! 3 won
The Int candidate takes the nextcallee and then fires up a Promise to be executed in parallel, after some timeout, and then returns. We can't use nextsame here, because it'd be trying to nextsame the Promise's block instead of our original routine.
Besides those already mentioned above, re-dispatch is helpful in many more situations. For instance, for dispatching to wrapped routines:
# enable wrapping: use soft; # function to be wrapped: sub square-root($x) { $x.sqrt } &square-root.wrap(sub ($num) { nextsame if $num >= 0; 1i * callwith(abs($num)); }); say square-root(4); # OUTPUT: «2» say square-root(-4); # OUTPUT: «0+2i»
Another use case is to re-dispatch to methods from parent classes.
say Version.new('1.0.2') # OUTPUT: v1.0.2
class LoggedVersion is Version { method new(|c) { note "New version object created with arguments " ~ c.perl; nextsame; } } say LoggedVersion.new('1.0.2'); # OUTPUT: # New version object created with arguments \("1.0.2") # v1.0.2
Coercion types force a specific type for routine arguments while allowing the routine itself to accept a wider input. When invoked, the arguments are narrowed automatically to the stricter type, and therefore within the routine the arguments have always the desired type.
In the case the arguments cannot be converted to the stricter type, a Type Check error is thrown.
sub double(Int(Cool) $x) { 2 * $x } say double '21';# OUTPUT: «42» say double 21; # OUTPUT: «42» say double Any; # Type check failed in binding $x; expected 'Cool' but got 'Any'
In the above example, the Int is the target type to which the argument $x will be coerced, and Cool is the type that the routine accepts as wider input.
If the accepted wider input type is Any, it is possible to abbreviate the coercion Int(Any) by omitting the Any type, thus resulting in Int().
The coercion works by looking for a method with the same name as the target type: if such method is found on the argument, it is invoked to convert the latter to the expected narrow type. From the above, it is clear that it is possible to provide coercion among user types just providing the required methods:
class Bar { has $.msg; } class Foo { has $.msg = "I'm a foo!"; # allows coercion from Foo to Bar method Bar { Bar.new(:msg($.msg ~ ' But I am now Bar.')); } } # wants a Bar, but accepts Any sub print-bar(Bar() $bar) { say $bar.^name; # OUTPUT: «Bar» say $bar.msg; # OUTPUT: «I'm a foo! But I am now Bar.» } print-bar Foo.new;
In the above code, once a Foo instance is passed as argument to print-bar, the Foo.Bar method is called and the result is placed into $bar.
Coercion types are supposed to work wherever types work, but Rakudo currently (2018.05) only implements them in signatures, for both parameters and return types.
Non-parameter coercion types will theoretically be working in 6.2. Updated the reference above to latest version.Coercion also works with return types:
sub are-equal (Int $x, Int $y --> Bool(Int) ) { $x - $y }; for (2,4) X (1,2) -> ($a,$b) { say "Are $a and $b equal? ", are-equal($a, $b); } # OUTPUT: «Are 2 and 1 equal? TrueAre 2 and 2 equal? FalseAre 4 and 1 equal? TrueAre 4 and 2 equal? True»
In this case, we are coercing an Int to a Bool, which is then printed (put into a string context) in the for loop that calls the function.
Declaring a sub MAIN is not compulsory in Perl 6 scripts, but you can provide one to create a command line interface for your script.
Parsing and interpreting text
Grammar is a powerful tool used to destructure text and often to return data structures that have been created by interpreting that text.
For example, Perl 6 is parsed and executed using a Perl 6-style grammar.
An example that's more practical to the common Perl 6 user is the JSON::Tiny module, which can deserialize any valid JSON file; however, the deserializing code is written in less than 100 lines of simple, extensible code.
If you didn't like grammar in school, don't let that scare you off grammars. Grammars allow you to group regexes, just as classes allow you to group methods of regular code.
The main ingredient of grammars is named regexes. While the syntax of Perl 6 Regexes is outside the scope of this document, named regexes have a special syntax, similar to subroutine definitions:
my regex number { \d+ [ \. \d+ ]? }
In this case, we have to specify that the regex is lexically scoped using the my keyword, because named regexes are normally used within grammars.
Being named gives us the advantage of being able to easily reuse the regex elsewhere:
say so "32.51" ~~ &number; # OUTPUT: «True» say so "15 + 4.5" ~~ /<number>\s* '+' \s*<number>/ # OUTPUT: «True»
regex isn't the only declarator for named regexes. In fact, it's the least common. Most of the time, the token or rule declarators are used. These are both ratcheting, which means that the match engine won't back up and try again if it fails to match something. This will usually do what you want, but isn't appropriate for all cases:
my regex works-but-slow { .+ q } my token fails-but-fast { .+ q } my $s = 'Tokens won\'t backtrack, which makes them fail quicker!'; say so $s ~~ &works-but-slow; # OUTPUT: «True» say so $s ~~ &fails-but-fast; # OUTPUT: «False» # the entire string get taken by the .+
Note that non-backtracking works on terms, that is, as the example below, if you have matched something, then you will never backtrack. But when you fail to match, if there is another candidate introduced by | or ||, you will retry to match again.
my token tok-a { .* d }; my token tok-b { .* d | bd }; say so "bd" ~~ &tok-a; # OUTPUT: «False» say so "bd" ~~ &tok-b; # OUTPUT: «True»
The only difference between the token and rule declarators is that the rule declarator causes :sigspace to go into effect for the Regex:
my token non-space-y { 'once' 'upon' 'a' 'time' } my rule space-y { 'once' 'upon' 'a' 'time' } say so 'onceuponatime' ~~ &non-space-y; # OUTPUT: «True» say so 'once upon a time' ~~ &non-space-y; # OUTPUT: «False» say so 'onceuponatime' ~~ &space-y; # OUTPUT: «False» say so 'once upon a time' ~~ &space-y; # OUTPUT: «True»
Grammar is the superclass that classes automatically get when they are declared with the grammar keyword instead of class. Grammars should only be used to parse text; if you wish to extract complex data, you can add actions within the grammar, or an action object is recommended to be used in conjunction with the grammar. If action objects are not used, .parse returns a Match object and sets, by default, the default match object $/, to the same value.
Grammars are composed of rules, tokens and regexes; these are actually methods, since grammars are classes.
These methods can share a name and functionality in common, and thus can use proto.
For instance, if you have a lot of alternations, it may become difficult to produce readable code or subclass your grammar. In the Actions class below, the ternary in method TOP is less than ideal and it becomes even worse the more operations we add:
grammar Calculator { token TOP { [ <add> | <sub> ] } rule add { <num> '+' <num> } rule sub { <num> '-' <num> } token num { \d+ } } class Calculations { method TOP ($/) { make $<add> ?? $<add>.made !! $<sub>.made; } method add ($/) { make [+] $<num>; } method sub ($/) { make [-] $<num>; } } say Calculator.parse('2 + 3', actions => Calculations).made; # OUTPUT: «5»
To make things better, we can use proto regexes that look like :sym<...> adverbs on tokens:
grammar Calculator { token TOP { <calc-op> } proto rule calc-op {*} rule calc-op:sym<add> { <num> '+' <num> } rule calc-op:sym<sub> { <num> '-' <num> } token num { \d+ } } class Calculations { method TOP ($/) { make $<calc-op>.made; } method calc-op:sym<add> ($/) { make [+] $<num>; } method calc-op:sym<sub> ($/) { make [-] $<num>; } } say Calculator.parse('2 + 3', actions => Calculations).made; # OUTPUT: «5»
In this grammar the alternation has now been replaced with <calc-op>, which is essentially the name of a group of values we'll create. We do so by defining a rule prototype with proto rule calc-op. Each of our previous alternations have been replaced by a new rule calc-op definition and the name of the alternation is attached with :sym<> adverb.
In the class that declares actions, we now got rid of the ternary operator and simply take the .made value from the $<calc-op> match object. And the actions for individual alternations now follow the same naming pattern as in the grammar: method calc-op:sym<add> and method calc-op:sym<sub>.
The real beauty of this method can be seen when you subclass the grammar and action classes. Let's say we want to add a multiplication feature to the calculator:
grammar BetterCalculator is Calculator { rule calc-op:sym<mult> { <num> '*' <num> } } class BetterCalculations is Calculations { method calc-op:sym<mult> ($/) { make [*] $<num> } } say BetterCalculator.parse('2 * 3', actions => BetterCalculations).made; # OUTPUT: «6»
All we had to add are an additional rule and action to the calc-op group and the thing works—all thanks to proto regexes.
grammar Foo { token TOP { \d+ } }
The TOP token is the default first token attempted to match when parsing with a grammar. Note that if you're parsing with the .parse method, token TOP is automatically anchored to the start and end of the string. If you don't want to parse the whole string, look up .subparse.
Using rule TOP or regex TOP is also acceptable.
A different token can be chosen to be matched first using the :rule named argument to .parse, .subparse, or .parsefile. These are all Grammar methods.
The default ws matches zero or more whitespace characters, as long as that point is not within a word (in code form, that's regex ws { <!ww> \s* }):
# First <.ws> matches word boundary at the start of the line # and second <.ws> matches the whitespace between 'b' and 'c' say 'ab c' ~~ /<.ws> ab <.ws> c /; # OUTPUT: «「ab c」» # Failed match: there is neither any whitespace nor a word # boundary between 'a' and 'b' say 'ab' ~~ /. <.ws> b/; # OUTPUT: «Nil» # Successful match: there is a word boundary between ')' and 'b' say ')b' ~~ /. <.ws> b/; # OUTPUT: «「)b」»
Please bear in mind that we're preceding ws with a dot to avoid capturing, which we are not interested in. Since in general whitespace is a separator, this is how it's mostly found.
When rule is used instead of token, :sigspace is enabled by default and any whitespace after terms and closing parenthesis/brackets are turned into a non-capturing call to ws, written as <.ws> where . means non-capturing. That is to say:
rule entry { <key> '=' <value> }
Is the same as:
token entry { <key> <.ws> '=' <.ws> <value> <.ws> }
You can also redefine the default ws token:
grammar Foo { rule TOP { \d \d } }.parse: "4 \n\n 5"; # Succeeds grammar Bar { rule TOP { \d \d } token ws { \h* } }.parse: "4 \n\n 5"; # Fails
And even capture it, but you need to use it explicitly:
grammar Foo { rule TOP {\d <ws> \d} }; my $parsed = Foo.parse: "3 3"; say $parsed<ws>; # OUTPUT: «「」»
The <sym> token can be used inside proto regexes to match the string value of the :sym adverb for that particular regex:
grammar Foo { token TOP { <letter>+ } proto token letter {*} token letter:sym<P> { <sym> } token letter:sym<e> { <sym> } token letter:sym<r> { <sym> } token letter:sym<l> { <sym> } token letter:sym<*> { . } }.parse("I ♥ Perl", actions => class { method TOP($/) { make $<letter>.grep(*.<sym>).join } }).made.say; # OUTPUT: «Perl»
This comes in handy when you're already differentiating the proto regexes with the strings you're going to match, as using <sym> token prevents repetition of those strings.
The <?> is the always succeed assertion. When used as a grammar token, it can be used to trigger an Action class method. In the following grammar we look for Arabic digits and define a succ token with the always succeed assertion.
In the action class, we use calls to the succ method to do set up (in this case, we prepare a new element in @!numbers). In the digit method, we use the Arabic digit as an index into a list of Devanagari digits and add it to the last element of @!numbers. Thanks to succ, the last element will always be the number for the currently parsed digit digits.
grammar Digifier { rule TOP { [ <.succ> <digit>+ ]+ } token succ { <?> } token digit { <[0..9]> } } class Devanagari { has @!numbers; method digit ($/) { @!numbers.tail ~= <० १ २ ३ ४ ५ ६ ७ ८ ९>[$/] } method succ ($) { @!numbers.push: '' } method TOP ($/) { make @!numbers[^(*-1)] } } say Digifier.parse('255 435 777', actions => Devanagari.new).made; # OUTPUT: «(२५५ ४३५ ७७७)»
It's fine to use methods instead of rules or tokens in a grammar, as long as they return a Match:
grammar DigitMatcher { method TOP (:$full-unicode) { $full-unicode ?? self.num-full !! self.num-basic; } token num-full { \d+ } token num-basic { <[0..9]>+ } }
The grammar above will attempt different matches depending on the argument provided to the subparse methods:
say +DigitMatcher.subparse: '12७१७९०९', args => \(:full-unicode); # OUTPUT: «12717909» say +DigitMatcher.subparse: '12७१७९०९', args => \(:!full-unicode); # OUTPUT: «12»
Variables can be defined in tokens by prefixing the lines of code defining them with :. Arbitrary code can be embedded anywhere in a token by surrounding it with curly braces. This is useful for keeping state between tokens, which can be used to alter how the grammar will parse text. Using dynamic variables (variables with $*, @*, &*, %* twigils) in tokens cascades down through all tokens defined thereafter within the one where it's defined, avoiding having to pass them from token to token as arguments.
One use for dynamic variables is guards for matches. This example uses guards to explain which regex classes parse whitespace literally:
grammar GrammarAdvice { rule TOP { :my Int $*USE-WS; "use" <type> "for" <significance> "whitespace by default" } token type { | "rules" { $*USE-WS = 1 } | "tokens" { $*USE-WS = 0 } | "regexes" { $*USE-WS = 0 } } token significance { | <?{ $*USE-WS == 1 }> "significant" | <?{ $*USE-WS == 0 }> "insignificant" } }
Here, text such as "use rules for significant whitespace by default" will only match if the state assigned by whether rules, tokens, or regexes are mentioned matches with the correct guard:
say GrammarAdvice.subparse("use rules for significant whitespace by default"); # OUTPUT: «use rules for significant whitespace by default» say GrammarAdvice.subparse("use tokens for insignificant whitespace by default"); # OUTPUT: «use tokens for insignificant whitespace by default» say GrammarAdvice.subparse("use regexes for insignificant whitespace by default"); # OUTPUT: «use regexes for insignificant whitespace by default» say GrammarAdvice.subparse("use regexes for significant whitespace by default") # OUTPUT: #<failed match>
Attributes may be defined in grammars. However, they can only be accessed by methods. Attempting to use them from within a token will throw an exception because tokens are methods of Match, not of the grammar itself. Note that mutating an attribute from within a method called in a token will only modify the attribute for that token's own match object! Grammar attributes can be accessed in the match returned after parsing if made public:
grammar HTTPRequest { has Bool $.invalid; token TOP { <type> <path> 'HTTP/1.1' \r\n [<field> \r\n]+ \r\n $<body>=.* } token type { | GET | POST | OPTIONS | HEAD | PUT | DELETE | TRACE | CONNECT | \S+ <.error> } token path { | '/' [[\w+]+ % \/] [\.\w+]? | '*' | \S+ <.error> } token field { | $<name>=\w+ : $<value>=<-[\r\n]>* | <-[\r\n]>+ <.error> } method error(--> ::?CLASS:D) { $!invalid = True; self; } } my $header = "MEOWS / HTTP/1.1\r\nHost: docs.perl6.org\r\nsup lol\r\n\r\n"; my $/ = HTTPRequest.parse($header); say $<type>.invalid; # OUTPUT: True say $<path>.invalid; # OUTPUT: (Bool) say $<field>».invalid; # OUTPUT: [(Bool) True]
To pass arguments into a grammar, you can use the named argument of :args on any of the parsing methods of grammar. The arguments passed should be in a list.
grammar demonstrate-arguments { rule TOP ($word) { "I like" $word } } # Notice the comma after "sweets" when passed to :args to coerce it to a list say demonstrate-arguments.parse("I like sweets", :args(("sweets",))); # OUTPUT: «「I like sweets」»
Once the arguments are passed in, they can be used in a call to a named regex inside the grammar.
grammar demonstrate-arguments-again { rule TOP ($word) { <phrase-stem><added-word($word)> } rule phrase-stem { "I like" } rule added-word($passed-word) { $passed-word } } say demonstrate-arguments-again.parse("I like vegetables", :args(("vegetables",))); # OUTPUT: 「I like vegetables」» # OUTPUT: «phrase-stem => 「I like 」» # OUTPUT: «added-word => 「vegetables」»
Alternatively, you can initialize dynamic variables and use any arguments that way within the grammar.
grammar demonstrate-arguments-dynamic { rule TOP ($*word, $*extra) { <phrase-stem><added-words> } rule phrase-stem { "I like" } rule added-words { $*word $*extra } } say demonstrate-arguments-dynamic.parse("I like everything else", :args(("everything", "else"))); # OUTPUT: «「I like everything else」» # OUTPUT: «phrase-stem => 「I like 」» # OUTPUT: «added-words => 「everything else」»
A successful grammar match gives you a parse tree of Match objects, and the deeper that match tree gets, and the more branches in the grammar are, the harder it becomes to navigate the match tree to get the information you are actually interested in.
To avoid the need for diving deep into a match tree, you can supply an actions object. After each successful parse of a named rule in your grammar, it tries to call a method of the same name as the grammar rule, giving it the newly created Match object as a positional argument. If no such method exists, it is skipped.
Here is a contrived example of a grammar and actions in action:
grammar TestGrammar { token TOP { \d+ } } class TestActions { method TOP($/) { $/.make(2 + $/); } } my $match = TestGrammar.parse('40', actions => TestActions.new); say $match; # OUTPUT: «「40」» say $match.made; # OUTPUT: «42»
An instance of TestActions is passed as named argument actions to the parse call, and when token TOP has matched successfully, it automatically calls method TOP, passing the match object as an argument.
To make it clear that the argument is a match object, the example uses $/ as a parameter name to the action method, though that's just a handy convention, nothing intrinsic. $match would have worked too. (Though using $/ does give the advantage of providing $<capture> as a shortcut for $/<capture>).
A slightly more involved example follows:
grammar KeyValuePairs { token TOP { [<pair> \n+]* } token ws { \h* } rule pair { <key=.identifier> '=' <value=.identifier> } token identifier { \w+ } } class KeyValuePairsActions { method pair ($/) { $/.make: $<key>.made => $<value>.made } method identifier($/) { # subroutine `make` is the same as calling .make on $/ make ~$/ } method TOP ($match) { # can use any variable name for parameter, not just $/ $match.make: $match<pair>».made } } my $actions = KeyValuePairsActions; my $res = KeyValuePairs.parse(q:to/EOI/, :$actions).made; second=b hits=42 perl=6 EOI for @$res -> $p { say "Key: $p.key()\tValue: $p.value()"; }
This produces the following output:
Key: second Value: b Key: hits Value: 42 Key: perl Value: 6
Rule pair, which parsed a pair separated by an equals sign, aliases the two calls to token identifier to separate capture names to make them available more easily and intuitively. The corresponding action method constructs a Pair object, and uses the .made property of the sub match objects. So it (like the action method TOP too) exploits the fact that action methods for submatches are called before those of the calling/outer regex. So action methods are called in post-order.
The action method TOP simply collects all the objects that were .made by the multiple matches of the pair rule, and returns them in a list.
Also note that KeyValuePairsActions was passed as a type object to method parse, which was possible because none of the action methods use attributes (which would only be available in an instance).
In other cases, action methods might want to keep state in attributes. Then of course you must pass an instance to method parse.
Note that token ws is special: when :sigspace is enabled (and it is when we are using rule), it replaces certain whitespace sequences. This is why the spaces around the equals sign in rule pair work just fine and why the whitespace before closing } does not gobble up the newlines looked for in token TOP.
Working with associative arrays/dictionaries/hashes
The Associative role underlies hashes and maps, as well as other classes such as MixHash. It defines the two types that will be used in associative classes; by default, you can use anything (literally, since any class that subclasses Any can be used) as a key, although it will be coerced to a string, and any object as value. You can access these types using the of and keyof methods.
By default, any object declared with the % sigil will get the Associative role, and will by default behave like a hash, but this role will only provide the two methods above, as well as the default Hash behavior.
say (%).^name ; # OUTPUT: «Hash»
Inversely, you cannot use the % sigil if the Associative role is not mixed in, but since this role does not have any associated properties, you will have to redefine the behavior of the hash subscript operator. In order to do that, there are several functions you will have to override:
class Logger does Associative[Cool,DateTime] { has %.store; method log( Cool $event ) { %.store{ DateTime.new( now ) } = $event; } multi method AT-KEY ( ::?CLASS:D: $key) { my @keys = %.store.keys.grep( /$key/ ); %.store{ @keys }; } multi method EXISTS-KEY (::?CLASS:D: $key) { %.store.keys.grep( /$key/ )??True!!False; } multi method DELETE-KEY (::?CLASS:D: $key) { X::Assignment::RO.new.throw; } multi method ASSIGN-KEY (::?CLASS:D: $key, $new) { X::Assignment::RO.new.throw; } multi method BIND-KEY (::?CLASS:D: $key, \new){ X::Assignment::RO.new.throw; } } say Logger.of; # OUTPUT: «(Cool)» my %logger := Logger.new; say %logger.of; # OUTPUT: «(Cool)» %logger.log( "Stuff" ); %logger.log( "More stuff"); say %logger<2018-05-26>; # OUTPUT: «(More stuff Stuff)» say %logger<2018-04-22>:exists; # OUTPUT: «False»
In this case, we are defining a logger with Associative semantics that will be able to use dates (or a part of them) as keys. Since we are parameterizing Associative to those particular classes, of will return the value type we have used, Cool in this case (we can log lists or strings only). Mixing the Associative role gives it the right to use the % sigil; binding is needed in the definition since %-sigiled variables get by default the Hash type.
This log is going to be append-only, which is why we escape the associative array metaphor to use a log method to add new events to the log. Once they have been added, however, we can retrieve them by date or check if they exist. For the first we have to override the AT-KEY multi method, for the latter EXIST-KEY. In the last two statements, we show how the subscript operation invokes AT-KEY, while the :exists adverb invokes EXISTS-KEY.
We override DELETE-KEY, ASSIGN-KEY and BIND-KEY, but only to throw an exception. Attempting to assign, delete, or bind a value to a key will result in a Cannot modify an immutable Str (value) exception thrown.
Making classes associative provides a very convenient way of using and working with them using hashes; an example can be seen in Cro, which uses it extensively for the convenience of using hashes to define structured requests and express its response.
A Hash is a mutable mapping from keys to values (called dictionary, hash table or map in other programming languages). The values are all scalar containers, which means you can assign to them. Maps are, on the other hand, immutable. Once a key has been paired with a value, this pairing cannot be changed.
Maps and hashes are usually stored in variables with the percent % sigil, which is used to indicate they are Associative.
Hash and map elements are accessed by key via the { } postcircumfix operator:
say %*ENV{'HOME', 'PATH'}.perl; # OUTPUT: «("/home/camelia", "/usr/bin:/sbin:/bin")»
The general Subscript rules apply providing shortcuts for lists of literal strings, with and without interpolation.
my %h = oranges => 'round', bananas => 'bendy'; say %h<oranges bananas>; # OUTPUT: «(round bendy)» my $fruit = 'bananas'; say %h«oranges "$fruit"»; # OUTPUT: «(round bendy)»
You can add new pairs simply by assigning to an unused key:
my %h; %h{'new key'} = 'new value';
Assigning a list of elements to a hash variable first empties the variable, and then iterates the elements of the right-hand side. If an element is a Pair, its key is taken as a new hash key, and its value as the new hash value for that key. Otherwise the value is coerced to Str and used as a hash key, while the next element of the list is taken as the corresponding value.
my %h = 'a', 'b', c => 'd', 'e', 'f';
Same as
my %h = a => 'b', c => 'd', e => 'f';
or
my %h = <a b c d e f>;
or even
my %h = %( a => 'b', c => 'd', e => 'f' );
or
my %h = [ a => 'b', c => 'd', e => 'f' ]; # This format is NOT recommended. # It cannot be a constant and there # will be problems with nested hashes
or
my $h = { a => 'b', c => 'd', e => 'f'};
Please note that curly braces are used only in the case that we are not assigning it to a %-sigiled variable; in case we use it for a %-sigiled variable we will get an Potential difficulties: Useless use of hash composer on right side of hash assignment; did you mean := instead? error. As this error indicates, however, we can use curly braces as long as we use also binding:
my %h := { a => 'b', c => 'd', e => 'f'}; say %h; # OUTPUT: «{a => b, c => d, e => f}»
Nested hashes can also be defined using the same syntax:
my %h = e => f => 'g'; say %h<e><f>; # OUTPUT: «g»
However, what you are defining here is a key pointing to a Pair, which is fine if that is what you want and your nested hash has a single key. But %h<e> will point to a Pair which will have these consequences:
my %h = e => f => 'g'; %h<e><q> = 'k'; # OUTPUT: «PairCannot modify an immutable Str (Nil) in block <unit>»
This, however, will effectively define a nested hash:
my %h = e => { f => 'g' }; say %h<e>.^name; # OUTPUT: «Hash» say %h<e><f>; # OUTPUT: «g»
If a Pair is encountered where a value is expected, it is used as a hash value:
my %h = 'a', 'b' => 'c'; say %h<a>.^name; # OUTPUT: «Pair» say %h<a>.key; # OUTPUT: «b»
If the same key appears more than once, the value associated with its last occurrence is stored in the hash:
my %h = a => 1, a => 2; say %h<a>; # OUTPUT: «2»
To assign a hash to a variable which does not have the % sigil, you may use the %() hash constructor:
my $h = %( a => 1, b => 2 ); say $h.^name; # OUTPUT: «Hash» say $h<a>; # OUTPUT: «1»
If one or more values reference the topic variable, $_, the right-hand side of the assignment will be interpreted as a Block, not a Hash:
my @people = [ %( id => "1A", firstName => "Andy", lastName => "Adams" ), %( id => "2B", firstName => "Beth", lastName => "Burke" ), # ... ]; sub lookup-user (Hash $h) { #`(Do something...) $h } my @names = map { # While this creates a hash: my $query = { name => "$person<firstName> $person<lastName>" }; say $query.^name; # OUTPUT: «Hash» # Doing this will create a Block. Oh no! my $query2 = { name => "$_<firstName> $_<lastName>" }; say $query2.^name; # OUTPUT: «Block» say $query2<name>; # fails CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::AdHoc: Type Block does not support associative indexing.» lookup-user($query); # Type check failed in binding $h; expected Hash but got Block }, @people;
This would have been avoided if you had used the %() hash constructor. Only use curly braces for creating Blocks.
You can assign to multiple keys at the same time with a slice.
my %h; %h<a b c> = 2 xx *; %h.perl.say; # OUTPUT: «{:a(2), :b(2), :c(2)}» my %h; %h<a b c> = ^3; %h.perl.say; # OUTPUT: «{:a(0), :b(1), :c(2)}»
By default keys in { } are forced to strings. To compose a hash with non-string keys, use a colon prefix:
my $when = :{ (now) => "Instant", (DateTime.now) => "DateTime" };
Note that with objects as keys, you often cannot use the <...> construct for key lookup, as it creates only strings and allomorphs. Use the {...} instead:
:{ 0 => 42 }<0>.say; # Int as key, IntStr in lookup; OUTPUT: «(Any)» :{ 0 => 42 }{0}.say; # Int as key, Int in lookup; OUTPUT: «42» :{ '0' => 42 }<0>.say; # Str as key, IntStr in lookup; OUTPUT: «(Any)» :{ '0' => 42 }{'0'}.say; # Str as key, Str in lookup; OUTPUT: «42» :{ <0> => 42 }<0>.say; # IntStr as key, IntStr in lookup; OUTPUT: «42»
Note: Rakudo implementation currently erroneously applies the same rules for :{ } as it does for { } and can construct a Block in certain circumstances. To avoid that, you can instantiate a parameterized Hash directly. Parameterization of %-sigiled variables is also supported:
my Num %foo1 = "0" => 0e0; # Str keys and Num values my %foo2{Int} = 0 => "x"; # Int keys and Any values my Num %foo3{Int} = 0 => 0e0; # Int keys and Num values Hash[Num,Int].new: 0, 0e0; # Int keys and Num values
Now if you want to define a hash to preserve the objects you are using as keys as the exact objects you are providing to the hash to use as keys, then object hashes are what you are looking for.
my %intervals{Instant}; my $first-instant = now; %intervals{ $first-instant } = "Our first milestone."; sleep 1; my $second-instant = now; %intervals{ $second-instant } = "Logging this Instant for spurious raisins."; for %intervals.sort -> (:$key, :$value) { state $last-instant //= $key; say "We noted '$value' at $key, with an interval of {$key - $last-instant}"; $last-instant = $key; }
This example uses an object hash that only accepts keys of type Instant to implement a rudimentary, yet type-safe, logging mechanism. We utilize a named state variable for keeping track of the previous Instant so that we can provide an interval.
The whole point of object hashes is to keep keys as objects-in-themselves. Currently object hashes utilize the WHICH method of an object, which returns a unique identifier for every mutable object. This is the keystone upon which the object identity operator (===) rests. Order and containers really matter here as the order of .keys is undefined and one anonymous list is never === to another.
my %intervals{Instant}; my $first-instant = now; %intervals{ $first-instant } = "Our first milestone."; sleep 1; my $second-instant = now; %intervals{ $second-instant } = "Logging this Instant for spurious raisins."; say ($first-instant, $second-instant) ~~ %intervals.keys; # OUTPUT: «False» say ($first-instant, $second-instant) ~~ %intervals.keys.sort; # OUTPUT: «False» say ($first-instant, $second-instant) === %intervals.keys.sort; # OUTPUT: «False» say $first-instant === %intervals.keys.sort[0]; # OUTPUT: «True»
Since Instant defines its own comparison methods, in our example a sort according to cmp will always provide the earliest instant object as the first element in the List it returns.
If you would like to accept any object whatsoever in your hash, you can use Any!
my %h{Any}; %h{(now)} = "This is an Instant"; %h{(DateTime.now)} = "This is a DateTime, which is not an Instant"; %h{"completely different"} = "Monty Python references are neither DateTimes nor Instants";
There is a more concise syntax which uses binding.
my %h := :{ (now) => "Instant", (DateTime.now) => "DateTime" };
The binding is necessary because an object hash is about very solid, specific objects, which is something that binding is great at keeping track of but about which assignment doesn't concern itself much.
Since 6.d was released, Junction s can also be used as hash keys. The result will also be a Junction of the same type used as key.
my %hash = %( a => 1, b => 2, c=> 3); say %hash{"a"|"c"}; # OUTPUT: «any(1, 3)» say %hash{"b"^"c"}; # OUTPUT: «one(2, 3)» say %hash{"a" & "c"}; # OUTPUT: «all(1, 3)»
If a Junction of any kind is used to define a key, it will have the same effect of defining elements of the Junction as separate keys:
my %hash = %( "a"|"b" => 1, c => 2 ); say %hash{"b"|"c"}; # OUTPUT: «any(1, 2)»
Place a type object in-between the declarator and the name to constrain the type of all values of a Hash.
my Int %h; put %h<Goku> = 900; try { %h<Vegeta> = "string"; CATCH { when X::TypeCheck::Binding { .message.put } } } # OUTPUT: # 9001 # Type check failed in assignment to %h; expected Int but got Str ("string")
You can do the same by a more readable syntax.
my %h of Int; # the same as my Int %h
If you want to constraint the type of all keys of a Hash, add {Type} following the name of variable.
my %h{Int};
Even put these two constraints together.
my %h{Int} of Int; put %h{21} = 42; try { %h{0} = "String"; CATCH { when X::TypeCheck::Binding { .message.put } } } try { %h<string> = 42; CATCH { when X::TypeCheck::Binding { .message.put } } } try { %h<string> = "String"; CATCH { when X::TypeCheck::Binding { .message.put } } } # OUTPUT: # 42 # Type check failed in binding to parameter 'assignval'; expected Int but got Str ("String") # Type check failed in binding to parameter 'key'; expected Int but got Str ("string") # Type check failed in binding to parameter 'key'; expected Int but got Str ("string")
A common idiom for processing the elements in a hash is to loop over the keys and values, for instance,
my %vowels = 'a' => 1, 'e' => 2, 'i' => 3, 'o' => 4, 'u' => 5; for %vowels.kv -> $vowel, $index { "$vowel: $index".say; }
gives output similar to this:
a: 1 e: 2 o: 4 u: 5 i: 3
where we have used the kv method to extract the keys and their respective values from the hash, so that we can pass these values into the loop.
Note that the order of the keys and values printed cannot be relied upon; the elements of a hash are not always stored the same way in memory for different runs of the same program. In fact, since version 2018.05, the order is guaranteed to be different in every invocation. Sometimes one wishes to process the elements sorted on, e.g., the keys of the hash. If one wishes to print the list of vowels in alphabetical order then one would write
my %vowels = 'a' => 1, 'e' => 2, 'i' => 3, 'o' => 4, 'u' => 5; for %vowels.sort(*.key)>>.kv -> ($vowel, $index) { "$vowel: $index".say; }
which prints
a: 1 e: 2 i: 3 o: 4 u: 5
in alphabetical order as desired. To achieve this result, we sorted the hash of vowels by key (%vowels.sort(*.key)) which we then ask for its keys and values by applying the .kv method to each element via the unary >> hyperoperator resulting in a List of key/value lists. To extract the key/value the variables thus need to be wrapped in parentheses.
An alternative solution is to flatten the resulting list. Then the key/value pairs can be accessed in the same way as with plain .kv:
my %vowels = 'a' => 1, 'e' => 2, 'i' => 3, 'o' => 4, 'u' => 5; for %vowels.sort(*.key)>>.kv.flat -> $vowel, $index { "$vowel: $index".say; }
You can also loop over a Hash using destructuring.
There may be times when you would like to modify the values of a hash while iterating over them.
my %answers = illuminatus => 23, hitchhikers => 42; # OUTPUT: «hitchhikers => 42, illuminatus => 23» for %answers.values -> $v { $v += 10 }; # Fails CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::AdHoc: Cannot assign to a readonly variable or a value»
This is traditionally accomplished by sending both the key and the value as follows.
my %answers = illuminatus => 23, hitchhikers => 42; for %answers.kv -> $k,$v { %answers{$k} = $v + 10 };
However, it is possible to leverage the signature of the block in order to specify that you would like read-write access to the values.
my %answers = illuminatus => 23, hitchhikers => 42; for %answers.values -> $v is rw { $v += 10 };
It is not possible directly to do in-place editing of hash keys, even in the case of object hashes; however, a key can be deleted and a new key/value pair added to achieve the same results. For example, given this hash:
my %h = a => 1, b => 2; for %h.keys.sort -> $k { # use sort to ease output comparisons print "$k => {%h{$k}}; "; } say ''; # OUTPUT: «a => 1; b => 2;»
replace key 'b' with 'bb' but retain 'b's value as the new key's value:
for %h.keys -> $k { if $k eq 'b' { my $v = %h{$k}; %h{$k}:delete; %h<bb> = $v; } } for %h.keys.sort -> $k { print "$k => {%h{$k}}; "; } say ''; # OUTPUT: «a => 1; bb => 2;»
Correctly use Perl 6 IO
The vast majority of common IO work is done by the IO::Path type. If you want to read from or write to a file in some form or shape, this is the class you want. It abstracts away the details of filehandles (or "file descriptors") and so you mostly don't even have to think about them.
Behind the scenes, IO::Path works with IO::Handle, a class which you can use directly if you need a bit more control than what IO::Path provides. When working with other processes, e.g. via Proc or Proc::Async types, you'll also be dealing with a subclass of IO::Handle: the IO::Pipe.
Lastly, you have the IO::CatHandle, as well as IO::Spec and its subclasses, that you'll rarely, if ever, use directly. These classes give you advanced features, such as operating on multiple files as one handle, or low-level path manipulations.
Along with all these classes, Perl 6 provides several subroutines that let you indirectly work with these classes. These come in handy if you like functional programming style or in Perl 6 one liners.
While IO::Socket and its subclasses also have to do with Input and Output, this guide does not cover them.
To represent paths as either files or directories, use IO::Path type. The simplest way to obtain an object of that type is to coerce a Str by calling the .IO method on it:
say 'my-file.txt'.IO; # OUTPUT: «"my-file.txt".IO»
It may seem like something is missing here—there is no volume or absolute path involved—but that information is actually present in the object. You can see it by using .perl method:
say 'my-file.txt'.IO.perl; # OUTPUT: «IO::Path.new("my-file.txt", :SPEC(IO::Spec::Unix), :CWD("/home/camelia"))»
The two extra attributes—SPEC and CWD—specify what type of operating system semantics the path should use as well as the "current working directory" for the path, i.e. if it's a relative path, then it's relative to that directory.
This means that regardless of how you made one, an IO::Path object technically always refers to an absolute path. This is why its .absolute and .relative methods return Str objects and they are the correct way to stringify a path.
However, don't be in a rush to stringify anything. Pass paths around as IO::Path objects. All the routines that operate on paths can handle them, so there's no need to convert them.
Let's make some files and write and read data from them! The spurt and slurp routines write and read the data in one chunk respectively. Unless you're working with very large files that are difficult to store entirely in memory all at the same time, these two routines are for you.
"my-file.txt".IO.spurt: "I ♥ Perl!";
The code above creates a file named my-file.txt in the current directory and then writes text I ♥ Perl! into it. If Perl 6 is your first language, celebrate your accomplishment! Try to open the file you created with a text editor to verify what you wrote with your program. If you already know some other language, you may be wondering if this guide missed anything like handling encoding or error conditions.
However, that is all the code you need. The string will be encoded in utf-8 encoding by default and the errors are handled via the Failure mechanism: these are exceptions you can handle using regular conditionals. In this case, we're letting all potential Failures get sunk after the call and so any Exceptions they contain will be thrown.
If you wanted to add more content to the file we created in the previous section, you could note the spurt documentation mentions :append as one of its argument options. However, for finer control, let's get ourselves an IO::Handle to work with:
my $fh = 'my-file.txt'.IO.open: :a; $fh.print: "I count: "; $fh.print: "$_ " for ^10; $fh.close;
The .open method call opens our IO::Path and returns an IO::Handle. We passed :a as argument, to indicate we want to open the file for writing in append mode.
In the next two lines of code, we use the usual .print method on that IO::Handle to print a line with 11 pieces of text (the 'I count: ' string and 10 numbers). Note that, once again, Failure mechanism takes care of all the error checking for us. If the .open fails, it returns a Failure, which will throw when we attempt to call method the .print on it.
Finally, we close the IO::Handle by calling the .close method on it. It is important that you do it, especially in large programs or ones that deal with a lot of files, as many systems have limits to how many files a program can have open at the same time. If you don't close your handles, eventually you'll reach that limit and the .open call will fail. Note that unlike some other languages, Perl 6 does not use reference counting, so the filehandles are NOT closed when the scope they're defined in is left. They will be closed only when they're garbage collected and failing to close the handles may cause your program to reach the file limit before the open handles get a chance to get garbage collected.
We've seen in previous sections that writing stuff to files is a single-line of code in Perl 6. Reading from them, is similarly easy:
say 'my-file.txt'.IO.slurp; # OUTPUT: «I ♥ Perl!» say 'my-file.txt'.IO.slurp: :bin; # OUTPUT: «Buf[uint8]:0x<49 20 e2 99 a5 20 50 65 72 6c 21>»
The .slurp method reads entire contents of the file and returns them as a single Str object, or as a Buf object, if binary mode was requested, by specifying :bin named argument.
Since slurping loads the entire file into memory, it's not ideal for working with huge files.
The IO::Path type offers two other handy methods: .words and .lines that lazily read the file in smaller chunks and return Seq objects that (by default) don't keep already-consumed values around.
Here's an example that finds lines in a text file that mention Perl and prints them out. Despite the file itself being too large to fit into available RAM, the program will not have any issues running, as the contents are processed in small chunks:
.say for '500-PetaByte-File.txt'.IO.lines.grep: *.contains: 'Perl';
Here's another example that prints the first 100 words from a file, without loading it entirely:
.say for '500-PetaByte-File.txt'.IO.words: 100
Note that we did this by passing a limit argument to .words instead of, say, using a list indexing operation. The reason for that is there's still a filehandle in use under the hood, and until you fully consume the returned Seq, the handle will remain open. If nothing references the Seq, eventually the handle will get closed, during a garbage collection run, but in large programs that work with a lot of files, it's best to ensure all the handles get closed right away. So, you should always ensure the Seq from IO::Path's .words and .lines methods is fully reified; and the limit argument is there to help you with that.
Of course, you can read from files using the IO::Handle type, which gives you a lot finer control over what you're doing:
given 'some-file.txt'.IO.open { say .readchars: 8; # OUTPUT: «I ♥ Perl» .seek: 1, SeekFromCurrent; say .readchars: 15; # OUTPUT: «I ♥ Programming» .close }
The IO::Handle gives you .read, .readchars, .get, .getc, .words, .lines, .slurp, .comb, .split, and .Supply methods to read data from it. Plenty of options; and the catch is you need to close the handle when you're done with it.
Unlike some languages, the handle won't get automatically closed when the scope it's defined in is left. Instead, it'll remain open until it's garbage collected. To make the closing business easier, some of the methods let you specify a :close argument, you can also use the will leave trait, or the does auto-close trait provided by the Trait::IO module.
This section describes how NOT to do Perl 6 IO.
You may have heard of $*SPEC and seen some code or books show its usage for splitting and joining path fragments. Some of the routine names it provides may even look familiar to what you've used in other languages.
However, unless you're writing your own IO framework, you almost never need to use $*SPEC directly. $*SPEC provides low-level stuff and its use will not only make your code tough to read, you'll likely introduce security issues (e.g. null characters)!
The IO::Path type is the workhorse of Perl 6 world. It caters to all the path manipulation needs as well as provides shortcut routines that let you avoid dealing with filehandles. Use that instead of the $*SPEC stuff.
Tip: you can join path parts with / and feed them to IO::Path's routines; they'll still do The Right Thing™ with them, regardless of the operating system.
# WRONG!! TOO MUCH WORK! my $fh = open $*SPEC.catpath: '', 'foo/bar', $file; my $data = $fh.slurp; $fh.close;
# RIGHT! Use IO::Path to do all the dirty work my $data = 'foo/bar'.IO.add($file).slurp;
However, it's fine to use it for things not otherwise provided by IO::Path. For example, the .devnull method:
{ temp $*OUT = open :w, $*SPEC.devnull; say "In space no one can hear you scream!"; } say "Hello";
Don't use the .Str method to stringify IO::Path objects, unless you just want to display them somewhere for information purposes or something. The .Str method returns whatever basic path string the IO::Path was instantiated with. It doesn't consider the value of the $.CWD attribute. For example, this code is broken:
my $path = 'foo'.IO; chdir 'bar'; # WRONG!! .Str DOES NOT USE $.CWD! run <tar -cvvf archive.tar>, $path.Str;
The chdir call changed the value of the current directory, but the $path we created is relative to the directory before that change.
However, the IO::Path object does know what directory it's relative to. We just need to use .absolute or .relative to stringify the object. Both routines return a Str object; they only differ in whether the result is an absolute or relative path. So, we can fix our code like this:
my $path = 'foo'.IO; chdir 'bar'; # RIGHT!! .absolute does consider the value of $.CWD! run <tar -cvvf archive.tar>, $path.absolute; # Also good: run <tar -cvvf archive.tar>, $path.relative;
While usually out of view, every IO::Path object, by default, uses the current value of $*CWD to set its $.CWD attribute. This means there are two things to pay attention to.
This code is a mistake:
# WRONG!! my $*CWD = "foo".IO;
The my $*CWD made $*CWD undefined. The .IO coercer then goes ahead and sets the $.CWD attribute of the path it's creating to the stringified version of the undefined $*CWD; an empty string.
The correct way to perform this operation is use temp instead of my. It'll localize the effect of changes to $*CWD, just like my would, but it won't make it undefined, so the .IO coercer will still get the correct old value:
temp $*CWD = "foo".IO;
Better yet, if you want to perform some code in a localized $*CWD, use the indir routine for that purpose.
Positional data constructs
Lists have been a central part of computing since before there were computers, during which time many devils have taken up residence in their details. They were actually one of the hardest parts of Perl 6 to design, but through persistence and patience, Perl 6 has arrived with an elegant system for handling them.
Literal List s are created with commas and semicolons, not with parentheses, so:
1, 2; # This is two-element list our $list = (1, 2); # This is also a List, in parentheses $list = (1; 2); # same List (see below) $list = (1); # This is not a List, just a 1 in parentheses $list = (1,); # This is a one-element List
There is one exception, empty lists are created with just a pair of parentheses:
(); # This is an empty List
(,); # This is a syntax error
Note that hanging commas are just fine as long as the beginning and end of a list are clear, so feel free to use them for easy code editing.
Parentheses can be used to mark the beginning and end of a List, so:
(1, 2), (1, 2); # This is a list of two lists.
Lists of Lists can also be created by combining comma and semicolon. This is also called multi-dimensional syntax, because it is most often used to index multidimensional arrays.
say so (1,2; 3,4) eqv ((1,2), (3,4)); # OUTPUT: «True» say so (1,2; 3,4;) eqv ((1,2), (3,4)); # OUTPUT: «True» say so ("foo";) eqv ("foo") eqv (("foo")); # not a list # OUTPUT: «True»
Unlike a comma, a hanging semicolon does not create a multidimensional list in a literal. However, be aware that this behavior changes in most argument lists, where the exact behavior depends on the function... But will usually be:
say('foo';); # a list with one element and the empty list # OUTPUT: «(foo)()» say(('foo';)); # no list, just the string "foo" # OUTPUT: «foo»
Because the semicolon doubles as a statement terminator it will end a literal list when used at the top level, instead creating a statement list. If you want to create a statement list inside parenthesis, use a sigil before the parenthesis:
say so (42) eqv $(my $a = 42; $a;); # OUTPUT: «True» say so (42,42) eqv (my $a = 42; $a;); # OUTPUT: «True»
Individual elements can be pulled out of a list using a subscript. The first element of a list is at index number zero:
say (1, 2)[0]; # says 1 say (1, 2)[1]; # says 2 say (1, 2)[2]; # says Nil
say (1, 2)[-1]; # Error
say ((<a b>,<c d>),(<e f>,<g h>))[1;0;1]; # says "f"
Variables in Perl 6 whose names bear the @ sigil are expected to contain some sort of list-like object. Of course, other variables may also contain these objects, but @-sigiled variables always do, and are expected to act the part.
By default, when you assign a List to an @-sigiled variable, you create an Array. Those are described below. If instead you want to refer directly to a List object using an @-sigiled variable, you can use binding with := instead.
my @a := 1, 2, 3;
One of the ways @-sigiled variables act like lists is by always supporting positional subscripting. Anything bound to a @-sigiled value must support the Positional role which guarantees that this is going to fail:
my @a := 1; # Type check failed in binding; expected Positional but got Int
To remove all elements from a Positional container assign Empty, the empty list () or a Slip of the empty list to the container.
my @a = 1, 2, 3; @a = (); @a = Empty; @a = |();
All lists may be iterated, which means taking each element from the list in order and stopping after the last element:
for 1, 2, 3 { .say } # OUTPUT: «123»
It is the rule by which the set of parameters passed to an iterator such as for is treated as a single argument, instead of several arguments; that is some-iterator( a, b, c, ...) will always be treated as some-iterator( list-or-array(a, b, c)) and never as (some-iterator(a))(b)..., that is, iterative application of the iterator to the first argument, then the result to the next argument, and so on. In this example
my @list = [ (1, 2, 3), (1, 2, ), [<a b c>, <d e f>], [[1]] ]; for @list -> @element { say "{@element} → {@element.^name}"; for @element -> $sub-element { say $sub-element; } } # OUTPUT #1 2 3 → List #1 #2 #3 #1 2 → List #1 #2 #a b c d e f → Array #(a b c) #(d e f) #1 → Array #1
Since what for receives is a single argument, it will be treated as a list of elements to iterate over. The rule of thumb is that if there's a comma, anything preceding it is an element and the list thus created becomes the single element. That happens in the case of the two arrays separated by a comma which are the third in the Array we are iterating. In general, quoting the article linked above, the single argument rule ... makes for behavior as the programmer would expect.
To test for elements in a List or Array, you can use the "is element of" Set operator.
my @a = <foo bar buzz>; say 'bar' (elem) @a; # OUTPUT: «True» say 'bar' ∈ @a; # same, using unicode version of operator
This is the equivalent of:
'bar' (elem) @a.Set; # convert the array to a Set first
except that, if possible, it won't actually do the conversion.
It basically compares the value with each element in the array using the === infix operator. If you want to use another way to compare values, you probably should use first.
Not all lists are born full of elements. Some only create as many elements as they are asked for. These are called sequences, which are of type Seq. As it so happens, loops return Seqs.
(loop { 42.say })[2] # OUTPUT: «424242»
So, it is fine to have infinite lists in Perl 6, just so long as you never ask them for all their elements. In some cases, you may want to avoid asking them how long they are too – Perl 6 will try to return Inf if it knows a sequence is infinite, but it cannot always know.
These lists can be built using the ... operator, which builds lazy lists using a variety of generating expressions.
Although the Seq class does provide some positional subscripting, it does not provide the full interface of Positional, so an @-sigiled variable may not be bound to a Seq, and trying to do so will yield an error.
my @s := <a b c>.Seq; CATCH { default { say .^name, ' ', .Str } } # OUTPUT «X::TypeCheck::Binding Type check failed in binding; expected Positional but got Seq ($(("a", "b","c").Seq))»
This is because the Seq does not keep values around after you have used them. This is useful behavior if you have a very long sequence, as you may want to throw values away after using them, so that your program does not fill up memory. For example, when processing a file of a million lines:
for 'filename'.IO.lines -> $line { do-something-with($line); }
You can be confident that the entire content of the file will not stay around in memory, unless you are explicitly storing the lines somewhere.
On the other hand, you may want to keep old values around in some cases. It is possible to hide a Seq inside a List, which will still be lazy, but will remember old values. This is done by calling the .list method. Since this List fully supports Positional, you may bind it directly to an @-sigiled variable.
my @s := (loop { 42.say }).list; @s[2]; # says 42 three times @s[1]; # does not say anything @s[4]; # says 42 two more times
You may also use the .cache method instead of .list, depending on how you want the references handled. See the page on Seq for details.
All lists mix in the Iterator role, and as such have an .iterator method they can use for a finer control over a list. We can use it like this, for instance:
my @multiples-of-five = 0,5,10 … 500; my $odd-iterator = @multiples-of-five.iterator; my $odd; repeat { $odd-iterator.skip-one; $odd = $odd-iterator.pull-one; say "→ $odd"; } until $odd.Str eq IterationEnd.Str;
Instead of using the iterator implicitly as we do in for loops, we explicitly assign it to the $odd-iterator variable to work over the odd elements of the sequence only. That way, we can skip even elements using .skip-one. We do have to test explicitly for termination, which we do in the until expression. When there's nothing left to iterate, $odd will have the value IterationEnd. Please check the documentation on Iterator s for the methods and functions that are available.
Sometimes you want to insert the elements of a list into another list. This can be done with a special type of list called a Slip.
say (1, (2, 3), 4) eqv (1, 2, 3, 4); # OUTPUT: «False» say (1, Slip.new(2, 3), 4) eqv (1, 2, 3, 4); # OUTPUT: «True» say (1, slip(2, 3), 4) eqv (1, 2, 3, 4); # OUTPUT: «True»
Another way to make a Slip is with the | prefix operator. Note that this has a tighter precedence than the comma, so it only affects a single value, but unlike the above options, it will break Scalars.
say (1, |(2, 3), 4) eqv (1, 2, 3, 4); # OUTPUT: «True» say (1, |$(2, 3), 4) eqv (1, 2, 3, 4); # OUTPUT: «True» say (1, slip($(2, 3)), 4) eqv (1, 2, 3, 4); # OUTPUT: «False»
Lists, Seqs, Arrays and any other class that implements the Iterator role can be lazy, which means that their values are computed on demand and stored for later use. One of the ways to create a lazy object is to use gather/take or the sequence operator. You can also write a class that implements the role Iterator and returns True on a call to is-lazy. Please note that some methods like elems cannot be called on a lazy List and will result in a thrown Exception.
# This array is lazy and its elements will not be available # until explicitly requested. my @lazy-array = lazy 1, 11, 121 ... 10**100; say @lazy-array.is-lazy; # OUTPUT: «True» say @lazy-array[]; # OUTPUT: «[...]» # Once all elements have been retrieved, the list # is no longer considered lazy. my @no-longer-lazy = eager @lazy-array; # Forcing eager evaluation say @no-longer-lazy.is-lazy; # OUTPUT: «False» say @no-longer-lazy[]; # OUTPUT: (sequence starting with «[1 11 121» ending with a 300 digit number)
In the example above, @lazy-array is an Array which, through construction, is made lazy. Calling is-lazy on it actually calls the method mixed in by the role Iterator, which, since it originates in a lazy list, is itself lazy.
A common use case for lazy Seqs is the processing of infinite sequences of numbers, whose values have not been computed yet and cannot be computed in their entirety. Specific values in the List will only be computed when they are needed.
my $l := 1, 2, 4, 8 ... Inf; say $l[0..16]; #OUTPUT: «(1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536)»
You can easily assign lazy objects to other objects, conserving their laziness:
my $l := 1, 2, 4, 8 ... Inf; # This is a lazy Seq. my @lazy-array = $l; say @lazy-array[10..15]; # OUTPUT: «(1024 2048 4096 8192 16384 32768)» say @lazy-array.is-lazy; # OUTPUT: «True»
The lists we have talked about so far (List, Seq and Slip) are all immutable. This means you cannot remove elements from them, or re-bind existing elements:
(1, 2, 3)[0]:delete; # Error Can not remove elements from a List (1, 2, 3)[0] := 0; # Error Cannot use bind operator with this left-hand side (1, 2, 3)[0] = 0; # Error Cannot modify an immutable Int
However, if any of the elements is wrapped in a Scalar you can still change the value which that Scalar points to:
my $a = 2; (1, $a, 3)[1] = 42; $a.say; # OUTPUT: «42»
that is, it is only the list structure itself – how many elements there are and each element's identity – that is immutable. The immutability is not contagious past the identity of the element.
So far we have mostly dealt with lists in neutral contexts. Lists are actually very context sensitive on a syntactical level.
When a list (or something that is going to be converted into a list) appears on the right-hand side of an assignment into a @-sigiled variable, it is "eagerly" evaluated. This means that a Seq will be iterated until it can produce no more elements, for instance. This is one of the places you do not want to put an infinite list, lest your program hang and, eventually, run out of memory:
my @divisors = (gather { for <2 3 5 7> { take $_ if 70 %% $_; } }); say @divisors; # OUTPUT: «[2 5 7]»
The gather statement creates a lazy list, which is eagerly evaluated when assigned to @divisors.
When you have a list that contains sub-lists, but you only want one flat list, you may flatten the list to produce a sequence of values as if all parentheses were removed. This works no matter how many levels deep the parentheses are nested.
say (1, (2, (3, 4)), 5).flat eqv (1, 2, 3, 4, 5) # OUTPUT: «True»
This is not really a syntactical "context" as much as it is a process of iteration, but it has the appearance of a context.
Note that Scalar s around a list will make it immune to flattening:
for (1, (2, $(3, 4)), 5).flat { .say } # OUTPUT: «12(3 4)5»
...but an @-sigiled variable will spill its elements.
my @l := 2, (3, 4); for (1, @l, 5).flat { .say }; # OUTPUT: «12345» my @a = 2, (3, 4); # Arrays are special, see below for (1, @a, 5).flat { .say }; # OUTPUT: «12(3 4)5»
When a list appears as arguments to a function or method call, special syntax rules are at play: the list is immediately converted into a Capture. A Capture itself has a List (.list) and a Hash (.hash). Any Pair literals whose keys are not quoted, or which are not parenthesized, never make it into .list. Instead, they are considered to be named arguments and squashed into .hash. See the page on Capture for the details of this processing.
Consider the following ways to make a new Array from a List. These ways place the List in an argument list context and because of that, the Array only contains 1 and 2 but not the Pair :c(3), which is ignored.
Array.new(1, 2, :c(3)); Array.new: 1, 2, :c(3); new Array: 1, 2, :c(3);
In contrast, these ways do not place the List in argument list context, so all the elements, even the Pair :c(3), are placed in the Array.
Array.new((1, 2, :c(3))); (1, 2, :c(3)).Array; my @a = 1, 2, :c(3); Array.new(@a); my @a = 1, 2, :c(3); Array.new: @a; my @a = 1, 2, :c(3); new Array: @a;
In argument list context the | prefix operator applied to a Positional will always slip list elements as positional arguments to the Capture, while a | prefix operator applied to an Associative will slip pairs in as named parameters:
my @a := 2, "c" => 3; Array.new(1, |@a, 4); # Array contains 1, 2, :c(3), 4 my %a = "c" => 3; Array.new(1, |%a, 4); # Array contains 1, 4
From the perspective of the List inside a slice subscript, is only remarkable in that it is unremarkable: because adverbs to a slice are attached after the ], the inside of a slice is not an argument list, and no special processing of pair forms happens.
Most Positional types will enforce an integer coercion on each element of a slice index, so pairs appearing there will generate an error, anyway:
(1, 2, 3)[1, 2, :c(3)] # OUTPUT: «Method 'Int' not found for invocant of class 'Pair'»
...however this is entirely up to the type – if it defines an order for pairs, it could consider :c(3) a valid index.
Indices inside a slice are usually not automatically flattened, but neither are sublists usually coerced to Int. Instead, the list structure is kept intact, causing a nested slice operation that replicates the structure in the result:
say ("a", "b", "c")[(1, 2), (0, 1)] eqv (("b", "c"), ("a", "b")) # OUTPUT: «True»
Slices can be taken also across several dimensions using semilists, which are lists of slices separated by semicolons:
my @sliceable = [[ ^10 ], ['a'..'h'], ['Ⅰ'..'Ⅺ']]; say @sliceable[ ^3; 4..6 ]; #OUTPUT: «(4 5 6 e f g Ⅴ Ⅵ Ⅶ)»
which is selecting the 4 to 6th element from the three first dimensions (^3).
A Range is a container for a lower and an upper boundary, either of which may be excluded. Generating a slice with a Range will include any index between the bounds, though an infinite Range will truncate non-existent elements. An infinite range with excluded upper boundary (e.g. 0..^Inf) is still infinite and will reach all elements.
my @a = 1..5; say @a[0..2]; # OUTPUT: «(1 2 3)» say @a[0..^2]; # OUTPUT: «(1 2)» say @a[0..*]; # OUTPUT: «(1 2 3 4 5)» say @a[0..^*]; # OUTPUT: «(1 2 3 4 5)» say @a[0..Inf-1]; # OUTPUT: «(1 2 3 4 5)»
Note that when the upper boundary is a WhateverCode instead of just a Whatever, the range is not infinite but becomes a Callable producing Ranges. This is normal behavior of the .. operator. The subscript operator [] evaluates the WhateverCode providing the list's .elems as an argument and uses the resulting range to slice:
say @a[0..*-1]; # OUTPUT: «(1 2 3 4 5)» say @a[0..^*-1]; # OUTPUT: «(1 2 3 4)» # Produces 0..^2.5 as the slice range say @a[0..^*/2]; # OUTPUT: «(1 2 3)»
Notice that 0..^* and 0..^*+0 behave consistently in subscripts despite one being an infinite range and the other a WhateverCode producing ranges, but 0..*+0 will give you an additional trailing Nil because, unlike the infinite range 0..*, it does not truncate.
Inside an Array Literal, the list of initialization values is not in capture context and is just a normal list. It is, however, eagerly evaluated just as in assignment.
say so [ 1, 2, :c(3) ] eqv Array.new((1, 2, :c(3))); # OUTPUT: «True» [while $++ < 2 { 42.say; 43 }].map: *.say; # OUTPUT: «42424343» (while $++ < 2 { 42.say; 43 }).map: *.say; # OUTPUT: «42434243»
Which brings us to Arrays...
Arrays differ from lists in three major ways: Their elements may be typed, they automatically itemize their elements, and they are mutable. Otherwise they are Lists and are accepted wherever lists are.
say Array ~~ List # OUTPUT: «True»
A fourth, more subtle, way they differ is that when working with Arrays, it can sometimes be harder to maintain laziness or work with infinite sequences.
Arrays may be typed such that their slots perform a typecheck whenever they are assigned to. An Array that only allows Int values to be assigned is of type Array[Int] and one can create one with Array[Int].new. If you intend to use an @-sigiled variable only for this purpose, you may change its type by specifying the type of the elements when declaring it:
my Int @a = 1, 2, 3; # An Array that contains only Ints # the same as my @a of Int = 1, 2, 3; # An Array of Ints my @b := Array[Int].new(1, 2, 3); # Same thing, but the variable is not typed my @b := Array[Int](1, 2, 3); # Rakudo shortcut for the same code say @b eqv @a; # says True. my @c = 1, 2, 3; # An Array that can contain anything say @b eqv @c; # says False because types do not match say @c eqv (1, 2, 3); # says False because one is a List say @b eq @c; # says True, because eq only checks values say @b eq (1, 2, 3); # says True, because eq only checks values @a[0] = 42; # fine @a[0] = "foo"; # error: Type check failed in assignment
In the above example we bound a typed Array object to a @-sigil variable for which no type had been specified. The other way around does not work – you may not bind an Array that has the wrong type to a typed @-sigiled variable:
my @a := Array[Int].new(1, 2, 3); # fine @a := Array[Str].new("a", "b"); # fine, can be re-bound my Int @b := Array[Int].new(1, 2, 3); # fine @b := Array.new(1, 2, 3); # error: Type check failed in binding
When working with typed arrays, it is important to remember that they are nominally typed. This means the declared type of an array is what matters. Given the following sub declaration:
sub mean(Int @a) { @a.sum / @a.elems }
Calls that pass an Array[Int] will be successful:
my Int @b = 1, 3, 5; say mean(@b); # @b is Array[Int] say mean(Array[Int].new(1, 3, 5)); # Anonymous Array[Int] say mean(my Int @ = 1, 3, 5); # Another anonymous Array[Int]
However, the following calls will all fail, due to passing an untyped array, even if the array just happens to contain Int values at the point it is passed:
my @c = 1, 3, 5; say mean(@c); # Fails, passing untyped Array say mean([1, 3, 5]); # Same say mean(Array.new(1, 3, 5)); # Same again
Note that in any given compiler, there may be fancy, under-the-hood, ways to bypass the type check on arrays, so when handling untrusted input, it can be good practice to perform additional type checks, where it matters:
for @a -> Int $i { $_++.say };
However, as long as you stick to normal assignment operations inside a trusted area of code, this will not be a problem, and typecheck errors will happen promptly during assignment to the array, if they cannot be caught at compile time. None of the core functions provided in Perl 6 for operating on lists should ever produce a wonky typed Array.
Nonexistent elements (when indexed), or elements to which Nil has been assigned, will assume a default value. This default may be adjusted on a variable-by-variable basis with the is default trait. Note that an untyped @-sigiled variable has an element type of Mu, however its default value is an undefined Any:
my @a; @a.of.perl.say; # OUTPUT: «Mu» @a.default.perl.say; # OUTPUT: «Any» @a[0].say; # OUTPUT: «(Any)» my Numeric @n is default(Real); @n.of.perl.say; # OUTPUT: «Numeric» @n.default.perl.say; # OUTPUT: «Real» @n[0].say; # OUTPUT: «(Real)»
To limit the dimensions of an Array, provide the dimensions separated by , or ; in square brackets after the name of the array container in case there is more than one dimension; these are called shaped arrays too. The values of such a kind of Array will default to Any. The shape can be accessed at runtime via the shape method.
my @a[2,2]; say @a.perl; # OUTPUT: «Array.new(:shape(2, 2), [Any, Any], [Any, Any])» say @a.shape; # OUTPUT: «(2 2)» my @just-three[3] = <alpha beta kappa>; say @just-three.perl; # OUTPUT: «Array.new(:shape(3,), ["alpha", "beta", "kappa"])»
Shape will control the amount of elements that can be assigned by dimension:
my @just-two[2] = <alpha beta kappa>; # Will throw exception: «Index 2 for dimension 1 out of range (must be 0..1)»
Assignment to a fixed size Array will promote a List of Lists to an Array of Arrays (making then mutable in the process).
my @a[2;2] = (1,2; 3,4); say @a.Array; # OUTPUT: «[1 2 3 4]» @a[1;1] = 42; say @a.perl; # OUTPUT: «Array.new(:shape(2, 2), [1, 2], [3, 42])»
As the third statement shows, you can assign directly to an element in a shaped array too. Note: the second statement works only from version 2018.09.
For most uses, Arrays consist of a number of slots each containing a Scalar of the correct type. Every such Scalar, in turn, contains a value of that type. Perl 6 will automatically type-check values and create Scalars to contain them when Arrays are initialized, assigned to, or constructed.
This is actually one of the trickiest parts of Perl 6 list handling to get a firm understanding of.
First, be aware that because itemization in Arrays is assumed, it essentially means that $(…)s are being put around everything that you assign to an array, if you do not put them there yourself. On the other side, Array.perl does not put $ to explicitly show scalars, unlike List.perl:
((1, 2), $(3, 4)).perl.say; # says "((1, 2), $(3, 4))" [(1, 2), $(3, 4)].perl.say; # says "[(1, 2), (3, 4)]" # ...but actually means: "[$(1, 2), $(3, 4)]"
It was decided all those extra dollar signs and parentheses were more of an eye sore than a benefit to the user. Basically, when you see a square bracket, remember the invisible dollar signs.
Second, remember that these invisible dollar signs also protect against flattening, so you cannot really flatten the elements inside of an Array with a normal call to flat or .flat.
((1, 2), $(3, 4)).flat.perl.say; # OUTPUT: «(1, 2, $(3, 4)).Seq» [(1, 2), $(3, 4)].flat.perl.say; # OUTPUT: «($(1, 2), $(3, 4)).Seq»
Since the square brackets do not themselves protect against flattening, you can still spill the elements out of an Array into a surrounding list using flat.
(0, [(1, 2), $(3, 4)], 5).flat.perl.say; # OUTPUT: «(0, $(1, 2), $(3, 4), 5).Seq»
...the elements themselves, however, stay in one piece.
This can irk users of data you provide if you have deeply nested Arrays where they want flat data. Currently they have to deeply map the structure by hand to undo the nesting:
say gather [0, [(1, 2), [3, 4]], $(5, 6)].deepmap: *.take; # OUTPUT: «(1 2 3 4 5 6)»
... Future versions of Perl 6 might find a way to make this easier. However, not returning Arrays or itemized lists from functions, when non-itemized lists are sufficient, is something that one should consider as a courtesy to their users:
Use Slips when you want to always merge with surrounding lists.
Use non-itemized lists when you want to make it easy for the user to flatten.
Use itemized lists to protect things the user probably will not want flattened.
Use Arrays as non-itemized lists of itemized lists, if appropriate.
Use Arrays if the user is going to want to mutate the result without copying it first.
The fact that all elements of an array are itemized (in Scalar containers) is more a gentleman's agreement than a universally enforced rule, and it is less well enforced that typechecks in typed arrays. See the section below on binding to Array slots.
Literal Arrays are constructed with a List inside square brackets. The List is eagerly iterated (at compile time if possible) and values in it are each type-checked and itemized. The square brackets themselves will spill elements into surrounding lists when flattened, but the elements themselves will not spill due to the itemization.
Unlike lists, Arrays are mutable. Elements may deleted, added, or changed.
my @a = "a", "b", "c"; @a.say; # OUTPUT: «[a b c]» @a.pop.say; # OUTPUT: «c» @a.say; # OUTPUT: «[a b]» @a.push("d"); @a.say; # OUTPUT: «[a b d]» @a[1, 3] = "c", "c"; @a.say; # OUTPUT: «[a c d c]»
Assignment of a list to an Array is eager. The list will be entirely evaluated, and should not be infinite or the program may hang. Assignment to a slice of an Array is, likewise, eager, but only up to the requested number of elements, which may be finite:
my @a; @a[0, 1, 2] = (loop { 42 }); @a.say; # OUTPUT: «[42 42 42]»
During assignment, each value will be typechecked to ensure it is a permitted type for the Array. Any Scalar will be stripped from each value and a new Scalar will be wrapped around it.
Individual Array slots may be bound the same way $-sigiled variables are:
my $b = "foo"; my @a = 1, 2, 3; @a[2] := $b; @a.say; # OUTPUT: «[1 2 "foo"]» $b = "bar"; @a.say; # OUTPUT: «[1 2 "bar"]»
... But binding Array slots directly to values is strongly discouraged. If you do, expect surprises with built-in functions. The only time this would be done is if a mutable container that knows the difference between values and Scalar-wrapped values is needed, or for very large Arrays where a native-typed array cannot be used. Such a creature should never be passed back to unsuspecting users.
Introspection and the Perl 6 object system
Perl 6 is built on a meta object layer. That means that there are objects (the meta objects) that control how various object-oriented constructs (such as classes, roles, methods, attributes or enums) behave.
The meta object has a practical benefit to the user when a normal object's type is needed. For example:
my $arr = [1, 2]; sub show-type($arr) { my $type = $arr.^name; say $type; } show-type $arr; # OUTPUT: «Array»
To get a more in-depth understanding of the meta object for a class, here is an example repeated twice: once as normal declarations in Perl 6, and once expressed through the meta model:
class A { method x() { say 42 } } A.x();
corresponds to:
constant A := Metamodel::ClassHOW.new_type( name => 'A' ); # class A { A.^add_method('x', my method x(A:) { say 42 }); # method x() A.^compose; # } A.x();
(except that the declarative form is executed at compile time, and the latter form does not).
The meta object behind an object can be obtained with $obj.HOW, where HOW stands for Higher Order Workings (or, HOW the *%@$ does this work?).
Here, the calls with .^ are calls to the meta object, so A.^compose is a shortcut for A.HOW.compose(A). The invocant is passed in the parameter list as well, to make it possible to support prototype-style type systems, where there is just one meta object (and not one meta object per type, as standard Perl 6 does it).
As the example above demonstrates, all object oriented features are available to the user, not just to the compiler. In fact the compiler just uses such calls to meta objects.
These are introspective macros that resemble method calls.
Metamethods are generally named with ALLCAPS, and it is considered good style to avoid creating your own methods with ALLCAPS names. This will avoid conflicts with any metamethods that may appear in future versions of the language.
The type object of the type. This is a pseudo-method that can be overloaded without producing error or warning, but will be ignored.
For example 42.WHAT returns the Int type object.
The object's identity value. This can be used for hashing and identity comparison, and is how the === infix operator is implemented.
The package supporting the object.
The memory address of the object. Note that this is not stable in implementations with moving/compacting garbage collectors. Use WHICH for a stable identity indicator.
Returns the metaclass object, as in "Higher Order Workings".
say (%).HOW.^name # OUTPUT: «Perl6::Metamodel::ClassHOW+{<anon>}»
HOW returns an object of type Perl6::Metamodel::ClassHOW in this case; objects of this type are used to build classes. The same operation on the & sigil will return Perl6::Metamodel::ParametricRoleGroupHOW. You will be calling this object whenever you use the ^ syntax to access meta methods. In fact, the code above is equivalent to say (&).HOW.HOW.name(&) which is much more unwieldy. Metamodel::ClassHOW is part of the Rakudo implementation, so use with caution.
The attached Pod value.
The object has a valid concrete representation. This is a pseudo-method that can be overloaded without producing error or warning, but will be ignored.
Returns True for instances and False for type objects.
Returns the underlying Scalar object, if there is one.
The presence of a Scalar object indicates that the object is "itemized".
.say for (1, 2, 3); # OUTPUT: «123», not itemized .say for $(1, 2, 3); # OUTPUT: «(1 2 3)», itemized say (1, 2, 3).VAR ~~ Scalar; # OUTPUT: «False» say $(1, 2, 3).VAR ~~ Scalar; # OUTPUT: «True»
Note: this documentation largely reflects the meta object system as implemented by the Rakudo Perl 6 compiler, since the design documents are very light on details.
For each type declarator keyword, such as class, role, enum, module, package, grammar or subset, there is a separate meta class in the Metamodel:: namespace. (Rakudo implements them in the Perl6::Metamodel:: namespace, and then maps Perl6::Metamodel to Metamodel).
Many of the these meta classes share common functionality. For example roles, grammars and classes can all contain methods and attributes, as well as being able to do roles. This shared functionality is implemented in roles which are composed into the appropriate meta classes. For example role Metamodel::RoleContainer implements the functionality that a type can hold roles and Metamodel::ClassHOW, which is the meta class behind the class keyword, does this role.
Most meta classes have a compose method that you must call when you're done creating or modifying a meta object. It creates method caches, validates things and so on, and weird behavior ensues if you forget to call it, so don't :-).
You might wonder how Metamodel::ClassHOW can be a class, when being a class is defined in terms of Metamodel::ClassHOW, or how the roles responsible for role handling can be roles. The answer is by magic.
Just kidding. Bootstrapping is implementation specific. Rakudo does it by using the object system of the language in which itself is implemented, which happens to be (nearly) a subset of Perl 6: NQP, Not Quite Perl. NQP has a primitive, class-like kind called knowhow, which is used to bootstrap its own classes and roles implementation. knowhow is built on primitives that the virtual machine under NQP provides.
Since the object model is bootstrapped in terms of lower-level types, introspection can sometimes return low-level types instead of the ones you expect, like an NQP-level routine instead of a normal Routine object, or a bootstrap-attribute instead of Attribute.
In Perl 6, a type is constructed as it is parsed, so in the beginning, it must be mutable. However if all types were always mutable, all reasoning about them would get invalidated at any modification of a type. For example the list of parent types and thus the result of type checking can change during that time.
So to get the best of both worlds, there is a time when a type transitions from mutable to immutable. This is called composition, and for syntactically declared types, it happens when the type declaration is fully parsed (so usually when the closing curly brace is parsed).
If you create types through the meta-object system directly, you must call .^compose on them before they become fully functional.
Most meta classes also use composition time to calculate some properties like the method resolution order, publish a method cache, and other house-keeping tasks. Meddling with types after they have been composed is sometimes possible, but usually a recipe for disaster. Don't do it.
The meta object protocol offers much power that regular Perl 6 code intentionally limits, such as calling private methods on classes that don't trust you, peeking into private attributes, and other things that usually simply aren't done.
Regular Perl 6 code has many safety checks in place; not so the meta model. It is close to the underlying virtual machine, and violating the contracts with the VM can lead to all sorts of strange behaviors that, in normal code, would obviously be bugs.
So be extra careful and thoughtful when writing meta types.
The meta object protocol is designed to be powerful enough to implement the Perl 6 object system. This power occasionally comes at the cost of convenience.
For example, when you write my $x = 42 and then proceed to call methods on $x, most of these methods end up acting on the integer 42, not on the scalar container in which it is stored. This is a piece of convenience found in ordinary Perl 6. Many parts of the meta object protocol cannot afford to offer the convenience of automatically ignoring scalar containers, because they are used to implement those scalar containers as well. So if you write my $t = MyType; ... ; $t.^compose you are composing the Scalar that the $-sigiled variable implies, not MyType.
The consequence is that you need to have a rather detailed understanding of the subtleties of Perl 6 in order to avoid pitfalls when working with the MOP, and can't expect the same "do what I mean" convenience that ordinary Perl 6 code offers.
Call into dynamic libraries that follow the C calling convention
The simplest imaginable use of NativeCall would look something like this:
use NativeCall; sub some_argless_function() is native('something') { * } some_argless_function();
The first line imports various traits and types. The next line looks like a relatively ordinary Perl 6 sub declaration—with a twist. We use the "native" trait in order to specify that the sub is actually defined in a native library. The platform-specific extension (e.g., .so or .dll), as well as any customary prefixes (e.g., 'lib') will be added for you.
The first time you call "some_argless_function", the "libsomething" will be loaded and the "some_argless_function" will be located in it. A call will then be made. Subsequent calls will be faster, since the symbol handle is retained.
Of course, most functions take arguments or return values—but everything else that you can do is just adding to this simple pattern of declaring a Perl 6 sub, naming it after the symbol you want to call and marking it with the "native" trait.
You will also need to declare and use native types. Please check the native types page for more information.
Sometimes you want the name of your Perl subroutine to be different from the name used in the library you're loading. Maybe the name is long or has different casing or is otherwise cumbersome within the context of the module you are trying to create.
NativeCall provides a symbol trait for you to specify the name of the native routine in your library that may be different from your Perl subroutine name.
unit module Foo; use NativeCall; our sub init() is native('foo') is symbol('FOO_INIT') { * }
Inside of libfoo there is a routine called FOO_INIT but, since we're creating a module called Foo and we'd rather call the routine as Foo::init, we use the symbol trait to specify the name of the symbol in libfoo and call the subroutine whatever we want ("init" in this case).
Normal Perl 6 signatures and the returns trait are used in order to convey the type of arguments a native function expects and what it returns. Here is an example.
use NativeCall; sub add(int32, int32) returns int32 is native("calculator") { * }
Here, we have declared that the function takes two 32-bit integers and returns a 32-bit integer. You can find the other types that you may pass in the native types page. Note that the lack of a returns trait is used to indicate void return type. Do not use the void type anywhere except in the Pointer parameterization.
For strings, there is an additional encoded trait to give some extra hints on how to do the marshaling.
use NativeCall; sub message_box(Str is encoded('utf8')) is native('gui') { * }
To specify how to marshal string return types, just apply this trait to the routine itself.
use NativeCall; sub input_box() returns Str is encoded('utf8') is native('gui') { * }
Note that a NULL string pointer can be passed by passing the Str type object; a NULL return will also be represented by the type object.
If the C function requires the lifetime of a string to exceed the function call, the argument must be manually encoded and passed as CArray[uint8]:
use NativeCall; # C prototype is void set_foo(const char *) sub set_foo(CArray[uint8]) is native('foo') { * } # C prototype is void use_foo(void) sub use_foo() is native('foo') { * } # will use pointer stored by set_foo() my $string = "FOO"; # The lifetime of this variable must be equal to the required lifetime of # the data passed to the C function. my $array = CArray[uint8].new($string.encode.list); set_foo($array); # ... use_foo(); # It's fine if $array goes out of scope starting from here.
When working with native functions, sometimes you need to specify what kind of native data structure is going to be used. is repr is the term employed for that.
use NativeCall; class timespec is repr('CStruct') { has uint32 $.tv_sec; has long $.tv_nanosecs; } sub clock_gettime(uint32 $clock-id, timespec $tspec --> uint32) is native { * }; my timespec $this-time .=new; my $result = clock_gettime( 0, $this-time); say "$result, $this-time"; # OUTPUT: «0, timespec<65385480>»
The original function we are calling, clock_gettime, uses a pointer to the timespec struct as second argument. We declare it as a class here, but specify its representation as is repr('CStruct'), to indicate it corresponds to a C data structure. When we create an object of that class, we are creating exactly the kind of pointer clock_gettime expects. This way, data can be transferred seamlessly to and from the native interface.
When the signature of your native function needs a pointer to some native type (int32, uint32, etc.) all you need to do is declare the argument is rw :
use NativeCall; # C prototype is void my_version(int *major, int *minor) sub my_version(int32 is rw, int32 is rw) is native('foo') { * } my_version(my int32 $major, my int32 $minor); # Pass a pointer to
Sometimes you need to get a pointer (for example, a library handle) back from a C library. You don't care about what it points to - you just need to keep hold of it. The Pointer type provides for this.
use NativeCall; sub Foo_init() returns Pointer is native("foo") { * } sub Foo_free(Pointer) is native("foo") { * }
This works out OK, but you may fancy working with a type named something better than Pointer. It turns out that any class with the representation "CPointer" can serve this role. This means you can expose libraries that work on handles by writing a class like this:
use NativeCall; class FooHandle is repr('CPointer') { # Here are the actual NativeCall functions. sub Foo_init() returns FooHandle is native("foo") { * } sub Foo_free(FooHandle) is native("foo") { * } sub Foo_query(FooHandle, Str) returns int8 is native("foo") { * } sub Foo_close(FooHandle) returns int8 is native("foo") { * } # Here are the methods we use to expose it to the outside world. method new { Foo_init(); } method query(Str $stmt) { Foo_query(self, $stmt); } method close { Foo_close(self); } # Free data when the object is garbage collected. submethod DESTROY { Foo_free(self); } }
Note that the CPointer representation can do nothing more than hold a C pointer. This means that your class cannot have extra attributes. However, for simple libraries this may be a neat way to expose an object oriented interface to it.
Of course, you can always have an empty class:
class DoorHandle is repr('CPointer') { }
And just use the class as you would use Pointer, but with potential for better type safety and more readable code.
Once again, type objects are used to represent NULL pointers.
C libraries can expose pointers to C functions as return values of functions and as members of Structures like, e.g., structs and unions.
Example of invoking a function pointer "$fptr" returned by a function "f", using a signature defining the desired function parameters and return value:
sub f() returns Pointer is native('mylib') { * } my $fptr = f(); my &newfunc = nativecast(:(Str, size_t --> int32), $fptr); say newfunc("test", 4);
NativeCall has some support for arrays. It is constrained to work with machine-size integers, doubles and strings, sized numeric types, arrays of pointers, arrays of structs, and arrays of arrays.
Perl 6 arrays, which support amongst other things laziness, are laid out in memory in a radically different way to C arrays. Therefore, the NativeCall library offers a much more primitive CArray type, which you must use if working with C arrays.
Here is an example of passing a C array.
sub RenderBarChart(Str, int32, CArray[Str], CArray[num64]) is native("chart") { * } my @titles := CArray[Str].new; @titles[0] = 'Me'; @titles[1] = 'You'; @titles[2] = 'Hagrid'; my @values := CArray[num64].new; @values[0] = 59.5e0; @values[1] = 61.2e0; @values[2] = 180.7e0; RenderBarChart('Weights (kg)', 3, @titles, @values);
Note that binding was used to @titles, not assignment! If you assign, you are putting the values into a Perl 6 array, and it will not work out. If this all freaks you out, forget you ever knew anything about the @ sigil and just use $ all the way when using NativeCall.
use NativeCall; my $titles = CArray[Str].new; $titles[0] = 'Me'; $titles[1] = 'You'; $titles[2] = 'Hagrid';
Getting return values for arrays works out just the same.
Some library APIs may take an array as a buffer that will be populated by the C function and, for instance, return the actual number of items populated:
use NativeCall; sub get_n_ints(CArray[int32], int32) returns int32 is native('ints') { * }
In these cases it is important that the CArray has at least the number of elements that are going to be populated before passing it to the native subroutine, otherwise the C function may stomp all over Perl's memory leading to possibly unpredictable behavior:
my $number_of_ints = 10; my $ints = CArray[int32].allocate($number_of_ints); # instantiates an array with 10 elements my $n = get_n_ints($ints, $number_of_ints);
Note: allocate was introduced in Rakudo 2018.05. Before that, you had to use this mechanism to extend an array to a number of elements:
my $ints = CArray[int32].new; my $number_of_ints = 10; $ints[$number_of_ints - 1] = 0; # extend the array to 10 items
The memory management of arrays is important to understand. When you create an array yourself, then you can add elements to it as you wish and it will be expanded for you as required. However, this may result in it being moved in memory (assignments to existing elements will never cause this, however). This means you'd best know what you're doing if you twiddle with an array after passing it to a C library.
By contrast, when a C library returns an array to you, then the memory can not be managed by NativeCall, and it doesn't know where the array ends. Presumably, something in the library API tells you this (for example, you know that when you see a null element, you should read no further). Note that NativeCall can offer you no protection whatsoever here - do the wrong thing, and you will get a segfault or cause memory corruption. This isn't a shortcoming of NativeCall, it's the way the big bad native world works. Scared? Here, have a hug. Good luck!
Besides the usual methods available on every Perl 6 instance, CArray provides the following methods that can be used to interact with the it from the Perl 6 point of view:
elems provides the number of elements within the array;
AT-POS provides a specific element at the given position (starting from zero);
list provides the List of elements within the array building it from the native array iterator.
As an example, consider the following simple piece of code:
use NativeCall; my $native-array = CArray[int32].new( 1, 2, 3, 4, 5 ); say 'Number of elements: ' ~ $native-array.elems; # walk the array for $native-array.list -> $elem { say "Current element is: $elem"; } # get every element by its index-based position for 0..$native-array.elems - 1 -> $position { say "Element at position $position is " ~ $native-array.AT-POS( $position ); }
that produces the following output
Number of elements: 5 Current element is: 1 Current element is: 2 Current element is: 3 Current element is: 4 Current element is: 5 Element at position 0 is 1 Element at position 1 is 2 Element at position 2 is 3 Element at position 3 is 4 Element at position 4 is 5
Thanks to representation polymorphism, it's possible to declare a normal looking Perl 6 class that, under the hood, stores its attributes in the same way a C compiler would lay them out in a similar struct definition. All it takes is a quick use of the "repr" trait:
class Point is repr('CStruct') { has num64 $.x; has num64 $.y; }
The attributes can only be of the types that NativeCall knows how to marshal into struct fields. Currently, structs can contain machine-sized integers, doubles, strings, and other NativeCall objects (CArrays, and those using the CPointer and CStruct reprs). Other than that, you can do the usual set of things you would with a class; you could even have some of the attributes come from roles or have them inherited from another class. Of course, methods are completely fine too. Go wild!
CStruct objects are passed to native functions by reference and native functions must also return CStruct objects by reference. The memory management rules for these references are very much like the rules for arrays, though simpler since a struct is never resized. When you create a struct, the memory is managed for you and when the variable(s) pointing to the instance of a CStruct go away, the memory will be freed when the GC gets to it. When a CStruct-based type is used as the return type of a native function, the memory is not managed for you by the GC.
NativeCall currently doesn't put object members in containers, so assigning new values to them (with =) doesn't work. Instead, you have to bind new values to the private members:
class MyStruct is repr('CStruct') { has CArray[num64] $!arr; has Str $!str; has Point $!point; # Point is a user-defined class submethod TWEAK { my $arr := CArray[num64].new; $arr[0] = 0.9e0; $arr[1] = 0.2e0; $!arr := $arr; $!str := 'Perl 6 is fun'; $!point := Point.new; } }
As you may have predicted by now, a NULL pointer is represented by the type object of the struct type.
Likewise, it is possible to declare a Perl 6 class that stores its attributes the same way a C compiler would lay them out in a similar union definition; using the CUnion representation:
use NativeCall; class MyUnion is repr('CUnion') { has int32 $.flags32; has int64 $.flags64; } say nativesizeof(MyUnion.new); # OUTPUT: «8» # ie. max(sizeof(MyUnion.flags32), sizeof(MyUnion.flags64))
CStructs and CUnions can be in turn referenced by—or embedded into—a surrounding CStruct and CUnion. To say the former we use has as usual, and to do the latter we use the HAS declarator instead:
class MyStruct is repr('CStruct') { has Point $.point; # referenced has int32 $.flags; } say nativesizeof(MyStruct.new); # OUTPUT: «16» # ie. sizeof(struct Point *) + sizeof(int32_t) class MyStruct2 is repr('CStruct') { HAS Point $.point; # embedded has int32 $.flags; } say nativesizeof(MyStruct2.new); # OUTPUT: «24» # ie. sizeof(struct Point) + sizeof(int32_t)
When allocating a struct for use as a struct, make sure that you allocate your own memory in your C functions. If you're passing a struct into a C function which needs a Str/char* allocated ahead of time, be sure to assign a container for a variable of type Str prior to passing your struct into the function.
class AStringAndAnInt is repr("CStruct") { has Str $.a_string; has int32 $.an_int32; sub init_struct(AStringAndAnInt is rw, Str, int32) is native('simple-struct') { * } submethod BUILD(:$a_string, :$an_int) { init_struct(self, $a_string, $an_int); } }
In this code we first set up our members, $.a_string and $.an_int32. After that we declare our init_struct() function for the init() method to wrap around; this function is then called from BUILD to effectively assign the values before returning the created object.
typedef struct a_string_and_an_int32_t_ { char *a_string; int32_t an_int32; } a_string_and_an_int32_t;
Here's the structure. Notice how we've got a char * there.
void init_struct(a_string_and_an_int32_t *target, char *str, int32_t int32) { target->an_int32 = int32; target->a_string = strdup(str); return; }
In this function we initialize the C structure by assigning an integer by value, and passing the string by reference. The function allocates memory that it points <char *a_string> to within the structure as it copies the string. (Note you will also have to manage deallocation of the memory as well to avoid memory leaks.)
# A long time ago in a galaxy far, far away... my $foo = AStringAndAnInt.new(a_string => "str", an_int => 123); say "foo is {$foo.a_string} and {$foo.an_int32}"; # OUTPUT: «foo is str and 123»
You can type your Pointer by passing the type as a parameter. It works with the native type but also with CArray and CStruct defined types. NativeCall will not implicitly allocate the memory for it even when calling new on them. It's mostly useful in the case of a C routine returning a pointer, or if it's a pointer embedded in a CStruct.
use NativeCall; sub strdup(Str $s --> Pointer[Str]) is native {*} my Pointer[Str] $p = strdup("Success!"); say $p.deref;
You have to call .deref on Pointers to access the embedded type. In the example above, declaring the type of the pointer avoids typecasting error when dereferenced. Please note that the original strdup returns a pointer to char; we are using Pointer<Str>.
my Pointer[int32] $p; #For a pointer on int32; my Pointer[MyCstruct] $p2 = some_c_routine(); my MyCstruct $mc = $p2.deref; say $mc.field1;
It's quite common for a native function to return a pointer to an array of elements. Typed pointers can be dereferenced as an array to obtain individual elements.
my $n = 5; # returns a pointer to an array of length $n my Pointer[Point] $plot = some_other_c_routine($n); # display the 5 elements in the array for 1 .. $n -> $i { my $x = $plot[$i - 1].x; my $y = $plot[$i - 1].y; say "$i: ($x, $y)"; }
Pointers can also be updated to reference successive elements in the array:
my Pointer[Point] $elem = $plot; # show differences between successive points for 1 ..^ $n { my Point $lo = $elem.deref; ++$elem; # equivalent to $elem = $elem.add(1); my Point $hi = (++$elem).deref; my $dx = $hi.x = $lo.x; my $dy = $hi.y = $lo.y; say "$_: delta ($dx, $dy)"; }
Void pointers can also be used by declaring them Pointer[void]. Please consult the native types documentation for more information on the subject.
Let's say there is some C code that caches strings passed, like so:
#include <stdlib.h> static char *__VERSION; char * get_version() { return __VERSION; } char * set_version(char *version) { if (__VERSION != NULL) free(__VERSION); __VERSION = version; return __VERSION; }
If you were to write bindings for get_version and set_version, they would initially look like this, but will not work as intended:
sub get_version(--> Str) is native('./version') { * } sub set_version(Str --> Str) is native('./version') { * } say set_version('1.0.0'); # 1.0.0 say get_version; # Differs on each run say set_version('1.0.1'); # Double free; segfaults
This code segfaults on the second set_version call because it tries to free the string passed on the first call after the garbage collector had already done so. If the garbage collector shouldn't free a string passed to a native function, use explicitly-manage with it:
say set_version(explicitly-manage('1.0.0')); # 1.0.0 say get_version; # 1.0.0 say set_version(explicitly-manage('1.0.1')); # 1.0.1 say get_version; # 1.0.1
Bear in mind all memory management for explicitly managed strings must be handled by the C library itself or through the NativeCall API to prevent memory leaks.
Blobs and Bufs are the Perl 6 way of storing binary data. We can use them for interchange of data with native functions and data structures, although not directly. We will have to use nativecast.
my $blob = Blob.new(0x22, 0x33); my $src = nativecast(Pointer, $blob);
This $src can then be used as an argument for any native function that takes a Pointer. The opposite, putting values pointed to by a Pointer into a Buf or using it to initialize a Blob is not directly supported. You might want to use NativeHelpers::Blob to do this kind of operations.
my $esponja = blob-from-pointer( $inter, :2elems, :type(Blob[int8])); say $esponja;
NativeCall also supports native functions that take functions as arguments. One example of this is using function pointers as callbacks in an event-driven system. When binding these functions via NativeCall, one needs only provide the equivalent signature as a constraint on the code parameter. In the case of NativeCall, however, as of Rakudo 2019.07, a space between the function argument and the signature, and the colon of a normal Signature literal is omitted, as in:
use NativeCall; # void SetCallback(int (*callback)(const char *)) my sub SetCallback(&callback (Str --> int32)) is native('mylib') { * }
Note: the native code is responsible for memory management of values passed to Perl 6 callbacks this way. In other words, NativeCall will not free() strings passed to callbacks.
The native trait accepts the library name, the full path, or a subroutine returning either of the two. When using the library name, the name is assumed to be prepended with "lib" and appended with ".so" (or just appended with ".dll" on Windows), and will be searched for in the paths in the LD_LIBRARY_PATH (PATH on Windows) environment variable.
use NativeCall; constant LIBMYSQL = 'mysqlclient'; constant LIBFOO = '/usr/lib/libfoo.so.1'; sub LIBBAR { my $path = qx/pkg-config --libs libbar/.chomp; $path ~~ s/\/[[\w+]+ % \/]/\0\/bar/; $path } # and later sub mysql_affected_rows returns int32 is native(LIBMYSQL) {*}; sub bar is native(LIBFOO) {*} sub baz is native(LIBBAR) {*}
You can also put an incomplete path like './foo' and NativeCall will automatically put the right extension according to the platform specification. If you wish to suppress this expansion, simply pass the string as the body of a block.
sub bar is native({ './lib/Non Standard Naming Scheme' }) {*}
BE CAREFUL: the native trait and constant are evaluated at compile time. Don't write a constant that depends on a dynamic variable like:
# WRONG: constant LIBMYSQL = %*ENV<P6LIB_MYSQLCLIENT> || 'mysqlclient';
This will keep the value given at compile time. A module will be precompiled and LIBMYSQL will keep the value it acquires when the module gets precompiled.
If you write native('foo') NativeCall will search libfoo.so under Unix like system (libfoo.dynlib on OS X, foo.dll on win32). In most modern system it will require you or the user of your module to install the development package because it's recommended to always provide an API/ABI version to a shared library, so libfoo.so ends often being a symbolic link provided only by a development package.
To avoid that, the native trait allows you to specify the API/ABI version. It can be a full version or just a part of it. (Try to stick to Major version, some BSD code does not care for Minor.)
use NativeCall; sub foo1 is native('foo', v1) {*} # Will try to load libfoo.so.1 sub foo2 is native('foo', v1.2.3) {*} # Will try to load libfoo.so.1.2.3 my List $lib = ('foo', 'v1'); sub foo3 is native($lib) {*}
The native trait also accepts a Callable as argument, allowing you to provide your own way to handle the way it will find the library file to load.
use NativeCall; sub foo is native(sub {'libfoo.so.42'}) {*}
It will only be called at the first invocation of the sub.
If you want to call a C function that's already loaded, either from the standard library or from your own program, you can omit the value, so is native.
For example on a UNIX-like operating system, you could use the following code to print the home directory of the current user:
use NativeCall; my class PwStruct is repr('CStruct') { has Str $.pw_name; has Str $.pw_passwd; has uint32 $.pw_uid; has uint32 $.pw_gid; has Str $.pw_gecos; has Str $.pw_dir; has Str $.pw_shell; } sub getuid() returns uint32 is native { * }; sub getpwuid(uint32 $uid) returns PwStruct is native { * }; say getpwuid(getuid()).pw_dir;
Though of course $*HOME is a much easier way :-)
Variables exported by a library – also named "global" or "extern" variables – can be accessed using cglobal. For example:
my $var := cglobal('libc.so.6', 'errno', int32)
This code binds to $var a new Proxy object that redirects all its accesses to the integer variable named "errno" as exported by the "libc.so.6" library.
NativeCall offers support to use classes and methods from C++ as shown in https://github.com/rakudo/rakudo/blob/master/t/04-nativecall/13-cpp-mangling.t (and its associated C++ file). Note that at the moment it's not as tested and developed as C support.
The NativeCall library exports several subroutines to help you work with data from native libraries.
sub nativecast($target-type, $source) is export(:DEFAULT)
This will cast the Pointer $source to an object of $target-type. The source pointer will typically have been obtained from a call to a native subroutine that returns a pointer or as a member of a struct, this may be specified as void * in the C library definition for instance, but you may also cast from a pointer to a less specific type to a more specific one.
As a special case, if a Signature is supplied as $target-type then a subroutine will be returned which will call the native function pointed to by $source in the same way as a subroutine declared with the native trait. This is described in Function Pointers.
sub cglobal($libname, $symbol, $target-type) is export is rw
This returns a Proxy object that provides access to the extern named $symbol that is exposed by the specified library. The library can be specified in the same ways that they can be to the native trait.
sub nativesizeof($obj) is export(:DEFAULT)
This returns the size in bytes of the supplied object, it can be thought of as being equivalent to sizeof in C. The object can be a builtin native type such as int64 or num64, a CArray or a class with the repr CStruct, CUnion or CPointer.
sub explicitly-manage($str) is export(:DEFAULT)
This returns a CStr object for the given Str. If the string returned is passed to a NativeCall subroutine, it will not be freed by the runtime's garbage collector.
Some specific examples, and instructions to use examples above in particular platforms.
The PostgreSQL examples in DBIish make use of the NativeCall library and is native to use the native _putenv function call in Windows.
NOTE: Please bear in mind that, under the hood, Debian has substituted MySQL with MariaDB since the Stretch version, so if you want to install MySQL, use MySQL APT repository instead of the default repository.
To use the MySQL example in DBIish, you'll need to install MySQL server locally; on Debian-esque systems it can be installed with something like:
wget https://dev.mysql.com/get/mysql-apt-config_0.8.10-1_all.deb sudo dpkg -i mysql-apt-config_0.8.10-1_all.deb # Don't forget to select 5.6.x sudo apt-get update sudo apt-get install mysql-community-server -y sudo apt-get install libmysqlclient18 -y
Prepare your system along these lines before trying out the examples:
$ mysql -u root -p SET PASSWORD = PASSWORD('sa'); DROP DATABASE test; CREATE DATABASE test;
Here is an example of a Windows API call:
use NativeCall; sub MessageBoxA(int32, Str, Str, int32) returns int32 is native('user32') { * } MessageBoxA(0, "We have NativeCall", "ohai", 64);
This is an example for calling a standard function and using the returned information in a Perl 6 program.
getaddrinfo is a POSIX standard function for obtaining network information about a network node, e.g., google.com. It is an interesting function to look at because it illustrates a number of the elements of NativeCall.
The Linux manual provides the following information about the C callable function:
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
The function returns a response code 0 = error, 1 = success. The data are extracted from a linked list of addrinfo elements, with the first element pointed to by res.
From the table of NativeCall Types we know that an int is int32. We also know that a char * is one of the forms C for a C Str, which maps simply to Str. But addrinfo is a structure, which means we will need to write our own Type class. However, the function declaration is straightforward:
sub getaddrinfo( Str $node, Str $service, Addrinfo $hints, Pointer $res is rw ) returns int32 is native { * }
Note that $res is to be written by the function, so it must be labeled as rw. Since the library is standard POSIX, the library name can be the Type definition or null.
We now have to handle structure Addrinfo. The Linux Manual provides this information:
struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; socklen_t ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next; };
The int, char* parts are straightforward. Some research indicates that socklen_t can be architecture dependent, but is an unsigned integer of at least 32 bits. So socklen_t can be mapped to the uint32 type.
The complication is sockaddr which differs depending on whether ai_socktype is undefined, INET, or INET6 (a standard v4 IP address or a v6 address).
So we create a Perl 6 class to map to the C struct addrinfo; while we're at it, we also create another class for SockAddr which is needed for it.
class SockAddr is repr('CStruct') { has int32 $.sa_family; has Str $.sa_data; } class Addrinfo is repr('CStruct') { has int32 $.ai_flags; has int32 $.ai_family; has int32 $.ai_socktype; has int32 $.ai_protocol; has int32 $.ai_addrlen; has SockAddr $.ai_addr is rw; has Str $.ai_cannonname is rw; has Addrinfo $.ai_next is rw; }
The is rw on the last three attributes reflects that these were defined in C to be pointers.
The important thing here for mapping to a C Struct is the structure of the state part of the class, that is the attributes. However, a class can have methods and NativeCall does not 'touch' them for mapping to C. This means that we can add extra methods to the class to unpack the attributes in a more readable manner, e.g.,
method flags { do for AddrInfo-Flags.enums { .key if $!ai_flags +& .value } }
By defining an appropriate enum, flags will return a string of keys rather than a bit packed integer.
The most useful information in the sockaddr structure is the address of node, which depends on the family of the Socket. So we can add method address to the Perl 6 class that interprets the address depending on the family.
In order to get a human readable IP address, there is the C function inet_ntop which returns a char * given a buffer with the addrinfo.
Putting all these together, leads to the following program:
#!/usr/bin/env perl6 use v6; use NativeCall; constant \INET_ADDRSTRLEN = 16; constant \INET6_ADDRSTRLEN = 46; enum AddrInfo-Family ( AF_UNSPEC => 0; AF_INET => 2; AF_INET6 => 10; ); enum AddrInfo-Socktype ( SOCK_STREAM => 1; SOCK_DGRAM => 2; SOCK_RAW => 3; SOCK_RDM => 4; SOCK_SEQPACKET => 5; SOCK_DCCP => 6; SOCK_PACKET => 10; ); enum AddrInfo-Flags ( AI_PASSIVE => 0x0001; AI_CANONNAME => 0x0002; AI_NUMERICHOST => 0x0004; AI_V4MAPPED => 0x0008; AI_ALL => 0x0010; AI_ADDRCONFIG => 0x0020; AI_IDN => 0x0040; AI_CANONIDN => 0x0080; AI_IDN_ALLOW_UNASSIGNED => 0x0100; AI_IDN_USE_STD3_ASCII_RULES => 0x0200; AI_NUMERICSERV => 0x0400; ); sub inet_ntop(int32, Pointer, Blob, int32 --> Str) is native {} class SockAddr is repr('CStruct') { has uint16 $.sa_family; } class SockAddr-in is repr('CStruct') { has int16 $.sin_family; has uint16 $.sin_port; has uint32 $.sin_addr; method address { my $buf = buf8.allocate(INET_ADDRSTRLEN); inet_ntop(AF_INET, Pointer.new(nativecast(Pointer,self)+4), $buf, INET_ADDRSTRLEN) } } class SockAddr-in6 is repr('CStruct') { has uint16 $.sin6_family; has uint16 $.sin6_port; has uint32 $.sin6_flowinfo; has uint64 $.sin6_addr0; has uint64 $.sin6_addr1; has uint32 $.sin6_scope_id; method address { my $buf = buf8.allocate(INET6_ADDRSTRLEN); inet_ntop(AF_INET6, Pointer.new(nativecast(Pointer,self)+8), $buf, INET6_ADDRSTRLEN) } } class Addrinfo is repr('CStruct') { has int32 $.ai_flags; has int32 $.ai_family; has int32 $.ai_socktype; has int32 $.ai_protocol; has uint32 $.ai_addrNativeCalllen; has SockAddr $.ai_addr is rw; has Str $.ai_cannonname is rw; has Addrinfo $.ai_next is rw; method flags { do for AddrInfo-Flags.enums { .key if $!ai_flags +& .value } } method family { AddrInfo-Family($!ai_family) } method socktype { AddrInfo-Socktype($!ai_socktype) } method address { given $.family { when AF_INET { nativecast(SockAddr-in, $!ai_addr).address } when AF_INET6 { nativecast(SockAddr-in6, $!ai_addr).address } } } } sub getaddrinfo(Str $node, Str $service, Addrinfo $hints, Pointer $res is rw --> int32) is native {}; sub freeaddrinfo(Pointer) is native {} sub MAIN() { my Addrinfo $hint .= new(:ai_flags(AI_CANONNAME)); my Pointer $res .= new; my $rv = getaddrinfo("google.com", Str, $hint, $res); say "return val: $rv"; if ( ! $rv ) { my $addr = nativecast(Addrinfo, $res); while $addr { with $addr { say "Name: ", $_ with .ai_cannonname; say .family, ' ', .socktype; say .address; $addr = .ai_next; } } } freeaddrinfo($res); }
This produces the following output:
return val: 0 Name: google.com AF_INET SOCK_STREAM 216.58.219.206 AF_INET SOCK_DGRAM 216.58.219.206 AF_INET SOCK_RAW 216.58.219.206 AF_INET6 SOCK_STREAM 2607:f8b0:4006:800::200e AF_INET6 SOCK_DGRAM 2607:f8b0:4006:800::200e AF_INET6 SOCK_RAW 2607:f8b0:4006:800::200e
How the different newline characters are handled, and how to change the behavior
Different operating systems use different characters, or combinations of them, to represent the transition to a new line. Every language has its own set of rules to handle this. Perl 6 has the following ones:
\n in a string literal means Unicode codepoint 10.
The default nl-out that is appended to a string by say is also \n.
On output, when on Windows, the encoder will by default transform a \n into a \r\n when it's going to a file, process, or terminal (it won't do this on a socket, however).
On input, on any platform, the decoder will by default normalize \r\n into \n for input from a file, process, or terminal (again, not socket).
These above two points together mean that you can - socket programming aside - expect to never see a \r\n inside of your program (this is how things work in numerous other languages too).
The :$translate-nl named parameter exists in various places to control this transformation, for instance, in Proc::Async.new and Proc::Async.Supply.
A \n in the regex language is logical, and will match a \r\n.
You can change the default behavior for a particular handle by setting the :nl-out attribute when you create that handle.
my $crlf-out = open(IO::Special.new('<STDOUT>'), :nl-out("\\\n\r")); $*OUT.say: 1; #OUTPUT: «1» $crlf-out.say: 1; #OUTPUT: «1\␍»
In this example, where we are replicating standard output to a new handle by using IO::Special, we are appending a \ to the end of the string, followed by a newline  and a carriage return ␍; everything we print to that handle will get those characters at the end of the line, as shown.
In regular expressions, \n is defined in terms of the Unicode definition of logical newline. It will match . and also \v, as well as any class that includes whitespace.
Numeric types available in Perl 6
The Int type offers arbitrary-size integer numbers. They can get as big as your computer memory allows, although some implementations choose to throw a numeric overflow error when asked to produce integers of truly staggering size:
say 10**600**600 # OUTPUT: «Numeric overflow»
Unlike some languages, division performed using / operator when both operands are of Int type, would produce a fractional number, without any rounding performed.
say 4/5; # OUTPUT: «0.8»
The type produced by this division is either a Rat or a Num type. The Rat is produced if, after reduction, the fraction's denominator is smaller than 64 bits, otherwise a Num type is produced.
The div and narrow routines can be helpful if you wish to end up with an Int result, whenever possible. The div operator performs integer division, discarding the remainder, while narrow fits the number into the narrowest type it'll fit:
say 5 div 2; # OUTPUT: «2» # Result `2` is narrow enough to be an Int: say (4/2).narrow; # OUTPUT: «2» say (4/2).narrow.^name; # OUTPUT: «Int» # But 2.5 has fractional part, so it ends up being a Rat type: say (5/2).narrow.^name; # OUTPUT: «Rat» say (5/2).narrow; # OUTPUT: «2.5» # Denominator is too big for a Rat, so a Num is produced: say 1 / 10⁹⁹; # OUTPUT: «1e-99»
Perl 6 has a FatRat type that offers arbitrary precision fractions. How come a limited-precision Num is produced instead of a FatRat type in the last example above? The reason is: performance. Most operations are fine with a little bit of precision lost and so do not require the use of a more expensive FatRat type. You'll need to instantiate one yourself if you wish to have the extra precision.
The Num type offers double-precision floating-point decimal numbers, sometimes called "doubles" in other languages.
A Num literal is written with the exponent separated using the letter e. Keep in mind that the letter e is required even if the exponent is zero, as otherwise you'll get a Rat rational literal instead:
say 42e0.^name; # OUTPUT: «Num» say 42.0.^name; # OUTPUT: «Rat»
Case-sensitive words Inf and NaN represent the special values infinity and not-a-number respectively. The U+221E INFINITY (∞) character can be used instead of Inf:
Perl 6 follows the IEEE 754-2008 Standard for Floating-Point Arithmetic as much as possible, with more conformance planned to be implemented in later language versions. The language guarantees the closest representable number is chosen for any given Num literal and does offer support for negative zero and denormals (also known as "subnormals").
Keep in mind that output routines like say or put do not try very hard to distinguish between how Numeric types are output and may choose to display a Num as an Int or a Rat number. For a more definitive string to output, use the perl method:
say 1e0; # OUTPUT: «1» say .5e0; # OUTPUT: «0.5» say 1e0.perl; # OUTPUT: «1e0» say .5e0.perl; # OUTPUT: «0.5e0»
The Complex type numerics of the complex plane. The Complex objects consist of two Num objects representing the real and imaginary portions of the complex number.
To create a Complex, you can use the postfix i operator on any other non-complex number, optionally setting the real part with addition. To use the i operator on NaN or Inf literals, separate it from them with a backslash.
say 42i; # OUTPUT: «0+42i» say 73+42i; # OUTPUT: «73+42i» say 73+Inf\i; # OUTPUT: «73+Inf\i»
Keep in mind the above syntax is just an addition expression and precedence rules apply. It also cannot be used in places that forbid expressions, such as literals in routine parameters.
# Precedence of `*` is higher than that of `+` say 2 * 73+10i; # OUTPUT: «146+10i»
To avoid these issues, you can choose to use the Complex literal syntax instead, which involves surrounding the real and imaginary parts with angle brackets, without any spaces:
say 2 * <73+10i>; # OUTPUT: «146+20i» multi how-is-it (<2+4i>) { say "that's my favorite number!" } multi how-is-it (|) { say "meh" } how-is-it 2+4i; # OUTPUT: «that's my favorite number!» how-is-it 3+2i; # OUTPUT: «meh»
The types that do the Rational role offer high-precision and arbitrary-precision decimal numbers. Since the higher the precision the larger the performance penalty, the Rational types come in two flavors: Rat and FatRat. The Rat is the most often-used variant that degrades into a Num in most cases, when it can no longer hold all of the requested precision. The FatRat is the arbitrary-precision variant that keeps growing to provide all of the requested precision.
The most common of Rational types. It supports rationals with denominators as large as 64 bits (after reduction of the fraction to the lowest denominator). Rat objects with larger denominators can be created directly, however, when Rats with such denominators are the result of mathematical operations, they degrade to a Num object.
The Rat literals use syntax similar to Num literals in many other languages, using the dot to indicate the number is a decimal:
say .1 + .2 == .3; # OUTPUT: «True»
If you try to execute a statement similar to the above in many common languages, you'll get False as the answer, due to imprecision of floating point math. To get the same result in Perl 6, you'd have to use Num literals instead:
say .1e0 + .2e0 == .3e0; # OUTPUT: «False»
You can also use / division operator with Int or Rat objects to produce a Rat:
say 3/4; # OUTPUT: «0.75» say 3/4.2; # OUTPUT: «0.714286» say 1.1/4.2; # OUTPUT: «0.261905»
Keep in mind the above syntax is just a division expression and precedence rules apply. It also cannot be used in places that forbid expressions, such as literals in routine parameters.
# Precedence of power operators is higher than division say 3/2²; # OUTPUT: «0.75»
To avoid these issues, you can choose to use the Rational literal syntax instead, which involves surrounding the numerator and denominator with angle brackets, without any spaces:
say <3/2>²; # OUTPUT: «2.25» multi how-is-it (<3/2>) { say "that's my favorite number!" } multi how-is-it (|) { say "meh" } how-is-it 3/2; # OUTPUT: «that's my favorite number!» how-is-it 1/3; # OUTPUT: «meh»
Lastly, any Unicode character with property No that represents a fractional number can be used as a Rat literal:
say ½ + ⅓ + ⅝ + ⅙; # OUTPUT: «1.625»
If a mathematical operation that produces a Rat answer would produce a Rat with denominator larger than 64 bits, that operation would instead return a Num object. When constructing a Rat (i.e. when it is not a result of some mathematical expression), however, a larger denominator can be used:
my $a = 1 / (2⁶⁴ - 1); say $a; # OUTPUT: «0.000000000000000000054» say $a.^name; # OUTPUT: «Rat» say $a.nude; # OUTPUT: «(1 18446744073709551615)» my $b = 1 / 2⁶⁴; say $b; # OUTPUT: «5.421010862427522e-20» say $b.^name; # OUTPUT: «Num» my $c = Rat.new(1, 2⁶⁴); say $c; # OUTPUT: «0.000000000000000000054» say $c.^name; # OUTPUT: «Rat» say $c.nude; # OUTPUT: «(1 18446744073709551616)» say $c.Num; # OUTPUT: «5.421010862427522e-20»
The last Rational type—FatRat—keeps all of the precision you ask of it, storing the numerator and denominator as two Int objects. A FatRat is more infectious than a Rat, so many math operations with a FatRat will produce another FatRat, preserving all of the available precision. Where a Rat degrades to a Num, math with a FatRat keeps chugging along:
say ((42 + Rat.new(1,2))/999999999999999999).^name; # OUTPUT: «Rat» say ((42 + Rat.new(1,2))/9999999999999999999).^name; # OUTPUT: «Num» say ((42 + FatRat.new(1,2))/999999999999999999).^name; # OUTPUT: «FatRat» say ((42 + FatRat.new(1,2))/99999999999999999999999).^name; # OUTPUT: «FatRat»
There's no special operator or syntax available for construction of FatRat objects. Simply use FatRat.new method, giving numerator as first positional argument and denominator as the second.
If your program requires a significant amount of FatRat creation, you could create your own custom operator:
sub infix:<🙼> { FatRat.new: $^a, $^b } say (1🙼3).perl; # OUTPUT: «FatRat.new(1, 3)»
Keep in mind that output routines like say or put do not try very hard to distinguish between how Numeric types are output and may choose to display a Num as an Int or a Rat number. For a more definitive string to output, use the perl method:
say 1.0; # OUTPUT: «1» say ⅓; # OUTPUT: «0.333333» say 1.0.perl; # OUTPUT: «1.0» say ⅓.perl; # OUTPUT: «<1/3>»
For even more information, you may choose to see the Rational object in the nude, displaying its numerator and denominator:
say ⅓; # OUTPUT: «0.333333» say 4/2; # OUTPUT: «2» say ⅓.perl; # OUTPUT: «<1/3>» say <4/2>.nude; # OUTPUT: «(2 1)»
In many languages division by zero is an immediate exception. In Perl 6, what happens depends on what you're dividing and how you use the result.
Perl 6 follows IEEE 754-2008 Standard for Floating-Point Arithmetic, but for historical reasons 6.c and 6.d language versions do not comply fully. Num division by zero produces a Failure, while Complex division by zero produces NaN components, regardless of what the numerator is.
As of 6.e language, both Num and Complex division by zero will produce a -Inf, +Inf, or NaN depending on whether the numerator was negative, positive, or zero, respectively (for Complex the real and imaginary components are Num and are considered separately).
Division of Int numerics produces a Rat object (or a Num, if after reduction the denominator is larger than 64-bits, which isn't the case when you're dividing by zero). This means such division never produces an Exception or a Failure. The result is a Zero-Denominator Rational, which can be explosive.
A Zero-Denominator Rational is a numeric that does role Rational, which among core numerics would be Rat and FatRat objects, which has denominator of zero. The numerator of such Rationals is normalized to -1, 0, or 1 depending on whether the original numerator is negative, zero or positive, respectively.
Operations that can be performed without requiring actual division to occur are non-explosive. For example, you can separately examine numerator and denominator in the nude or perform mathematical operations without any exceptions or failures popping up.
Converting zero-denominator rationals to Num follows the IEEE conventions, and the result is a -Inf, Inf, or NaN, depending on whether the numerator is negative, positive, or zero, respectively. The same is true going the other way: converting ±Inf/NaN to one of the Rational types will produce a zero-denominator rational with an appropriate numerator:
say <1/0>.Num; # OUTPUT: «Inf» say <-1/0>.Num; # OUTPUT: «-Inf» say <0/0>.Num; # OUTPUT: «NaN» say Inf.Rat.nude; # OUTPUT: «(1 0)»
All other operations that require non-IEEE division of the numerator and denominator to occur will result in X::Numeric::DivideByZero exception to be thrown. The most common of such operations would likely be trying to print or stringify a zero-denominator rational:
say 0/0; # OUTPUT: # Attempt to divide by zero using div # in block <unit> at -e line 1
Allomorphs are subclasses of two types that can behave as either of them. For example, the allomorph IntStr is the subclass of Int and Str types and will be accepted by any type constraint that requires an Int or Str object.
Allomorphs can be created using angle brackets, either used standalone or as part of a hash key lookup; directly using method .new and are also provided by some constructs such as parameters of sub MAIN.
say <42>.^name; # OUTPUT: «IntStr» say <42e0>.^name; # OUTPUT: «NumStr» say < 42+42i>.^name; # OUTPUT: «ComplexStr» say < 1/2>.^name; # OUTPUT: «RatStr» say <0.5>.^name; # OUTPUT: «RatStr» @*ARGS = "42"; sub MAIN($x) { say $x.^name } # OUTPUT: «IntStr» say IntStr.new(42, "42").^name; # OUTPUT: «IntStr»
A couple of constructs above have a space after the opening angle bracket. That space isn't accidental. Numerics that are often written using an operator, such as 1/2 (Rat, division operator) and 1+2i (Complex, addition) can be written as a literal that doesn't involve the use of an operator: angle brackets without any spaces between the angle brackets and the characters inside. By adding spaces within the angle brackets, we tell the compiler that not only we want a Rat or Complex literal, but we also want it to be an allomorph: the RatStr or ComplexStr, in this case.
If the numeric literal doesn't use any operators, then writing it inside the angle brackets, even without including any spaces within, would produce the allomorph. (Logic: if you didn't want the allomorph, you wouldn't use the angle brackets. The same isn't true for operator-using numbers as some constructs, such as signature literals, do not let you use operators, so you can't just omit angle brackets for such numeric literals).
The core language offers the following allomorphs:
Type | Allomorph of | Example |
---|---|---|
IntStr | Int and Str | <42> |
NumStr | Num and Str | <42e0> |
ComplexStr | Complex and Str | < 1+2i> |
RatStr | Rat and Str | <1.5> |
Note: there is no FatRatStr type.
Keep in mind that allomorphs are simply subclasses of the two (or three) types they represent. Just as a variable or parameter type-constrained to Foo can accept any subclass of Foo, so will a variable or parameter type-constrained to Int will accept an IntStr allomorph:
sub foo(Int $x) { say $x.^name } foo <42>; # OUTPUT: «IntStr» my Num $y = <42e0>; say $y.^name; # OUTPUT: «NumStr»
This, of course, also applies to parameter coercers:
sub foo(Int(Cool) $x) { say $x.^name } foo <42>; # OUTPUT: «IntStr»
The given allomorph is already an object of type Int, so it does not get converted to a "plain" Int in this case.
Of course, the power of allomorphs would be severely diminished if there were no way to "collapse" them to one of their components. Thus, if you explicitly call a method with the name of the type to coerce to, you'll get just that component. The same applies to any proxy methods, such as calling method .Numeric instead of .Int or using the prefix:<~> operator instead of .Str method call.
my $al := IntStr.new: 42, "forty two"; say $al.Str; # OUTPUT: «forty two» say +$al; # OUTPUT: «42» say <1/99999999999999999999>.Rat.^name; # OUTPUT: «Rat» say <1/99999999999999999999>.FatRat.^name; # OUTPUT: «FatRat»
A handy way to coerce a whole list of allomorphs is by applying the hyper operator to the appropriate prefix:
say map *.^name, <42 50e0 100>; # OUTPUT: «(IntStr NumStr IntStr)» say map *.^name, +«<42 50e0 100>; # OUTPUT: «(Int Num Int)» say map *.^name, ~«<42 50e0 100>; # OUTPUT: «(Str Str Str)»
The above discussion on coercing allomorphs becomes more important when we consider object identity. Some constructs utilize it to ascertain whether two objects are "the same". And while to humans an allomorphic 42 and regular 42 might appear "the same", to those constructs, they're entirely different objects:
# "42" shows up twice in the result: 42 and <42> are different objects: say unique 1, 1, 1, 42, <42>; # OUTPUT: «(1 42 42)» # Use a different operator to `unique` with: say unique :with(&[==]), 1, 1, 1, 42, <42>; # OUTPUT: «(1 42)» # Or coerce the input instead (faster than using a different `unique` operator): say unique :as(*.Int), 1, 1, 1, 42, <42>; # OUTPUT: «(1 42)» say unique +«(1, 1, 1, 42, <42>); # OUTPUT: «(1 42)» # Parameterized Hash with `Any` keys does not stringify them; our key is of type `Int`: my %h{Any} = 42 => "foo"; # But we use the allomorphic key of type `IntStr`, which is not in the Hash: say %h<42>:exists; # OUTPUT: «False» # Must use curly braces to avoid the allomorph: say %h{42}:exists; # OUTPUT: «True» # We are using a set operator to look up an `Int` object in a list of `IntStr` objects: say 42 ∈ <42 100 200>; # OUTPUT: «False» # Convert it to an allomorph: say <42> ∈ <42 100 200>; # OUTPUT: «True» # Or convert the items in the list to plain `Int` objects: say 42 ∈ +«<42 100 200>; # OUTPUT: «True»
Be mindful of these object identity differences and coerce your allomorphs as needed.
As the name suggests, native numerics offer access to native numerics—i.e. those offered directly by your hardware. This in turn offers two features: overflow/underflow and better performance.
NOTE: at the time of this writing (2018.05), certain implementations (such as Rakudo) offer somewhat spotty details on native types, such as whether int64 is available and is of 64-bit size on 32-bit machines, and how to detect when your program is running on such hardware.
Native type | Base numeric | Size |
---|---|---|
int | integer | 64-bits |
int8 | integer | 8-bits |
int16 | integer | 16-bits |
int32 | integer | 32-bits |
int64 | integer | 64-bits |
uint | unsigned integer | 64-bits |
uint8 | unsigned integer | 8-bits |
uint16 | unsigned integer | 16-bits |
uint32 | unsigned integer | 32-bits |
uint64 | unsigned integer | 64-bits |
num | floating point | 64-bits |
num32 | floating point | 32-bits |
num64 | floating point | 64-bits |
atomicint | integer | sized to offer CPU-provided atomic operations. (typically 64 bits on 64-bit platforms and 32 bits on 32-bit ones) |
To create a natively-typed variable or parameter, simply use the name of one of the available numerics as the type constraint:
my int32 $x = 42; sub foo(num $y) {} class { has int8 $.z }
At times, you may wish to coerce some value to a native type without creating any usable variables. There are no .int or similar coercion methods (method calls are latebound, so they're not well-suited for this purpose). Instead, simply use an anonymous variable:
some-native-taking-sub (my int $ = $y), (my int32 $ = $z)
Trying to assign a value that does not fit into a particular native type, produces an exception. This includes attempting to give too large an argument to a native parameter:
my int $x = 2¹⁰⁰; # OUTPUT: # Cannot unbox 101 bit wide bigint into native integer # in block <unit> at -e line 1 sub f(int $x) { $x }; say f 2⁶⁴ # OUTPUT: # Cannot unbox 65 bit wide bigint into native integer # in sub f at -e line 1 # in block <unit> at -e line 1
However, modifying an already-existing value in such a way that it becomes too big/small, produces overflow/underflow behavior:
my int $x = 2⁶³-1; say $x; # OUTPUT: «9223372036854775807» say ++$x; # OUTPUT: «-9223372036854775808» my uint8 $x; say $x; # OUTPUT: «0» say $x -= 100; # OUTPUT: «156»
Creating objects that utilize native types does not involve direct assignment by the programmer; that is why these constructs offer overflow/underflow behavior instead of throwing exceptions.
say Buf.new(1000, 2000, 3000).List; # OUTPUT: «(232 208 184)» say my uint8 @a = 1000, 2000, 3000; # OUTPUT: «232 208 184»
While they can be referred to as "native types", native numerics are not actually classes that have any sort of methods available. However, you can call any of the methods available on non-native versions of these numerics. What's going on?
my int8 $x = -42; say $x.abs; # OUTPUT: «42»
This behavior is known as "auto-boxing". The compiler automatically "boxes" the native type into a full-featured higher-level type with all the methods. In other words, the int8 above was automatically converted to an Int and it's the Int class that then provided the abs method that was called.
This detail is significant when you're using native types for performance gains. If the code you're using results in a lot of auto-boxing being performed you might get worse performance with native types than you would with non-natives:
my $a = -42; my int $a-native = -42; { for ^1000_000 { $a.abs }; say now - ENTER now } # OUTPUT: «0.38180862» { for ^1000_000 { $a-native.abs }; say now - ENTER now } # OUTPUT: «0.938720»
As you can see above, the native variant is more than twice slower. The reason is the method call requires the native type to be boxed, while no such thing is needed in the non-native variant, hence the performance loss.
In this particular case, we can simply switch to a subroutine form of abs, which can work with native types without boxing them. In other cases, you may need to seek out other solutions to avoid excessive autoboxing, including switching to non-native types for a portion of the code.
my $a = -42; my int $a-native = -42; { for ^1000_000 { abs $a }; say now - ENTER now } # OUTPUT: «0.38229177» { for ^1000_000 { abs $a-native }; say now - ENTER now } # OUTPUT: «0.3088305»
Since there are no classes behind native types, there are no type objects you'd normally get with variables that haven't been initialized. Thus, native types are automatically initialized to zero. In 6.c language, native floating point types (num, num32, and num64) were initialized to value NaN; in 6.d language the default is 0e0.
It is possible to have native candidates alongside non-native candidates to, for example, offer faster algorithms with native candidates when sizes are predictable, but to fallback to slower non-native alternatives otherwise. The following are the rules concerning multi-dispatch involving native candidates.
First, the size of the native type does not play a role in dispatch and an int8 is considered to be the same as int16 or int:
multi foo(int $x) { say "int" } multi foo(int32 $x) { say "int32" } foo my int $x = 42; # OUTPUT: # Ambiguous call to 'foo(Int)'; these signatures all match: # :(int $x) # :(int32 $x)
Second, if a routine is an only—i.e. it is not a multi—that takes a non-native type but a native one was given during the call, or vice-versa, then the argument will be auto-boxed or auto-unboxed to make the call possible. If the given argument is too large to fit into the native parameter, an exception will be thrown:
-> int {}( 42 ); # OK; auto-unboxing -> int {}( 2¹⁰⁰ ); # Too large; exception -> Int {}( 2¹⁰⁰ ); # OK; non-native parameter -> Int {}( my int $ = 42 ); # OK; auto-boxing
When it comes to multi routines, native arguments will always be auto-boxed if no native candidates are available to take them:
multi foo (Int $x) { $x } say foo my int $ = 42; # OUTPUT: «42»
The same luxury is not afforded when going the other way. If only a native candidate is available, a non-native argument will not be auto-unboxed and instead an exception indicating no candidates matched will be thrown (the reason for this asymmetry is a native type can always be boxed, but a non-native may be too large to fit into a native):
multi f(int $x) { $x } my $x = 2; say f $x; # OUTPUT: # Cannot resolve caller f(Int); none of these signatures match: # (int $x) # in block <unit> at -e line 1
However, this rule is waived if a call is being made where one of the arguments is a native type and another one is a numeric literal:
multi f(int, int) {} f 42, my int $x; # Successful call
This way you do not have to constantly write, for example, $n +> 2 as $n +> (my int $ = 2). The compiler knows the literal is small enough to fit to a native type and converts it to a native.
The language offers some operations that are guaranteed to be performed atomically, i.e. safe to be executed by multiple threads without the need for locking with no risk of data races.
For such operations, the atomicint native type is required. This type is similar to a plain native int, except it is sized such that CPU-provided atomic operations can be performed upon it. On a 32-bit CPU it will typically be 32 bits in size, and on an a 64-bit CPU it will typically be 64 bits in size.
# !!WRONG!! Might be non-atomic on some systems my int $x; await ^100 .map: { start $x⚛++ }; say $x; # OUTPUT: «98» # RIGHT! The use of `atomicint` type guarantees operation is atomic my atomicint $x; await ^100 .map: { start $x⚛++ }; say $x; # OUTPUT: «100»
The similarity to int is present in multi dispatch as well: an atomicint, plain int, and the sized int variants are all considered to be the same by the dispatcher and cannot be differentiated through multi-dispatch.
Numeric "infectiousness" dictates the resultant type when two numerics of different types are involved in some mathematical operations. A type is said to be more infectious than the other type if the result is of that type rather than the type of the other operand. For example, Num type is more infectious than an Int, thus we can expect 42e0 + 42 to produce a Num as the result.
The infectiousness is as follows, with the most infectious type listed first:
Complex
Num
FatRat
Rat
Int
say (2 + 2e0).^name; # Int + Num => OUTPUT: «Num» say (½ + ½).^name; # Rat + Rat => OUTPUT: «Rat» say (FatRat.new(1,2) + ½).^name; # FatRat + Rat => OUTPUT: «FatRat»
The allomorphs have the same infectiousness as their numeric component. Native types get autoboxed and have the same infectiousness as their boxed variant.
Object orientation in Perl 6
Perl 6 provides strong support for Object Oriented Programming (OOP). Although Perl 6 allows programmers to program in multiple paradigms, Object Oriented Programming is at the heart of the language.
Perl 6 comes with a wealth of predefined types, which can be classified in two categories: regular and native types. Everything that you can store in a variable is either a native value or an object. That includes literals, types (type objects), code and containers.
Native types are used for low-level types (like uint64). Even if native types do not have the same capabilities as objects, if you call methods on them, they are automatically boxed into normal objects.
Everything that is not a native value is an object. Objects do allow for both inheritance and encapsulation.
To call a method on an object, add a dot, followed by the method name:
say "abc".uc; # OUTPUT: «ABC»
This calls the uc method on "abc", which is an object of type Str. To supply arguments to the method, add arguments inside parentheses after the method.
my $formatted-text = "Fourscore and seven years ago...".indent(8); say $formatted-text; # OUTPUT: « Fourscore and seven years ago...»
$formatted-text now contains the above text, but indented 8 spaces.
Multiple arguments are separated by commas:
my @words = "Abe", "Lincoln"; @words.push("said", $formatted-text.comb(/\w+/)); say @words; # OUTPUT: «[Abe Lincoln said (Fourscore and seven years ago)]»
Similarly, multiple arguments can be specified by placing a colon after the method and separating the argument list with a comma:
say @words.join('--').subst: 'years', 'DAYS'; # OUTPUT: «Abe--Lincoln--said--Fourscore and seven DAYS ago»
Since you have to put a : after the method if you want to pass arguments without parentheses, a method call without a colon or parentheses is unambiguously a method call without an argument list:
say 4.log: ; # OUTPUT: «1.38629436111989» ( natural logarithm of 4 ) say 4.log: +2; # OUTPUT: «2» ( base-2 logarithm of 4 ) say 4.log +2; # OUTPUT: «3.38629436111989» ( natural logarithm of 4, plus 2 )
Many operations that don't look like method calls (for example, smartmatching or interpolating an object into a string) might result in method calls under the hood.
Methods can return mutable containers, in which case you can assign to the return value of a method call. This is how read-writable attributes to objects are used:
$*IN.nl-in = "\r\n";
Here, we call method nl-in on the $*IN object, without arguments, and assign to the container it returned with the = operator.
All objects support methods from class Mu, which is the type hierarchy root. All objects derive from Mu.
Types themselves are objects and you can get the type object by writing its name:
my $int-type-obj = Int;
You can request the type object of anything by calling the WHAT method, which is actually a macro in method form:
my $int-type-obj = 1.WHAT;
Type objects (other than Mu) can be compared for equality with the === identity operator:
sub f(Int $x) { if $x.WHAT === Int { say 'you passed an Int'; } else { say 'you passed a subtype of Int'; } }
Although, in most cases, the .isa method will suffice:
sub f($x) { if $x.isa(Int) { ... } ... }
Subtype checking is done by smartmatching:
if $type ~~ Real { say '$type contains Real or a subtype thereof'; }
Classes are declared using the class keyword, typically followed by a name.
class Journey { }
This declaration results in a type object being created and installed in the current package and current lexical scope under the name Journey. You can also declare classes lexically:
my class Journey { }
This restricts their visibility to the current lexical scope, which can be useful if the class is an implementation detail nested inside a module or another class.
Attributes are variables that exist per instance of a class; when instantiated to a value, the association between the variable and its value is called a property. They are where the state of an object is stored. In Perl 6, all attributes are private, which means they can be accessed directly only by the class instance itself. They are typically declared using the has declarator and the ! twigil.
class Journey { has $!origin; has $!destination; has @!travelers; has $!notes; }
While there is no such thing as a public (or even protected) attribute, there is a way to have accessor methods generated automatically: replace the ! twigil with the . twigil (the . should remind you of a method call).
class Journey { has $.origin; has $.destination; has @!travelers; has $.notes; }
This defaults to providing a read-only accessor. In order to allow changes to the attribute, add the is rw trait:
class Journey { has $.origin; has $.destination; has @!travelers; has $.notes is rw; }
Now, after a Journey object is created, its .origin, .destination, and .notes will all be accessible from outside the class, but only .notes can be modified.
If an object is instantiated without certain attributes, such as origin or destination, we may not get the desired result. To prevent this, provide default values or make sure that an attribute is set on object creation by marking an attribute with an is required trait.
class Journey { # error if origin is not provided has $.origin is required; # set the destination to Orlando as default (unless that is the origin!) has $.destination = self.origin eq 'Orlando' ?? 'Kampala' !! 'Orlando'; has @!travelers; has $.notes is rw; }
Since classes inherit a default constructor from Mu and we have requested that some accessor methods are generated for us, our class is already somewhat functional.
# Create a new instance of the class. my $vacation = Journey.new( origin => 'Sweden', destination => 'Switzerland', notes => 'Pack hiking gear!' ); # Use an accessor; this outputs Sweden. say $vacation.origin; # Use an rw accessor to change the value. $vacation.notes = 'Pack hiking gear and sunglasses!';
Note that, although the default constructor can initialize read-only attributes, it will only set attributes that have an accessor method. That is, even if you pass travelers => ["Alex", "Betty"] to the default constructor, the attribute @!travelers is not initialized.
Methods are declared with the method keyword inside a class body.
class Journey { has $.origin; has $.destination; has @!travelers; has $.notes is rw; method add-traveler($name) { if $name ne any(@!travelers) { push @!travelers, $name; } else { warn "$name is already going on the journey!"; } } method describe() { "From $!origin to $!destination" } }
A method can have a signature, just like a subroutine. Attributes can be used in methods and can always be used with the ! twigil, even if they are declared with the . twigil. This is because the . twigil declares a ! twigil and generates an accessor method.
Looking at the code above, there is a subtle but important difference between using $!origin and $.origin in the method describe. $!origin is an inexpensive and obvious lookup of the attribute. $.origin is a method call and thus may be overridden in a subclass. Only use $.origin if you want to allow overriding.
Unlike subroutines, additional named arguments will not produce compile time or runtime errors. That allows chaining of methods via Re-dispatching.
You may write your own accessors to override any or all of the autogenerated ones.
my $ⲧ = " " xx 4; # A tab-like thing class Journey { has $.origin; has $.destination; has @.travelers; has Str $.notes is rw; multi method notes() { "$!notes\n" }; multi method notes( Str $note ) { $!notes ~= "$note\n$ⲧ" }; method Str { "⤷ $!origin\n$ⲧ" ~ self.notes() ~ "$!destination ⤶\n" }; } my $trip = Journey.new( :origin<Here>, :destination<There>, travelers => <þor Freya> ); $trip.notes("First steps"); notes $trip: "Almost there"; print $trip; # OUTPUT: #⤷ Here # First steps # Almost there # #There ⤶
The declared multi method notes overrides the auto-generated methods implicit in the declaration of $.notes, using a different signature for reading and writing.
Please note that in notes $trip: "Almost there" we are using indirect invocant syntax, which puts first the method name, then the object, and then, separated by a colon, the arguments: method invocant: arguments. We can use this syntax whenever it feels more natural than the classical period-and-parentheses one. It works exactly in the same way.
Method names can be resolved at runtime with the ."" operator.
class A { has $.b }; my $name = 'b'; A.new."$name"().say; # OUTPUT: «(Any)»
The syntax used to update $.notes changed in this section with respect to the previous #Attributes section. Instead of an assignment:
$vacation.notes = 'Pack hiking gear and sunglasses!';
we now do a method call:
$trip.notes("First steps");
Overriding the default auto-generated accessor means it is no longer available to provide a mutable container on return for an assignment. A method call is the preferred approach to adding computation and logic to the update of an attribute. Many modern languages can update an attribute by overloading assignment with a “setter” method. While Perl 6 can overload the assignment operator for this purpose with a Proxy object, overloading assignment to set attributes with complex logic is currently discouraged as weaker object oriented design.
A method's signature can have an explicit invocant as its first parameter followed by a colon, which allows for the method to refer to the object it was called on.
class Foo { method greet($me: $person) { say "Hi, I am $me.^name(), nice to meet you, $person"; } } Foo.new.greet("Bob"); # OUTPUT: «Hi, I am Foo, nice to meet you, Bob»
Providing an invocant in the method signature also allows for defining the method as either as a class method, or as an object method, through the use of type constraints. The ::?CLASS variable can be used to provide the class name at compile time, combined with either :U (for class methods) or :D (for instance methods).
class Pizza { has $!radius = 42; has @.ingredients; # class method: construct from a list of ingredients method from-ingredients(::?CLASS:U $pizza: @ingredients) { $pizza.new( ingredients => @ingredients ); } # instance method method get-radius(::?CLASS:D:) { $!radius } } my $p = Pizza.from-ingredients: <cheese pepperoni vegetables>; say $p.ingredients; # OUTPUT: «[cheese pepperoni vegetables]» say $p.get-radius; # OUTPUT: «42» say Pizza.get-radius; # This will fail. CATCH { default { put .^name ~ ":\n" ~ .Str } }; # OUTPUT: «X::Parameter::InvalidConcreteness: # Invocant of method 'get-radius' must be # an object instance of type 'Pizza', # not a type object of type 'Pizza'. # Did you forget a '.new'?»
A method can be both a class and object method by using the multi declarator:
class C { multi method f(::?CLASS:U:) { say "class method" } multi method f(::?CLASS:D:) { say "object method" } } C.f; # OUTPUT: «class method» C.new.f; # OUTPUT: «object method»
Inside a method, the term self is available and bound to the invocant object. self can be used to call further methods on the invocant, including constructors:
class Box { has $.data; method make-new-box-from() { self.new: data => $!data; } }
self can be used in class or instance methods as well, though beware of trying to invoke one type of method from the other:
class C { method g() { 42 } method f(::?CLASS:U:) { self.g } method d(::?CLASS:D:) { self.f } } C.f; # OUTPUT: «42» C.new.d; # This will fail. CATCH { default { put .^name ~ ":\n" ~ .Str } }; # OUTPUT: «X::Parameter::InvalidConcreteness: # Invocant of method 'f' must be a type object of type 'C', # not an object instance of type 'C'. Did you forget a 'multi'?»
self can also be used with attributes, as long as they have an accessor. self.a will call the accessor for an attribute declared as has $.a. However, there is a difference between self.a and $.a, since the latter will itemize; $.a will be equivalent to self.a.item or $(self.a).
class A { has $.x = (1, 2, 3); method b() { .say for self.x; .say for $.x } }; A.new.b; # OUTPUT: «123(1 2 3)»
The colon-syntax for method arguments is only supported for method calls using self, not the shortcut.
Note that if the relevant methods bless, CREATE of Mu are not overloaded, self will point to the type object in those methods.
On the other hand, the submethods BUILD and TWEAK are called on instances, in different stages of initialization. Submethods of the same name from subclasses have not yet run, so you should not rely on potentially virtual method calls inside these methods.
Methods with an exclamation mark ! before the method name are not callable from anywhere outside the defining class; such methods are private in the sense that they are not visible from outside the class that declares them. Private methods are invoked with an exclamation mark instead of a dot:
class FunMath { has $.value is required; method !do-subtraction( $num ) { if $num ~~ Str { return $!value + (-1 * $num.chars); } return $!value + (-1 * $num); } method minus( $minuend: $subtrahend ) { # invoking the private method on the explicit invocant $minuend!do-subtraction($subtrahend); } } my $five = FunMath.new(value => 5); say $five.minus(6); # OUTPUT: «-1» say $five.do-subtraction(6); CATCH { default { put .^name ~ ":\n" ~ .Str } } # OUTPUT: «X::Method::NotFound: # No such method 'do-subtraction' for invocant of type # 'FunMath'. Did you mean '!do-subtraction'?»
Private methods are not inherited by subclasses.
Submethods are public methods that will not be inherited by subclasses. The name stems from the fact that they are semantically similar to subroutines.
Submethods are useful for object construction and destruction tasks, as well as for tasks that are so specific to a certain type that subtypes would certainly have to override them.
For example, the default method new calls submethod BUILD on each class in an inheritance chain:
class Point2D { has $.x; has $.y; submethod BUILD(:$!x, :$!y) { say "Initializing Point2D"; } } class InvertiblePoint2D is Point2D { submethod BUILD() { say "Initializing InvertiblePoint2D"; } method invert { self.new(x => - $.x, y => - $.y); } } say InvertiblePoint2D.new(x => 1, y => 2); # OUTPUT: «Initializing Point2D» # OUTPUT: «Initializing InvertiblePoint2D» # OUTPUT: «InvertiblePoint2D.new(x => 1, y => 2)»
See also: Object construction.
Classes can have parent classes.
class Child is Parent1 is Parent2 { }
If a method is called on the child class, and the child class does not provide that method, the method of that name in one of the parent classes is invoked instead, if it exists. The order in which parent classes are consulted is called the method resolution order (MRO). Perl 6 uses the C3 method resolution order. You can ask a type for its MRO through a call to its meta class:
say List.^mro; # ((List) (Cool) (Any) (Mu))
If a class does not specify a parent class, Any is assumed by default. All classes directly or indirectly derive from Mu, the root of the type hierarchy.
All calls to public methods are "virtual" in the C++ sense, which means that the actual type of an object determines which method to call, not the declared type:
class Parent { method frob { say "the parent class frobs" } } class Child is Parent { method frob { say "the child's somewhat more fancy frob is called" } } my Parent $test; $test = Child.new; $test.frob; # calls the frob method of Child rather than Parent # OUTPUT: «the child's somewhat more fancy frob is called»
Objects are generally created through method calls, either on the type object or on another object of the same type.
Class Mu provides a constructor method called new, which takes named arguments and uses them to initialize public attributes.
class Point { has $.x; has $.y; } my $p = Point.new( x => 5, y => 2); # ^^^ inherited from class Mu say "x: ", $p.x; say "y: ", $p.y; # OUTPUT: «x: 5» # OUTPUT: «y: 2»
Mu.new calls method bless on its invocant, passing all the named arguments. bless creates the new object, and then walks all subclasses in reverse method resolution order (i.e. from Mu to most derived classes) and in each class checks for the existence of a method named BUILD. If the method exists, the method is called with all the named arguments from the new method. If not, the public attributes from this class are initialized from named arguments of the same name. In either case, if neither BUILD nor the default mechanism has initialized the attribute, default values are applied. This means that BUILD may change an attribute, but it does not have access to the contents of the attribute declared as its default; these are available only during TWEAK (see below), which can 'see' the contents of an attribute initialized in the declaration of the class.
After the BUILD methods have been called, methods named TWEAK are called, if they exist, again with all the named arguments that were passed to new. See an example of its use below.
Due to the default behavior of BUILD and TWEAK submethods, named arguments to the constructor new derived from Mu can correspond directly to public attributes of any of the classes in the method resolution order, or to any named parameter of any BUILD or TWEAK submethod.
This object construction scheme has several implications for customized constructors. First, custom BUILD methods should always be submethods, otherwise they break attribute initialization in subclasses. Second, BUILD submethods can be used to run custom code at object construction time. They can also be used for creating aliases for attribute initialization:
class EncodedBuffer { has $.enc; has $.data; submethod BUILD(:encoding(:$enc), :$data) { $!enc := $enc; $!data := $data; } } my $b1 = EncodedBuffer.new( encoding => 'UTF-8', data => [64, 65] ); my $b2 = EncodedBuffer.new( enc => 'UTF-8', data => [64, 65] ); # both enc and encoding are allowed now
Since passing arguments to a routine binds the arguments to the parameters, a separate binding step is unnecessary if the attribute is used as a parameter. Hence the example above could also have been written as:
submethod BUILD(:encoding(:$!enc), :$!data) { # nothing to do here anymore, the signature binding # does all the work for us. }
However, be careful when using this auto-binding of attributes when the attribute may have special type requirements, such as an :$!id that must be a positive integer. Remember, default values will be assigned unless you specifically take care of this attribute, and that default value will be Any, which would cause a type error.
The third implication is that if you want a constructor that accepts positional arguments, you must write your own new method:
class Point { has $.x; has $.y; method new($x, $y) { self.bless(:$x, :$y); } }
However this is considered poor practice, because it makes correct initialization of objects from subclasses harder.
Another thing to note is that the name new is not special in Perl 6. It is merely a common convention, one that is followed quite thoroughly in most Perl 6 classes. You can call bless from any method at all, or use CREATE to fiddle around with low-level workings.
The TWEAK submethod allows you to check things or modify attributes after object construction:
class RectangleWithCachedArea { has ($.x1, $.x2, $.y1, $.y2); has $.area; submethod TWEAK() { $!area = abs( ($!x2 - $!x1) * ( $!y2 - $!y1) ); } } say RectangleWithCachedArea.new( x2 => 5, x1 => 1, y2 => 1, y1 => 0).area; # OUTPUT: «4»
The cloning is done using the clone method available on all objects, which shallow-clones both public and private attributes. New values for public attributes can be supplied as named arguments.
class Foo { has $.foo = 42; has $.bar = 100; } my $o1 = Foo.new; my $o2 = $o1.clone: :bar(5000); say $o1; # Foo.new(foo => 42, bar => 100) say $o2; # Foo.new(foo => 42, bar => 5000)
See document for clone for details on how non-scalar attributes get cloned, as well as examples of implementing your own custom clone methods.
Roles are a collection of attributes and methods; however, unlike classes, roles are meant for describing only parts of an object's behavior; this is why, in general, roles are intended to be mixed in classes and objects. In general, classes are meant for managing objects and roles are meant for managing behavior and code reuse within objects.
Roles use the keyword role preceding the name of the role that is declared. Roles are mixed in using the does keyword preceding the name of the role that is mixed in.
constant ⲧ = " " xx 4; #Just a ⲧab role Notable { has Str $.notes is rw; multi method notes() { "$!notes\n" }; multi method notes( Str $note ) { $!notes ~= "$note\n" ~ ⲧ }; } class Journey does Notable { has $.origin; has $.destination; has @.travelers; method Str { "⤷ $!origin\n" ~ ⲧ ~ self.notes() ~ "$!destination ⤶\n" }; } my $trip = Journey.new( :origin<Here>, :destination<There>, travelers => <þor Freya> ); $trip.notes("First steps"); notes $trip: "Almost there"; print $trip; # OUTPUT: #⤷ Here # First steps # Almost there # #There ⤶
Roles are immutable as soon as the compiler parses the closing curly brace of the role declaration.
Role application differs significantly from class inheritance. When a role is applied to a class, the methods of that role are copied into the class. If multiple roles are applied to the same class, conflicts (e.g. attributes or non-multi methods of the same name) cause a compile-time error, which can be solved by providing a method of the same name in the class.
This is much safer than multiple inheritance, where conflicts are never detected by the compiler, but are instead resolved to the superclass that appears earlier in the method resolution order, which might not be what the programmer wanted.
For example, if you've discovered an efficient method to ride cows, and are trying to market it as a new form of popular transportation, you might have a class Bull, for all the bulls you keep around the house, and a class Automobile, for things that you can drive.
class Bull { has Bool $.castrated = False; method steer { # Turn your bull into a steer $!castrated = True; return self; } } class Automobile { has $.direction; method steer($!direction) { } } class Taurus is Bull is Automobile { } my $t = Taurus.new; say $t.steer; # OUTPUT: «Taurus.new(castrated => Bool::True, direction => Any)»
With this setup, your poor customers will find themselves unable to turn their Taurus and you won't be able to make more of your product! In this case, it may have been better to use roles:
role Bull-Like { has Bool $.castrated = False; method steer { # Turn your bull into a steer $!castrated = True; return self; } } role Steerable { has Real $.direction; method steer(Real $d = 0) { $!direction += $d; } } class Taurus does Bull-Like does Steerable { }
This code will die with something like:
===SORRY!=== Method 'steer' must be resolved by class Taurus because it exists in multiple roles (Steerable, Bull-Like)
This check will save you a lot of headaches:
class Taurus does Bull-Like does Steerable { method steer($direction?) { self.Steerable::steer($direction) } }
When a role is applied to a second role, the actual application is delayed until the second role is applied to a class, at which point both roles are applied to the class. Thus
role R1 { # methods here } role R2 does R1 { # methods here } class C does R2 { }
produces the same class C as
role R1 { # methods here } role R2 { # methods here } class C does R1 does R2 { }
When a role contains a stubbed method, a non-stubbed version of a method of the same name must be supplied at the time the role is applied to a class. This allows you to create roles that act as abstract interfaces.
role AbstractSerializable { method serialize() { ... } # literal ... here marks the # method as a stub } # the following is a compile time error, for example # Method 'serialize' must be implemented by Point because # it's required by a role class APoint does AbstractSerializable { has $.x; has $.y; } # this works: class SPoint does AbstractSerializable { has $.x; has $.y; method serialize() { "p($.x, $.y)" } }
The implementation of the stubbed method may also be provided by another role.
Roles cannot inherit from classes, but they may carry classes, causing any class which does that role to inherit from the carried classes. So if you write:
role A is Exception { } class X::Ouch does A { } X::Ouch.^parents.say # OUTPUT: «((Exception))»
then X::Ouch will inherit directly from Exception, as we can see above by listing its parents.
As they do not use what can properly be called inheritance, roles are not part of the class hierarchy. Roles are listed with the .^roles meta-method instead, which uses transitive as flag for including all levels or just the first one. Despite this, a class or instance may still be tested with smartmatches or type constraints to see if it does a role.
role F { } class G does F { } G.^roles.say; # OUTPUT: «((F))» role Ur {} role Ar does Ur {} class Whim does Ar {}; Whim.^roles(:!transitive).say; # OUTPUT: «((Ar))» say G ~~ F; # OUTPUT: «True» multi a (F $a) { "F".say } multi a ($a) { "not F".say } a(G); # OUTPUT: «F»
A method defined directly in a class will always override definitions from applied roles or from inherited classes. If no such definition exists, methods from roles override methods inherited from classes. This happens both when said class was brought in by a role, and also when said class was inherited directly.
role M { method f { say "I am in role M" } } class A { method f { say "I am in class A" } } class B is A does M { method f { say "I am in class B" } } class C is A does M { } B.new.f; # OUTPUT «I am in class B» C.new.f; # OUTPUT «I am in role M»
Note that each candidate for a multi-method is its own method. In this case, the above only applies if two such candidates have the same signature. Otherwise, there is no conflict, and the candidate is just added to the multi-method.
Any attempt to directly instantiate a role or use it as a type object will automatically create a class with the same name as the role, making it possible to transparently use a role as if it were a class.
role Point { has $.x; has $.y; method abs { sqrt($.x * $.x + $.y * $.y) } method dimensions { 2 } } say Point.new(x => 6, y => 8).abs; # OUTPUT «10» say Point.dimensions; # OUTPUT «2»
We call this automatic creation of classes punning, and the generated class a pun.
Punning is not caused by most meta-programming constructs, however, as those are sometimes used to work directly with roles.
Roles can be parameterized, by giving them a signature in square brackets:
role BinaryTree[::Type] { has BinaryTree[Type] $.left; has BinaryTree[Type] $.right; has Type $.node; method visit-preorder(&cb) { cb $.node; for $.left, $.right -> $branch { $branch.visit-preorder(&cb) if defined $branch; } } method visit-postorder(&cb) { for $.left, $.right -> $branch { $branch.visit-postorder(&cb) if defined $branch; } cb $.node; } method new-from-list(::?CLASS:U: *@el) { my $middle-index = @el.elems div 2; my @left = @el[0 .. $middle-index - 1]; my $middle = @el[$middle-index]; my @right = @el[$middle-index + 1 .. *]; self.new( node => $middle, left => @left ?? self.new-from-list(@left) !! self, right => @right ?? self.new-from-list(@right) !! self, ); } } my $t = BinaryTree[Int].new-from-list(4, 5, 6); $t.visit-preorder(&say); # OUTPUT: «546» $t.visit-postorder(&say); # OUTPUT: «465»
Here the signature consists only of a type capture, but any signature will do:
enum Severity <debug info warn error critical>; role Logging[$filehandle = $*ERR] { method log(Severity $sev, $message) { $filehandle.print("[{uc $sev}] $message\n"); } } Logging[$*OUT].log(debug, 'here we go'); # OUTPUT: «[DEBUG] here we go»
You can have multiple roles of the same name, but with different signatures; the normal rules of multi dispatch apply for choosing multi candidates.
Roles can be mixed into objects. A role's given attributes and methods will be added to the methods and attributes the object already has. Multiple mixins and anonymous roles are supported.
role R { method Str() {'hidden!'} }; my $i = 2 but R; sub f(\bound){ put bound }; f($i); # OUTPUT: «hidden!» my @positional := <a b> but R; say @positional.^name; # OUTPUT: «List+{R}»
Note that the object got the role mixed in, not the object's class or the container. Thus, @-sigiled containers will require binding to make the role stick as is shown in the example with @positional. Some operators will return a new value, which effectively strips the mixin from the result. That is why it might be more clear to mix in the role in the declaration of the variable using does:
role R {}; my @positional does R = <a b>; say @positional.^name; # OUTPUT: «Array+{R}»
The operator infix:<but> is narrower than the list constructor. When providing a list of roles to mix in, always use parentheses.
role R1 { method m {} } role R2 { method n {} } my $a = 1 but R1,R2; # R2 is in sink context, issues a WARNING say $a.^name; # OUTPUT: «Int+{R1}» my $all-roles = 1 but (R1,R2); say $all-roles.^name; # OUTPUT: «Int+{R1,R2}»
Mixins can be used at any point in your object's life.
# A counter for Table of Contents role TOC-Counter { has Int @!counters is default(0); method Str() { @!counters.join: '.' } method inc($level) { @!counters[$level - 1]++; @!counters.splice($level); self } } my Num $toc-counter = NaN; # don't do math with Not A Number say $toc-counter; # OUTPUT: «NaN» $toc-counter does TOC-Counter; # now we mix the role in $toc-counter.inc(1).inc(2).inc(2).inc(1).inc(2).inc(2).inc(3).inc(3); put $toc-counter / 1; # OUTPUT: «NaN» (because that's numerical context) put $toc-counter; # OUTPUT: «2.2.2» (put will call TOC-Counter::Str)
Roles can be anonymous.
my %seen of Int is default(0 but role :: { method Str() {'NULL'} }); say %seen<not-there>; # OUTPUT: «NULL» say %seen<not-there>.defined; # OUTPUT: «True» (0 may be False but is well defined) say Int.new(%seen<not-there>); # OUTPUT: «0»
Perl 6 has a meta object system, which means that the behavior of objects, classes, roles, grammars, enums, etc. are themselves controlled by other objects; those objects are called meta objects. Meta objects are, like ordinary objects, instances of classes, in this case we call them meta classes.
For each object or class you can get the meta object by calling .HOW on it. Note that although this looks like a method call, it works more like a macro.
So, what can you do with the meta object? For one you can check if two objects have the same meta class by comparing them for equality:
say 1.HOW === 2.HOW; # OUTPUT: «True» say 1.HOW === Int.HOW; # OUTPUT: «True» say 1.HOW === Num.HOW; # OUTPUT: «False»
Perl 6 uses the word HOW (Higher Order Workings) to refer to the meta object system. Thus it should be no surprise that in Rakudo, the class name of the meta class that controls class behavior is called Perl6::Metamodel::ClassHOW. For each class there is one instance of Perl6::Metamodel::ClassHOW.
But of course the meta model does much more for you. For example, it allows you to introspect objects and classes. The calling convention for methods on meta objects is to call the method on the meta object and pass in the object of interest as first argument to the object. So to get the name of the class of an object, you could write:
my $object = 1; my $metaobject = 1.HOW; say $metaobject.name($object); # OUTPUT: «Int» # or shorter: say 1.HOW.name(1); # OUTPUT: «Int»
(The motivation is that Perl 6 also wants to allow a more prototype-based object system, where it's not necessary to create a new meta object for every type).
There's a shortcut to keep from using the same object twice:
say 1.^name; # OUTPUT: «Int» # same as say 1.HOW.name(1); # OUTPUT: «Int»
See Metamodel::ClassHOW for documentation on the meta class of class and also the general documentation on the meta object protocol.
Common Perl 6 infixes, prefixes, postfixes, and more!
See creating operators on how to define new operators.
In an expression like 1 + 2 * 3, the 2 * 3 is evaluated first because the infix * has tighter precedence than the +.
The following table summarizes the precedence levels in Perl 6, from tightest to loosest:
A | Level | Examples |
---|---|---|
N | Terms | 42 3.14 "eek" qq["foo"] $x :!verbose @$array rand time now ∅ |
L | Method postfix | .meth .+ .? .* .() .[] .{} .<> .«» .:: .= .^ .: |
N | Autoincrement | ++ -- |
R | Exponentiation | ** |
L | Symbolic unary | ! + - ~ ? | || +^ ~^ ?^ ^ |
L | Dotty infix | .= . |
L | Multiplicative | * × / ÷ % %% +& +< +> ~& ~< ~> ?& div mod gcd lcm |
L | Additive | + - − +| +^ ~| ~^ ?| ?^ |
L | Replication | x xx |
X | Concatenation | ~ o ∘ |
X | Junctive and | & (&) (.) ∩ ⊍ |
X | Junctive or | | ^ (|) (^) (+) (-) ∪ ⊖ ⊎ ∖ |
L | Named unary | temp let |
N | Structural infix | but does <=> leg unicmp cmp coll .. ..^ ^.. ^..^ |
C | Chaining infix | != ≠ == < <= ≤ > >= ≥ eq ne lt le gt ge ~~ === eqv !eqv =~= ≅ (elem) (cont) (<) (>) (<=) (>=) (<+) (>+) ∈ ∉ ∋ ∌ ⊂ ⊄ ⊃ ⊅ ⊆ ⊈ ⊇ ⊉ ≼ ≽ |
X | Tight and | && |
X | Tight or | || ^^ // min max |
R | Conditional | ?? !! ff ff^ ^ff ^ff^ fff fff^ ^fff ^fff^ |
R | Item assignment | = => += -= **= xx= |
L | Loose unary | so not |
X | Comma operator | , : |
X | List infix | Z minmax X X~ X* Xeqv ... … ...^ …^ |
R | List prefix | print push say die map substr ... [+] [*] any Z= |
X | Loose and | and andthen notandthen |
X | Loose or | or xor orelse |
X | Sequencer | <==, ==>, <<==, ==>> |
N | Terminator | ; {...}, unless, extra ), ], } |
Using two ! symbols below generically to represent any pair of operators that have the same precedence, the associativities specified above for binary operators are interpreted as follows:
A | Assoc | Meaning of $a ! $b ! $c |
---|---|---|
L | left | ($a ! $b) ! $c |
R | right | $a ! ($b ! $c) |
N | non | ILLEGAL |
C | chain | ($a ! $b) and ($b ! $c) |
X | list | infix:<!>($a; $b; $c) |
For unary operators this is interpreted as:
A | Assoc | Meaning of !$a! |
---|---|---|
L | left | (!$a)! |
R | right | !($a!) |
N | non | ILLEGAL |
In the operator descriptions below, a default associativity of left is assumed.
Operators can occur in several positions relative to a term:
+term | prefix |
term1 + term2 | infix |
term++ | postfix |
(term) | circumfix |
term1[term2] | postcircumfix |
.+(term) | method |
Each operator (except method operators) is also available as a subroutine. The name of the routine is formed from the operator category, followed by a colon, then a list quote construct with the symbol(s) that make up the operator:
infix:<+>(1, 2); # same as 1 + 2 circumfix:«[ ]»(<a b c>); # same as [<a b c>]
As a special case, a listop (list operator) can stand either as a term or as a prefix. Subroutine calls are the most common listops. Other cases include meta-reduced infix operators ([+] 1, 2, 3) and the #prefix ... etc. stub operators.
Defining custom operators is covered in Defining operators functions.
Metaoperators can be parameterized with other operators or subroutines in the same way as functions can take functions as parameters. To use a subroutine as a parameter, prefix its name with a &. Perl 6 will generate the actual combined operator in the background, allowing the mechanism to be applied to user defined operators. To disambiguate chained metaoperators, enclose the inner operator in square brackets. There are quite a few metaoperators with different semantics as explained, next.
Each substitution operator comes into two main forms: a lowercase one (e.g., s///) that performs in-place (i.e., destructive behavior; and an uppercase form (e.g., S///) that provides a non-destructive behavior.
my $str = 'old string'; $str ~~ s/o .+ d/new/; say $str; # OUTPUT: «new string»
s/// operates on the $_ topical variable, changing it in place. It uses the given Regex to find portions to replace and changes them to the provided replacement string. Sets $/ to the Match object or, if multiple matches were made, a List of Match objects. Returns $/.
It's common to use this operator with the ~~ smartmatch operator, as it aliases left-hand side to $_, which s/// uses.
Regex captures can be referenced in the replacement part; it takes the same adverbs as the .subst method, which go between the s and the opening /, separated with optional whitespace:
my $str = 'foo muCKed into the lEn'; # replace second 'o' with 'x' $str ~~ s:2nd/o/x/; # replace 'M' or 'L' followed by non-whitespace stuff with 'd' # and lower-cased version of that stuff: $str ~~ s :g :i/<[ML]> (\S+)/d{lc $0}/; say $str; # OUTPUT: «fox ducked into the den»
You can also use a different delimiter:
my $str = 'foober'; $str ~~ s!foo!fox!; $str ~~ s{b(.)r} = " d$0n"; say $str; # OUTPUT: «fox den»
Non-paired characters can simply replace the original slashes. Paired characters, like curly braces, are used only on the match portion, with the substitution given by assignment (of anything: a string, a routine call, etc.).
say S/o .+ d/new/ with 'old string'; # OUTPUT: «new string» S:g/« (.)/$0.uc()/.say for <foo bar ber>; # OUTPUT: «FooBarBer»
S/// uses the same semantics as the s/// operator, except it leaves the original string intact and returns the resultant string instead of $/ ($/ still being set to the same values as with s///).
Note: since the result is obtained as a return value, using this operator with the ~~ smartmatch operator is a mistake and will issue a warning. To execute the substitution on a variable that isn't the $_ this operator uses, alias it to $_ with given, with, or any other way. Alternatively, use the .subst method.
my $str = 'old string'; $str ~~ tr/dol/wne/; say $str; # OUTPUT: «new string»
tr/// operates on the $_ topical variable and changes it in place. It behaves similar to Str.trans called with a single Pair argument, where key is the matching part (characters dol in the example above) and value is the replacement part (characters wne in the example above). Accepts the same adverbs as Str.trans. Returns the StrDistance object that measures the distance between original value and the resultant string.
my $str = 'old string'; $str ~~ tr:c:d/dol st//; say $str; # OUTPUT: «ring»
with 'old string' { say TR/dol/wne/; # OUTPUT: «new string» }
TR/// behaves the same as the tr/// operator, except that it leaves the $_ value untouched and instead returns the resultant string.
say TR:d/dol // with 'old string'; # OUTPUT: «string»
Infix operators can be combined with the assignment operator to modify a value and apply the result to a container in one go. Containers will be autovivified if possible. Some examples:
my $a = 32; $a += 10; # 42 $a -= 2; # 40 $a = 3; $a min= 5; # still 3 $a min= 2; # 2 my $s = 'a'; $s ~= 'b'; # 'ab'
This behavior is automatically extended to include custom-defined infix operators.
sub infix:<space-concat> ($a, $b) { $a ~ " " ~ $b }; my $a = 'word1'; $a space-concat= 'word2'; # RESULT: «'word1 word2'»
Although not strictly operators, methods can be used in the same fashion.
my Real $a = 1/2; $a = 3.14; $a .= round; # RESULT: «3»
The result of a relational operator returning Bool can be negated by prefixing with !. To avoid visual confusion with the !! operator, you may not modify any operator already beginning with !.
There are shortcuts for !== and !eq, namely != and ne.
my $a = True; say so $a != True; # OUTPUT: «False» my $i = 10; my $release = Date.new(:2015year, :12month, :24day); my $today = Date.today; say so $release !before $today; # OUTPUT: «False»
Any infix operator may be called with its two arguments reversed by prefixing with R. Associativity of operands is reversed as well.
say 4 R/ 12; # OUTPUT: «3» say [R/] 2, 4, 16; # OUTPUT: «2» say [RZ~] <1 2 3>,<4 5 6> # OUTPUT: «(41 52 63)»
Hyper operators include « and », with their ASCII variants << and >>. They apply a given operator enclosed (or preceded or followed, in the case of unary operators) by « and/or » to one or two lists, returning the resulting list, with the pointy part of « or » aimed at the shorter list. Single elements are turned to a list, so they can be used too. If one of the lists is shorter than the other, the operator will cycle over the shorter list until all elements of the longer list are processed.
say (1, 2, 3) »*» 2; # OUTPUT: «(2 4 6)» say (1, 2, 3, 4) »~» <a b>; # OUTPUT: «(1a 2b 3a 4b)» say (1, 2, 3) »+« (4, 5, 6); # OUTPUT: «(5 7 9)» say (&sin, &cos, &sqrt)».(0.5); # OUTPUT: «(0.479425538604203 0.877582561890373 0.707106781186548)»
The last example illustrates how postcircumfix operators (in this case .()) can also be hypered.
my @a = <1 2 3>; my @b = <4 5 6>; say (@a,@b)»[1]; # OUTPUT: «(2 5)»
In this case, it's the postcircumfix[] which is being hypered.
Assignment metaoperators can be hyped.
my @a = 1, 2, 3; say @a »+=» 1; # OUTPUT: «[2 3 4]» my ($a, $b, $c); (($a, $b), $c) «=» ((1, 2), 3); say "$a, $c"; # OUTPUT: «1, 3»
Hyper forms of unary operators have the pointy bit aimed at the operator and the blunt end at the list to be operated on.
my @wisdom = True, False, True; say !« @wisdom; # OUTPUT: «[False True False]» my @a = 1, 2, 3; @a»++; # OUTPUT: «(2, 3, 4)»
Hyper operators are defined recursively on nested arrays.
say -« [[1, 2], 3]; # OUTPUT: «[[-1 -2] -3]»
Also, methods can be called in an out of order, concurrent fashion. The resulting list will be in order. Note that all hyper operators are candidates for parallelism and will cause tears if the methods have side effects. The optimizer has full reign over hyper operators, which is the reason that they cannot be defined by the user.
class CarefulClass { method take-care {} } my CarefulClass @objs; my @results = @objs».take-care(); my @slops; # May Contain Nuts @slops».?this-method-may-not-exist();
Hyper operators can work with hashes. The pointy direction indicates if missing keys are to be ignored in the resulting hash. The enclosed operator operates on all values that have keys in both hashes.
%foo «+» %bar; | intersection of keys |
%foo »+« %bar; | union of keys |
%outer »+» %inner; | only keys of %inner that exist in %outer will occur in the result |
my %outer = 1, 2, 3 Z=> <a b c>; my %inner = 1, 2 Z=> <x z>; say %outer «~» %inner; # OUTPUT: «{"1" => "ax", "2" => "bz"}»
Hyper operators can take user-defined operators as their operator argument.
sub pretty-file-size (Int $size --> Str) { # rounding version of infix:</>(Int, Int) sub infix:<r/>(Int \i1, Int \i2) { round(i1 / i2, 0.1) } # we build a vector of fractions of $size and zip that with the fitting prefix for $size «[r/]« (2**60, 2**50, 2**40, 2**30, 2**20, 2**10) Z <EB PB TB GB MB KB> -> [\v,\suffix] { # starting with the biggest suffix, # we take the first that is 0.5 of that suffix or bigger return v ~ ' ' ~ suffix if v > 0.4 } # this be smaller or equal then 0.4 KB return $size.Str; } for 60, 50, 40, 30, 20, 10 -> $test { my &a = { (2 ** $test) * (1/4, 1/2, 1, 10, 100).pick * (1..10).pick }; print pretty-file-size(a.Int) xx 2, ' '; } # OUTPUT: «10 EB 4 EB 2 PB 5 PB 0.5 PB 4 TB 300 GB 4.5 GB 50 MB 200 MB 9 KB 0.6 MB»
Whether hyperoperators descend into child lists depends on the nodality of the inner operator of a chain. For the hyper method call operator (».), the nodality of the target method is significant.
say (<a b>, <c d e>)».elems; # OUTPUT: «(2 3)» say (<a b>, <c d e>)».&{ .elems }; # OUTPUT: «((1 1) (1 1 1))»
You can chain hyper operators to destructure a List of Lists.
my $neighbors = ((-1, 0), (0, -1), (0, 1), (1, 0)); my $p = (2, 3); say $neighbors »>>+<<» ($p, *); # OUTPUT: «((1 3) (2 2) (2 4) (3 3))»
The reduction metaoperator, [ ], reduces a list with the given infix operator. It gives the same result as the reduce routine - see there for details.
# These two are equivalent: say [+] 1, 2, 3; # OUTPUT: «6» say reduce &infix:<+>, 1, 2, 3; # OUTPUT: «6»
No whitespace is allowed between the square brackets and the operator. To wrap a function instead of an operator, provide an additional layer of square brackets:
sub plus { $^a + $^b }; say [[&plus]] 1, 2, 3; # OUTPUT: «6»
The argument list is iterated without flattening. This means that you can pass a nested list to the reducing form of a list infix operator:
say [X~] (1, 2), <a b>; # OUTPUT: «(1a 1b 2a 2b)»
which is equivalent to 1, 2 X~ <a b>.
By default, only the final result of the reduction is returned. Prefix the wrapped operator with a \, to return a lazy list of all intermediate values instead. This is called a "triangular reduce". If the non-meta part contains a \ already, quote it with [] (e.g. [\[\x]]).
my @n = [\~] 1..*; say @n[^5]; # OUTPUT: «(1 12 123 1234 12345)»
The cross metaoperator, X, will apply a given infix operator in order of cross product to all lists, such that the rightmost operator varies most quickly.
1..3 X~ <a b> # RESULT: «<1a, 1b, 2a, 2b, 3a, 3b>»
The zip metaoperator (which is not the same thing as Z) will apply a given infix operator to pairs taken one left, one right, from its arguments. The resulting list is returned.
my @l = <a b c> Z~ 1, 2, 3; # RESULT: «[a1 b2 c3]»
If one of the operands runs out of elements prematurely, the zip operator will stop. An infinite list can be used to repeat elements. A list with a final element of * will repeat its 2nd last element indefinitely.
my @l = <a b c d> Z~ ':' xx *; # RESULT: «<a: b: c: d:>» @l = <a b c d> Z~ 1, 2, *; # RESULT: «<a1 b2 c2 d2>»
If an infix operator is not given, the , (comma operator) will be used by default:
my @l = 1 Z 2; # RESULT: «[(1 2)]»
The sequential metaoperator, S, will suppress any concurrency or reordering done by the optimizer. Most simple infix operators are supported.
say so 1 S& 2 S& 3; # OUTPUT: «True»
To avoid ambiguity when chaining metaoperators, use square brackets to help the compiler understand you.
my @a = 1, 2, 3; my @b = 5, 6, 7; @a X[+=] @b; say @a; # OUTPUT: «[19 20 21]»
The quote-words construct breaks up the contents on whitespace and returns a List of the words. If a word looks like a number literal or a Pair literal, it's converted to the appropriate number.
say <a b c>[1]; # OUTPUT: «b»
An empty group () creates an empty list. Parentheses around non-empty expressions simply structure the expression, but do not have additional semantics.
In an argument list, putting parenthesis around an argument prevents it from being interpreted as a named argument.
multi sub p(:$a!) { say 'named' } multi sub p($a) { say 'positional' } p a => 1; # OUTPUT: «named» p (a => 1); # OUTPUT: «positional»
If the content is empty, or contains a single list that starts with a Pair literal or %-sigiled variable, and the $_ variable or placeholder parameters are not used, the constructor returns a Hash. Otherwise it constructs a Block.
To force construction of a Block, follow the opening brace with a semicolon. To always ensure you end up with a Hash, you can use %( ) coercer or hash routine instead:
{}.^name.say; # OUTPUT: «Hash» {;}.^name.say; # OUTPUT: «Block» {:$_}.^name.say; # OUTPUT: «Block» %(:$_).^name.say; # OUTPUT: «Hash» hash(:$_).^name.say; # OUTPUT: «Hash»
The Array constructor returns an itemized Array that does not flatten in list context. Check this:
say .perl for [3,2,[1,0]]; # OUTPUT: «32$[1, 0]»
This array is itemized, in the sense that every element constitutes an item, as shown by the $ preceding the last element of the array, the (list) item contextualizer.
Terms have their own extended documentation.
sub postcircumfix:<[ ]>(@container, **@index, :$k, :$v, :$kv, :$p, :$exists, :$delete)
Universal interface for positional access to zero or more elements of a @container, a.k.a. "array indexing operator".
my @alphabet = 'a' .. 'z'; say @alphabet[0]; # OUTPUT: «a» say @alphabet[1]; # OUTPUT: «b» say @alphabet[*-1]; # OUTPUT: «z» say @alphabet[100]:exists; # OUTPUT: «False» say @alphabet[15, 4, 17, 11].join; # OUTPUT: «perl» say @alphabet[23 .. *].perl; # OUTPUT: «("x", "y", "z")» @alphabet[1, 2] = "B", "C"; say @alphabet[0..3].perl # OUTPUT: «("a", "B", "C", "d")»
See Subscripts, for a more detailed explanation of this operator's behavior and for how to implement support for it in custom types.
sub postcircumfix:<{ }>(%container, **@key, :$k, :$v, :$kv, :$p, :$exists, :$delete)
Universal interface for associative access to zero or more elements of a %container, a.k.a. "hash indexing operator".
my %color = kiwi => "green", banana => "yellow", cherry => "red"; say %color{"banana"}; # OUTPUT: «yellow» say %color{"cherry", "kiwi"}.perl; # OUTPUT: «("red", "green")» say %color{"strawberry"}:exists; # OUTPUT: «False» %color{"banana", "lime"} = "yellowish", "green"; %color{"cherry"}:delete; say %color; # OUTPUT: «banana => yellowish, kiwi => green, lime => green»
See postcircumfix < > and postcircumfix « » for convenient shortcuts, and Subscripts for a more detailed explanation of this operator's behavior and how to implement support for it in custom types.
Decontainerization operator, which extracts the value from a container and makes it independent of the container type.
use JSON::Tiny; my $config = from-json('{ "files": 3, "path": "/home/perl6/perl6.pod6" }'); say $config.perl; # OUTPUT: «${:files(3), :path("/home/perl6/perl6.pod6")}» my %config-hash = $config<>; say %config-hash.perl; # OUTPUT: «{:files(3), :path("/home/perl6/perl6.pod6")}»
It's a Hash in both cases, and it can be used like that; however, in the first case it was in item context, and in the second case it has been extracted to its proper context.
Shortcut for postcircumfix { } that quotes its argument using the same rules as the quote-words operator of the same name.
my %color = kiwi => "green", banana => "yellow", cherry => "red"; say %color<banana>; # OUTPUT: «yellow» say %color<cherry kiwi>.perl; # OUTPUT: «("red", "green")» say %color<strawberry>:exists; # OUTPUT: «False»
Technically, not a real operator; it's syntactic sugar that's turned into the { } postcircumfix operator at compile-time.
Shortcut for postcircumfix { } that quotes its argument using the same rules as the interpolating quote-words operator of the same name.
my %color = kiwi => "green", banana => "yellow", cherry => "red"; my $fruit = "kiwi"; say %color«cherry "$fruit"».perl; # OUTPUT: «("red", "green")»
Technically, not a real operator; it's syntactic sugar that's turned into the { } postcircumfix operator at compile-time.
The call operator treats the invocant as a Callable and invokes it, using the expression between the parentheses as arguments.
Note that an identifier followed by a pair of parentheses is always parsed as a subroutine call.
If you want your objects to respond to the call operator, implement a method CALL-ME.
The operator for calling one method, $invocant.method.
Technically, not a real operator; it's syntax special-cased in the compiler.
The operator to call a subroutine (with at least one positional argument), such as a method. The invocant will be bound to the first positional argument.
Technically, not a real operator; it's syntax special-cased in the compiler.
my sub f($invocant){ "The arg has a value of $invocant" } 42.&f; # OUTPUT: «The arg has a value of 42» 42.&(-> $invocant { "The arg has a value of $invocant" }); # OUTPUT: «The arg has a value of 42»
A mutating method call. $invocant.=method desugars to $invocant = $invocant.method, similar to = .
Technically, not a real operator; it's syntax special-cased in the compiler.
A meta-method call. $invocant.^method calls method on $invocant's metaclass. It desugars to $invocant.HOW.method($invocant, ...). See the meta-object protocol documentation for more information.
Technically, not a real operator; it's syntax special-cased in the compiler.
Safe call operator. $invocant.?method calls method method on $invocant if it has a method of such name. Otherwise it returns Nil.
Technically, not a real operator; it's syntax special-cased in the compiler.
$foo.+meth walks the MRO and calls all the methods called meth and submethods called meth if the type is the same as type of $foo. Those methods might be multis, in which case the matching candidate would be called.
After that, a List of the results are returned. If no such method was found, it throws a X::Method::NotFound exception.
class A { method foo { say "from A"; } } class B is A { multi method foo { say "from B"; } multi method foo(Str) { say "from B (Str)"; } } class C is B is A { multi method foo { say "from C"; } multi method foo(Str) { say "from C (Str)"; } } say C.+foo; # OUTPUT: «from Cfrom Bfrom A(True True True)»
$foo.*meth walks the MRO and calls all the methods called meth and submethods called meth if the type is the same as type of $foo. Those methods might be multis, in which case the matching candidate would be called.
After that, a List of the results are returned. If no such method was found, an empty List is returned.
Technically, postfix .+ calls .* at first. Read postfix .+ section to see examples.
This is the hyper method call operator. Will call a method on all elements of a List out of order and return the list of return values in order.
my @a = <a b c>; my @b = @a».ord; # OUTPUT: «[97, 98, 99]» # The first parameter of a method is the invocant. sub foo(Str:D $c){ $c.ord * 2 }; # So we can pretend to have a method call with a sub that got a good # first positional argument. say @a».&foo; # Blocks have an implicit positional arguments that lands in $_. The latter can # be omitted for method calls. say @a».&{ .ord};
Hyper method calls may appear to be the same as doing a map call, however along with being a hint to the compiler that it can parallelize the call, the behavior is also affected by nodality of the method being invoked, depending on which either nodemap or deepmap semantics are used to perform the call.
The nodality is checked by looking up whether the Callable provides nodal method. If the hyper is applied to a method, that Callable is that method name, looked up on List type; if the hyper is applied to a routine (e.g. ».&foo), that routine functions as that Callable. If the Callable is determined to provide nodal method, nodemap semantics are used to perform the hyper call, otherwise duckmap semantics are used.
Take care to avoid a common mistake of expecting side-effects to occur in order. The following say is not guaranteed to produce the output in order:
@a».say; # WRONG! Could produce abc or cba or any other order
In most cases, a dot may be placed before a postfix or postcircumfix:
my @a; @a[1, 2, 3]; @a.[1, 2, 3]; # Same
This can be useful for visual clarity or brevity. For example, if an object's attribute is a function, putting a pair of parentheses after the attribute name will become part of the method call. So, either two pairs of parentheses must be used or a dot has to come before the parentheses to separate it from the method call.
class Operation { has $.symbol; has &.function; } my $addition = Operation.new(:symbol<+>, :function{ $^a + $^b }); say $addition.function()(1, 2); # OUTPUT: «3» # OR say $addition.function.(1, 2); # OUTPUT: «3»
If the postfix is an identifier, however, it will be interpreted as a normal method call.
1.i # No such method 'i' for invocant of type 'Int'
Technically, not a real operator; it's syntax special-cased in the compiler.
An operator in prefix form can still be called like a method, that is, using the . methodop notation, by preceding it by a colon. For example:
my $a = 1; say ++$a; # OUTPUT: «2» say $a.:<++>; # OUTPUT: «3»
Technically, not a real operator; it's syntax special-cased in the compiler, that is why it's classified as a methodop.
A class-qualified method call, used to call a method as defined in a parent class or role, even after it has been redefined in the child class.
class Bar { method baz { 42 } } class Foo is Bar { method baz { "nope" } } say Foo.Bar::baz; # OUTPUT: «42»
Creates an object that concatenates, in a class-dependent way, the contents of the variable on the left hand side and the expression on the right hand side:
my %a = :11a, :22b; %a ,= :33x; say %a # OUTPUT: «{a => 11, b => 22, x => 33}»
multi sub prefix:<++>($x is rw) is assoc<non>
This is the . Increments its argument by one and returns the updated value.
my $x = 3; say ++$x; # OUTPUT: «4» say $x; # OUTPUT: «4»
It works by calling the succ method (for successor) on its argument, which gives custom types the freedom to implement their own increment semantics.
multi sub prefix:<-->($x is rw) is assoc<non>
Decrements its argument by one and returns the updated value.
my $x = 3; say --$x; # OUTPUT: «2» say $x; # OUTPUT: «2»
It works by calling the pred method (for predecessor) on its argument, which gives custom types the freedom to implement their own decrement semantics.
multi sub postfix:<++>($x is rw) is assoc<non>
Increments its argument by one and returns the original value.
my $x = 3; say $x++; # OUTPUT: «3» say $x; # OUTPUT: «4»
It works by calling the succ method (for successor) on its argument, which gives custom types the freedom to implement their own increment semantics.
Note that this does not necessarily return its argument; e.g., for undefined values, it returns 0:
my $x; say $x++; # OUTPUT: «0» say $x; # OUTPUT: «1»
Increment on Str will increment the number part of a string and assign the resulting string to the container. A is rw-container is required.
my $filename = "somefile-001.txt"; say $filename++ for 1..3; # OUTPUT: «somefile-001.txtsomefile-002.txtsomefile-003.txt»
multi sub postfix:<-->($x is rw) is assoc<non>
Decrements its argument by one and returns the original value.
my $x = 3; say $x--; # OUTPUT: «3» say $x; # OUTPUT: «2»
It works by calling the pred method (for predecessor) on its argument, which gives custom types the freedom to implement their own decrement semantics.
Note that this does not necessarily return its argument;e.g., for undefined values, it returns 0:
my $x; say $x--; # OUTPUT: «0» say $x; # OUTPUT: «-1»
Decrement on Str will decrement the number part of a string and assign the resulting string to the container. A is rw-container is required. Crossing 0 is prohibited and throws X::AdHoc.
my $filename = "somefile-003.txt"; say $filename-- for 1..3; # OUTPUT: «somefile-003.txtsomefile-002.txtsomefile-001.txt»
multi sub infix:<**>(Any, Any --> Numeric:D) is assoc<right>
The exponentiation operator coerces both arguments to Numeric and calculates the left-hand-side raised to the power of the right-hand side.
If the right-hand side is a non-negative integer and the left-hand side is an arbitrary precision type (Int, FatRat), then the calculation is carried out without loss of precision.
Unicode superscripts will behave in exactly the same way.
sub squared( Int $num ) { $num² }; say squared($_) for ^5; OUTPUT: «014916»
It also works for sequences of several Unicode superscript numbers:
sub twenty-second-power( Int $num ) { $num²² }; say twenty-second-power($_) for ^5; # OUTPUT: «0141943043138105960917592186044416»
multi sub prefix:<?>(Mu --> Bool:D)
Coerces the argument to Bool by calling the Bool method on it. Note that this collapses Junctions.
multi sub prefix:<!>(Mu --> Bool:D)
Negated boolean context operator.
Coerces the argument to Bool by calling the Bool method on it, and returns the negation of the result. Note that this collapses Junctions.
multi sub prefix:<+>(Any --> Numeric:D)
Coerces the argument to Numeric by calling the Numeric method on it.
multi sub prefix:<->(Any --> Numeric:D)
Negative numeric context operator.
Coerces the argument to Numeric by calling the Numeric method on it, and then negates the result.
multi sub prefix:<~>(Any --> Str:D)
Coerces the argument to Str by calling the Str method on it.
Flattens objects of type Capture, Pair, List, Map and Hash into an argument list.
sub slurpee( |args ){ say args.perl }; slurpee( <a b c d>, { e => 3 }, 'e' => 'f' => 33 ) # OUTPUT: «\(("a", "b", "c", "d"), {:e(3)}, :e(:f(33)))»
Please see the Signature page, specially the section on Captures for more information on the subject.
Outside of argument lists, it returns a Slip, which makes it flatten into the outer list. Inside argument list Positional s are turned into positional arguments and Associative s are turned into named arguments.
multi sub prefix:<+^>(Any --> Int:D)
Integer bitwise negation operator: Coerces the argument to Int and does a bitwise negation on the result, assuming two's complement.
Coerces the argument to a non-variable-encoding string buffer type (e.g. buf8, buf16, buf32) and then flips each bit in that buffer.
Please note that this has not yet been implemented.
multi sub prefix:<?^>(Mu --> Bool:D)
Boolean bitwise negation operator: Coerces the argument to Bool and then does a bit flip, which makes it the same as prefix:<!> .
multi sub prefix:<^>(Any --> Range:D)
Coerces the argument to Numeric, and generates a range from 0 up to (but excluding) the argument.
say ^5; # OUTPUT: «0..^5» for ^5 { } # 5 iterations
These operators are like their Method Postfix counterparts, but require surrounding whitespace (before and/or after) to distinguish them.
Calls the right-side method on the value in the left-side container, replacing the resulting value in the left-side container.
In most cases, this behaves identically to the postfix mutator, but the precedence is lower:
my $a = -5; say ++$a.=abs; # OUTPUT: «6»
say ++$a .= abs; # OUTPUT: «Cannot modify an immutable Int # in block <unit> at <tmp> line 1»
Calls the following method (whose name must be alphabetic) on the left-side invocant.
Note that the infix form of the operator has a slightly lower precedence than postfix .meth.
say -5.abs; # like: -(5.abs) # OUTPUT: «-5» say -5 . abs; # like: (-5) . abs # OUTPUT: «5» say -5 .abs; # following whitespace is optional # OUTPUT: «5»
multi sub infix:<*>(Any, Any --> Numeric:D)
Coerces both arguments to Numeric and multiplies them. The result is of the wider type. See Numeric for details.
multi sub infix:</>(Any, Any --> Numeric:D)
Coerces both argument to Numeric and divides the left through the right number. Division of Int values returns Rat, otherwise the "wider type" rule described in Numeric holds.
multi sub infix:<div>(Int:D, Int:D --> Int:D)
Integer division operator. Rounds down.
multi sub infix:<%>($x, $y --> Numeric:D)
Modulo operator. Coerces to Numeric first.
Generally the following identity holds:
my ($x, $y) = 1,2; $x % $y == $x - floor($x / $y) * $y
multi sub infix:<%%>($a, $b --> Bool:D)
Divisibility operator. Returns True if $a % $b == 0.
multi sub infix:<mod>(Int:D $a, Int:D $b --> Int:D)
Integer modulo operator. Returns the remainder of an integer modulo operation.
multi sub infix:<+&>($a, $b --> Int:D)
Numeric bitwise AND operator. Coerces both arguments to Int and does a bitwise AND operation assuming two's complement.
multi sub infix:<< +< >>($a, $b --> Int:D)
Integer bit shift to the left.
multi sub infix:<< +> >>($a, $b --> Int:D)
Integer bit shift to the right.
Coerces each argument to a non-variable-encoding string buffer type (e.g. buf8, buf16, buf32) and then performs a numeric bitwise AND on corresponding integers of the two buffers, padding the shorter buffer with zeroes.
Coerces the left argument to a non-variable-encoding string buffer type (e.g. buf8, buf16, buf32) and then performs a numeric bitwise left shift on the bits of the buffer.
Please note that this has not yet been implemented.
Coerces the left argument to a non-variable-encoding string buffer type (e.g. buf8, buf16, buf32) and then performs a numeric bitwise right shift on the bits of the buffer.
Please note that this has not yet been implemented.
multi sub infix:<gcd>($a, $b --> Int:D)
Coerces both arguments to Int and returns the greatest common divisor. If one of its arguments is 0, the other is returned (when both arguments are 0, the operator returns 0).
multi sub infix:<lcm>($a, $b --> Int:D)
Coerces both arguments to Int and returns the least common multiple; that is, the smallest integer that is evenly divisible by both arguments.
multi sub infix:<+>($a, $b --> Numeric:D)
Coerces both arguments to Numeric and adds them.
multi sub infix:<->($a, $b --> Numeric:D)
Coerces both arguments to Numeric and subtracts the second from the first.
multi sub infix:<+|>($a, $b --> Int:D)
Integer bitwise OR operator: Coerces both arguments to Int and does a bitwise OR (inclusive OR) operation.
multi sub infix:<+^>($a, $b --> Int:D)
Integer bitwise XOR operator: Coerces both arguments to Int and does a bitwise XOR (exclusive OR) operation.
Coerces each argument to a non-variable-encoding string buffer type (e.g. buf8, buf16, buf32) and then performs a numeric bitwise OR on corresponding integers of the two buffers, padding the shorter buffer with zeroes.
Coerces each argument to a non-variable-encoding string buffer type (e.g. buf8, buf16, buf32) and then performs a numeric bitwise XOR on corresponding integers of the two buffers, padding the shorter buffer with zeroes.
multi sub infix:<?^>(Mu $x = Bool::False) multi sub infix:<?^>(Mu \a, Mu \b)
Boolean bitwise XOR operator: Coerces the argument(s) to Bool and performs logical XOR on them: it will return True if and only if just one of the argument is true. It returns identity on a single argument.
multi sub infix:<?|>($a, $b --> Bool:D)
Coerces both arguments to Bool and does a logical OR (inclusive OR) operation.
sub infix:<x>($a, $b --> Str:D)
Repeats the string $a $b times, if necessary coercing $a to Str and $b Int. Returns an empty string if $b <= 0 . An exception X::Numeric::CannotConvert will be thrown if $b is -Inf or NaN.
say 'ab' x 3; # OUTPUT: «ababab» say 42 x 3; # OUTPUT: «424242» my $a = 'a'.IO; my $b = 3.5; say $a x $b; # OUTPUT: «aaa»
Defined as:
multi sub infix:<xx>() multi sub infix:<xx>(Mu \x) multi sub infix:<xx>(&x, Num:D() $n) multi sub infix:<xx>(&x, Whatever) multi sub infix:<xx>(&x, Bool:D $b) multi sub infix:<xx>(&x, Int:D $n) multi sub infix:<xx>(Mu \x, Num:D() $n) multi sub infix:<xx>(Mu \x, Whatever) multi sub infix:<xx>(Mu \x, Bool:D $b) multi sub infix:<xx>(Mu \x, Int:D $n)
In general, it returns a Sequence of $a repeated and evaluated $b times ($b is coerced to Int). If $b <= 0 , the empty list is returned. It will return an error with no operand, and return the operand itself with a single operand. An exception X::Numeric::CannotConvert will be thrown if $b is -Inf or NaN.
The left-hand side is evaluated for each repetition, so
say [1, 2] xx 5; # OUTPUT: «([1 2] [1 2] [1 2] [1 2] [1 2])»
returns five distinct arrays (but with the same content each time), and
rand xx 3
returns three pseudo random numbers that are determined independently.
The right-hand side can be *, in which case a lazy, infinite list is returned. If it's a Bool, a Seq with a single element is returned if it's True.
Same as the rest of the infix operators, these can be combined with metaoperators such as assignment, for instance.
multi sub infix:<~>(Any, Any) multi sub infix:<~>(Str:D, Str:D) multi sub infix:<~>(Buf:D, Buf:D)
This is the string concatenation operator, which coerces both arguments to Str and concatenates them. If both arguments are Buf, a combined buffer is returned.
say 'ab' ~ 'c'; # OUTPUT: «abc»
multi sub infix:<∘>() multi sub infix:<∘>(&f) multi sub infix:<∘>(&f, &g --> Block:D)
The function composition operator infix:<∘> or infix:<o> combines two functions, so that the left function is called with the return value of the right function. If the .count of the left function is greater than 1, the return value of the right function will be slipped into the left function.
Both .count and .arity of the right-hand side will be maintained.
sub f($p){ say 'f'; $p / 2 } sub g($p){ say 'g'; $p * 2 } my &composed = &f ∘ &g; say composed 2; # OUTPUT: «gf2» # equivalent to: say 2.&g.&f; # or to: say f g 2;
sub f($a, $b, $c) { [~] $c, $b, $a } sub g($str){ $str.comb } my &composed = &f ∘ &g; say composed 'abc'; # OUTPUT: «cba» # equivalent to: say f |g 'abc';
The single-arg candidate returns the given argument as is. The zero-arg candidate returns an identity routine that simply returns its argument.
my &composed = [∘] &uc; say composed 'foo'; # OUTPUT: «FOO» my &composed = [∘]; say composed 'foo'; # OUTPUT: «foo»
multi sub infix:<&>($a, $b --> Junction:D) is assoc<list>
Creates an all Junction from its arguments. See Junction for more details.
multi sub infix:<(&)>(**@p) multi sub infix:<∩>(**@p)
Returns the intersection of all of its arguments. This creates a new Set that contains only the elements common to all of the arguments if none of the arguments are a Bag, BagHash, Mix or MixHash.
say <a b c> (&) <b c d>; # OUTPUT: «set(b c)» <a b c d> ∩ <b c d e> ∩ <c d e f>; # OUTPUT: «set(c d)»
If any of the arguments are Baggy or Mixy>, the result is a new Bag (or Mix) containing the common elements, each weighted by the largest common weight (which is the minimum of the weights of that element over all arguments).
say <a a b c a> (&) bag(<a a b c c>); # OUTPUT: «Bag(a(2), b, c)»
∩ is equivalent to (&), at codepoint U+2229 (INTERSECTION).
multi sub infix:<(.)>(**@p) multi sub infix:<⊍>(**@p)
Baggy multiplication operator.
Returns the Baggy multiplication of its arguments, i.e., a Bag that contains each element of the arguments with the weights of the element across the arguments multiplied together to get the new weight. Returns a Mix if any of the arguments is a Mixy.
say <a b c> (.) <a b c d>; # OUTPUT: «Bag(a, b, c)» # Since 1 * 0 == 0, in the case of 'd' say <a a b c a d> ⊍ bag(<a a b c c>); # OUTPUT: «Bag(a(6), b, c(2))»
⊍ is equivalent to (.), at codepoint U+228D (MULTISET MULTIPLICATION).
multi sub infix:<|>($a, $b --> Junction:D) is assoc<list>
Creates an any Junction from its arguments.
my $three-letters = /<[a b c]>/ | /<[i j k]>/ | /<[x y z]>/; say $three-letters.perl; # OUTPUT: «any(/<[a b c]>/, /<[i j k]>/, /<[x y z]>/)» say 'b' ~~ $three-letters; # OUTPUT: «True»
This first creates an any Junction of three regular expressions (every one of them matching any of 3 letters), and then uses smartmatching to check whether the letter b matches any of them, resulting in a positive match. See also Junction for more details.
multi sub infix:<(|)>(**@p) multi sub infix:<∪>(**@p)
Returns the union of all of its arguments. This creates a new Set that contains all the elements its arguments contain if none of the arguments are a Bag, BagHash, Mix or MixHash.
say <a b d> ∪ bag(<a a b c>); # OUTPUT: «Bag(a(2), b, c, d)»
If any of the arguments are Baggy or Mixy>, the result is a new Bag (or Mix) containing all the elements, each weighted by the highest weight that appeared for that element.
say <a b d> ∪ bag(<a a b c>); # OUTPUT: «Bag(a(2), b, c, d)»
∪ is equivalent to (|), at codepoint U+222A (UNION).
multi sub infix:<(+)>(**@p) multi sub infix:<⊎>(**@p)
Returns the Baggy addition of its arguments. This creates a new Bag from each element of the arguments with the weights of the element added together to get the new weight, if none of the arguments are a Mix or MixHash.
say <a a b c a d> (+) <a a b c c>; # OUTPUT: «Bag(a(5), b(2), c(3), d)»
If any of the arguments is a Mixy, the result is a new Mix.
say <a b c> (+) (a => 2.5, b => 3.14).Mix; # OUTPUT: «Mix(a(3.5), b(4.14), c)»
⊎ is equivalent to (+), at codepoint U+228E (MULTISET UNION).
multi sub infix:<(-)>(**@p) multi sub infix:<∖>(**@p)
Returns the set difference of all its arguments. This creates a new Set that contains all the elements the first argument has but the rest of the arguments don't, i.e., of all the elements of the first argument, minus the elements from the other arguments. But only if none of the arguments are a Bag, BagHash, Mix or MixHash.
say <a a b c a d> (-) <a a b c c>; # OUTPUT: «set(d)» say <a b c d e> (-) <a b c> (-) <a b d>; # OUTPUT: «set(e)»
If any of the arguments are Baggy or Mixy>, the result is a new Bag (or Mix) containing all the elements remaining after the first argument with its weight subtracted by the weight of that element in each of the other arguments.
say <a a b c a d> (-) bag(<a b c c>); # OUTPUT: «Bag(a(2), d)» say <a a b c a d> ∖ mix(<a b c c>); # OUTPUT: «Mix(a(2), c(-1), d)»
∖ is equivalent to (-), at codepoint U+2216 (SET MINUS).
multi sub infix:<^>($a, $b --> Junction:D) is assoc<list>
Creates a one Junction from its arguments. See Junction for more details.
multi sub infix:<(^)>($a, $b) multi sub infix:<⊖>($a,$b) multi sub infix:<(^)>(**@p) multi sub infix:<⊖>(**@p)
Symmetric set difference operator.
Returns the symmetric set difference of all its arguments. This creates a new Set made up of all the elements that $a has but $b doesn't and all the elements $b has but $a doesn't if none of the arguments are a Bag, BagHash, Mix or MixHash. Equivalent to ($a ∖ $b) ∪ ($b ∖ $a).
say <a b> (^) <b c>; # OUTPUT: «set(a c)»
If any of the arguments are Baggy or Mixy>, the result is a new Bag (or Mix).
say <a b> ⊖ bag(<b c>); # OUTPUT: «Bag(a, c)»
⊖ is equivalent to (^), at codepoint U+2296 (CIRCLED MINUS).
sub prefix:<temp>(Mu $a is rw)
"temporizes" the variable passed as the argument. The variable begins with the same value as it had in the outer scope, but can be assigned new values in this scope. Upon exiting the scope, the variable will be restored to its original value.
my $a = "three"; say $a; # OUTPUT: «three» { temp $a; say $a; # OUTPUT: «three» $a = "four"; say $a; # OUTPUT: «four» } say $a; # OUTPUT: «three»
You can also assign immediately as part of the call to temp:
temp $a = "five";
Be warned the temp effects get removed once the block is left. If you were to access the value from, say, within a Promise after the temp was undone, you'd get the original value, not the temp one:
my $v = "original"; { temp $v = "new one"; start { say "[PROMISE] Value before block is left: `$v`"; sleep 1; say "[PROMISE] Block was left while we slept; value is now `$v`"; } sleep ½; say "About to leave the block; value is `$v`"; } say "Left the block; value is now `$v`"; sleep 2; # OUTPUT: # [PROMISE] Value before block is left: `new one` # About to leave the block; value is `new one` # Left the block; value is now `original` # [PROMISE] Block was left while we slept; value is now `original`
sub prefix:<let>(Mu $a is rw)
Refers to a variable in an outer scope whose value will be restored if the block exits unsuccessfully, implying that the block returned a defined object.
my $name = "Jane Doe"; { let $name = prompt("Say your name "); die if !$name; CATCH { default { say "No name entered" } } say "We have $name"; } say "We got $name";
This code provides a default name for $name. If the user exits from the prompt or simply does not provide a valid input for $name; let will restore the default value provided at the top. If user input is valid, it will keep that.
this is duplicated in variables.podsub infix:<does>(Mu $obj, Mu $role) is assoc<non>
Mixes $role into $obj at runtime. Requires $obj to be mutable.
Similar to but operator, the $role can instead be an instantiated object, in which case, the operator will create a role for you automatically. The role will contain a single method named the same as $obj.^name and that returns $obj:
my $o = class { method Str { "original" } }.new; put $o; # OUTPUT: «original» $o does "modded"; put $o; # OUTPUT: «modded»
If methods of the same name are present already, the last mixed in role takes precedence.
multi sub infix:<but>(Mu $obj1, Mu $role) is assoc<non> multi sub infix:<but>(Mu $obj1, Mu:D $obj2) is assoc<non>
Creates a copy of $obj with $role mixed in. Since $obj is not modified, but can be used to created immutable values with mixins.
Instead of a role, you can provide an instantiated object. In this case, the operator will create a role for you automatically. The role will contain a single method named the same as $obj.^name and that returns $obj:
my $forty-two = 42 but 'forty two'; say $forty-two+33; # OUTPUT: «75» say $forty-two.^name; # OUTPUT: «Int+{<anon|1>}» say $forty-two.Str; # OUTPUT: «forty two»
Calling ^name shows that the variable is an Int with an anonymous object mixed in. However, that object is of type Str, so the variable, through the mixin, is endowed with a method with that name, which is what we use in the last sentence.
We can also mixin classes, even created on the fly.
my $s = 12 but class Warbles { method hi { 'hello' } }.new; say $s.Warbles.hi; # OUTPUT: «hello» say $s + 42; # OUTPUT: «54»
To access the mixed-in class, as above, we use the class name as is shown in the second sentence. If methods of the same name are present already, the last mixed in role takes precedence. A list of methods can be provided in parentheses separated by comma. In this case conflicts will be reported at runtime.
multi sub infix:<cmp>(Any, Any) multi sub infix:<cmp>(Real:D, Real:D) multi sub infix:<cmp>(Str:D, Str:D) multi sub infix:<cmp>(Version:D, Version:D)
Generic, "smart" three-way comparator.
Compares strings with string semantics, numbers with number semantics, Pair objects first by key and then by value etc.
if $a eqv $b, then $a cmp $b always returns Order::Same.
say (a => 3) cmp (a => 4); # OUTPUT: «Less» say 4 cmp 4.0; # OUTPUT: «Same» say 'b' cmp 'a'; # OUTPUT: «More»
Defined as:
multi sub infix:<coll>(Str:D \a, Str:D \b --> Order:D) multi sub infix:<coll>(Cool:D \a, Cool:D \b --> Order:D) multi sub infix:<coll>(Pair:D \a, Pair:D \b --> Order:D)
coll is a sorting operator that takes pairs of Strs, Cools or Pairs and returns an Order that uses the $*COLLATION order. The default behavior disregards diacritic marks and capitalization, for instance.
say "b" cmp "à"; # OUTPUT: «Less» say "b" coll "à"; # OUTPUT: «More»
In the first case, lexicographic or codepoint order is taken into account. In the second, which uses coll, the diacritic is not considered and sorting happens according to intuitive order.
NOTE: These are not yet implemented in the JVM.
Defined as:
multi sub infix:<unicmp>(Str:D \a, Str:D \b --> Order:D) multi sub infix:<unicmp>(Pair:D \a, Pair:D \b --> Order:D) multi sub infix:<coll>(Pair:D \a, Pair:D \b --> Order:D)
Unlike the cmp operator which sorts according to codepoint, unicmp and coll sort according to how most users would expect, that is, disregarding aspects of the particular character like capitalization.
say 'a' unicmp 'Z'; # Less say 'a' coll 'Z'; # Less say 'a' cmp 'Z'; # More
The main difference between coll and unicmp is that the behavior of the former can be changed by the $*COLLATION dynamic variable.
NOTE: These are not yet implemented in the JVM.
multi sub infix:<leg>(Any, Any) multi sub infix:<leg>(Str:D, Str:D)
String three-way comparator. Short for less, equal or greater?.
Coerces both arguments to Str and then does a lexicographic comparison.
say 'a' leg 'b'; # OUTPUT: «Less» say 'a' leg 'a'; # OUTPUT: «Same» say 'b' leg 'a'; # OUTPUT: «More»
multi sub infix:«<=>»($a, $b --> Order:D) is assoc<non>
Coerces both arguments to Real and then does a numeric comparison.
multi sub infix:<..>($a, $b --> Range:D) is assoc<non>
Constructs a Range from the arguments.
multi sub infix:<..^>($a, $b --> Range:D) is assoc<non>
Constructs a Range from the arguments, excluding the end point.
multi sub infix:<^..>($a, $b --> Range:D) is assoc<non>
Constructs a Range from the arguments, excluding the start point.
multi sub infix:<^..^>($a, $b --> Range:D) is assoc<non>
Constructs a Range from the arguments, excluding both start and end point.
multi sub infix:<==>(Any, Any) multi sub infix:<==>(Int:D, Int:D) multi sub infix:<==>(Num:D, Num:D) multi sub infix:<==>(Rational:D, Rational:D) multi sub infix:<==>(Real:D, Real:D) multi sub infix:<==>(Complex:D, Complex:D) multi sub infix:<==>(Numeric:D, Numeric:D)
Coerces both arguments to Numeric (if necessary); returns True if they are equal.
sub infix:<!=>(Mu, Mu --> Bool:D)
Coerces both arguments to Numeric (if necessary); returns True if they are distinct.
Is an alias to !==.
Numeric inequality operator.
Equivalent to !=, at codepoint U+2260 (NOT EQUAL TO).
multi sub infix:«<»(Int:D, Int:D) multi sub infix:«<»(Num:D, Num:D) multi sub infix:«<»(Real:D, Real:D)
Coerces both arguments to Real (if necessary); returns True if the first argument is smaller than the second.
multi sub infix:«<=»(Int:D, Int:D) multi sub infix:«<=»(Num:D, Num:D) multi sub infix:«<=»(Real:D, Real:D)
Numeric less than or equal to operator.
Coerces both arguments to Real (if necessary); returns True if the first argument is smaller than or equal to the second.
Numeric less than or equal to operator.
Equivalent to <=, at codepoint U+2264 (LESS-THAN OR EQUAL TO).
multi sub infix:«>»(Int:D, Int:D) multi sub infix:«>»(Num:D, Num:D) multi sub infix:«>»(Real:D, Real:D)
Numeric greater than operator.
Coerces both arguments to Real (if necessary); returns True if the first argument is larger than the second.
multi sub infix:«>=»(Int:D, Int:D) multi sub infix:«>=»(Num:D, Num:D) multi sub infix:«>=»(Real:D, Real:D)
Numeric greater than or equal to operator.
Coerces both arguments to Real (if necessary); returns True if the first argument is larger than or equal to the second.
Numeric greater than or equal to operator.
Equivalent to >=, at codepoint U+2265 (GREATER-THAN OR EQUAL TO).
multi sub infix:<eq>(Any, Any) multi sub infix:<eq>(Str:D, Str:D)
Coerces both arguments to Str (if necessary); returns True if both are equal.
Mnemonic: equal
multi sub infix:<ne>(Mu, Mu) multi sub infix:<ne>(Str:D, Str:D)
Coerces both arguments to Str (if necessary); returns False if both are equal.
Mnemonic: not equal
multi sub infix:<gt>(Mu, Mu) multi sub infix:<gt>(Str:D, Str:D)
Coerces both arguments to Str (if necessary); returns True if the first is larger than the second, as determined by lexicographic comparison.
Mnemonic: greater than
multi sub infix:<ge>(Mu, Mu) multi sub infix:<ge>(Str:D, Str:D)
String greater than or equal to operator.
Coerces both arguments to Str (if necessary); returns True if the first is equal to or larger than the second, as determined by lexicographic comparison.
Mnemonic: greater or equal
multi sub infix:<lt>(Mu, Mu) multi sub infix:<lt>(Str:D, Str:D)
Coerces both arguments to Str (if necessary); returns True if the first is smaller than the second, as determined by lexicographic comparison.
Mnemonic: less than
multi sub infix:<le>(Mu, Mu) multi sub infix:<le>(Str:D, Str:D)
String less than or equal to operator.
Coerces both arguments to Str (if necessary); returns True if the first is equal to or smaller than the second, as determined by lexicographic comparison.
Mnemonic: less or equal
multi sub infix:<before>(Any, Any) multi sub infix:<before>(Real:D, Real:D) multi sub infix:<before>(Str:D, Str:D) multi sub infix:<before>(Version:D, Version:D)
Generic ordering, uses the same semantics as cmp. Returns True if the first argument is smaller than the second.
multi sub infix:<after>(Any, Any) multi sub infix:<after>(Real:D, Real:D) multi sub infix:<after>(Str:D, Str:D) multi sub infix:<after>(Version:D, Version:D)
Generic ordering, uses the same semantics as cmp. Returns True if the first argument is larger than the second.
sub infix:<eqv>(Any, Any)
Equivalence operator. Returns True if the two arguments are structurally the same, i.e. from the same type and (recursively) contain equivalent values.
say [1, 2, 3] eqv [1, 2, 3]; # OUTPUT: «True» say Any eqv Any; # OUTPUT: «True» say 1 eqv 2; # OUTPUT: «False» say 1 eqv 1.0; # OUTPUT: «False»
Lazy Iterables cannot be compared, as they're assumed to be infinite. However, the operator will do its best and return False if the two lazy Iterables are of different types or if only one Iterable is lazy.
say (1…∞) eqv (1…∞).List; # Both lazy, but different types; OUTPUT: «False» say (1…∞) eqv (1…3); # Same types, but only one is lazy; OUTPUT: «False» (try say (1…∞) eqv (1…∞)) # Both lazy and of the same type. Cannot compare; throws. orelse say $!.^name; # OUTPUT: «X::Cannot::Lazy»
The default eqv operator even works with arbitrary objects. E.g., eqv will consider two instances of the same object as being structurally equivalent:
my class A { has $.a; } say A.new(a => 5) eqv A.new(a => 5); # OUTPUT: «True»
Although the above example works as intended, the eqv code might fall back to a slower code path in order to do its job. One way to avoid this is to implement an appropriate infix eqv operator:
my class A { has $.a; } multi infix:<eqv>(A $l, A $r) { $l.a eqv $r.a } say A.new(a => 5) eqv A.new(a => 5); # OUTPUT: «True»
Note that eqv does not work recursively on every kind of container type, e.g. Set:
my class A { has $.a; } say Set(A.new(a => 5)) eqv Set(A.new(a => 5)); # OUTPUT: «False»
Even though the contents of the two sets are eqv, the sets are not. The reason is that eqv delegates the equality check to the Set object which relies on element-wise === comparison. Turning the class A into a value type by giving it a WHICH method produces the expected behavior:
my class A { has $.a; method WHICH { ValueObjAt.new: "A|$!a.WHICH()" } } say Set(A.new(a => 5)) eqv Set(A.new(a => 5)); # OUTPUT: «True»
sub infix:<===>(Any, Any)
Value identity operator. Returns True if both arguments are the same object, disregarding any containerization.
my class A { }; my $a = A.new; say $a === $a; # OUTPUT: «True» say A.new === A.new; # OUTPUT: «False» say A === A; # OUTPUT: «True»
For value types, === behaves like eqv:
say 'a' === 'a'; # OUTPUT: «True» say 'a' === 'b'; # OUTPUT: «False» my $b = 'a'; say $b === 'a'; # OUTPUT: «True» # different types say 1 === 1.0; # OUTPUT: «False»
=== uses the WHICH method to obtain the object identity.
If you want to create a class that should act as a value type, then that class must create an instance method WHICH, that should return a ValueObjAt object that won't change for the lifetime of the object.
multi sub infix:<=:=>(Mu \a, Mu \b)
Container identity operator. Returns True if both arguments are bound to the same container. If it returns True, it generally means that modifying one will also modify the other.
my ($a, $b) = (1, 3); say $a =:= $b; # OUTPUT: «False» $b = 2; say $a; # OUTPUT: «1» $b := $a; say $a =:= $b; # OUTPUT: «True» $a = 5; say $b; # OUTPUT: «5»
The smartmatch operator aliases the left-hand side to $_, then evaluates the right-hand side and calls .ACCEPTS($_) on it. The semantics are left to the type of the right-hand side operand.
Here is a partial list of some of the built-in smartmatching functionality. For full details, see ACCEPTS documentation for the type on the right-hand side of the operator.
Right-hand side | Comparison semantics |
---|---|
Mu:U | type check |
Str | string equality |
Numeric | numeric equality |
Regex | regex match |
Callable | boolean result of invocation |
Set/Bag | equal element values |
Any:D | object identity |
multi sub infix:<=~=>(Any, Any) multi sub infix:<=~=>(Int:D, Int:D) multi sub infix:<=~=>(Num:D, Num:D) multi sub infix:<=~=>(Rational:D, Rational:D) multi sub infix:<=~=>(Real:D, Real:D) multi sub infix:<=~=>(Complex:D, Complex:D) multi sub infix:<=~=>(Numeric:D, Numeric:D)
The approximately-equal operator ≅, whose ASCII variant is =~=, calculates the relative difference between the left-hand and right-hand sides and returns True if the difference is less than $*TOLERANCE (which defaults to 1e-15). However, if either side is zero then it checks that the absolute difference between the sides is less than $*TOLERANCE. Note that this operator is not arithmetically symmetrical (doesn't do ± Δ):
my $x = 1; say ($x + $*TOLERANCE) =~= $x; # OUTPUT: «False» say ($x - $*TOLERANCE) =~= $x; # OUTPUT: «True»
The tolerance is supposed to be modifiable via an adverb:
my ($x, $y) = 42, 42.1; say $x =~= $y :tolerance(.1);
However, this is not yet implemented. The same effect can be achieved by assigning to $*TOLERANCE.
{ my $*TOLERANCE = .1; say 11 =~= 10; # OUTPUT: «True» }
Note that setting $*TOLERANCE = 0 will cause all comparisons to fail.
{ my $*TOLERANCE = 0; say 1 =~= 1; # OUTPUT: «False» }
multi sub infix:<(elem)>($a,$b --> Bool:D) multi sub infix:<∈>($a,$b --> Bool:D)
Returns True if $a is an element of $b.
say 2 (elem) (1, 2, 3); # OUTPUT: «True» say 4 ∈ (1, 2, 3); # OUTPUT: «False»
∈ is equivalent to (elem), at codepoint U+2208 (ELEMENT OF).
multi sub infix:<∉>($a,$b --> Bool:D)
Returns True if $a is not an element of $b. Equivalent to !(elem).
say 4 ∉ (1, 2, 3); # OUTPUT: «True» say 2 !(elem) (1, 2, 3); # OUTPUT: «False»
∉ is codepoint U+2209 (NOT AN ELEMENT OF).
multi sub infix:<(cont)>($a,$b --> Bool:D) multi sub infix:<∋>($a,$b --> Bool:D)
Returns True if $a is an element of $b.
say (1,2,3) (cont) 2; # OUTPUT: «True» say (1, 2, 3) ∋ 4; # OUTPUT: «False»
∋ is equivalent to (cont), at codepoint U+220B (CONTAINS AS MEMBER).
multi sub infix:<∌>($a,$b --> Bool:D)
Returns True if $a is not an element of $b. Equivalent to !(cont).
say (1,2,3) ∌ 4; # OUTPUT: «True» say (1,2,3) !(cont) 2; # OUTPUT: «False»
∉ is codepoint U+220C (DOES NOT CONTAIN AS MEMBER).
multi sub infix:<< (<) >>($a,$b --> Bool:D) multi sub infix:<⊂>($a,$b --> Bool:D)
Returns True if $a is a strict subset of $b, i.e., that all the elements of $a are elements of $b but $a is a smaller set than $b.
say (1,2,3) (<) (2,3,1); # OUTPUT: «False» say (2,3) (<) (2,3,1); # OUTPUT: «True» say 4 ⊂ (1,2,3); # OUTPUT: «False»
⊂ is equivalent to (<), at codepoint U+2282 (SUBSET OF).
multi sub infix:<⊄>($a,$b --> Bool:D)
Returns True if $a is not a strict subset of $b. Equivalent to !(<).
say (1,2,3) ⊄ (2,3,1); # OUTPUT: «True» say (2,3) ⊄ (2,3,1); # OUTPUT: «False» say 4 !(<) (1,2,3); # OUTPUT: «True»
⊄ is codepoint U+2284 (NOT A SUBSET OF).
multi sub infix:<< (<=) >>($a,$b --> Bool:D) multi sub infix:<⊆>($a,$b --> Bool:D)
Subset of or equal to operator.
Returns True if $a is a subset of $b, i.e., that all the elements of $a are elements of $b but $a is a smaller or equal sized set than $b.
say (1,2,3) (<=) (2,3,1); # OUTPUT: «True» say (2,3) (<=) (2,3,1); # OUTPUT: «True» say 4 ⊆ (1,2,3); # OUTPUT: «False»
⊆ is equivalent to (<=), at codepoint U+2286 (SUBSET OF OR EQUAL TO).
multi sub infix:<⊈>($a,$b --> Bool:D)
Not a subset of nor equal to operator.
Returns True if $a is not a subset of $b. Equivalent to !(<=).
say (1,2,3) ⊄ (2,3,1); # OUTPUT: «True» say (2,3) ⊄ (2,3,1); # OUTPUT: «False» say 4 !(<=) (1,2,3); # OUTPUT: «True»
⊈ is codepoint U+2288 (NEITHER A SUBSET OF NOR EQUAL TO).
multi sub infix:<< (>) >>($a,$b --> Bool:D) multi sub infix:<⊃>($a,$b --> Bool:D)
Returns True if $a is a strict superset of $b, i.e., that all the elements of $b are elements of $a but $a is a larger set than $b.
say (1,2,3) (>) (2,3,1); # OUTPUT: «False» say (1,2,3) (>) (2,3); # OUTPUT: «True» say 4 ⊃ (1,2,3); # OUTPUT: «False»
⊃ is equivalent to (>), at codepoint U+2283 (SUPERSET OF).
multi sub infix:<⊅>($a,$b --> Bool:D)
Returns True if $a is not a strict superset of $b. Equivalent to !(>).
say (1,2,3) ⊅ (2,3,1); # OUTPUT: «True» say (1,2,3) ⊅ (2,3); # OUTPUT: «False» say 4 !(>) (1,2,3); # OUTPUT: «True»
⊅ is codepoint U+2285 (NOT A SUPERSET OF).
multi sub infix:<< (>=) >>($a,$b --> Bool:D) multi sub infix:<⊇>($a,$b --> Bool:D)
Superset of or equal to operator.
Returns True if $a is a superset of $b, i.e., that all the elements of $b are elements of $a but $a is a larger or equal sized set than $b.
say (1,2,3) (>=) (2,3,1); # OUTPUT: «True» say (1,2,3) (>=) (2,3); # OUTPUT: «True» say 4 ⊇ (1,2,3); # OUTPUT: «False»
⊇ is equivalent to (>=), at codepoint U+2287 (SUPERSET OF OR EQUAL TO).
multi sub infix:<⊉>($a,$b --> Bool:D)
Not a superset of nor equal to operator.
Returns True if $a is not a superset of $b. Equivalent to !(>=).
say (1,2,3) ⊉ (2,3,1); # OUTPUT: «False» say (1,2,3) ⊉ (2,3); # OUTPUT: «False» say 4 !(>=) (1,2,3); # OUTPUT: «True»
⊉ is codepoint U+2289 (NEITHER A SUPERSET OF OR EQUAL TO).
Returns the first argument that evaluates to False in boolean context, otherwise returns the last argument.
Note that this short-circuits, i.e. if one of the arguments evaluates to a false value, the arguments to the right are never evaluated.
sub a { 1 } sub b { 0 } sub c { die "never called" }; say a() && b() && c(); # OUTPUT: «0»
Returns the first argument that evaluates to True in boolean context, otherwise returns the last argument.
Note that this short-circuits; i.e., if one of the arguments evaluates to a true value, the remaining arguments are not evaluated.
sub a { 0 } sub b { 1 } sub c { die "never called" }; say a() || b() || c(); # OUTPUT: «1»
Short-circuit exclusive-or. Returns the true argument if there is one (and only one). Returns the last argument if all arguments are false. Returns Nil when more than one argument is true.
This operator short-circuits in the sense that it does not evaluate any arguments after a 2nd true result.
say 0 ^^ 42; # OUTPUT: «42» say '' ^^ 0; # OUTPUT: «0» say 0 ^^ 42 ^^ 1 ^^ die "never called"; # OUTPUT: «Nil»
Note that the semantics of this operator may not be what you assume: infix ^^ flips to the first true value it finds and then flips to Nil forever after the second, no matter how many more true values there are. (In other words, it has "find the one true value" semantics, not "boolean parity" semantics.)
The defined-or operator or infix // returns the first defined operand, or else the last operand. Short-circuits.
say Any // 0 // 42; # OUTPUT: «0»
Returns the smallest of the arguments, as determined by cmp semantics.
my $foo = 42; $foo min= 0 # read as: $foo decreases to 0
Returns the largest of the arguments, as determined by cmp semantics.
my $foo = -42; $foo max= 0 # read as: $foo increases to 0
Returns the Range starting from the lowest to the highest of the values, as determined by the cmp semantics. For instance:
# numeric comparison 10 minmax 3; # 3..10 # string comparison '10' minmax '3'; # "10".."3" 'z' minmax 'k'; # "k".."z"
If the lowest and highest values coincide, the operator returns a Range made by the same value:
1 minmax 1; # 1..1
When applied to Lists, the operator evaluates the lowest and highest values among all available values:
(10,20,30) minmax (0,11,22,33); # 0..33 ('a','b','z') minmax ('c','d','w'); # "a".."z"
Similarly, when applied to Hashes, it performs a cmp way comparison:
my %winner = points => 30, misses => 10; my %loser = points => 20, misses => 10; %winner cmp %loser; # More %winner minmax %loser; # ${:misses(10), :points(20)}..${:misses(10), :points(30)}
Also called ternary or conditional operator, $condition ?? $true !! $false evaluates $condition and returns the expression right behind ??, in this case $true if it is True, otherwise evaluates and returns the expression behind !!, $false in this case.
sub infix:<ff>(Mu $a, Mu $b)
Also called the flipflop operator, compares both arguments to $_ (that is, $_ ~~ $a and $_ ~~ $b). Evaluates to False until the left-hand smartmatch is True, at which point it evaluates to True until the right-hand smartmatch is True.
In effect, the left-hand argument is the "start" condition and the right-hand is the "stop" condition. This construct is typically used to pick up only a certain section of lines. For example:
my $excerpt = q:to/END/; Here's some unimportant text. =begin code This code block is what we're after. We'll use 'ff' to get it. =end code More unimportant text. END my @codelines = gather for $excerpt.lines { take $_ if "=begin code" ff "=end code" } # this will print four lines, starting with "=begin code" and ending with # "=end code" say @codelines.join("\n");
After matching the start condition, the operator will then match the same $_ to the stop condition and act accordingly if successful. In this example, only the first element is printed:
for <AB C D B E F> { say $_ if /A/ ff /B/; # OUTPUT: «AB» }
If you only want to test against a start condition and have no stop condition, * can be used as such.
for <A B C D E> { say $_ if /C/ ff *; # OUTPUT: «CDE» }
For the sed-like version, which does not try $_ on the stop condition after succeeding on the start condition, see fff.
This operator cannot be overloaded, as it's handled specially by the compiler.
sub infix:<^ff>(Mu $a, Mu $b)
Works like ff, except it does not return True for items matching the start condition (including items also matching the stop condition).
A comparison:
my @list = <A B C>; say $_ if /A/ ff /C/ for @list; # OUTPUT: «ABC» say $_ if /A/ ^ff /C/ for @list; # OUTPUT: «BC»
The sed-like version can be found in ^fff.
This operator cannot be overloaded, as it's handled specially by the compiler.
sub infix:<ff^>(Mu $a, Mu $b)
Works like ff, except it does not return True for items matching the stop condition (including items that first matched the start condition).
my @list = <A B C>; say $_ if /A/ ff /C/ for @list; # OUTPUT: «ABC» say $_ if /A/ ff^ /C/ for @list; # OUTPUT: «AB»
The sed-like version can be found in fff^.
This operator cannot be overloaded, as it's handled specially by the compiler.
sub infix:<^ff^>(Mu $a, Mu $b)
Works like ff, except it does not return True for items matching either the stop or start condition (or both).
my @list = <A B C>; say $_ if /A/ ff /C/ for @list; # OUTPUT: «ABC» say $_ if /A/ ^ff^ /C/ for @list; # OUTPUT: «B»
The sed-like version can be found in ^fff^.
This operator cannot be overloaded, as it's handled specially by the compiler.
sub infix:<fff>(Mu $a, Mu $b)
Performs a sed-like flipflop operation, wherein it returns False until the left argument smartmatches against $_, then returns True until the right argument smartmatches against $_.
Works similarly to ff, except that it only tries one argument per invocation. That is, if $_ smartmatches the left argument, fff will not then try to match that same $_ against the right argument.
for <AB C D B E F> { say $_ if /A/ fff /B/; # OUTPUT: «ABCDB» }
The non-sed-like flipflop (which after successfully matching the left argument against $_ will try that same $_ against the right argument and act accordingly). See ff.
This operator cannot be overloaded, as it's handled specially by the compiler.
sub infix:<^fff>(Mu $a, Mu $b)
Like fff, except it does not return true for matches to the left argument.
my @list = <A B C>; say $_ if /A/ fff /C/ for @list; # OUTPUT: «ABC» say $_ if /A/ ^fff /C/ for @list; # OUTPUT: «BC»
For the non-sed version, see ^ff.
This operator cannot be overloaded, as it's handled specially by the compiler.
sub infix:<fff^>(Mu $a, Mu $b)
Like fff, except it does not return true for matches to the right argument.
my @list = <A B C>; say $_ if /A/ fff /C/ for @list; # OUTPUT: «ABC» say $_ if /A/ fff^ /C/ for @list; # OUTPUT: «AB»
For the non-sed version, see ff^.
This operator cannot be overloaded, as it's handled specially by the compiler.
sub infix:<^fff^>(Mu $a, Mu $b)
Like fff, except it does not return true for matches to either the left or right argument.
my @list = <A B C>; say $_ if /A/ fff /C/ for @list; # OUTPUT: «ABC» say $_ if /A/ ^fff^ /C/ for @list; # OUTPUT: «B»
For the non-sed version, see ^ff^.
This operator cannot be overloaded, as it's handled specially by the compiler.
sub infix:<=>(Mu $a is rw, Mu $b)
Called the item assignment operator, it Places the value of the right-hand side into the container on the left-hand side. Its exact semantics are left to the container type on the left-hand side.
(Note that item assignment and list assignment have different precedence levels, and the syntax of the left-hand side decides whether an equal sign = is parsed as item assignment or list assignment operator).
sub infix:«=>»($key, Mu $value --> Pair:D)
Pair constructor.
Constructs a Pair object with the left-hand side as the key and the right-hand side as the value.
Note that the => operator is syntactically special-cased, in that it allows unquoted identifier on the left-hand side.
my $p = a => 1; say $p.key; # OUTPUT: «a» say $p.value; # OUTPUT: «1»
A Pair within an argument list with an unquoted identifier on the left is interpreted as a named argument.
See the Terms language documentation for more ways to create Pair objects.
multi sub prefix:<not>(Mu $x --> Bool:D)
Evaluates its argument in boolean context (and thus collapses Junctions), and negates the result. Please note that not is easy to misuse. See traps.
multi sub prefix:<so>(Mu $x --> Bool:D)
Evaluates its argument in boolean context (and thus collapses Junctions), and returns the result.
sub infix:<,>(*@a --> List:D) is assoc<list>
Constructs a higher-order Cool from its arguments.
my @list = :god('Þor'), ['is',"mighty"]; say @list; # OUTPUT: «[god => Þor [is mighty]]» my %hash = :god('Þor'), :is("mighty"); say %hash.perl; # OUTPUT: «{:god("Þor"), :is("mighty")}» my %a = :11a, :22b; say %(%a, :33x); # OUTPUT: «{a => 11, b => 22, x => 33}»
In the first case it returns a List, in the second case, since the arguments are Pairs, it builds a Hash.
It can also be used for constructing variables from other variables, collating elements of different types, in this case a Hash and a Pair:
my %features = %hash, :wields("hammer"); say %features; # OUTPUT: «{god => Þor, is => mighty, wields => hammer}»
The comma is also used syntactically as the separator of arguments in calls.
Used as an argument separator just like infix , and marks the argument to its left as the invocant. That turns what would otherwise be a function call into a method call.
substr('abc': 1); # same as 'abc'.substr(1)
Infix : is only allowed after the first argument of a non-method call. In other positions, it's a syntax error.
sub infix:<Z>(**@lists --> Seq:D) is assoc<chain>
The Zip operator interleaves the lists passed to Z like a zipper, taking index-corresponding elements from each operand. The returned Seq contains nested lists, each with a value from every operand in the chain. If one of the operands runs out of elements prematurely, the zip operator will stop.
say (1, 2 Z <a b c> Z <+ ->).perl; # OUTPUT: «((1, "a", "+"), (2, "b", "-")).Seq» for <a b c> Z <1 2 3 4> -> [$l, $r] { say "$l:$r" } # OUTPUT: «a:1b:2c:3»
The Z operator also exists as a metaoperator, in which case the inner lists are replaced by the value from applying the operator to the list:
say 100, 200 Z+ 42, 23; # OUTPUT: «(142 223)» say 1..3 Z~ <a b c> Z~ 'x' xx 3; # OUTPUT: «(1ax 2bx 3cx)»
Defined as:
multi sub infix:<X>(+lol, :&with! --> Seq:D) multi sub infix:<X>(+lol --> Seq:D)
Creates a cross product from all the lists, ordered so that the rightmost elements vary most rapidly, and returns a Seq:
1..3 X <a b c> X 9 # produces ((1 a 9) (1 b 9) (1 c 9) # (2 a 9) (2 b 9) (2 c 9) # (3 a 9) (3 b 9) (3 c 9))
The X operator also exists as a metaoperator, in which case the inner lists are replaced by the value from applying the operator to the list:
1..3 X~ <a b c> X~ 9 # produces (1a9 1b9 1c9 2a9 2b9 2c9 3a9 3b9 3c9)
multi sub infix:<...>(**@) is assoc<list> multi sub infix:<...^>(**@) is assoc<list>
The sequence operator, which can be written either as ... or as … (with variants ...^ and …^) will produce (possibly lazy) generic sequences on demand.
The left-hand side will always include the initial elements; it may include a generator too (after the first element or elements). The right-hand side will have an endpoint, which can be Inf or * for "infinite" lists (that is, lazy lists whose elements are only produced on demand), an expression which will end the sequence when True, or other elements such as Junctions.
The sequence operator invokes the generator with as many arguments as necessary. The arguments are taken from the initial elements and the already generated elements. The default generator is *.succ or *.pred, depending on how the end points compare:
say 1 ... 4; # OUTPUT: «(1 2 3 4)» say 4 ... 1; # OUTPUT: «(4 3 2 1)» say 'a' ... 'e'; # OUTPUT: «(a b c d e)» say 'e' ... 'a'; # OUTPUT: «(e d c b a)»
An endpoint of * (Whatever), Inf or ∞ generates on demand an infinite sequence, with a default generator of *.succ
say (1 ... *)[^5]; # OUTPUT: «(1 2 3 4 5)»
Custom generators need to be the last element of the list before the '...' operator. This one takes two arguments, and generates the eight first Fibonacci numbers
say (1, 1, -> $a, $b { $a + $b } ... *)[^8]; # OUTPUT: «(1 1 2 3 5 8 13 21)» # same but shorter say (1, 1, * + * ... *)[^8]; # OUTPUT: «(1 1 2 3 5 8 13 21)»
Of course the generator can also take only one argument.
say 5, { $_ * 2 } ... 40; # OUTPUT: «5 10 20 40»
There must be at least as many initial elements as arguments to the generator.
Without a generator and with more than one initial element and all initial elements numeric, the sequence operator tries to deduce the generator. It knows about arithmetic and geometric sequences.
say 2, 4, 6 ... 12; # OUTPUT: «(2 4 6 8 10 12)» say 1, 2, 4 ... 32; # OUTPUT: «(1 2 4 8 16 32)»
If the endpoint is not *, it's smartmatched against each generated element and the sequence is terminated when the smartmatch succeeded. For the ... operator, the final element is included, for the ...^ operator it's excluded.
This allows you to write
say 1, 1, * + * ...^ *>= 100;
to generate all Fibonacci numbers up to but excluding 100.
The ... operators consider the initial values as "generated elements" as well, so they are also checked against the endpoint:
my $end = 4; say 1, 2, 4, 8, 16 ... $end; # OUTPUT: «(1 2 4)»
In this context, it acts as the list assignment operator. Its exact semantics are left to the container type on the left-hand side. See Array and Hash for common cases.
The distinction between item assignment and list assignment is determined by the parser depending on the syntax of the left-hand side.
Binding operator. Whereas $x = $y puts the value in $y into $x, $x := $y makes $x and $y the same thing.
my $a = 42; my $b = $a; $b++; say $a;
This will output 42, because $a and $b both contained the number 42, but the containers were different.
my $a = 42; my $b := $a; $b++; say $a;
This will output 43, since $b and $a both represented the same object.
If type constrains on variables or containers are present a type check will be performed at runtime. On failure X::TypeCheck::BindingType will be thrown.
Please note that := is a compile time operator. As such it can not be referred to at runtime and thus can't be used as an argument to metaoperators.
Read-only binding operator, not yet implemented in Rakudo. See infix :=.
Called the yada, yada, yada operator or stub operator, if it's the only statement in a routine or type, it marks that routine or type as a stub (which is significant in the context of pre-declaring types and composing roles).
If the ... statement is executed, it calls fail, with the default message Stub code executed.
If it's the only statement in a routine or type, it marks that routine or type as a stub (which is significant in the context of pre-declaring types and composing roles).
If the !!! statement is executed, it calls die, with the default message Stub code executed.
If it's the only statement in a routine or type, it marks that routine or type as a stub (which is significant in the context of pre-declaring types and composing roles).
If the ??? statement is executed, it calls warn, with the default message Stub code executed.
Any infix operator (except for non-associating operators) can be surrounded by square brackets in term position to create a list operator that reduces using that operation.
say [+] 1, 2, 3; # 1 + 2 + 3 = 6 my @a = (5, 6); say [*] @a; # 5 * 6 = 30
Reduction operators have the same associativity as the operators they are based on.
say [-] 4, 3, 2; # 4-3-2 = (4-3)-2 = -1 say [**] 4, 3, 2; # 4**3**2 = 4**(3**2) = 262144
Same as infix &&, except with looser precedence.
Short-circuits so that it returns the first operand that evaluates to False, otherwise returns the last operand. Note that and is easy to misuse, see traps.
The andthen operator returns Empty upon encountering the first undefined argument, otherwise the last argument. Last argument is returned as-is, without being checked for definedness at all. Short-circuits. The result of the left side is bound to $_ for the right side, or passed as arguments if the right side is a Callable, whose count must be 0 or 1.
A handy use of this operator is to alias a routine's return value to $_ and to do additional manipulation with it, such as printing or returning it to caller. Since the andthen operator short-circuits, statements on the right-hand side won't get executed, unless left-hand side is defined (tip: Failures are never defined, so you can handle them with this operator).
sub load-data { rand > .5 or return; # simulated load data failure; return Nil (rand > .3 ?? 'error' !! 'good data') xx 10 # our loaded data } load-data.first: /good/ andthen say "$_ is good"; # OUTPUT: «(good data is good)» load-data() andthen .return; # return loaded data, if it's defined die "Failed to load data!!";
The above example will print good data is good only if the subroutine returned any items that match /good/ and will die unless loading data returned a defined value. The aliasing behavior lets us pipe the values across the operator.
The andthen operator is a close relative of with statement modifier, and some compilers compile with to andthen, meaning these two lines have equivalent behavior:
.say with 42; 42 andthen .say;
The notandthen operator returns Empty upon encountering the first defined argument, otherwise the last argument. Last argument is returned as-is, without being checked for definedness at all. Short-circuits. The result of the left side is bound to $_ for the right side, or passed as arguments if the right side is a Callable, whose count must be 0 or 1.
At first glance, notandthen might appear to be the same thing as the orelse operator. The difference is subtle: notandthen returns Empty when it encounters a defined item (that isn't the last item), whereas orelse returns that item. In other words, notandthen is a means to act when items aren't defined, whereas orelse is a means to obtain the first defined item:
sub all-sensors-down { [notandthen] |@_, True } sub first-working-sensor { [orelse] |@_, 'default sensor' } all-sensors-down Nil, Nil, Nil and say 'OMG! All sensors are down!'; # OUTPUT:«OMG! All sensors are down!» say first-working-sensor Nil, Nil, Nil; # OUTPUT:«default sensor» all-sensors-down Nil, 42, Nil and say 'OMG! All sensors are down!'; # No output say first-working-sensor Nil, 42, Nil; # OUTPUT:«42»
The notandthen operator is a close relative of without statement modifier, and some compilers compile without to notandthen, meaning these two lines have equivalent behavior:
sub good-things { fail } 'boo'.say without good-things; good-things() notandthen 'boo'.say;
Same as infix ||, except with looser precedence.
Returns the first argument that evaluates to True in boolean context, or otherwise the last argument, it short-circuits. Please note that or is easy to misuse. See traps.
The orelse operator is similar to infix //, except with looser precedence and $_ aliasing.
Returns the first defined argument, or else the last argument. Last argument is returned as-is, without being checked for definedness at all. Short-circuits. The result of the left side is bound to $_ for the right side, or passed as an argument if the right side is a Callable, whose count must be 0 or 1.
This operator is useful for handling Failures returned by routines since the expected value is usually defined and Failure never is:
sub meows { ++$ < 4 ?? fail 'out of meows!' !! '🐱' } sub meows-processor1 { meows() orelse .return } # return handled Failure sub meows-processor2 { meows() orelse fail $_ } # return re-armed Failure sub meows-processor3 { # Use non-Failure output, or else print a message that stuff's wrong meows() andthen .say orelse ‘something's wrong’.say; } say "{.^name}, {.handled}" # OUTPUT: «Failure, True» given meows-processor1; say "{.^name}, {.handled}" # OUTPUT: «Failure, False» given meows-processor2; meows-processor3; # OUTPUT: «something's wrong» meows-processor3; # OUTPUT: «🐱»
Same as infix ^^, except with looser precedence.
Returns the operand that evaluates to True in boolean context, if and only if the other operand evaluates to False in boolean context. If both operands evaluate to False, returns the last argument. If both operands evaluate to True, returns Nil.
When chaining, returns the operand that evaluates to True, if and only if there is one such operand. If more than one operand is true, it short-circuits after evaluating the second and returns Nil. If all operands are false, returns the last one.
This feed operator takes the result from the left and passes it to the next (right) routine as the last parameter.
my @array = (1, 2, 3, 4, 5); @array ==> sum() ==> say(); # OUTPUT: «15»
This simple example, above, is the equivalent of writing:
my @array = (1, 2, 3, 4, 5); say(sum(@array)); # OUTPUT: «15»
Or if using methods:
my @array = (1, 2, 3, 4, 5); @array.sum.say; # OUTPUT: «15»
The precedence is very loose so you will need to use parentheses to assign the result or you can even just use another feed operator! In the case of routines/methods that take a single argument or where the first argument is a block, it's often required that you call with parentheses (though this is not required for the very last routine/method).
This "traditional" structure, read bottom-to-top, with the last two lines creating the data structure that is going to be processed
my @fractions = <TWO THREE FOUR FIVE SEVEN> »~» " " X~ <FIFTHS SIXTHS EIGHTHS>; my @result = map { .uniparse }, # (3) Converts to unicode grep { .uniparse }, # (2) Checks if it parses map( {"VULGAR FRACTION " ~ $^þ }, @fractions); # (1) Adds string to input # @result is [⅖ ⅗ ⅜ ⅘ ⅚ ⅝ ⅞]
Now we use the feed operator (left-to-right) with parentheses, read top-to-bottom
my @result = ( <TWO THREE FOUR FIVE SEVEN> »~» " " X~ <FIFTHS SIXTHS EIGHTHS> # (1) Input ==> map( {"VULGAR FRACTION " ~ $^þ } ) # (2) Converts to Unicode name ==> grep({ .uniparse }) # (3) Filters only real names ==> map( { .uniparse} ); # (4) Converts to unicode );
For illustration, method chaining equivalent, read top-to-bottom, using the same sequence as above
my @result = ( <TWO THREE FOUR FIVE SEVEN> »~» " " X~ <FIFTHS SIXTHS EIGHTHS>) .map( {"VULGAR FRACTION " ~ $^þ } ) .grep({ .uniparse }) .map({ .uniparse });
Although in this particular case the result is the same, the feed operator ==> more clearly shows intent with arrow pointing in the direction of the data flow. To assign without the need of parentheses use another feed operator
my @result; <people of earth> ==> map({ .tc }) ==> grep /<[PE]>/ ==> sort() ==> @result;
It can be useful to capture a partial result, however, unlike the leftward feed operator, it does require parentheses or a semicolon
my @result; <people of earth> ==> map({ .tc }) ==> my @caps; @caps # also could wrap in parentheses instead ==> grep /<[PE]>/ ==> sort() ==> @result;
The feed operator lets you construct method-chaining-like patterns out of routines and the results of methods on unrelated data. In method-chaining, you are restricted to the methods available on the data or the result of previous method call. With feed operators, that restriction is gone. The resulting code could also be seen to be more readable than a series of method calls broken over multiple lines.
Note: In the future, this operator will see some change as it gains the ability to run list operations in parallel. It will enforce that the left operand is enclosable as a closure (that can be cloned and run in a subthread).
This leftward feed operator takes the result from the right and passes it to the previous (left) routine as the last parameter. This elucidates the right-to-left dataflow for a series of list manipulating functions.
# Traditional structure, read bottom-to-top my @result = sort # (4) Sort, result is <Earth People> grep { /<[PE]>/ }, # (3) Look for P or E map { .tc }, # (2) Capitalize the words <people of earth>; # (1) Start with the input # Feed (right-to-left) with parentheses, read bottom-to-top my @result = ( sort() # (4) Sort, result is <Earth People> <== grep({ /<[PE]>/ }) # (3) Look for P or E <== map({ .tc }) # (2) Capitalize the words <== <people of earth> # (1) Start with the input ); # To assign without parentheses, use another feed operator my @result <== sort() # (4) Sort, result is <Earth People> <== grep({ /<[PE]>/ }) # (3) Look for P or E <== map({ .tc }) # (2) Capitalize the words <== <people of earth>; # (1) Start with the input # It can be useful to capture a partial result my @result <== sort() <== grep({ /<[PE]>/ }) <== my @caps # unlike ==>, there's no need for additional statement <== map({ .tc }) <== <people of earth>;
Unlike the rightward feed operator, the result is not closely mappable to method-chaining. However, compared to the traditional structure above where each argument is separated by a line, the resulting code is more demonstrative than commas. The leftward feed operator also allows you to "break into" the statement and capture an intermediary result which can be extremely useful for debugging or to take that result and create another variation on the final result.
Note: In the future, this operator will see some change as it gains the ability to run list operations in parallel. It will enforce that the right operand is enclosable as a closure (that can be cloned and run in a subthread).
In general, infix operators can be applied to a single or no element without yielding an error, generally in the context of a reduce operation.
say [-] () # OUTPUT: «0»
The design documents specify that this should return an identity value, and that an identity value must be specified for every operator. In general, the identity element returned should be intuitive. However, here is a table that specifies how it is defined for operator classes in Perl 6, which corresponds to the table in the above definition in the types and operators defined by the language:
Operator class | Identity value |
---|---|
Equality | Bool::True |
Arithmetic + | 0 |
Arithmetic * | 1 |
Comparison | True |
Bitwise | 0 |
Stringy | '' |
Sets | Empty set or equivalent |
Or-like Bool | False |
And-like Bool | True |
For instance, union of an empty list will return an empty set:
say [∪]; # OUTPUT: «set()»
This only applies to operators where empty or 0 is always a valid operand. For instance, applying it to division will yield an exception.
say [%] (); # OUTPUT: «(exit code 1) No zero-arg meaning for infix:<%>
Organizing and referencing namespaced program elements
TODO * Take a lot of stuff from S02 for this * Document 'import'Packages are nested namespaces of named program elements. Modules, classes, grammars, and others are types of packages. Like files in a directory, you can generally refer to named elements with their short-name if they are local, or with the longer name that includes the namespace to disambiguate as long as their scope allows that.
A package name is anything that is a legal part of a variable name (not counting the sigil). This includes:
class Foo { sub zape () { say "zipi" } class Bar { method baz () { return 'Þor is mighty' } our &zape = { "zipi" }; our $quux = 42; } } my $foo; # simple identifiers say Foo::Bar.baz; # calling a method; OUTPUT: «Þor is mighty» say Foo::Bar::zape; # compound identifiers separated by ::; OUTPUT: «zipi» my $bar = 'Bar'; say $Foo::($bar)::quux; # compound identifiers with interpolations; OUTPUT: «42» $42; # numeric names $!; # certain punctuation variables
:: is used to separate nested package names.
Packages do not really have an identity; they can be simply part of a module or class name, for instance. They are more similar to namespaces than to modules; with a module of the same name capturing the identity of a package if it exists.
package Foo:ver<0> {}; module Foo:ver<1> {}; say Foo.^ver; # OUTPUT: «1»
The syntax allows the declared package to use a version, but as a matter of fact, it's dismissed; only modules and classes have an identity that might include auth and ver.
Ordinary package-qualified names look like this: $Foo::Bar::quux, which would be the $quux variable in package Foo::Bar; Foo::Bar::zape would represent the &zape variable in the same package.
Sometimes it's clearer to keep the sigil with the variable name, so an alternate way to write this is:
Foo::Bar::<$quux>
This does not work with the Foo«&zape» variable, since subs, by default, have lexical scope. The name is resolved at compile time because the variable name is a constant. We can access the rest of the variables in Bar (as shown in the example above) since classes, by default, have package scope.
If the name part before :: is null, it means the package is unspecified and must be searched for. Generally this means that an initial :: following the main sigil is a no-op on names that are known at compile time, though ::() can also be used to introduce an interpolation. Also, in the absence of another sigil, :: can serve as its own sigil indicating intentional use of a not-yet-declared package name.
The following pseudo-package names are reserved at the front of a name:
MY | Symbols in the current lexical scope (aka $?SCOPE) |
OUR | Symbols in the current package (aka $?PACKAGE) |
CORE | Outermost lexical scope, definition of standard Perl |
GLOBAL | Interpreter-wide package symbols, really UNIT::GLOBAL |
PROCESS | Process-related globals (superglobals). The last place dynamic variable lookup will look. |
COMPILING | Lexical symbols in the scope being compiled |
The following relative names are also reserved but may be used anywhere in a name:
CALLER | Dynamic symbols in the immediate caller's lexical scope |
CALLERS | Dynamic symbols in any caller's lexical scope |
DYNAMIC | Dynamic symbols in my or any caller's lexical scope |
OUTER | Symbols in the next outer lexical scope |
OUTERS | Symbols in any outer lexical scope |
LEXICAL | Dynamic symbols in my or any outer's lexical scope |
UNIT | Symbols in the outermost lexical scope of compilation unit |
SETTING | Lexical symbols in the unit's DSL (usually CORE) |
PARENT | Symbols in this package's parent package (or lexical scope) |
CLIENT | The nearest CALLER that comes from a different package |
The file's scope is known as UNIT, but there are one or more lexical scopes outside of that corresponding to the linguistic setting (often known as the prelude in other cultures). Hence, the SETTING scope is equivalent to UNIT::OUTERS. For a standard Perl 6 program SETTING is the same as CORE, but various startup options (such as -n or -p) can put you into a domain specific language, in which case CORE remains the scope of the standard language, while SETTING represents the scope defining the DSL that functions as the setting of the current file. When used as a search term in the middle of a name, SETTING includes all its outer scopes up to CORE. To get only the setting's outermost scope, use UNIT::OUTER instead.
You may interpolate a string into a package or variable name using ::($expr) where you'd ordinarily put a package or variable name. The string is allowed to contain additional instances of ::, which will be interpreted as package nesting. You may only interpolate entire names, since the construct starts with ::, and either ends immediately or is continued with another :: outside the parentheses. Most symbolic references are done with this notation:
my $foo = "Foo"; my $bar = "Bar"; my $foobar = "Foo::Bar"; $::($bar) # lexically-scoped $Bar $::("MY::$bar") # lexically-scoped $Bar $::("OUR::$bar") # package-scoped $Bar $::("GLOBAL::$bar") # global $Bar $::("PROCESS::$bar") # process $Bar $::("PARENT::$bar") # current package's parent's $Bar $::($foobar) # $Foo::Bar @::($foobar)::baz # @Foo::Bar::baz @::($foo)::Bar::baz # @Bar::Bar::baz @::($foobar)baz # ILLEGAL at compile time (no operator baz) @::($foo)::($bar)::baz # @Foo::Bar::baz
An initial :: doesn't imply global; here as part of the interpolation syntax it doesn't even imply package. After the interpolation of the ::() component, the indirect name is looked up exactly as if it had been there in the original source code, with priority given first to leading pseudo-package names, then to names in the lexical scope (searching scopes outwards, ending at CORE). The current package is searched last.
Use the MY pseudopackage to limit the lookup to the current lexical scope, and OUR to limit the scopes to the current package scope.
In the same vein, class and method names can be interpolated too:
role with-method { method a-method { return 'in-a-method of ' ~ $?CLASS.^name }; } class a-class does with-method { method another-method { return 'in-another-method' }; } class b-class does with-method {}; my $what-class = 'a-class'; say ::($what-class).a-method; # OUTPUT: «in-a-method of a-class» $what-class = 'b-class'; say ::($what-class).a-method; # OUTPUT: «in-a-method of b-class» my $what-method = 'a-method'; say a-class."$what-method"(); # OUTPUT: «in-a-method of a-class» $what-method = 'another-method'; say a-class."$what-method"(); # OUTPUT: «in-another-method»
To do direct lookup in a package's symbol table without scanning, treat the package name as a hash:
Foo::Bar::{'&baz'} # same as &Foo::Bar::baz PROCESS::<$IN> # same as $*IN Foo::<::Bar><::Baz> # same as Foo::Bar::Baz
Unlike ::() symbolic references, this does not parse the argument for ::, nor does it initiate a namespace scan from that initial point. In addition, for constant subscripts, it is guaranteed to resolve the symbol at compile time.
The null pseudo-package is the same search list as an ordinary name search. That is, the following are all identical in meaning:
$foo ::{'$foo'} ::<$foo>
Each of them scans the lexical scopes outward, and then the current package scope (though the package scope is then disallowed when "strict" is in effect).
Subscript the package object itself as a hash object, the key of which is the variable name, including any sigil. The package object can be derived from a type name by use of the :: postfix:
MyType::<$foo>
Methods—including auto-generated methods, such as public attributes' accessors—are stored in the class meta object and can be looked up through by the lookup method.
Str.^lookup('chars')
Interpreter globals live in the GLOBAL package. The user's program starts in the GLOBAL package, so "our" declarations in the mainline code go into that package by default. Process-wide variables live in the PROCESS package. Most predefined globals such as $*UID and $*PID are actually process globals.
Measuring and improving runtime or compile-time performance
This page is about computer performance in the context of Perl 6.
Make sure you're not wasting time on the wrong code: start by identifying your "critical 3%" by profiling your code's performance. The rest of this document shows you how to do that.
Expressions of the form now - INIT now, where INIT is a phase in the running of a Perl 6 program, provide a great idiom for timing code snippets.
Use the m: your code goes here #perl6 channel evalbot to write lines like:
m: say now - INIT now rakudo-moar abc1234: OUTPUT«0.0018558»
The now to the left of INIT runs 0.0018558 seconds later than the now to the right of the INIT because the latter occurs during the INIT phase.
When using the MoarVM backend, the Rakudo compiler's --profile command line option writes the profile data to an HTML file.
This file will open to the "Overview" section, which gives some overall data about how the program ran, e.g., total runtime, time spent doing garbage collection. One important piece of information you'll get here is percentage of the total call frames (i.e., blocks) that were interpreted (slowest, in red), speshed (faster, in orange), and jitted (fastest, in green).
The next section, "Routines", is probably where you'll spend the most time. It has a sortable and filterable table of routine (or block) name+file+line, the number of times it ran, the inclusive time (time spent in that routine + time spent in all routines called from it), exclusive time (just the time spent in that routine), and whether it was interpreted, speshed, or jitted (same color code as the "Overview" page). Sorting by exclusive time is a good way to know where to start optimizing. Routines with a filename that starts like SETTING::src/core/ or gen/moar/ are from the compiler, a good way to just see the stuff from your own code is to put the filename of the script you profiled in the "Name" search box.
The "Call Graph" section gives a flame graph representation of much of the same information as the "Routines" section.
The "Allocations" section gives you information about the amount of different types that were allocated, as well as which routines did the allocating.
The "GC" section gives you detailed information about all the garbage collections that occurred.
The "OSR / Deopt" section gives you information about On Stack Replacements (OSRs), which is when routines are "upgraded" from interpreted to speshed or jitted. Deopts are the opposite, when speshed or jitted code has to be "downgraded" to being interpreted.
If the profile data is too big, it could take a long time for a browser to open the file. In that case, output to a file with a .json extension using the --profile=filename option, then open the file with the Qt viewer.
To deal with even larger profiles, output to a file with a .sql extension. This will write the profile data as a series of SQL statements, suitable for opening in SQLite.
# create a profile perl6 --profile=demo.sql -e 'say (^20).combinations(3).elems' # create a SQLite database sqlite3 demo.sqlite # load the profile data sqlite> .read demo.sql # the query below is equivalent to the default view of the "Routines" tab in the HTML profile sqlite> select case when r.name = "" then "<anon>" else r.name end as name, r.file, r.line, sum(entries) as entries, sum(case when rec_depth = 0 then inclusive_time else 0 end) as inclusive_time, sum(exclusive_time) as exclusive_time from calls c, routines r where c.id = r.id group by c.id order by inclusive_time desc limit 30;
The in-progress, next-gen profiler is moarperf, which can accept .sql or SQLite files and has a bunch of new functionality compared to the original profiler. However, it has more dependencies than the relatively stand-alone original profiler, so you'll have to install some modules before using it.
To learn how to interpret the profile info, use the prof-m: your code goes here evalbot (explained above) and ask questions on the IRC channel.
If you want to profile the time and memory it takes to compile your code, use Rakudo's --profile-compile or --profile-stage options.
Use perl6-bench.
If you run perl6-bench for multiple compilers (typically, versions of Perl 5, Perl 6, or NQP), results for each are visually overlaid on the same graphs, to provide for quick and easy comparison.
Once you've used the above techniques to identify the code to improve, you can then begin to address (and share) the problem with others:
For each problem, distill it down to a one-liner or the gist and either provide performance numbers or make the snippet small enough that it can be profiled using prof-m: your code or gist URL goes here.
Think about the minimum speed increase (or ram reduction or whatever) you need/want, and think about the cost associated with achieving that goal. What's the improvement worth in terms of people's time and energy?
Let others know if your Perl 6 use-case is in a production setting or just for fun.
This bears repeating: make sure you're not wasting time on the wrong code. Start by identifying the "critical 3%" of your code.
A quick, fun, productive way to try improve code line-by-line is to collaborate with others using the #perl6 evalbot camelia.
With multi-dispatch, you can drop in new variants of routines "alongside" existing ones:
# existing code generically matches a two arg foo call: multi sub foo(Any $a, Any $b) { ... } # new variant takes over for a foo("quux", 42) call: multi sub foo("quux", Int $b) { ... }
The call overhead of having multiple foo definitions is generally insignificant (though see discussion of where below), so if your new definition handles its particular case more efficiently than the previously existing set of definitions, then you probably just made your code that much more efficient for that case.
Most where clauses – and thus most subsets – force dynamic (runtime) type checking and call resolution for any call it might match. This is slower, or at least later, than compile-time.
Method calls are generally resolved as late as possible (dynamically at runtime), whereas sub calls are generally resolved statically at compile-time.
One of the most reliable techniques for making large performance improvements, regardless of language or compiler, is to pick a more appropriate algorithm.
A classic example is Boyer-Moore. To match a small string in a large string, one obvious way to do it is to compare the first character of the two strings and then, if they match, compare the second characters, or, if they don't match, compare the first character of the small string with the second character in the large string, and so on. In contrast, the Boyer-Moore algorithm starts by comparing the *last* character of the small string with the correspondingly positioned character in the large string. For most strings, the Boyer-Moore algorithm is close to N times faster algorithmically, where N is the length of the small string.
The next couple sections discuss two broad categories for algorithmic improvement that are especially easy to accomplish in Perl 6. For more on this general topic, read the wikipedia page on algorithmic efficiency, especially the 'See also' section near the end.
This is another very important class of algorithmic improvement.
See the slides for Parallelism, Concurrency, and Asynchrony in Perl 6 and/or the matching video.
There are plenty of high performance C libraries that you can use within Perl 6 and NativeCall makes it easy to create wrappers for them. There's experimental support for C++ libraries, too.
If you want to use Perl 5 modules in Perl 6, mix in Perl 6 types and the Meta-Object Protocol.
More generally, Perl 6 is designed to smoothly interoperate with other languages and there are a number of modules aimed at facilitating the use of libs from other langs.
To date, the focus for the compiler has been correctness, not how fast it generates code or how fast or lean the code it generates runs. But that's expected to change, eventually... You can talk to compiler devs on the freenode IRC channels #perl6 and #moarvm about what to expect. Better still, you can contribute yourself:
Rakudo is largely written in Perl 6. So if you can write Perl 6, then you can hack on the compiler, including optimizing any of the large body of existing high-level code that impacts the speed of your code (and everyone else's).
Most of the rest of the compiler is written in a small language called NQP that's basically a subset of Perl 6. If you can write Perl 6, you can fairly easily learn to use and improve the mid-level NQP code too, at least from a pure language point of view. To dig into NQP and Rakudo's guts, start with NQP and internals course.
If low-level C hacking is your idea of fun, checkout MoarVM and visit the freenode IRC channel #moarvm (logs).
Some known current Rakudo performance weaknesses not yet covered in this page include the use of gather/take, junctions, regexes, and string handling in general.
If you think some topic needs more coverage on this page, please submit a PR or tell someone your idea. Thanks. :)
If you've tried everything on this page to no avail, please consider discussing things with a compiler dev on #perl6, so we can learn from your use-case and what you've found out about it so far.
Once a dev knows of your plight, allow enough time for an informed response (a few days or weeks, depending on the exact nature of your problem and potential solutions).
If that hasn't worked out, please consider filing an issue about your experience at our user experience repo before moving on.
Thanks. :)
Using the types the compiler and hardware make available to you
Perl 6 offers a set of native types with a fixed, and known, representation in memory. This page shows which ones exist and how they can be used. Please check also the page on native numerics for more information on them.
Some simple types in Perl 6 have a native representation, indicating that they will use the C language representation provided by the compiler, operating system and machine. These are the four native types available:
int | Equivalent to Int (with limited range) |
uint | Equivalent to Int (with limited range) with the unsigned trait |
num | Equivalent to Num |
str | Equivalent to Str |
However, these types do not necessarily have the size that is required by the NativeCall interface (e.g., Perl 6's int can be 8 bytes but C's int is only 4 bytes); the types below will have to be used instead of the types int or num listed above.
In general, these variables will behave in the same way as regular scalar variables, in a behavior that is called auto-boxing; however, there are some differences, since what you are actually declaring is how they will be represented, not their actual type. The first one is that their type will be actually their equivalent type, not their native type.
my int $intillo = 3; say $intillo.^name; # OUTPUT: «Int»
This obviously means that they will smartmatch their equivalent (auto-boxed) type, not their native type:
my str $strillo = "tres"; say $strillo ~~ str; # OUTPUT: «False» say $strillo ~~ Str; # OUTPUT: «True»
And also that they will always have a default value, unlike their non-native counterparts:
say (my Str $); # OUTPUT: «(Str)» say (my str $); # OUTPUT: «» say (my num $); # OUTPUT: «0»
Note: In v6.c, the default value for num would have been a NaN.
This is due to the fact that Natives don't know their types because they're just values, without any meta-data. In multi-dispatch, you can have a native candidate, but you cannot differentiate different sizes of the same native type. That is, you can have an Int and int candidates, but there would be an ambiguity between, for instance int, atomicint or int64 candidates.
They cannot be bound either. Trying to do my num $numillo := 3.5 will raise the exception Cannot bind to natively typed variable '$variable-name'; use assignment instead.
Native types can also be composite.
my int @intillos = ^10_000_000; say [+] @intillos; # OUTPUT: «49999995000000»
In this case, nativeness extends to the composite type, which will be array
my num @many-pi = ^8 »*» π ; say @many-pi.^name; # OUTPUT: «array[num]»
Native arrays are Iterable, but they are not a subclass of List. However, they behave similarly to Arrays; for instance, they can be shaped:
my str @letter-pairs[10] = 'a'..'j' Z~ 'A'..'J'; say @letter-pairs.perl; # OUTPUT: «array[str].new(:shape(10,), ["aA", "bB", "cC", "dD", "eE", "fF", "gG", "hH", "iI", "jJ"])»
What has been mentioned about types with native representation also applies here; they will be auto-boxed to Perl 6 types and will not be boundable. However, these types, which are listed in the table below, have the characteristic of being usable in NativeCall functions.
int8 | (int8_t in C) |
int16 | (int16_t in C) |
int32 | (int32_t in C) |
int64 | (int64_t in C) |
byte, uint8 | (uint8_t in C) |
uint16 | (uint16_t in C) |
uint32 | (uint32_t in C) |
uint64 | (uint64_t in C) |
num32 | (float in C) |
num64 | (double in C) |
These types have a fixed size representation which is independent of the platform, and thus can be used safely for those native calls. Nothing prevents us from using them in any other environment, if we so wish. In the same way as the types above, this size will have to be taken into account when assigning values to variables of this type:
my byte $intillo = 257; say $intillo; # OUTPUT: «1»
Since byte is able to hold only 8 bits, it will wrap over and assign the result of the original value modulo 256, which is what is shown.
The main difference between types with declared native size and those without is the use of is nativesize in their declaration. For instance, int8 is declared in this way:
my native int8 is repr('P6int') is Int is nativesize(8) { }
Indicating that it will use, besides an integer representation (P6int), a native size of only 8 bits. This trait, however, is not intended to be used in your programs since it is not part of the Perl 6 specification.
The native void type corresponds to the C void type. Although, being a valid type, you can use it in expressions:
use NativeCall; my void $nothing; say $nothing.perl; # OUTPUT: «NativeCall::Types::void»
In practice, it is an Uninstantiable type that can rarely be used by itself, and in fact it is explicitly forbidden in return types. However, it is generally found in typed pointers representing the equivalent to the void * pointer in C.
sub malloc( int32 $size --> Pointer[void] ) is native { * }; my Pointer[void] $for-malloc = malloc( 32 ); say $for-malloc.perl;
You can also nativecast Blobs to this kind of pointer in case you need to work with them in native functions that use the type
use NativeCall; my Pointer[void] $native = nativecast(Pointer[void], Blob.new(0x22, 0x33));
However, outside that, the functionality it offers is quite limited, since pointers to void cannot be dereferenced:
use NativeCall; my Pointer[void] $native = nativecast(Pointer[void], Buf.new(0x22, 0x33)); say $native.deref; # ERROR OUTPUT: «Internal error: unhandled target type»
In this context, atomic refers to safe operation under threading. Perl 6 provides a type, atomicint, and some operations which, together, guarantee this. Please check the atomic operations section on the Numerics page for more information on this.
The types described in this section are Rakudo specific, so they are not guaranteed to be in other implementations or remain the same in future versions.
long | (long in C) |
longlong | (longlong in C) |
ulong | (long and unsigned in C) |
ulonglong | (longlong and unsigned in C) |
size_t | (size_t and unsigned in C) |
ssize_t | (size_t in C) |
bool | (bool in C) |
You can use them in the same way they would be used in native C:
use NativeCall; my $just-an-array = CArray[int32].new( 1, 2, 3, 4, 5 ); loop ( my size_t $i = 0; $i < $just-an-array.elems; $i++ ) { say $just-an-array[$i]; }
Which would print the five elements of the array, as it should be expected.
Program execution phases and corresponding phaser blocks
The lifetime (execution timeline) of a program is broken up into phases. A phaser is a block of code called during a specific execution phase.
A phaser block is just a trait of the closure containing it, and is automatically called at the appropriate moment. These auto-called blocks are known as phasers, since they generally mark the transition from one phase of computing to another. For instance, a CHECK block is called at the end of compiling a compilation unit. Other kinds of phasers can be installed as well; these are automatically called at various times as appropriate, and some of them respond to various control exceptions and exit values. For instance, some phasers might be called if the exit from a block is successful or not, with success in this case defined by returning with a defined value or list without any Failure or exception in the process.
Here is a summary:
BEGIN {...} # * at compile time, as soon as possible, only ever runs once CHECK {...} # * at compile time, as late as possible, only ever runs once INIT {...} # * at runtime, as soon as possible, only ever runs once END {...} # at runtime, as late as possible, only ever runs once DOC [BEGIN|CHECK|INIT] {...} # only in documentation mode ENTER {...} # * at every block entry time, repeats on loop blocks. LEAVE {...} # at every block exit time (even stack unwinds from exceptions) KEEP {...} # at every successful block exit, part of LEAVE queue UNDO {...} # at every unsuccessful block exit, part of LEAVE queue FIRST {...} # at loop initialization time, before any ENTER NEXT {...} # at loop continuation time, before any LEAVE LAST {...} # at loop termination time, after any LEAVE PRE {...} # assert precondition at every block entry, before ENTER POST {...} # assert postcondition at every block exit, after LEAVE CATCH {...} # catch exceptions, before LEAVE CONTROL {...} # catch control exceptions, before LEAVE LAST {...} # supply tapped by whenever-block is done, runs very last QUIT {...} # catch async exceptions within a whenever-block, runs very last COMPOSE {...} # when a role is composed into a class (Not yet implemented) CLOSE {...} # appears in a supply block, called when the supply is closed
Phasers marked with a * have a runtime value, and if evaluated earlier than their surrounding expression, they simply save their result for use in the expression later when the rest of the expression is evaluated:
my $compiletime = BEGIN { now }; our $random = ENTER { rand };
As with other statement prefixes, these value-producing constructs may be placed in front of either a block or a statement:
my $compiletime = BEGIN now; our $random = ENTER rand;
Most of these phasers will take either a block or a function reference. The statement form can be particularly useful to expose a lexically scoped declaration to the surrounding lexical scope without "trapping" it inside a block.
These declare the same variables with the same scope as the preceding example, but run the statements as a whole at the indicated time:
BEGIN my $compiletime = now; ENTER our $random = rand;
(Note, however, that the value of a variable calculated at compile time may not persist under runtime cloning of any surrounding closure.)
Most of the non-value-producing phasers may also be so used:
END say my $accumulator;
Note, however, that
END say my $accumulator = 0;
sets the variable to 0 at END time, since that is when the "my" declaration is actually executed. Only argumentless phasers may use the statement form. This means that CATCH and CONTROL always require a block, since they take an argument that sets $_ to the current topic, so that the innards are able to behave as a switch statement. (If bare statements were allowed, the temporary binding of $_ would leak out past the end of the CATCH or CONTROL, with unpredictable and quite possibly dire consequences. Exception handlers are supposed to reduce uncertainty, not increase it.)
Some of these phasers also have corresponding traits that can be set on variables; they use will followed by the name of the phaser in lowercase. These have the advantage of passing the variable in question into the closure as its topic:
our $h will enter { .rememberit() } will undo { .forgetit() };
Only phasers that can occur multiple times within a block are eligible for this per-variable form; this excludes CATCH and others like CLOSE or QUIT.
The topic of the block outside a phaser is still available as OUTER::<$_> . Whether the return value is modifiable may be a policy of the phaser in question. In particular, the return value should not be modified within a POST phaser, but a LEAVE phaser could be more liberal.
Any phaser defined in the lexical scope of a method is a closure that closes over self as well as normal lexicals. (Or equivalently, an implementation may simply turn all such phasers into submethods whose primed invocant is the current object.)
When multiple phasers are scheduled to run at the same moment, the general tiebreaking principle is that initializing phasers execute in order declared, while finalizing phasers execute in the opposite order, because setup and teardown usually want to happen in the opposite order from each other.
Compilation begins
BEGIN {...} # at compile time, As soon as possible, only ever runs once CHECK {...} # at compile time, As late as possible, only ever runs once COMPOSE {...} # when a role is composed into a class (Not yet implemented)
Execution begins
INIT {...} # at runtime, as soon as possible, only ever runs once
Before block execution begins
PRE {...} # assert precondition at every block entry, before ENTER
Loop execution begins
FIRST {...} # at loop initialization time, before any ENTER
Block execution begins
ENTER {...} # at every block entry time, repeats on loop blocks.
Exception maybe happens
CATCH {...} # catch exceptions, before LEAVE CONTROL {...} # catch control exceptions, before LEAVE
End of loop, either continuing or finished
NEXT {...} # at loop continuation time, before any LEAVE LAST {...} # at loop termination time, after any LEAVE
End of block
LEAVE {...} # when blocks exits, even stack unwinds from exceptions KEEP {...} # at every successful block exit, part of LEAVE queue UNDO {...} # at every unsuccessful block exit, part of LEAVE queue
Postcondition for block
POST {...} # assert postcondition at every block exit, after LEAVE
Async whenever-block is complete
LAST {...} # if ended normally with done, runs once after block QUIT {...} # catch async exceptions
Program terminating
END {...} # at runtime, ALAP, only ever runs once
Runs at compile time, as soon as the code in the phaser has compiled, only runs once.
The return value is available for use in later phases:
say "About to print 3 things"; for ^3 { say ^10 .pick ~ '-' ~ BEGIN { say "Generating BEGIN value"; ^10 .pick } } # OUTPUT: # Generating BEGIN value # About to print 3 things # 3-3 # 4-3 # 6-3
The ^10 .pick in the phaser is generated only once and is then re-used by the loop during runtime. Note how the say in the BEGIN block is executed before the say that is above the loop.
Runs at compile time, as late as possible, only runs once.
Can have a return value that is provided even in later phases.
Code that is generated at runtime can still fire off CHECK and INIT phasers, though of course those phasers can't do things that would require travel back in time. You need a wormhole for that.
Runs after compilation during main execution, as soon as possible, only runs once. It can have a return value that is provided even in later phases.
When phasers are in different modules, the INIT and END phasers are treated as if declared at use time in the using module. (It is erroneous to depend on this order if the module is used more than once, however, since the phasers are only installed the first time they're noticed.)
Code that is generated at runtime can still fire off CHECK and INIT phasers, though of course those phasers can't do things that would require travel back in time. You need a wormhole for that.
An INIT only runs once for all copies of a cloned closure.
Runs after compilation during main execution, as late as possible, only runs once.
When phasers are in different modules, the INIT and END phasers are treated as if declared at use time in the using module. (It is erroneous to depend on this order if the module is used more than once, however, since the phasers are only installed the first time they're noticed.)
Execution in the context of a block has its own phases.
Block-leaving phasers wait until the call stack is actually unwound to run. Unwinding happens only after some exception handler decides to handle the exception that way. That is, just because an exception is thrown past a stack frame does not mean we have officially left the block yet, since the exception might be resumable. In any case, exception handlers are specified to run within the dynamic scope of the failing code, whether or not the exception is resumable. The stack is unwound and the phasers are called only if an exception is not resumed.
These can occur multiple times within the block. So they aren't really traits, exactly--they add themselves onto a list stored in the actual trait. If you examine the ENTER trait of a block, you'll find that it's really a list of phasers rather than a single phaser.
All of these phaser blocks can see any previously declared lexical variables, even if those variables have not been elaborated yet when the closure is invoked (in which case the variables evaluate to an undefined value.)
Runs at every block entry time, repeats on loop blocks.
Can have a return value that is provided even in later phases.
An exception thrown from an ENTER phaser will abort the ENTER queue, but one thrown from a LEAVE phaser will not.
Runs at every block exit time (even stack unwinds from exceptions), except when the program exits abruptly (e.g. with exit).
LEAVE phasers for a given block are necessarily evaluated after any CATCH and CONTROL phasers. This includes the LEAVE variants, KEEP and UNDO. POST phasers are evaluated after everything else, to guarantee that even LEAVE phasers can't violate postconditions.
An exception thrown from an ENTER phaser will abort the ENTER queue, but one thrown from a LEAVE phaser will not.
If a POST fails or any kind of LEAVE block throws an exception while the stack is unwinding, the unwinding continues and collects exceptions to be handled. When the unwinding is completed all new exceptions are thrown from that point.
sub answer() { LEAVE say „I say after the return value.“; 42 # this is the return value }
Note: be mindful of LEAVE phasers directly in blocks of routines, as they will get executed even when an attempt to call the routine with wrong arguments is made:
sub foo (Int) { say "Hello!"; LEAVE say "oh noes!" } try foo rand; # OUTPUT: «oh noes!»
Although the subroutine's body did not get run, because the sub expects an Int and rand returned a Num, its block was entered and left (when param binding failed), and so the LEAVE phaser was run.
Runs at every successful block exit, as part of the LEAVE queue (shares the same order of execution).
Runs at every unsuccessful block exit, as part of the LEAVE queue (shares the same order of execution).
Asserts a precondition at every block entry. Runs before the ENTER phase.
PRE phasers fire off before any ENTER or FIRST.
The exceptions thrown by failing PRE and POST phasers cannot be caught by a CATCH in the same block, which implies that POST phaser are not run if a PRE phaser fails.
Asserts a postcondition at every block entry. Runs after the LEAVE phase.
For phasers such as KEEP and POST that are run when exiting a scope normally, the return value (if any) from that scope is available as the current topic within the phaser.
The POST block can be defined in one of two ways. Either the corresponding POST is defined as a separate phaser, in which case PRE and POST share no lexical scope. Alternately, any PRE phaser may define its corresponding POST as an embedded phaser block that closes over the lexical scope of the PRE.
If a POST fails or any kind of LEAVE block throws an exception while the stack is unwinding, the unwinding continues and collects exceptions to be handled. When the unwinding is completed all new exceptions are thrown from that point.
The exceptions thrown by failing PRE and POST phasers cannot be caught by a CATCH in the same block, which implies that POST phaser are not run if a PRE phaser fails.
FIRST, NEXT, and LAST are meaningful only within the lexical scope of a loop, and may occur only at the top level of such a loop block.
Runs at loop initialization, before ENTER.
Runs when loop is continued (either through next or because you got to the bottom of the loop and are looping back around), before LEAVE.
A NEXT executes only if the end of the loop block is reached normally, or an explicit next is executed. In distinction to LEAVE phasers, a NEXT phaser is not executed if the loop block is exited via any exception other than the control exception thrown by next. In particular, a last bypasses evaluation of NEXT phasers.
Runs when a loop is finished because the condition is met, or when it exits using last or return; it is executed after LEAVE.
Runs when an exception is raised by the current block, before the LEAVE phase.
Runs when a control exception is raised by the current block, before the LEAVE phase. It is raised by return, fail, redo, next, last, done, emit, take, warn, proceed and succeed.
say elems gather { CONTROL { when CX::Warn { say "WARNING!!! $_"; .resume } when CX::Take { say "Don't take my stuff"; .resume } when CX::Done { say "Done"; .resume } } warn 'people take stuff here'; take 'keys'; done; } # OUTPUT: # WARNING!!! people take stuff here # Don't take my stuff # Done # 0
Runs when a role is composed into a class.
Runs when a Supply finishes with a call to done or when a supply block exits normally. It runs completely after the whenever block it is placed within finishes.
This phaser reuses the name LAST, but works differently from the LAST loop phaser. This phaser is similar to setting the done routine while tapping a supply with tap.
Runs when a Supply terminates early with an exception. It runs after the whenever block it is placed within finishes.
This phaser is similar to setting the quit routine while tapping a Supply with tap.
Appears in a supply block. Called when the supply is closed.
The phasers BEGIN, CHECK and INIT are run only in documentation mode when prefixed with the DOC keyword. The compiler is in documentation when run with --doc.
DOC INIT { say 'init' } # prints 'init' at initialization time when in documentation mode.
Special modules that define certain aspects of the behavior of the code
In Perl 6, pragmas are directive used to either identify a specific version of Perl 6 to be used or to modify the compiler's normal behavior in some way. The use keyword enables a pragma (similar to how you can use a module). To disable a pragma, use the no keyword:
use v6.c; # use 6.c language version no worries; # don't issue compile time warnings
Following is a list of pragmas with a short description of each pragma's purpose or a link to more details about its use. (Note: Pragmas marked "[NYI]" are not yet implemented, and those marked "[TBD]" are to be defined later.)
This pragma states the version of the compiler that is going to be used, and turns on its features if they are optional.
use v6; # Load latest supported version (non-PREVIEW). # Also, useful for producing better errors when accidentally # executing the program with `perl` instead of `perl6`
use v6.c; # Use the "Christmas" version of Perl 6
use v6.d; # Use the "Diwali" version of Perl 6
From 2018.11, which implemented 6.d, this pragma does not do anything.
use v6.d.PREVIEW; # On 6.d-capable compilers, enables 6.d features, # otherwise enables the available experimental # preview features for 6.d language
Since these pragmas turn on the compiler version, they should be the first statement in the file (preceding comments and Pod are fine).
This pragma is not currently part of any Perl 6 specification, but is present in Rakudo as a synonym to use nqp (see below).
use MONKEY;
Turns on all available MONKEY pragmas, currently the three above; thus, it would be equivalent to
use MONKEY-TYPING; use MONKEY-SEE-NO-EVAL; use MONKEY-GUTS;
Applies the is dynamic trait to variables in the pragma's lexical scope. The effect can be restricted to a subset of variables by listing their names as arguments. By default applies to all variables.
# Apply is dynamic only to $x, but not to $y
use dynamic-scope <$x>;
sub poke {
say $CALLER::x;
say $CALLER::y;
}
my $x = 23;
my $y = 34;
poke;
# OUTPUT:
# 23
# Cannot access '$y' through CALLER, because it is not declared as dynamic
This pragma is not currently part of any Perl 6 specification and was added in Rakudo 2019.03.
Allows use of experimental features
A lexical pragma that makes Failures returned from routines fatal. For example, prefix + on a Str coerces it to Numeric, but will return a Failure if the string contains non-numeric characters. Saving that Failure in a variable prevents it from being sunk, and so the first code block below reaches the say $x.^name; line and prints Failure in output.
In the second block, the use fatal pragma is enabled, so the say line is never reached because the Exception contained in the Failure returned from prefix + gets thrown and the CATCH block gets run, printing the Caught... line. Note that both blocks are the same program and use fatal only affects the lexical block it was used in:
{ my $x = +"a"; say $x.^name; CATCH { default { say "Caught {.^name}" } } } # OUTPUT: «Failure» { use fatal; my $x = +"a"; say $x.^name; CATCH { default { say "Caught {.^name}" } } } # OUTPUT: «Caught X::Str::Numeric»
Inside try blocks, the fatal pragma is enabled by default, and you can disable it with no fatal:
try { my $x = +"a"; say $x.^name; CATCH { default { say "Caught {.^name}" } } } # OUTPUT: «Caught X::Str::Numeric» try { no fatal; my $x = +"a"; say $x.^name; CATCH { default { say "Caught {.^name}" } } } # OUTPUT: «Failure»
[NYI]
[NYI]
[2018.09 and later]
Allow for some other language constructs that were deemed to be a trap that warranted a warning and/or an error in normal Perl 6 programming. Currently, Perl5 and C++ are allowed.
sub abs() { say "foo" } abs; # Unsupported use of bare "abs"; in Perl 6 please use .abs if you meant # to call it as a method on $_, or use an explicit invocant or argument, # or use &abs to refer to the function as a noun
In this case, providing an abs sub that doesn't take any arguments, did not make the compilation error go away.
use isms <Perl5>; sub abs() { say "foo" } abs; # foo
With this, the compiler will allow the offending Perl 5 construct, allowing the code to actually be executed.
If you do not specify any language, all known language constructs are allowed.
use isms; # allow for Perl5 and C++ isms
This pragma adds subdirectories to the library search path so that the interpreter can find the modules.
use lib <lib /opt/lib /usr/local/lib>;
This will search the directories passed in a list. Please check the modules documentation for more examples.
Set the value of the $?NL constant in the scope it is called. Possible values are :lf (which is the default, indicating Line Feed), :crlf (indicating Carriage Return, Line Feed) and :cr (indicating Carriage Return).
Use at your own risk.
This is a Rakudo-specific pragma. With it, Rakudo provides access to the nqp opcodes in a top level namespace:
use nqp; nqp::say("hello world");
This uses the underlying nqp say opcode instead of the Perl 6 routine. This pragma may make your code rely on a particular version of nqp, and since that code is not part of the Perl 6 specification, it's not guaranteed to be stable. You may find a large number of usages in the Rakudo core, which are used to make the core functionality as fast as possible. Future optimizations in the code generation of Rakudo may obsolete these usages.
[NYI]
The default allows precompilation of source code, specifically if used in a module. If for whatever reason you do not want the code (of your module) to be precompiled, you can use no precompilation. This will prevent the entire compilation unit (usually a file) from being precompiled.
strict is the default behavior, and requires that you declare variables before using them. You can relax this restriction with no.
no strict; $x = 42; # OK
When use trace is activated, any line of code executing will be written to STDERR. You can use no trace to switch off the feature, so this only happens for certain sections of code.
Lexically controls whether compile-time warnings generated by the compiler get shown. Enabled by default.
$ perl6 -e 'say :foo<>.Pair' Potential difficulties: Pair with <> really means an empty list, not null string; use :foo('') to represent the null string, or :foo() to represent the empty list more accurately at -e:1 ------> say :foo<>⏏.Pair foo => Nil $ perl6 -e 'no worries; say :foo<>.Pair' foo => Nil
Writing strings, word lists, and regexes in Perl 6
Strings are usually represented in Perl 6 code using some form of quoting construct. The most minimalistic of these is Q, usable via the shortcut 「…」, or via Q followed by any pair of delimiters surrounding your text. Most of the time, though, the most you'll need is '…' or "…", described in more detail in the following sections.
Q[ A literal string ] 「 More plainly. 」 Q ^ Almost any non-word character can be a delimiter! ^ Q 「「 Delimiters can be repeated/nested if they are adjacent. 」」
Delimiters can be nested, but in the plain Q form, backslash escapes aren't allowed. In other words, basic Q strings are as literal as possible.
Some delimiters are not allowed immediately after Q, q, or qq. Any characters that are allowed in identifiers are not allowed to be used, since in such a case, the quoting construct together with such characters are interpreted as an identifier. In addition, ( ) is not allowed because that is interpreted as a function call. If you still wish to use those characters as delimiters, separate them from Q, q, or qq with a space. Please note that some natural languages use a left delimiting quote on the right side of a string. Q will not support those as it relies on unicode properties to tell left and right delimiters apart.
Q' this will not work! ' Q( this won't work either! )
The examples above will produce an error. However, this will work
Q ( this is fine, because of space after Q ) Q ' and so is this ' Q<Make sure you < match > opening and closing delimiters> Q{This is still a closing curly brace → \ }
These examples produce:
this is fine, because of space after Q and so is this Make sure you <match> opening and closing delimiters This is still a closing curly brace → \
The behavior of quoting constructs can be modified with adverbs, as explained in detail in later sections.
Short | Long | Meaning |
:x | :exec | Execute as command and return results |
:w | :words | Split result on words (no quote protection) |
:ww | :quotewords | Split result on words (with quote protection) |
:q | :single | Interpolate \\, \qq[...] and escaping the delimiter with \ |
:double | Interpolate with :s, :a, :h, :f, :c, :b | |
:s | :scalar | Interpolate $ vars |
:a | :array | Interpolate @ vars |
:h | :hash | Interpolate % vars |
:f | :function | Interpolate & calls |
:c | :closure | Interpolate {...} expressions |
:b | :backslash | Enable backslash escapes (\n, \qq, \$foo, etc) |
:to | :heredoc | Parse result as heredoc terminator |
:v | :val | Convert to allomorph if possible |
'Very plain'; q[This back\slash stays]; q[This back\\slash stays]; # Identical output q{This is not a closing curly brace → \}, but this is → }; Q :q $There are no backslashes here, only lots of \$\$\$>!$; '(Just kidding. There\'s no money in that string)'; 'No $interpolation {here}!'; Q:q!Just a literal "\n" here!;
The q form allows for escaping characters that would otherwise end the string using a backslash. The backslash itself can be escaped, too, as in the third example above. The usual form is '…' or q followed by a delimiter, but it's also available as an adverb on Q, as in the fifth and last example above.
These examples produce:
Very plain This back\slash stays This back\slash stays This is not a closing curly brace → } but this is → There are no backslashes here, only lots of $$$! (Just kidding. There's no money in that string) No $interpolation {here}! Just a literal "\n" here
The \qq[...] escape sequence enables qq interpolation for a portion of the string. Using this escape sequence is handy when you have HTML markup in your strings, to avoid interpretation of angle brackets as hash keys:
my $var = 'foo'; say '<code>$var</code> is <var>\qq[$var.uc()]</var>'; # OUTPUT: «<code>$var</code> is <var>FOO</var>»
my $color = 'blue'; say " My favorite color is $color ! "
My favorite color is blue!
The qq form – usually written using double quotes – allows for interpolation of backslash sequences and variables, i.e., variables can be written within the string so that the content of the variable is inserted into the string. It is also possible to escape variables within a qq-quoted string:
say " The \ $color variable contains the value '$color' " ;
The $color variable contains the value 'blue'
Another feature of qq is the ability to interpolate Perl 6 code from within the string, using curly braces:
my ($x, $y, $z) = 4, 3.5, 3; say "This room is $x m by $y m by $z m."; say "Therefore its volume should be { $x * $y * $z } m³!";
This room is 4 m by 3.5 m by 3 m. Therefore its volume should be 42 m³!
By default, only variables with the $ sigil are interpolated normally. This way, when you write "documentation@perl6.org", you aren't interpolating the @perl6 variable. If that's what you want to do, append a [] to the variable name:
my @neighbors = "Felix", "Danielle", "Lucinda"; say "@neighbors [] and I try our best to coexist peacefully."
Felix Danielle Lucinda and I try our best to coexist peacefully.
Often a method call is more appropriate. These are allowed within qq quotes as long as they have parentheses after the call. Thus the following code will work:
say "@neighbors . join (', ') and I try our best to coexist peacefully."
Felix, Danielle, Lucinda and I try our best to coexist peacefully.
However, "@example.com" produces @example.com.
To call a subroutine, use the &-sigil.
say "abc&uc("def")ghi"; # OUTPUT: «abcDEFghi»
Postcircumfix operators and therefore subscripts are interpolated as well.
my %h = :1st; say "abc%h<st>ghi"; # OUTPUT: «abc1ghi»
To enter unicode sequences, use \x or \x[] with the hex-code of the character or a list of characters.
my $s = "I \x2665 Perl 6!"; say $s; # OUTPUT: «I ♥ Perl 6!» $s = "I really \x[2661,2665,2764,1f495] Perl 6!"; say $s; # OUTPUT: «I really ♡♥❤💕 Perl 6!»
You can also use unicode names , named sequences and name aliases with \c[].
my $s = "Camelia \c[BROKEN HEART] my \c[HEAVY BLACK HEART]!"; say $s; # OUTPUT: «Camelia 💔 my ❤!»
Interpolation of undefined values will raise a control exception that can be caught in the current block with CONTROL.
sub niler {Nil}; my Str $a = niler; say("$a.html", "sometext"); say "alive"; # this line is dead code CONTROL { .die };
qw| ! @ # $ % ^ & * \| < > | eqv '! @ # $ % ^ & * | < >'.words.list; q:w { [ ] \{ \} } eqv ('[', ']', '{', '}'); Q:w | [ ] { } | eqv ('[', ']', '{', '}');
The :w form, usually written as qw, splits the string into "words". In this context, words are defined as sequences of non-whitespace characters separated by whitespace. The q:w and qw forms inherit the interpolation and escape semantics of the q and single quote string delimiters, whereas Qw and Q:w inherit the non-escaping semantics of the Q quoter.
This form is used in preference to using many quotation marks and commas for lists of strings. For example, where you could write:
my @directions = 'left', 'right,', 'up', 'down';
It's easier to write and to read this:
my @directions = qw|left right up down|;
say < a b c > eqv ('a', 'b', 'c'); # OUTPUT: «True» say < a b 42 > eqv ('a', 'b', '42'); # OUTPUT: «False», the 42 became an IntStr allomorph say < 42 > ~~ Int; # OUTPUT: «True» say < 42 > ~~ Str; # OUTPUT: «True»
The angle brackets quoting is like qw, but with extra feature that lets you construct allomorphs or literals of certain numbers:
say <42 4/2 1e6 1+1i abc>.perl; # OUTPUT: «(IntStr.new(42, "42"), RatStr.new(2.0, "4/2"), NumStr.new(1000000e0, "1e6"), ComplexStr.new(<1+1i>, "1+1i"), "abc")»
To construct a Rat or Complex literal, use angle brackets around the number, without any extra spaces:
say <42/10>.^name; # OUTPUT: «Rat» say <1+42i>.^name; # OUTPUT: «Complex» say < 42/10 >.^name; # OUTPUT: «RatStr» say < 1+42i >.^name; # OUTPUT: «ComplexStr»
Compared to 42/10 and 1+42i, there's no division (or addition) operation involved. This is useful for literals in routine signatures, for example:
sub close-enough-π (<355/113>) { say "Your π is close enough!" } close-enough-π 710/226; # OUTPUT: «Your π is close enough!»
# WRONG: can't do this, since it's a division operation sub compilation-failure (355/113) {}
The qw form of word quoting will treat quote characters literally, leaving them in the resulting words:
say qw{"a b" c}.perl; # OUTPUT: «("\"a", "b\"", "c")»
Thus, if you wish to preserve quoted sub-strings as single items in the resulting words you need to use the qww variant:
say qww{"a b" c}.perl; # OUTPUT: «("a b", "c")»
The qw form of word quoting doesn't interpolate variables:
my $a = 42; say qw{$a b c}; # OUTPUT: «$a b c»
Thus, if you wish for variables to be interpolated within the quoted string, you need to use the qqw variant:
my $a = 42; my @list = qqw{$a b c}; say @list; # OUTPUT: «[42 b c]»
Note that variable interpolation happens before word splitting:
my $a = "a b"; my @list = qqw{$a c}; .say for @list; # OUTPUT: «abc»
The qqw form of word quoting will treat quote characters literally, leaving them in the resulting words:
my $a = 42; say qqw{"$a b" c}.perl; # OUTPUT: «("\"42", "b\"", "c")»
Thus, if you wish to preserve quoted sub-strings as single items in the resulting words you need to use the qqww variant:
my $a = 42; say qqww{"$a b" c}.perl; # OUTPUT: «("42 b", "c")»
Quote protection happens before interpolation, and interpolation happens before word splitting, so quotes coming from inside interpolated variables are just literal quote characters:
my $a = "1 2"; say qqww{"$a" $a}.perl; # OUTPUT: «("1 2", "1", "2")» my $b = "1 \"2 3\""; say qqww{"$b" $b}.perl; # OUTPUT: «("1 \"2 3\"", "1", "\"2", "3\"")»
This style of quoting is like qqww, but with the added benefit of constructing allomorphs (making it functionally equivalent to qq:ww:v). The ASCII equivalent to « » are double angle brackets << >>.
# Allomorph Construction my $a = 42; say « $a b c ».perl; # OUTPUT: «(IntStr.new(42, "42"), "b", "c")» my $a = 42; say << $a b c >>.perl; # OUTPUT: «(IntStr.new(42, "42"), "b", "c")» # Quote Protection my $a = 42; say « "$a b" c ».perl; # OUTPUT: «("42 b", "c")» my $a = 42; say << "$a b" c >>.perl; # OUTPUT: «("42 b", "c")»
To run a string as an external program, not only is it possible to pass the string to the shell or run functions but one can also perform shell quoting. There are some subtleties to consider, however. qx quotes don't interpolate variables. Thus
my $world = "there"; say qx{echo "hello $world"}
prints simply hello. Nevertheless, if you have declared an environment variable before calling perl6, this will be available within qx, for instance
WORLD="there" perl6 > say qx{echo "hello $WORLD"}
will now print hello there.
The result of calling qx is returned, so this information can be assigned to a variable for later use:
my $output = qx{echo "hello!"}; say $output; # OUTPUT: «hello!»
See also shell, run and Proc::Async for other ways to execute external commands.
If one wishes to use the content of a Perl 6 variable within an external command, then the qqx shell quoting construct should be used:
my $world = "there"; say qqx{echo "hello $world"}; # OUTPUT: «hello there»
Again, the output of the external command can be kept in a variable:
my $word = "cool"; my $option = "-i"; my $file = "/usr/share/dict/words"; my $output = qqx{grep $option $word $file}; # runs the command: grep -i cool /usr/share/dict/words say $output; # OUTPUT: «CooleyCooley'sCoolidgeCoolidge'scool...»
See also run and Proc::Async for better ways to execute external commands.
A convenient way to write multi-line string literals are heredocs, which let you choose the delimiter yourself:
say q:to/END/; Here is some multi-line string END
The contents of the heredoc always begin on the next line, so you can (and should) finish the line.
my $escaped = my-escaping-function(q:to/TERMINATOR/, language => 'html'); Here are the contents of the heredoc. Potentially multiple lines. TERMINATOR
If the terminator is indented, that amount of indention is removed from the string literals. Therefore this heredoc
say q:to/END/; Here is some multi line string END
produces this output:
Here is some multi line string
Heredocs include the newline from before the terminator.
To allow interpolation of variables use the qq form, but you will then have to escape meta characters {\ as well as $ if it is not the sigil for a defined variable. For example:
my $f = 'db.7.3.8'; my $s = qq:to/END/; option \{ file "$f"; }; END say $s;
would produce:
option { file "db.7.3.8"; };
You can begin multiple Heredocs in the same line.
my ($first, $second) = qq:to/END1/, qq:to/END2/; FIRST MULTILINE STRING END1 SECOND MULTILINE STRING END2
Literal strings permit interpolation of embedded quoting constructs by using the escape sequences such as these:
my $animal="quaggas"; say 'These animals look like \qq[$animal]'; # OUTPUT: «These animals look like quaggas» say 'These animals are \qqw[$animal or zebras]'; # OUTPUT: «These animals are quaggas or zebras»
In this example, \qq will do double-quoting interpolation, and \qqw word quoting with interpolation. Escaping any other quoting construct as above will act in the same way, allowing interpolation in literal strings.
For information about quoting as applied in regexes, see the regular expression documentation.
Pattern matching against strings
A regular expression is a sequence of characters that defines a certain text pattern, typically one that one wishes to find in some large body of text.
In theoretical computer science and formal language theory, regular expressions are used to describe so-called regular languages. Since their inception in the 1950's, practical implementations of regular expressions, for instance in the text search and replace functions of text editors, have outgrown their strict scientific definition. In acknowledgement of this, and in an attempt to disambiguate, a regular expression in Perl 6 is normally referred to as a regex (from: regular expression), a term that is also in common use in other programming languages.
In Perl 6, regexes are written in a domain-specific language, i.e. a sublanguage or slang. This page describes this language, and explains how regexes can be used to search for text patterns in strings in a process called pattern matching.
Fundamentally, Perl 6 regexes are very much like subroutines: both are code objects, and just as you can have anonymous subs and named subs, you can have anonymous and named regexes.
A regex, whether anonymous or named, is represented by a Regex object. Yet, the syntax for constructing anonymous and named Regex objects differs. We will therefore discuss them in turn.
An anonymous regex may be constructed in one of the following ways:
rx/pattern/; # an anonymous Regex object; 'rx' stands for 'regex' /pattern/; # an anonymous Regex object; shorthand for 'rx/.../' regex { pattern }; # keyword-declared anonymous regex; this form is # intended for defining named regexes and is discussed # in that context in the next section
The rx/ / form has two advantages over the bare shorthand form / /.
Firstly, it enables the use of delimiters other than the slash, which may be used to improve the readability of the regex definition:
rx{ '/tmp/'.* }; # the use of curly braces as delimiters makes this first rx/ '/tmp/'.* /; # definition somewhat easier on the eyes than the second
Although the choice is vast, not every character may be chosen as an alternative regex delimiter:
You cannot use whitespace or alphanumeric characters as delimiters. Whitespace in regex definition syntax is generally optional, except where it is required to distinguish from function call syntax (discussed hereafter).
Parentheses can be used as alternative regex delimiters, but only with a space between rx and the opening delimiter. This is because identifiers that are immediately followed by parentheses are always parsed as a subroutine call. For example, in rx() the call operator () invokes the subroutine rx. The form rx ( abc ), however, does define a Regex object.
Use of a colon as a delimiter would clash with the use of adverbs, which take the form :adverb; accordingly, such use of the colon is forbidden.
The hashmark # is not available as a delimiter since it is parsed as the start of a comment that runs until the end of the line.
Secondly, the rx form enables the use of regex adverbs, which may be placed between rx and the opening delimiter to modify the definition of the entire regex:
rx:r:s/pattern/; # :r (:ratchet) and :s (:sigspace) adverbs, defining # a racheting regex in which whitespace is significant
Although anonymous regexes are not, as such, named, they may effectively be given a name by putting them inside a named variable, after which they can be referenced, both outside of an embedding regex and from within an embedding regex by means of interpolation:
my $regex = / R \w+ /; say "Zen Buddists like Raku too" ~~ $regex; # OUTPUT: 「Raku」 my $regex = /pottery/; "Japanese pottery rocks!" ~~ / <$regex> /; # Interpolation of $regex into /.../ say $/; # OUTPUT: 「pottery」
A named regex may be constructed using the regex declarator as follows:
regex R { pattern }; # a named Regex object, named 'R'
Unlike with the rx form, you cannot chose your preferred delimiter: curly braces are mandatory. In this regard it should be noted that the definition of a named regex using the regex form is syntactically similar to the definition of a subroutine:
my sub S { /pattern/ }; # definition of Sub object (returning a Regex) my regex R { pattern }; # definition of Regex object
which emphasizes the fact that a Regex object represents code rather than data:
&S ~~ Code; # OUTPUT: True &R ~~ Code; # OUTPUT: True &R ~~ Method; # OUTPUT: True (A Regex is really a Method!)
Also unlike with the rx form for defining an anonymous regex, the definition of a named regex using the regex keyword does not allow for adverbs to be inserted before the opening delimiter. Instead, adverbs that are to modify the entire regex pattern may be included first thing within the curly braces:
regex R { :i pattern }; # :i (:ignorecase), renders pattern case insensitive
Alternatively, by way of shorthand, it is also possible (and recommended) to use the rule and token variants of the regex declarator for defining a Regex when the :ratchet and :sigspace adverbs are of interest:
regex R { :r pattern }; # apply :r (:ratchet) to entire pattern
and, alternatively
token R { pattern }; # same thing: 'token' implies ':r'
Or
regex R { :r :s pattern }; # apply :r (:ratchet) and :s (:sigspace) to pattern
with this alternative:
rule R { pattern }; # same thing: 'rule' implies ':r:s'
Named regexes may be used as building blocks for other regexes, as they are methods that may called from within other regexes using the <regex-name> syntax. When they are used this way, they are often referred to as subrules; see for more details on their use here. Grammars are the natural habitat of subrules, but many common predefined character classes are also implemented as named regexes.
Whitespace in regexes is ignored unless the :sigspace adverb is used to make whitespace syntactically significant.
In addition to whitespace, comments may be used inside of regexes to improve their comprehensibility just as in code in general. This is true for both single line comments and multi line/embedded comments:
my $regex = rx/ \d ** 4 #`(match the year YYYY) '-' \d ** 2 # ...the month MM '-' \d ** 2 /; # ...and the day DD say '2015-12-25'.match($regex); # OUTPUT: «「2015-12-25」»
There are a variety of ways to match a string against a regex. Irrespective of the syntax chosen, a successful match results in a Match object. In case the match is unsuccessful, the result is Nil. In either case, the result of the match operation is available via the special match variable $/.
The most common ways to match a string against an anonymous regex /pattern/ or against a named regex R include the following:
Smartmatch: "string" ~~ /pattern/, or "string" ~~ /<R>/
Smartmatching a string against a Regex performs a regex match of the string against the Regex:
say "Go ahead, make my day." ~~ / \w+ /; # OUTPUT: «「Go」» my regex R { me|you }; say "You talkin' to me?" ~~ / <R> /; # OUTPUT: «「me」 R => 「me」» say "May the force be with you." ~~ &R ; # OUTPUT: «「you」»
The different outputs of the last two statements show that these two ways of smartmatching against a named regex are not identical. The difference arises because the method call <R> from within the anonymous regex / / installs a so-called 'named capture' in the Match object, while the smartmatch against the named Regex as such does not.
Explicit topic match: m/pattern/, or m/<R>/
The match operator m/ / immediately matches the topic variable $_ against the regex following the m.
As with the rx/ / syntax for regex definitions, the match operator may be used with adverbs in between m and the opening regex delimiter, and with delimiters other than the slash. However, while the rx/ / syntax may only be used with regex adverbs that affect the compilation of the regex, the m/ / syntax may additionally be used with matching adverbs that determine how the regex engine is to perform pattern matching.
Here's an example that illustrates the primary difference between the m/ / and / / syntax:
my $match; $_ = "abc"; $match = m/.+/; say $match; say $match.^name; # OUTPUT: «「abc」Match» $match = /.+/; say $match; say $match.^name; # OUTPUT: «/.+/Regex»
Implicit topic match in sink and boolean contexts
In case a Regex object is used in sink context, or in a context in which it is coerced to Bool, the topic variable $_ is automatically matched against it:
$_ = "dummy string"; # Set the topic explicitly rx/ s.* /; # Regex object in sink context matches automatically say $/; # OUTPUT: 「string」 say $/ if rx/ d.* /; # Regex object in boolean context matches automatically # OUTPUT: 「dummy string」
Match method: "string".match: /pattern/, or "string".match: /<R>/
The match method is analogous to the m/ / operator discussed above. Invoking it on a string, with a Regex as an argument, matches the string against the Regex.
Parsing grammars: grammar-name.parse($string)
Although parsing a Grammar involves more than just matching a string against a regex, this powerful regex-based text destructuring tool can't be left out from this overview of common pattern matching methods.
If you feel that your needs exceed what simple regexes have to offer, check out this grammar tutorial|/language/grammar_tutorial> to take regexes to the next level.
A regex describes a pattern to be matched in terms of literals and metacharacters. Alphanumeric characters and the underscore _ constitute the literals: these characters match themselves and nothing else. Other characters act as metacharacters and may, as such, have a special meaning, either by themselves (such as the dot ., which serves as a wildcard) or together with other characters in larger metasyntactic constructs (such as <?before ...>, which defines a lookahead assertion).
In its simplest form a regex comprises only literals:
/Cześć/; # "Hello" in Polish /こんばんは/; # "Good afternoon" in Japanese /Καλησπέρα/; # "Good evening" in Greek
If you want a regex to literally match one or more characters that normally act as metacharacters, those characters must either be escaped using a backslash, or be quoted using single or double quotes.
The backslash serves as a switch. It switches a single metacharacter into a literal, and vice versa:
/ \# /; # matches the hash metacharacter literally / \w /; # turns literal 'w' into a character class (see below) /Hallelujah\!/; # matches string 'Hallelujah!' incl. exclamation mark
Even if a metacharacter does not (yet) have a special meaning in Perl 6, escaping (or quoting) it is required to ensure that the regex compiles and matches the character literally. This allows the clear distinction between literals and metacharacters to be maintained. So, for instance, to match a comma this will work:
/ \, /; # matches a literal comma ','
while this will fail:
/ , /; # !! error: an as-yet meaningless/unrecognized metacharacter # does not automatically match literally
While an escaping backslash exerts its effect on the next individual character, both a single metacharacter and a sequence of metacharacters may be turned into literally matching strings by quoting them in single or double quotes:
/ "abc" /; # quoting literals does not make them more literal / "Hallelujah!" /; # yet, this form is generally preferred over /Hallelujah\!/ / "two words" /; # quoting a space renders it significant, so this matches # the string 'two words' including the intermediate space / '#!:@' /; # this regex matches the string of metacharacters '#!:@'
Quoting does not simply turn every metacharacter into a literal, however. This is because quotes allow for backslash-escapes and interpolation. Specifically: in single quotes, the backslash may be used to escape single quotes and the backslash itself; double quotes additionally enable the interpolation of variables, and of code blocks of the form {...}. Hence all of this works:
/ '\\\'' /; # matches a backslash followed by a single quote: \' my $x = 'Hi'; / "$x there!" /; # matches the string 'Hi there!' / "1 + 1 = {1+1}" /; # matches the string '1 + 1 = 2'
while these examples illustrate mistakes that you will want to avoid:
/ '\' /; # !! error: this is NOT the way to literally match a # backslash because now it escapes the second quote /"Price tag $0.50"/; # !! error: "$0" is interpreted as the first positional # capture (which is Nil), not as '$0'
Strings are searched left to right, so it is enough if only part of the string matches the regex:
if 'Life, the Universe and Everything' ~~ / and / { say ~$/; # OUTPUT: «and» say $/.prematch; # OUTPUT: «Life, the Universe » say $/.postmatch; # OUTPUT: « Everything» say $/.from; # OUTPUT: «19» say $/.to; # OUTPUT: «22» };
Match results are always stored in the $/ variable and are also returned from the match. They are both of type Match if the match was successful; otherwise both are of type Nil.
An unescaped dot . in a regex matches any single character.
So, these all match:
'perl' ~~ /per./; # matches the whole string 'perl' ~~ / per . /; # the same; whitespace is ignored 'perl' ~~ / pe.l /; # the . matches the r 'speller' ~~ / pe.l/; # the . matches the first l
while this doesn't match:
'perl' ~~ /. per /;
because there's no character to match before per in the target string.
Notably . also matches a logical newline \n:
my $text = qq:to/END/ Although I am a multi-line text, I can be matched with /.*/. END ; say $text ~~ / .* /; # OUTPUT «「Although I am amulti-line text,I can be matchedwith /.*/.」»
There are predefined character classes of the form \w. Its negation is written with an upper-case letter, \W.
\n matches a logical newline. \N matches a single character that's not a logical newline.
The definition of what constitutes a logical newline follows the Unicode definition of a line boundary and includes in particular all of: a line feed (LF) \U+000A, a vertical tab (VT) \U+000B, a form feed (FF) \U+000C, a carriage return (CR) \U+000D, and the Microsoft Windows style newline sequence CRLF.
The interpretation of \n in regexes is independent of the value of the variable $?NL controlled by the newline pragma.
\t matches a single tab/tabulation character, U+0009. \T matches a single character that is not a tab.
Note that exotic tabs like the U+000B VERTICAL TABULATION character are not included here.
\h matches a single horizontal whitespace character. \H matches a single character that is not a horizontal whitespace character.
Examples of horizontal whitespace characters are
U+0020 SPACE U+00A0 NO-BREAK SPACE U+0009 CHARACTER TABULATION U+2001 EM QUAD
Vertical whitespace such as newline characters are explicitly excluded; those can be matched with \v; \s matches any kind of whitespace.
\v matches a single vertical whitespace character. \V matches a single character that is not vertical whitespace.
Examples of vertical whitespace characters:
U+000A LINE FEED U+000B VERTICAL TABULATION U+000C FORM FEED U+000D CARRIAGE RETURN U+0085 NEXT LINE U+2028 LINE SEPARATOR U+2029 PARAGRAPH SEPARATOR
Use \s to match any kind of whitespace, not just vertical whitespace.
\s matches a single whitespace character. \S matches a single character that is not whitespace.
say $/.prematch if 'Match the first word.' ~~ / \s+ /; # OUTPUT: «Match»
\d matches a single digit (Unicode property N) and \D matches a single character that is not a digit.
'ab42' ~~ /\d/ and say ~$/; # OUTPUT: «4» 'ab42' ~~ /\D/ and say ~$/; # OUTPUT: «a»
Note that not only the Arabic digits (commonly used in the Latin alphabet) match \d, but also digits from other scripts.
Examples of digits are:
U+0035 5 DIGIT FIVE U+0BEB ௫ TAMIL DIGIT FIVE U+0E53 ๓ THAI DIGIT THREE U+17E5 ៥ KHMER DIGIT FIVE
\w matches a single word character, i.e. a letter (Unicode category L), a digit or an underscore. \W matches a single character that is not a word character.
Examples of word characters:
0041 A LATIN CAPITAL LETTER A 0031 1 DIGIT ONE 03B4 δ GREEK SMALL LETTER DELTA 03F3 ϳ GREEK LETTER YOT 0409 Љ CYRILLIC CAPITAL LETTER LJE
Class | Shorthand | Description |
---|---|---|
<alpha> | Alphabetic characters plus underscore (_) | |
<digit> | \d | Decimal digits |
<xdigit> | Hexadecimal digit [0-9A-Fa-f] | |
<alnum> | \w | <alpha> plus <digit> |
<punct> | Punctuation and Symbols (only Punct beyond ASCII) | |
<graph> | <alnum> plus <punct> | |
<space> | \s | Whitespace |
<cntrl> | Control characters | |
<print> | <graph> plus <space>, but no <cntrl> | |
<blank> | \h | Horizontal whitespace |
<lower> | <:Ll> | Lowercase characters |
<upper> | <:Lu> | Uppercase characters |
<same> | Matches between two identical characters | |
<wb> | Word boundary | |
<ws> | Whitespace. This is actually a default rule. | |
<ww> | Within word | |
<ident> | Identifier. Also a default rule. |
The predefined character classes in the leftmost column are all of the form <name>, a hint to the fact that they are implemented as built-in named regexes. As such they are subject to the usual capturing semantics. This means that if a character class is called with the syntax <name> (i.e. as indicated in the leftmost column), it will not only match, but also capture, installing a correspondingly named 'named capture' in the resulting Match object. In case just a match and no capture is desired, the capture may be suppressed through the use of call syntax that includes a leading dot: <.name>.
Note that the character classes <same>, <wb> and <ww> are so-called zero-width assertions, which do not really match any character.
The character classes mentioned so far are mostly for convenience; another approach is to use Unicode character properties. These come in the form <:property>, where property can be a short or long Unicode General Category name. These use pair syntax.
To match against a Unicode property you can use either smartmatch or uniprop:
"a".uniprop('Script'); # OUTPUT: «Latin» "a" ~~ / <:Script<Latin>> /; # OUTPUT: «「a」» "a".uniprop('Block'); # OUTPUT: «Basic Latin» "a" ~~ / <:Block('Basic Latin')> /; # OUTPUT: «「a」»
These are the Unicode general categories used for matching:
Short | Long |
---|---|
L | Letter |
LC | Cased_Letter |
Lu | Uppercase_Letter |
Ll | Lowercase_Letter |
Lt | Titlecase_Letter |
Lm | Modifier_Letter |
Lo | Other_Letter |
M | Mark |
Mn | Nonspacing_Mark |
Mc | Spacing_Mark |
Me | Enclosing_Mark |
N | Number |
Nd | Decimal_Number or digit |
Nl | Letter_Number |
No | Other_Number |
P | Punctuation or punct |
Pc | Connector_Punctuation |
Pd | Dash_Punctuation |
Ps | Open_Punctuation |
Pe | Close_Punctuation |
Pi | Initial_Punctuation |
Pf | Final_Punctuation |
Po | Other_Punctuation |
S | Symbol |
Sm | Math_Symbol |
Sc | Currency_Symbol |
Sk | Modifier_Symbol |
So | Other_Symbol |
Z | Separator |
Zs | Space_Separator |
Zl | Line_Separator |
Zp | Paragraph_Separator |
C | Other |
Cc | Control or cntrl |
Cf | Format |
Cs | Surrogate |
Co | Private_Use |
Cn | Unassigned |
For example, <:Lu> matches a single, upper-case letter.
Its negation is this: <:!property>. So, <:!Lu> matches a single character that is not an upper-case letter.
Categories can be used together, with an infix operator:
Operator | Meaning |
---|---|
+ | set union |
- | set difference |
To match either a lower-case letter or a number, write <:Ll+:N> or <:Ll+:Number> or <+ :Lowercase_Letter + :Number>.
It's also possible to group categories and sets of categories with parentheses; for example:
say $0 if 'perl6' ~~ /\w+(<:Ll+:N>)/ # OUTPUT: «「6」»
Sometimes the pre-existing wildcards and character classes are not enough. Fortunately, defining your own is fairly simple. Within <[ ]>, you can put any number of single characters and ranges of characters (expressed with two dots between the end points), with or without whitespace.
"abacabadabacaba" ~~ / <[ a .. c 1 2 3 ]>* /; # Unicode hex codepoint range "ÀÁÂÃÄÅÆ" ~~ / <[ \x[00C0] .. \x[00C6] ]>* /; # Unicode named codepoint range "αβγ" ~~ /<[\c[GREEK SMALL LETTER ALPHA]..\c[GREEK SMALL LETTER GAMMA]]>*/;
Within the < > you can use + and - to add or remove multiple range definitions and even mix in some of the Unicode categories above. You can also write the backslashed forms for character classes between the [ ].
/ <[\d] - [13579]> /; # starts with \d and removes odd ASCII digits, but not quite the same as / <[02468]> /; # because the first one also contains "weird" unicodey digits
You can include Unicode properties in the list as well:
/<:Zs + [\x9] - [\xA0]>/ # Any character with "Zs" property, or a tab, but not a "no-break space"
You can use \ to escape characters that would have some meaning in the regular expression:
say "[ hey ]" ~~ /<-[ \] \[ \s ]>+/; # OUTPUT: «「hey」»
To negate a character class, put a - after the opening angle bracket:
say 'no quotes' ~~ / <-[ " ]> + /; # <-["]> matches any character except "
A common pattern for parsing quote-delimited strings involves negated character classes:
say '"in quotes"' ~~ / '"' <-[ " ]> * '"'/;
This regex first matches a quote, then any characters that aren't quotes, and then a quote again. The meaning of * and + in the examples above are explained in the next section on quantifiers.
Just as you can use the - for both set difference and negation of a single value, you can also explicitly put a + in front:
/ <+[123]> / # same as <[123]>
A quantifier makes the preceding atom match a variable number of times. For example, a+ matches one or more a characters.
Quantifiers bind tighter than concatenation, so ab+ matches one a followed by one or more bs. This is different for quotes, so 'ab'+ matches the strings ab, abab, ababab etc.
The + quantifier makes the preceding atom match one or more times, with no upper limit.
For example, to match strings of the form key=value, you can write a regex like this:
/ \w+ '=' \w+ /
The * quantifier makes the preceding atom match zero or more times, with no upper limit.
For example, to allow optional whitespace between a and b you can write:
/ a \s* b /
The ? quantifier makes the preceding atom match zero or once.
For example, to match dog or dogs, you can write:
/ dogs? /
To quantify an atom an arbitrary number of times, use the ** quantifier, which takes a single Int or a Range on the right-hand side that specifies the number of times to match. If a Range is specified, the end-points specify the minimum and maximum number of times to match.
say 'abcdefg' ~~ /\w ** 4/; # OUTPUT: «「abcd」» say 'a' ~~ /\w ** 2..5/; # OUTPUT: «Nil» say 'abc' ~~ /\w ** 2..5/; # OUTPUT: «「abc」» say 'abcdefg' ~~ /\w ** 2..5/; # OUTPUT: «「abcde」» say 'abcdefg' ~~ /\w ** 2^..^5/; # OUTPUT: «「abcd」» say 'abcdefg' ~~ /\w ** ^3/; # OUTPUT: «「ab」» say 'abcdefg' ~~ /\w ** 1..*/; # OUTPUT: «「abcdefg」»
Only basic literal syntax for the right-hand side of the quantifier is supported, to avoid ambiguities with other regex constructs. If you need to use a more complex expression, for example, a Range made from variables, enclose the Range in curly braces:
my $start = 3; say 'abcdefg' ~~ /\w ** {$start .. $start+2}/; # OUTPUT: «「abcde」» say 'abcdefg' ~~ /\w ** {π.Int}/; # OUTPUT: «「abc」»
Negative values are treated like zero:
say 'abcdefg' ~~ /\w ** {-Inf}/; # OUTPUT: «「」» say 'abcdefg' ~~ /\w ** {-42}/; # OUTPUT: «「」» say 'abcdefg' ~~ /\w ** {-10..-42}/; # OUTPUT: «「」» say 'abcdefg' ~~ /\w ** {-42..-10}/; # OUTPUT: «「」»
If then, the resultant value is Inf or NaN or the resultant Range is empty, non-Numeric, contains NaN end-points, or has minimum effective end-point as Inf, the X::Syntax::Regex::QuantifierValue exception will be thrown:
(try say 'abcdefg' ~~ /\w ** {42..10}/ ) orelse say ($!.^name, $!.empty-range); # OUTPUT: «(X::Syntax::Regex::QuantifierValue True)» (try say 'abcdefg' ~~ /\w ** {Inf..Inf}/) orelse say ($!.^name, $!.inf); # OUTPUT: «(X::Syntax::Regex::QuantifierValue True)» (try say 'abcdefg' ~~ /\w ** {NaN..42}/ ) orelse say ($!.^name, $!.non-numeric-range); # OUTPUT: «(X::Syntax::Regex::QuantifierValue True)» (try say 'abcdefg' ~~ /\w ** {"a".."c"}/) orelse say ($!.^name, $!.non-numeric-range); # OUTPUT: «(X::Syntax::Regex::QuantifierValue True)» (try say 'abcdefg' ~~ /\w ** {Inf}/) orelse say ($!.^name, $!.inf); # OUTPUT: «(X::Syntax::Regex::QuantifierValue True)» (try say 'abcdefg' ~~ /\w ** {NaN}/) orelse say ($!.^name, $!.non-numeric); # OUTPUT: «(X::Syntax::Regex::QuantifierValue True)»
To more easily match things like comma separated values, you can tack on a % modifier to any of the above quantifiers to specify a separator that must occur between each of the matches. For example, a+ % ',' will match a or a,a or a,a,a, etc. To also match trailing delimiters ( a, or a,a, ), you can use %% instead of %.
The quantifier interacts with % and controls the number of overall repetitions that can match successfully, so a* % ',' also matches the empty string. If you want match words delimited by commas, you might need to nest an ordinary and a modified quantifier:
say so 'abc,def' ~~ / ^ [\w+] ** 1 % ',' $ /; # Output: «False» say so 'abc,def' ~~ / ^ [\w+] ** 2 % ',' $ /; # Output: «True»
One way to prevent backtracking is through the use of the ratchet adverb as described below. Another more fine-grained way of preventing backtracking in regexes is attaching a : modifier to a quantifier:
my $str = "ACG GCT ACT An interesting chain"; say $str ~~ /<[ACGT\s]>+ \s+ (<[A..Z a..z \s]>+)/; # OUTPUT: «「ACG GCT ACT An interesting chain」 0 => 「An interesting chain」» say $str ~~ /<[ACGT\s]>+: \s+ (<[A..Z a..z \s]>+)/; # OUTPUT: «Nil»
In the second case, the A in An had already been "absorbed" by the pattern, preventing the matching of the second part of the pattern, after \s+. Generally we will want the opposite: prevent backtracking to match precisely what we are looking for.
In most cases, you will want to prevent backtracking for efficiency reasons, for instance here:
say $str ~~ m:g/[(<[ACGT]> **: 3) \s*]+ \s+ (<[A..Z a..z \s]>+)/; # OUTPUT: # (「ACG GCT ACT An interesting chain」 # 0 => 「ACG」 # 0 => 「GCT」 # 0 => 「ACT」 # 1 => 「An interesting chain」)
Although in this case, eliminating the : from behind ** would make it behave exactly in the same way. The best use is to create tokens that will not be backtracked:
$_ = "ACG GCT ACT IDAQT"; say m:g/[(\w+:) \s*]+ (\w+) $$/; # OUTPUT: # (「ACG GCT ACT IDAQT」 # 0 => 「ACG」 # 0 => 「GCT」 # 0 => 「ACT」 # 1 => 「IDAQT」)
Without the : following \w+, the ID part captured would have been simply T, since the pattern would go ahead and match everything, leaving a single letter to match the \w+ expression at the end of the line.
By default, quantifiers request a greedy match:
'abababa' ~~ /a .* a/ && say ~$/; # OUTPUT: «abababa»
You can attach a ? modifier to the quantifier to enable frugal matching:
'abababa' ~~ /a .*? a/ && say ~$/; # OUTPUT: «aba»
You can also enable frugal matching for general quantifiers:
say '/foo/o/bar/' ~~ /\/.**?{1..10}\//; # OUTPUT: «「/foo/」» say '/foo/o/bar/' ~~ /\/.**!{1..10}\//; # OUTPUT: «「/foo/o/bar/」»
Greedy matching can be explicitly requested with the ! modifier.
To match one of several possible alternatives, separate them by ||; the first matching alternative wins.
For example, ini files have the following form:
[section] key = value
Hence, if you parse a single line of an ini file, it can be either a section or a key-value pair and the regex would be (to a first approximation):
/ '[' \w+ ']' || \S+ \s* '=' \s* \S* /
That is, either a word surrounded by square brackets, or a string of non-whitespace characters, followed by zero or more spaces, followed by the equals sign =, followed again by optional whitespace, followed by another string of non-whitespace characters.
An empty string as the first branch is ignored, to allow you to format branches consistently. You could have written the previous example as
/ || '[' \w+ ']' || \S+ \s* '=' \s* \S* /
Even in non-backtracking contexts, the alternation operator || tries all the branches in order until the first one matches.
In short, in regex branches separated by |, the longest token match wins, independent of the textual ordering in the regex. However, what | really does is more than that. It does not decide which branch wins after finishing the whole match, but follows the longest-token matching (LTM) strategy.
Briefly, what | does is this:
First, select the branch which has the longest declarative prefix.
say "abc" ~~ /ab | a.* /; # Output: ⌜abc⌟ say "abc" ~~ /ab | a {} .* /; # Output: ⌜ab⌟ say "if else" ~~ / if | if <.ws> else /; # Output: 「if」 say "if else" ~~ / if | if \s+ else /; # Output: 「if else」
As is shown above, a.* is a declarative prefix, while a {} .* terminates at {}, then its declarative prefix is a. Note that non-declarative atoms terminate declarative prefix. This is quite important if you want to apply | in a rule, which automatically enables :s, and <.ws> accidentally terminates declarative prefix.
If it's a tie, select the match with the highest specificity.
say "abc" ~~ /a. | ab { print "win" } /; # Output: win「ab」
When two alternatives match at the same length, the tie is broken by specificity. That is, ab, as an exact match, counts as closer than a., which uses character classes.
If it's still a tie, use additional tie-breakers.
say "abc" ~~ /a\w| a. { print "lose" } /; # Output: ⌜ab⌟
If the tie breaker above doesn't work, then the textually earlier alternative takes precedence.
For more details, see the LTM strategy.
Using a quoted list in a regex is equivalent to specifying the longest-match alternation of the list's elements. So, the following match:
say 'food' ~~ /< f fo foo food >/; # OUTPUT: «「food」»
is equivalent to:
say 'food' ~~ / f | fo | foo | food /; # OUTPUT: «「food」»
Note that the space after the first < is significant here: <food> calls the named rule food while < food > and < food> specify quoted lists with a single element, 'food'.
If the first branch is an empty string, it is ignored. This allows you to format your regexes consistently:
/ | f | fo | foo | food /
Arrays can also be interpolated into a regex to achieve the same effect:
my @increasingly-edible = <f fo foo food>; say 'food' ~~ /@increasingly-edible/; # OUTPUT: «「food」»
This is documented further under Regex Interpolation, below.
Matches successfully if all &&-delimited segments match the same substring of the target string. The segments are evaluated left to right.
This can be useful for augmenting an existing regex. For example if you have a regex quoted that matches a quoted string, then / <quoted> && <-[x]>* / matches a quoted string that does not contain the character x.
Note that you cannot easily obtain the same behavior with a lookahead, that is, a regex doesn't consume characters, because a lookahead doesn't stop looking when the quoted string stops matching.
say 'abc' ~~ / <?before a> && . /; # OUTPUT: «Nil» say 'abc' ~~ / <?before a> . && . /; # OUTPUT: «「a」» say 'abc' ~~ / <?before a> . /; # OUTPUT: «「a」» say 'abc' ~~ / <?before a> .. /; # OUTPUT: «「ab」»
Just like with ||, empty first branches are ignored.
Much like && in a regex, it matches successfully if all segments separated by & match the same part of the target string.
& (unlike &&) is considered declarative, and notionally all the segments can be evaluated in parallel, or in any order the compiler chooses.
Just like with || and &, empty first branches are ignored.
Regexes search an entire string for matches. Sometimes this is not what you want. Anchors match only at certain positions in the string, thereby anchoring the regex match to that position.
The ^ anchor only matches at the start of the string:
say so 'properly' ~~ / perl/; # OUTPUT: «True» say so 'properly' ~~ /^ perl/; # OUTPUT: «False» say so 'perly' ~~ /^ perl/; # OUTPUT: «True» say so 'perl' ~~ /^ perl/; # OUTPUT: «True»
The $ anchor only matches at the end of the string:
say so 'use perl' ~~ / perl /; # OUTPUT: «True» say so 'use perl' ~~ / perl $/; # OUTPUT: «True» say so 'perly' ~~ / perl $/; # OUTPUT: «False»
You can combine both anchors:
say so 'use perl' ~~ /^ perl $/; # OUTPUT: «False» say so 'perl' ~~ /^ perl $/; # OUTPUT: «True»
Keep in mind that ^ matches the start of a string, not the start of a line. Likewise, $ matches the end of a string, not the end of a line.
The following is a multi-line string:
my $str = chomp q:to/EOS/; Keep it secret and keep it safe EOS # 'safe' is at the end of the string say so $str ~~ /safe $/; # OUTPUT: «True» # 'secret' is at the end of a line, not the string say so $str ~~ /secret $/; # OUTPUT: «False» # 'Keep' is at the start of the string say so $str ~~ /^Keep /; # OUTPUT: «True» # 'and' is at the start of a line -- not the string say so $str ~~ /^and /; # OUTPUT: «False»
The ^^ anchor matches at the start of a logical line. That is, either at the start of the string, or after a newline character. However, it does not match at the end of the string, even if it ends with a newline character.
The $$ anchor matches at the end of a logical line. That is, before a newline character, or at the end of the string when the last character is not a newline character.
To understand the following example, it's important to know that the q:to/EOS/...EOS heredoc syntax removes leading indention to the same level as the EOS marker, so that the first, second and last lines have no leading space and the third and fourth lines have two leading spaces each.
my $str = q:to/EOS/; There was a young man of Japan Whose limericks never would scan. When asked why this was, He replied "It's because I always try to fit as many syllables into the last line as ever I possibly can." EOS # 'There' is at the start of string say so $str ~~ /^^ There/; # OUTPUT: «True» # 'limericks' is not at the start of a line say so $str ~~ /^^ limericks/; # OUTPUT: «False» # 'as' is at start of the last line say so $str ~~ /^^ as/; # OUTPUT: «True» # there are blanks between start of line and the "When" say so $str ~~ /^^ When/; # OUTPUT: «False» # 'Japan' is at end of first line say so $str ~~ / Japan $$/; # OUTPUT: «True» # there's a . between "scan" and the end of line say so $str ~~ / scan $$/; # OUTPUT: «False» # matched at the last line say so $str ~~ / '."' $$/; # OUTPUT: «True»
To match any word boundary, use <|w> or <?wb>. This is similar to \b in other languages. To match the opposite, any character that is not bounding a word, use <!|w> or <!wb>. This is similar to \B in other languages.
These are both zero-width regex elements.
say "two-words" ~~ / two<|w>\-<|w>words /; # OUTPUT: «「two-words」» say "twowords" ~~ / two<!|w><!|w>words /; # OUTPUT: «「twowords」»
<< matches a left word boundary. It matches positions where there is a non-word character at the left, or the start of the string, and a word character to the right.
>> matches a right word boundary. It matches positions where there is a word character at the left and a non-word character at the right, or the end of the string.
These are both zero-width regex elements.
my $str = 'The quick brown fox'; say so ' ' ~~ /\W/; # OUTPUT: «True» say so $str ~~ /br/; # OUTPUT: «True» say so $str ~~ /<< br/; # OUTPUT: «True» say so $str ~~ /br >>/; # OUTPUT: «False» say so $str ~~ /own/; # OUTPUT: «True» say so $str ~~ /<< own/; # OUTPUT: «False» say so $str ~~ /own >>/; # OUTPUT: «True» say so $str ~~ /<< The/; # OUTPUT: «True» say so $str ~~ /fox >>/; # OUTPUT: «True»
You can also use the variants « and » :
my $str = 'The quick brown fox'; say so $str ~~ /« own/; # OUTPUT: «False» say so $str ~~ /own »/; # OUTPUT: «True»
To see the difference between <|w> and «, »:
say "stuff here!!!".subst(:g, />>/, '|'); # OUTPUT: «stuff| here|!!!» say "stuff here!!!".subst(:g, /<</, '|'); # OUTPUT: «|stuff |here!!!» say "stuff here!!!".subst(:g, /<|w>/, '|'); # OUTPUT: «|stuff| |here|!!!»
Anchors are zero-width regex elements. Hence they do not use up a character of the input string, that is, they do not advance the current position at which the regex engine tries to match. A good mental model is that they match between two characters of an input string, or before the first, or after the last character of an input string.
Anchor | Description | Examples |
---|---|---|
^ | Start of string | "⏏two\nlines" |
^^ | Start of line | "⏏two\n⏏lines" |
$ | End of string | "two\nlines⏏" |
$$ | End of line | "two⏏\nlines⏏" |
<< or « | Left word boundary | "⏏two ⏏words" |
>> or » | Right word boundary | "two⏏ words⏏" |
<?wb> | Any word boundary | "⏏two⏏ ⏏words⏏~!" |
<!wb> | Not a word boundary | "t⏏w⏏o w⏏o⏏r⏏d⏏s~⏏!" |
<?ww> | Within word | "t⏏w⏏o w⏏o⏏r⏏d⏏s~!" |
<!ww> | Not within word | "⏏two⏏ ⏏words⏏~⏏!⏏" |
Zero-Width assertions can help you implement your own anchor: it turns another regex into an anchor, making them consume no characters of the input string. There are two variants: lookahead and lookbehind assertions.
Technically, anchors are also zero-width assertions, and they can look both ahead and behind.
Lookaround assertions work both ways. They match, but they don't consume a character.
my regex key {^^ <![#-]> \d+ } say "333" ~~ &key; # OUTPUT: «「333」» say '333$' ~~ m/ \d+ <?[$]>/; # OUTPUT: «「333」» say '$333' ~~ m/^^ <?[$]> . \d+ /; # OUTPUT: «「$333」»
They can be positive or negative: ![] is negative, while ?[] is positive; the square brackets will include the characters or backslashed character classes that are going to be matched.
You can use predefined character classes and Unicode properties directly preceded by the semicolon:
say '333' ~~ m/^^ <?alnum> \d+ /; # OUTPUT: «「333」» say '333' ~~ m/^^ <?:Nd> \d+ /; # OUTPUT: «「333」» say '333' ~~ m/^^ <!:L> \d+ /; # OUTPUT: «「333」» say '333' ~~ m/^^ \d+ <!:Script<Tamil>> /; # OUTPUT: «「33」»
In the first two cases, the character class matches, but does not consume, the first digit, which is then consumed by the expression; in the third, the negative lookaround assertion behaves in the same way. In the fourth statement the last digit is matched but not consumed, thus the match includes only the first two digits.
To check that a pattern appears before another pattern, use a lookahead assertion via the before assertion. This has the form:
<?before pattern>
Thus, to search for the string foo which is immediately followed by the string bar, use the following regexp:
/ foo <?before bar> /
For example:
say "foobar" ~~ / foo <?before bar> /; # OUTPUT: «foo»
However, if you want to search for a pattern which is not immediately followed by some pattern, then you need to use a negative lookahead assertion, this has the form:
<!before pattern>
In the following example, all occurrences of foo which is not before bar would match with
say "foobaz" ~~ / foo <!before bar> /; # OUTPUT: «foo»
Lookahead assertions can be used also with other patterns, like characters ranges, interpolated variables, subscripts and so on. In such cases it does suffice to use a ?, or a ! for the negate form. For instance, the following lines all produce the very same result:
say 'abcdefg' ~~ rx{ abc <?before def> }; # OUTPUT: 「abc」 say 'abcdefg' ~~ rx{ abc <?[ d..f ]> }; # OUTPUT: 「abc」 my @ending_letters = <d e f>; say 'abcdefg' ~~ rx{ abc <?@ending_letters> }; # OUTPUT: 「abc」
A practical use of lookahead assertions is in substitutions, where you only want to substitute regex matches that are in a certain context. For example, you might want to substitute only numbers that are followed by a unit (like kg), but not other numbers:
my @units = <kg m km mm s h>; $_ = "Please buy 2 packs of sugar, 1 kg each"; s:g[\d+ <?before \s* @units>] = 5 * $/; say $_; # OUTPUT: Please buy 2 packs of sugar, 5 kg each
Since the lookahead is not part of the match object, the unit is not substituted.
To check that a pattern appears after another pattern, use a lookbehind assertion via the after assertion. This has the form:
<?after pattern>
Therefore, to search for the string bar immediately preceded by the string foo, use the following regexp:
/ <?after foo> bar /
For example:
say "foobar" ~~ / <?after foo> bar /; # OUTPUT: «bar»
However, if you want to search for a pattern which is not immediately preceded by some pattern, then you need to use a negative lookbehind assertion, this has the form:
<!after pattern>
Hence all occurrences of bar which do not have foo before them would be matched by
say "fotbar" ~~ / <!after foo> bar /; # OUTPUT: «bar»
These are, as in the case of lookahead, zero-width assertions which do not consume characters, like here:
say "atfoobar" ~~ / (.**3) .**2 <?after foo> bar /; # OUTPUT: «「atfoobar」 0 => 「atf」»
where we capture the first 3 of the 5 characters before bar, but only if bar is preceded by foo. The fact that the assertion is zero-width allows us to use part of the characters in the assertion for capture.
In regular (non-regex) Perl 6, you can use parentheses to group things together, usually to override operator precedence:
say 1 + 4 * 2; # OUTPUT: «9», parsed as 1 + (4 * 2) say (1 + 4) * 2; # OUTPUT: «10»
The same grouping facility is available in regexes:
/ a || b c /; # matches 'a' or 'bc' / ( a || b ) c /; # matches 'ac' or 'bc'
The same grouping applies to quantifiers:
/ a b+ /; # matches an 'a' followed by one or more 'b's / (a b)+ /; # matches one or more sequences of 'ab' / (a || b)+ /; # matches a string of 'a's and 'b's, except empty string
An unquantified capture produces a Match object. When a capture is quantified (except with the ? quantifier) the capture becomes a list of Match objects instead.
The round parentheses don't just group, they also capture; that is, they make the string matched within the group available as a variable, and also as an element of the resulting Match object:
my $str = 'number 42'; if $str ~~ /'number ' (\d+) / { say "The number is $0"; # OUTPUT: The number is 42 # or say "The number is $/[0]"; # OUTPUT: The number is 42 }
Pairs of parentheses are numbered left to right, starting from zero.
if 'abc' ~~ /(a) b (c)/ { say "0: $0; 1: $1"; # OUTPUT: «0: a; 1: c» }
The $0 and $1 etc. syntax is shorthand. These captures are canonically available from the match object $/ by using it as a list, so $0 is actually syntactic sugar for $/[0].
Coercing the match object to a list gives an easy way to programmatically access all elements:
if 'abc' ~~ /(a) b (c)/ { say $/.list.join: ', ' # OUTPUT: «a, c» }
The parentheses in regexes perform a double role: they group the regex elements inside and they capture what is matched by the sub-regex inside.
To get only the grouping behavior, you can use square brackets [ ... ] which, by default, don't capture.
if 'abc' ~~ / [a||b] (c) / { say ~$0; # OUTPUT: «c» }
If you do not need the captures, using non-capturing [ ... ] groups provides the following benefits:
they more cleanly communicate the regex intent,
they make it easier to count the capturing groups that do mean and
they make matching a bit faster.
It is stated above that captures are numbered from left to right. While true in principle, this is also an over simplification.
The following rules are listed for the sake of completeness. When you find yourself using them regularly, it's worth considering named captures (and possibly subrules) instead.
Alternations reset the capture count:
/ (x) (y) || (a) (.) (.) / # $0 $1 $0 $1 $2
Example:
if 'abc' ~~ /(x)(y) || (a)(.)(.)/ { say ~$1; # OUTPUT: «b» }
If two (or more) alternations have a different number of captures, the one with the most captures determines the index of the next capture:
if 'abcd' ~~ / a [ b (.) || (x) (y) ] (.) / { # $0 $0 $1 $2 say ~$2; # OUTPUT: «d» }
Captures can be nested, in which case they are numbered per level; level 0 gets to use the capture variables, but it will become a list with the rest of the levels behaving as elements of that list
if 'abc' ~~ / ( a (.) (.) ) / { say "Outer: $0"; # OUTPUT: Outer: abc say "Inner: $0[0] and $0[1]"; # OUTPUT: Inner: b and c }
These capture variables are only available outside the regex.
# !!WRONG!! The $0 refers to a capture *inside* the second capture say "11" ~~ /(\d) ($0)/; # OUTPUT: «Nil»
In order to make them available inside the regex, you need to insert a code block behind the match; this code block may be empty if there's nothing meaningful to do:
# CORRECT: $0 is saved into a variable outside the second capture # before it is used inside say "11" ~~ /(\d) {} :my $c = $0; ($c)/; # OUTPUT: «「11」 0 => 「1」 1 => 「1」» say "Matched $c"; # OUTPUT: «Matched 1»
This code block publishes the capture inside the regex, so that it can be assigned to other variables or used for subsequent matches
say "11" ~~ /(\d) {} $0/; # OUTPUT: «「11」 0 => 「1」»
:my helps scoping the $c variable within the regex and beyond; in this case we can use it in the next sentence to show what has been matched inside the regex. This can be used for debugging inside regular expressions, for instance:
my $paragraph="line\nline2\nline3"; $paragraph ~~ rx| :my $counter = 0; ( \V* { ++$counter } ) *%% \n |; say "Matched $counter lines"; # OUTPUT: «Matched 3 lines»
Since :my blocks are simply declarations, the match variable $/ or numbered matches such as $0 will not be available in them unless they are previously published by inserting the empty block (or any block):
"aba" ~~ / (a) b {} :my $c = $/; /; say $c; # OUTPUT: «「ab」 0 => 「a」»
Any other code block will also reveal the variables and make them available in declarations:
"aba" ~~ / (a) {say "Check so far ", ~$/} b :my $c = ~$0; /; # OUTPUT: «Check so far a» say "Capture $c"; # OUTPUT: «Capture a»
The :our, similarly to our in classes, can be used in Grammars to declare variables that can be accessed, via its fully qualified name, from outside the grammar:
grammar HasOur { token TOP { :our $our = 'Þor'; $our \s+ is \s+ mighty } } say HasOur.parse('Þor is mighty'); # OUTPUT: «「Þor is mighty」» say $HasOur::our; # OUTPUT: «Þor»
Once the parsing has been done successfully, we use the FQN name of the $our variable to access its value, that can be none other than Þor.
Instead of numbering captures, you can also give them names. The generic, and slightly verbose, way of naming captures is like this:
if 'abc' ~~ / $<myname> = [ \w+ ] / { say ~$<myname> # OUTPUT: «abc» }
The square brackets in the above example, which don't usually capture, will now capture its grouping with the given name.
The access to the named capture, $<myname>, is a shorthand for indexing the match object as a hash, in other words: $/{ 'myname' } or $/<myname>.
We can also use parentheses in the above example, but they will work exactly the same as square brackets. The captured group will only be accessible by its name as a key from the match object and not from its position in the list with $/[0] or $0.
Named captures can also be nested using regular capture group syntax:
if 'abc-abc-abc' ~~ / $<string>=( [ $<part>=[abc] ]* % '-' ) / { say ~$<string>; # OUTPUT: «abc-abc-abc» say ~$<string><part>; # OUTPUT: «abc abc abc» say ~$<string><part>[0]; # OUTPUT: «abc» }
Coercing the match object to a hash gives you easy programmatic access to all named captures:
if 'count=23' ~~ / $<variable>=\w+ '=' $<value>=\w+ / { my %h = $/.hash; say %h.keys.sort.join: ', '; # OUTPUT: «value, variable» say %h.values.sort.join: ', '; # OUTPUT: «23, count» for %h.kv -> $k, $v { say "Found value '$v' with key '$k'"; # outputs two lines: # Found value 'count' with key 'variable' # Found value '23' with key 'value' } }
A more convenient way to get named captures is by using named regex as discussed in the Subrules section.
A <( token indicates the start of the match's overall capture, while the corresponding )> token indicates its endpoint. The <( is similar to other languages \K to discard any matches found before the \K.
say 'abc' ~~ / a <( b )> c/; # OUTPUT: «「b」» say 'abc' ~~ / <(a <( b )> c)>/; # OUTPUT: «「bc」»
As in the example above, you can see <( sets the start point and )> sets the endpoint; since they are actually independent of each other, the inner-most start point wins (the one attached to b) and the outer-most end wins (the one attached to c).
Regular expressions can also be used to substitute one piece of text for another. You can use this for anything, from correcting a spelling error (e.g., replacing 'Perl Jam' with 'Pearl Jam'), to reformatting an ISO8601 date from yyyy-mm-ddThh:mm:ssZ to mm-dd-yy h:m {AM,PM} and beyond.
Just like the search-and-replace editor's dialog box, the s/ / / operator has two sides, a left and right side. The left side is where your matching expression goes, and the right side is what you want to replace it with.
Substitutions are written similarly to matching, but the substitution operator has both an area for the regex to match, and the text to substitute:
s/replace/with/; # a substitution that is applied to $_ $str ~~ s/replace/with/; # a substitution applied to a scalar
The substitution operator allows delimiters other than the slash:
s|replace|with|; s!replace!with!; s,replace,with,;
Note that neither the colon : nor balancing delimiters such as {} or () can be substitution delimiters. Colons clash with adverbs such as s:i/Foo/bar/ and the other delimiters are used for other purposes.
If you use balancing curly braces, square brackets, or parentheses, the substitution works like this instead:
s[replace] = 'with';
The right-hand side is now a (not quoted) Perl 6 expression, in which $/ is available as the current match:
$_ = 'some 11 words 21'; s:g[ \d+ ] = 2 * $/; .say; # OUTPUT: «some 22 words 42»
Like the m// operator, whitespace is ignored in the regex part of a substitution.
The simplest thing to replace is a string literal. The string you want to replace goes on the left-hand side of the substitution operator, and the string you want to replace it with goes on the right-hand side; for example:
$_ = 'The Replacements'; s/Replace/Entrap/; .say; # OUTPUT: «The Entrapments»
Alphanumeric characters and the underscore are literal matches, just as in its cousin the m// operator. All other characters must be escaped with a backslash \ or included in quotes:
$_ = 'Space: 1999'; s/Space\:/Party like it's/; .say # OUTPUT: «Party like it's 1999»
Note that the matching restrictions only apply to the left-hand side of the substitution expression.
By default, substitutions are only done on the first match:
$_ = 'There can be twly two'; s/tw/on/; # replace 'tw' with 'on' once .say; # OUTPUT: «There can be only two»
Anything that can go into the m// operator can go into the left-hand side of the substitution operator, including wildcards and character classes. This is handy when the text you're matching isn't static, such as trying to match a number in the middle of a string:
$_ = "Blake's 9"; s/\d+/7/; # replace any sequence of digits with '7' .say; # OUTPUT: «Blake's 7»
Of course, you can use any of the +, * and ? modifiers, and they'll behave just as they would in the m// operator's context.
Just as in the match operator, capturing groups are allowed on the left-hand side, and the matched contents populate the $0..$n variables and the $/ object:
$_ = '2016-01-23 18:09:00'; s/ (\d+)\-(\d+)\-(\d+) /today/; # replace YYYY-MM-DD with 'today' .say; # OUTPUT: «today 18:09:00» "$1-$2-$0".say; # OUTPUT: «01-23-2016» "$/[1]-$/[2]-$/[0]".say; # OUTPUT: «01-23-2016»
Any of these variables $0, $1, $/ can be used on the right-hand side of the operator as well, so you can manipulate what you've just matched. This way you can separate out the YYYY, MM and DD parts of a date and reformat them into MM-DD-YYYY order:
$_ = '2016-01-23 18:09:00'; s/ (\d+)\-(\d+)\-(\d+) /$1-$2-$0/; # transform YYYY-MM-DD to MM-DD-YYYY .say; # OUTPUT: «01-23-2016 18:09:00»
Named capture can be used too:
$_ = '2016-01-23 18:09:00'; s/ $<y>=(\d+)\-$<m>=(\d+)\-$<d>=(\d+) /$<m>-$<d>-$<y>/; .say; # OUTPUT: «01-23-2016 18:09:00»
Since the right-hand side is effectively a regular Perl 6 interpolated string, you can reformat the time from HH:MM to h:MM {AM,PM} like so:
$_ = '18:38'; s/(\d+)\:(\d+)/{$0 % 12}\:$1 {$0 < 12 ?? 'AM' !! 'PM'}/; .say; # OUTPUT: «6:38 PM»
Using the modulo % operator above keeps the sample code under 80 characters, but is otherwise the same as $0 < 12 ?? $0 !! $0 - 12 . When combined with the power of the Parser Expression Grammars that really underlies what you're seeing here, you can use "regular expressions" to parse pretty much any text out there.
The full list of adverbs that you can apply to regular expressions can be found elsewhere in this document (section Adverbs), but the most common are probably :g and :i.
Global adverb :g
Ordinarily, matches are only made once in a given string, but adding the :g modifier overrides that behavior, so that substitutions are made everywhere possible. Substitutions are non-recursive; for example:
$_ = q{I can say "banana" but I don't know when to stop}; s:g/na/nana,/; # substitute 'nana,' for 'na' .say; # OUTPUT: «I can say "banana,nana," but I don't ...»
Here, na was found twice in the original string and each time there was a substitution. The substitution only applied to the original string, though. The resulting string was not impacted.
Insensitive adverb :i
Ordinarily, matches are case-sensitive. s/foo/bar/ will only match 'foo' and not 'Foo'. If the adverb :i is used, though, matches become case-insensitive.
$_ = 'Fruit'; s/fruit/vegetable/; .say; # OUTPUT: «Fruit» s:i/fruit/vegetable/; .say; # OUTPUT: «vegetable»
For more information on what these adverbs are actually doing, refer to the section Adverbs section of this document.
These are just a few of the transformations you can apply with the substitution operator. Some of the simpler uses in the real world include removing personal data from log files, editing MySQL timestamps into PostgreSQL format, changing copyright information in HTML files and sanitizing form fields in a web application.
As an aside, novices to regular expressions often get overwhelmed and think that their regular expression needs to match every piece of data in the line, including what they want to match. Write just enough to match the data you're looking for, no more, no less.
say S/o .+ d/new/ with 'old string'; # OUTPUT: «new string» S:g/« (.)/$0.uc()/.say for <foo bar ber>; # OUTPUT: «FooBarBer»
S/// uses the same semantics as the s/// operator, except it leaves the original string intact and returns the resultant string instead of $/ ($/ still being set to the same values as with s///).
Note: since the result is obtained as a return value, using this operator with the ~~ smartmatch operator is a mistake and will issue a warning. To execute the substitution on a variable that isn't the $_ this operator uses, alias it to $_ with given, with, or any other way. Alternatively, use the .subst method.
The ~ operator is a helper for matching nested subrules with a specific terminator as the goal. It is designed to be placed between an opening and closing delimiter pair, like so:
/ '(' ~ ')' <expression> /
However, it mostly ignores the left argument, and operates on the next two atoms (which may be quantified). Its operation on those next two atoms is to "twiddle" them so that they are actually matched in reverse order. Hence the expression above, at first blush, is merely shorthand for:
/ '(' <expression> ')' /
But beyond that, when it rewrites the atoms it also inserts the apparatus that will set up the inner expression to recognize the terminator, and to produce an appropriate error message if the inner expression does not terminate on the required closing atom. So it really does pay attention to the left delimiter as well, and it actually rewrites our example to something more like:
$<OPEN> = '(' <SETGOAL: ')'> <expression> [ $GOAL || <FAILGOAL> ]
FAILGOAL is a special method that can be defined by the user and it will be called on parse failure:
grammar A { token TOP { '[' ~ ']' \w+ }; method FAILGOAL($goal) { die "Cannot find $goal near position {self.pos}" } } say A.parse: '[good]'; # OUTPUT: «「[good]」» A.parse: '[bad'; # will throw FAILGOAL exception CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::AdHoc: Cannot find ']' near position 4»
Note that you can use this construct to set up expectations for a closing construct even when there's no opening delimiter:
"3)" ~~ / <?> ~ ')' \d+ /; # RESULT: «「3)」» "(3)" ~~ / <?> ~ ')' \d+ /; # RESULT: «「3)」»
Here <?> successfully matches the null string.
The order of the regex capture is original:
"abc" ~~ /a ~ (c) (b)/; say $0; # OUTPUT: «「c」» say $1; # OUTPUT: «「b」»
Just like you can put pieces of code into subroutines, you can also put pieces of regex into named rules.
my regex line { \N*\n } if "abc\ndef" ~~ /<line> def/ { say "First line: ", $<line>.chomp; # OUTPUT: «First line: abc» }
A named regex can be declared with my regex named-regex { body here }, and called with <named-regex>. At the same time, calling a named regex installs a named capture with the same name.
To give the capture a different name from the regex, use the syntax <capture-name=named-regex>. If no capture is desired, a leading dot or ampersand will suppress it: <.named-regex> if it is a method declared in the same class or grammar, <&named-regex> for a regex declared in the same lexical context.
Here's more complete code for parsing ini files:
my regex header { \s* '[' (\w+) ']' \h* \n+ } my regex identifier { \w+ } my regex kvpair { \s* <key=identifier> '=' <value=identifier> \n+ } my regex section { <header> <kvpair>* } my $contents = q:to/EOI/; [passwords] jack=password1 joy=muchmoresecure123 [quotas] jack=123 joy=42 EOI my %config; if $contents ~~ /<section>*/ { for $<section>.list -> $section { my %section; for $section<kvpair>.list -> $p { %section{ $p<key> } = ~$p<value>; } %config{ $section<header>[0] } = %section; } } say %config.perl; # OUTPUT: «{:passwords(${:jack("password1"), :joy("muchmoresecure123")}), # :quotas(${:jack("123"), :joy("42")})}»
Named regexes can and should be grouped in grammars. A list of predefined subrules is listed in S05-regex of design documents.
Instead of using a literal pattern for a regex match, you can use a variable that holds that pattern. This variable can then be 'interpolated' into a regex, such that its appearance in the regex is replaced with the pattern that it holds. The advantage of using interpolation this way, is that the pattern need not be hardcoded in the source of your Perl 6 program, but may instead be variable and generated at runtime.
There are four different ways of interpolating a variable into a regex as a pattern, which may be summarized as follows:
Syntax | Description |
---|---|
$variable | Interpolates stringified contents of variable literally. |
$(code) | Runs Perl 6 code inside the regex, and interpolates the stringified return value literally. |
<$variable> | Interpolates stringified contents of variable as a regex. |
<{code}> | Runs Perl 6 code inside the regex, and interpolates the stringified return value as a regex. |
Let's start with the first two syntactical forms: $variable and $(code). These forms will interpolate the stringified value of the variable or the stringified return value of the code literally, provided that the respective value isn't a Regex object. If the value is a Regex, it will not be stringified, but instead be interpolated as such. 'Literally' means strictly literally, that is: as if the respective stringified value is quoted with a basic Q string Q[...]. Consequently, the stringified value will not itself undergo any further interpolation.
For $variable this means the following:
my $string = 'Is this a regex or a string: 123\w+False$pattern1 ?'; my $pattern1 = 'string'; my $pattern2 = '\w+'; my $number = 123; my $regex = /\w+/; say $string.match: / 'string' /; # [1] OUTPUT: 「string」 say $string.match: / $pattern1 /; # [2] OUTPUT: 「string」 say $string.match: / $pattern2 /; # [3] OUTPUT: 「\w+」 say $string.match: / $regex /; # [4] OUTPUT: 「Is」 say $string.match: / $number /; # [5] OUTPUT: 「123」
In this example, the statements [1] and [2] are equivalent and meant to illustrate a plain case of regex interpolation. Since unescaped/unquoted alphabetic characters in a regex match literally, the single quotes in the regex of statement [1] are functionally redundant; they have merely been included to emphasize the correspondence between the first two statements. Statement [3] unambiguously shows that the string pattern held by $pattern2 is interpreted literally, and not as a regex. In case it would have been interpreted as a regex, it would have matched the first word of $string, i.e. 「Is」, as can be seen in statement [4]. Statement [5] shows how the stringified number is used as a match pattern.
This code exemplifies the use of the $(code) syntax:
my $string = 'Is this a regex or a string: 123\w+False$pattern1 ?'; my $pattern1 = 'string'; my $pattern3 = 'gnirts'; my $pattern4 = '$pattern1'; my $bool = True; my sub f1 { return Q[$pattern1] }; say $string.match: / $pattern3.flip /; # [6] OUTPUT: Nil say $string.match: / "$pattern3.flip()" /; # [7] OUTPUT: 「string」 say $string.match: / $($pattern3.flip) /; # [8] OUTPUT: 「string」 say $string.match: / $([~] $pattern3.comb.reverse) /; # [9] OUTPUT: 「string」 say $string.match: / $(!$bool) /; # [10] OUTPUT: 「False」 say $string.match: / $pattern4 /; # [11] OUTPUT: 「$pattern1」 say $string.match: / $(f1) /; # [12] OUTPUT: 「$pattern1」
Statement [6] does not work as probably intended. To the human reader, the dot . may seem to represent the method call operator, but since a dot is not a valid character for an ordinary identifier, and given the regex context, the compiler will parse it as the regex wildcard . that matches any character. The apparent ambiguity may be resolved in various ways, for instance through the use of straightforward string interpolation from the regex as in statement [7] (note that the inclusion of the call operator () is key here), or by using the second syntax form from the above table as in statement [8], in which case the match pattern string first emerges as the return value of the flip method call. Since general Perl 6 code may be run from within the parentheses of $( ), the same effect can also be achieved with a bit more effort, like in statement [9]. Statement [10] illustrates how the stringified version of the code's return value (the boolean value False) is matched literally.
Finally, statements [11] and [12] show how the value of $pattern4 and the return value of f1 are not subject to a further round of interpolation. Hence, in general, after possible stringification, $variable and $(code) provide for a strictly literal match of the variable or return value.
Now consider the second two syntactical forms from the table above: <$variable> and <{code}>. These forms will stringify the value of the variable or the return value of the code and interpolate it as a regex. If the respective value is a Regex, it is interpolated as such:
my $string = 'Is this a regex or a string: 123\w+$x ?'; my $pattern1 = '\w+'; my $number = 123; my sub f1 { return /s\w+/ }; say $string.match: / <$pattern1> /; # OUTPUT: 「Is」 say $string.match: / <$number> /; # OUTPUT: 「123」 say $string.match: / <{ f1 }> /; # OUTPUT: 「string」
Importantly, 'to interpolate as a regex' means to interpolate/insert into the target regex without protective quoting. Consequently, if the value of the variable $variable1 is itself of the form $variable2, evaluation of <$variable1> or <{ $variable1 }> inside a target regex /.../ will cause the target regex to assume the form /$variable2/. As described above, the evaluation of this regex will then trigger further interpolation of $variable2:
my $string = Q[Mindless \w+ $variable1 $variable2]; my $variable1 = Q[\w+]; my $variable2 = Q[$variable1]; my sub f1 { return Q[$variable2] }; # /<{ f1 }>/ ==> /$variable2/ ==> / '$variable1' / say $string.match: / <{ f1 }> /; # OUTPUT: 「$variable1」 # /<$variable2>/ ==> /$variable1/ ==> / '\w+' / say $string.match: /<$variable2>/; # OUTPUT: 「\w+」 # /<$variable1>/ ==> /\w+/ say $string.match: /<$variable1>/; # OUTPUT: 「Mindless」
When an array variable is interpolated into a regex, the regex engine handles it like a | alternative of the regex elements (see the documentation on embedded lists, above). The interpolation rules for individual elements are the same as for scalars, so strings and numbers match literally, and Regex objects match as regexes. Just as with ordinary | interpolation, the longest match succeeds:
my @a = '2', 23, rx/a.+/; say ('b235' ~~ / b @a /).Str; # OUTPUT: «b23»
The use of hashes in regexes is reserved.
The special operator <?{}> allows the evaluation of a boolean expression that can perform a semantic evaluation of the match before the regular expression continues. In other words, it is possible to check in a boolean context a part of a regular expression and therefore invalidate the whole match (or allow it to continue) even if the match succeeds from a syntactic point of view.
In particular the <?{}> operator requires a True value in order to allow the regular expression to match, while its negated form <!{}> requires a False value.
In order to demonstrate the above operator, please consider the following example that involves a simple IPv4 address matching:
my $localhost = '127.0.0.1'; my regex ipv4-octet { \d ** 1..3 <?{ True }> } $localhost ~~ / ^ <ipv4-octet> ** 4 % "." $ /; say $/<ipv4-octet>; # OUTPUT: [「127」 「0」 「0」 「1」]
The octet regular expression matches against a number made by one up to three digits. Each match is driven by the result of the <?{}>, that being the fixed value of True means that the regular expression match has to be always considered as good. As a counter-example, using the special constant value False will invalidate the match even if the regular expression matches from a syntactic point of view:
my $localhost = '127.0.0.1'; my regex ipv4-octet { \d ** 1..3 <?{ False }> } $localhost ~~ / ^ <ipv4-octet> ** 4 % "." $ /; say $/<ipv4-octet>; # OUTPUT: Nil
From the above examples, it should be clear that it is possible to improve the semantic check, for instance ensuring that each octet is really a valid IPv4 octet:
my $localhost = '127.0.0.1'; my regex ipv4-octet { \d ** 1..3 <?{ $/.Int <= 255 && $/.Int >= 0 }> } $localhost ~~ / ^ <ipv4-octet> ** 4 % "." $ /; say $/<ipv4-octet>; # OUTPUT: [「127」 「0」 「0」 「1」]
Please note that it is not required to evaluate the regular expression in-line, but also a regular method can be called to get the boolean value:
my $localhost = '127.0.0.1'; sub check-octet ( Int $o ){ $o <= 255 && $o >= 0 } my regex ipv4-octet { \d ** 1..3 <?{ &check-octet( $/.Int ) }> } $localhost ~~ / ^ <ipv4-octet> ** 4 % "." $ /; say $/<ipv4-octet>; # OUTPUT: [「127」 「0」 「0」 「1」]
Of course, being <!{}> the negation form of <?{}> the same boolean evaluation can be rewritten in a negated form:
my $localhost = '127.0.0.1'; sub invalid-octet( Int $o ){ $o < 0 || $o > 255 } my regex ipv4-octet { \d ** 1..3 <!{ &invalid-octet( $/.Int ) }> } $localhost ~~ / ^ <ipv4-octet> ** 4 % "." $ /; say $/<ipv4-octet>; # OUTPUT: [「127」 「0」 「0」 「1」]
Adverbs, which modify how regexes work and provide convenient shortcuts for certain kinds of recurring tasks, are combinations of one or more letters preceded by a colon :.
The so-called regex adverbs apply at the point where a regex is defined; additionally, matching adverbs apply at the point that a regex matches against a string and substitution adverbs are applied exclusively in substitutions.
This distinction often blurs, because matching and declaration are often textually close but using the method form of matching, that is, .match, makes the distinction clear.
say "Abra abra CADABRA" ~~ m:exhaustive/:i a \w+ a/; # OUTPUT: «(「Abra」 「abra」 「ADABRA」 「ADA」 「ABRA」)» my $regex = /:i a \w+ a /; say "Abra abra CADABRA".match($regex,:ex); # OUTPUT: «(「Abra」 「abra」 「ADABRA」 「ADA」 「ABRA」)»
In the first example, the matching adverb (:exhaustive) is contiguous to the regex adverb (:i), and as a matter of fact, the "definition" and the "matching" go together; however, by using match it becomes clear that :i is only used when defining the $regex variable, and :ex (short for :exhaustive) as an argument when matching. As a matter of fact, matching adverbs cannot even be used in the definition of a regex:
my $regex = rx:ex/:i a \w+ a /; # ===SORRY!=== Error while compiling (...)Adverb ex not allowed on rx
Regex adverbs like :i go into the definition line and matching adverbs like :overlap (which can be abbreviated to :ov) are appended to the match call:
my $regex = /:i . a/; for 'baA'.match($regex, :overlap) -> $m { say ~$m; } # OUTPUT: «baaA»
The adverbs that appear at the time of a regex declaration are part of the actual regex and influence how the Perl 6 compiler translates the regex into binary code.
For example, the :ignorecase (:i) adverb tells the compiler to ignore the distinction between upper case, lower case and title case letters.
So 'a' ~~ /A/ is false, but 'a' ~~ /:i A/ is a successful match.
Regex adverbs can come before or inside a regex declaration and only affect the part of the regex that comes afterwards, lexically. Note that regex adverbs appearing before the regex must appear after something that introduces the regex to the parser, like 'rx' or 'm' or a bare '/'. This is NOT valid:
my $rx1 = :i/a/; # adverb is before the regex is recognized => exception
but these are valid:
my $rx1 = rx:i/a/; # before my $rx2 = m:i/a/; # before my $rx3 = /:i a/; # inside
These two regexes are equivalent:
my $rx1 = rx:i/a/; # before my $rx2 = rx/:i a/; # inside
Whereas these two are not:
my $rx3 = rx/a :i b/; # matches only the b case insensitively my $rx4 = rx/:i a b/; # matches completely case insensitively
Square brackets and parentheses limit the scope of an adverb:
/ (:i a b) c /; # matches 'ABc' but not 'ABC' / [:i a b] c /; # matches 'ABc' but not 'ABC'
When two adverbs are used together, they keep their colon at the front
"þor is Þor" ~~ m:g:i/þ/; # OUTPUT: «(「þ」 「Þ」)»
That implies that when there are two vowels together after a :, they correspond to the same adverb, as in :ov or :P5.
The :ignoremark or :m adverb instructs the regex engine to only compare base characters, and ignore additional marks such as combining accents:
say so 'a' ~~ rx/ä/; # OUTPUT: «False» say so 'a' ~~ rx:ignoremark /ä/; # OUTPUT: «True» say so 'ỡ' ~~ rx:ignoremark /o/; # OUTPUT: «True>
The :ratchet or :r adverb causes the regex engine to not backtrack (see backtracking). Mnemonic: a ratchet only moves in one direction and can't backtrack.
Without this adverb, parts of a regex will try different ways to match a string in order to make it possible for other parts of the regex to match. For example, in 'abc' ~~ /\w+ ./, the \w+ first eats up the whole string, abc but then the . fails. Thus \w+ gives up a character, matching only ab, and the . can successfully match the string c. This process of giving up characters (or in the case of alternations, trying a different branch) is known as backtracking.
say so 'abc' ~~ / \w+ . /; # OUTPUT: «True» say so 'abc' ~~ / :r \w+ . /; # OUTPUT: «False»
Ratcheting can be an optimization, because backtracking is costly. But more importantly, it closely corresponds to how humans parse a text. If you have a regex my regex identifier { \w+ } and my regex keyword { if | else | endif }, you intuitively expect the identifier to gobble up a whole word and not have it give up its end to the next rule, if the next rule otherwise fails.
For example, you don't expect the word motif to be parsed as the identifier mot followed by the keyword if. Instead, you expect motif to be parsed as one identifier; and if the parser expects an if afterwards, best that it should fail than have it parse the input in a way you don't expect.
Since ratcheting behavior is often desirable in parsers, there's a shortcut to declaring a ratcheting regex:
my token thing { ... }; # short for my regex thing { :r ... };
The :sigspace or :s adverb makes whitespace significant in a regex.
say so "I used Photoshop®" ~~ m:i/ photo shop /; # OUTPUT: «True» say so "I used a photo shop" ~~ m:i :s / photo shop /; # OUTPUT: «True» say so "I used Photoshop®" ~~ m:i :s / photo shop /; # OUTPUT: «False»
m:s/ photo shop / acts the same as m/ photo <.ws> shop <.ws> /. By default, <.ws> makes sure that words are separated, so a b and ^& will match <.ws> in the middle, but ab won't.
Where whitespace in a regex turns into <.ws> depends on what comes before the whitespace. In the above example, whitespace in the beginning of a regex doesn't turn into <.ws>, but whitespace after characters does. In general, the rule is that if a term might match something, whitespace after it will turn into <.ws>.
In addition, if whitespace comes after a term but before a quantifier (+, *, or ?), <.ws> will be matched after every match of the term. So, foo + becomes [ foo <.ws> ]+. On the other hand, whitespace after a quantifier acts as normal significant whitespace; e.g., "foo+ " becomes foo+ <.ws>.
In all, this code:
rx :s { ^^ { say "No sigspace after this"; } <.assertion_and_then_ws> characters_with_ws_after+ ws_separated_characters * [ | some "stuff" .. . | $$ ] :my $foo = "no ws after this"; $foo }
Becomes:
rx { ^^ <.ws> { say "No space after this"; } <.assertion_and_then_ws> <.ws> characters_with_ws_after+ <.ws> [ws_separated_characters <.ws> ]* <.ws> [ | some <.ws> "stuff" <.ws> .. <.ws> . <.ws> | $$ <.ws> ] <.ws> :my $foo = "no ws after this"; $foo <.ws> }
If a regex is declared with the rule keyword, both the :sigspace and :ratchet adverbs are implied.
Grammars provide an easy way to override what <.ws> matches:
grammar Demo { token ws { <!ww> # only match when not within a word \h* # only match horizontal whitespace } rule TOP { # called by Demo.parse; a b '.' } } # doesn't parse, whitespace required between a and b say so Demo.parse("ab."); # OUTPUT: «False» say so Demo.parse("a b."); # OUTPUT: «True» say so Demo.parse("a\tb ."); # OUTPUT: «True» # \n is vertical whitespace, so no match say so Demo.parse("a\tb\n."); # OUTPUT: «False»
When parsing file formats where some whitespace (for example, vertical whitespace) is significant, it's advisable to override ws.
The :Perl5 or :P5 adverb switch the Regex parsing and matching to the way Perl 5 regexes behave:
so 'hello world' ~~ m:Perl5/^hello (world)/; # OUTPUT: «True» so 'hello world' ~~ m/^hello (world)/; # OUTPUT: «False» so 'hello world' ~~ m/^ 'hello ' ('world')/; # OUTPUT: «True»
The regular behavior is recommended and more idiomatic in Perl 6 of course, but the :Perl5 adverb can be useful when compatibility with Perl5 is required.
In contrast to regex adverbs, which are tied to the declaration of a regex, matching adverbs only make sense when matching a string against a regex.
They can never appear inside a regex, only on the outside – either as part of an m/.../ match or as arguments to a match method.
Positional adverbs make the expression match only the string in the indicated position:
my $data = "f fo foo fooo foooo fooooo foooooo"; say $data ~~ m:nth(4)/fo+/; # OUTPUT: «「foooo」» say $data ~~ m:1st/fo+/; # OUTPUT: «「fo」» say $data ~~ m:3rd/fo+/; # OUTPUT: «「fooo」» say $data ~~ m:nth(1,3)/fo+/; # OUTPUT: «(「fo」 「fooo」)»
As you can see, the adverb argument can also be a list. There's actually no difference between the :nth adverb and the rest. You choose them only based on legibility. From 6.d, you can also use Junctions as arguments.
my $data = "f fo foo fooo foooo fooooo foooooo"; say $data ~~ m:st(1|8)/fo+/; # OUTPUT: «True»
In this case, one of them exists (1), so it returns True. Observe that we have used :st. As said above, it's functionally equivalent, although obviously less legible than using :nth, so this last form is advised.
The :continue or short :c adverb takes an argument. The argument is the position where the regex should start to search. By default, it searches from the start of the string, but :c overrides that. If no position is specified for :c, it will default to 0 unless $/ is set, in which case, it defaults to $/.to.
given 'a1xa2' { say ~m/a./; # OUTPUT: «a1» say ~m:c(2)/a./; # OUTPUT: «a2» }
Note: unlike :pos, a match with :continue() will attempt to match further in the string, instead of failing:
say "abcdefg" ~~ m:c(3)/e.+/; # OUTPUT: «「efg」» say "abcdefg" ~~ m:p(3)/e.+/; # OUTPUT: «False»
To find all possible matches of a regex – including overlapping ones – and several ones that start at the same position, use the :exhaustive (short :ex) adverb.
given 'abracadabra' { for m:exhaustive/ a .* a / -> $match { say ' ' x $match.from, ~$match; } }
The above code produces this output:
abracadabra abracada abraca abra acadabra acada aca adabra ada abra
Instead of searching for just one match and returning a Match object, search for every non-overlapping match and return them in a List. In order to do this, use the :global adverb:
given 'several words here' { my @matches = m:global/\w+/; say @matches.elems; # OUTPUT: «3» say ~@matches[2]; # OUTPUT: «here» }
:g is shorthand for :global.
Anchor the match at a specific position in the string:
given 'abcdef' { my $match = m:pos(2)/.*/; say $match.from; # OUTPUT: «2» say ~$match; # OUTPUT: «cdef» }
:p is shorthand for :pos.
Note: unlike :continue, a match anchored with :pos() will fail, instead of attempting to match further down the string:
say "abcdefg" ~~ m:c(3)/e.+/; # OUTPUT: «「efg」» say "abcdefg" ~~ m:p(3)/e.+/; # OUTPUT: «False»
To get several matches, including overlapping matches, but only one (the longest) from each starting position, specify the :overlap (short :ov) adverb:
given 'abracadabra' { for m:overlap/ a .* a / -> $match { say ' ' x $match.from, ~$match; } }
produces
abracadabra acadabra adabra abra
You can apply matching adverbs (such as :global, :pos etc.) to substitutions. In addition, there are adverbs that only make sense for substitutions, because they transfer a property from the matched string to the replacement string.
The :samecase or :ii substitution adverb implies the :ignorecase adverb for the regex part of the substitution, and in addition carries the case information to the replacement string:
$_ = 'The cat chases the dog'; s:global:samecase[the] = 'a'; say $_; # OUTPUT: «A cat chases a dog»
Here you can see that the first replacement string a got capitalized, because the first string of the matched string was also a capital letter.
The :samemark or :mm adverb implies :ignoremark for the regex, and in addition, copies the markings from the matched characters to the replacement string:
given 'äộñ' { say S:mm/ a .+ /uia/; # OUTPUT: «üị̂ã» }
The :samespace or :ss substitution modifier implies the :sigspace modifier for the regex, and in addition, copies the whitespace from the matched string to the replacement string:
say S:samespace/a ./c d/.perl given "a b"; # OUTPUT: «"c d"» say S:samespace/a ./c d/.perl given "a\tb"; # OUTPUT: «"c\td"» say S:samespace/a ./c d/.perl given "a\nb"; # OUTPUT: «"c\nd"»
The ss/.../.../ syntactic form is a shorthand for s:samespace/.../.../.
Perl 6 defaults to backtracking when evaluating regular expressions. Backtracking is a technique that allows the engine to try different matching in order to allow every part of a regular expression to succeed. This is costly, because it requires the engine to usually eat up as much as possible in the first match and then adjust going backwards in order to ensure all regular expression parts have a chance to match.
In order to better understand backtracking, consider the following example:
my $string = 'PostgreSQL is an SQL database!'; say $string ~~ /(.+)(SQL) (.+) $1/; # OUTPUT: 「PostgreSQL is an SQL」
What happens in the above example is that the string has to be matched against the second occurrence of the word SQL, eating all characters before and leaving out the rest.
Since it is possible to execute a piece of code within a regular expression, it is also possible to inspect the Match object within the regular expression itself:
my $iteration = 0; sub show-captures( Match $m ){ my Str $result_split; say "\n=== Iteration {++$iteration} ==="; for $m.list.kv -> $i, $capture { say "Capture $i = $capture"; $result_split ~= '[' ~ $capture ~ ']'; } say $result_split; } $string ~~ /(.+)(SQL) (.+) $1 (.+) { show-captures( $/ ); }/;
The show-captures method will dump all the elements of $/ producing the following output:
=== Iteration 1 === Capture 0 = Postgre Capture 1 = SQL Capture 2 = is an [Postgre][SQL][ is an ]
showing that the string has been split around the second occurrence of SQL, that is the repetition of the first capture ($/[1]).
With that in place, it is now possible to see how the engine backtracks to find the above match: it does suffice to move the show-captures in the middle of the regular expression, in particular before the repetition of the first capture $1 to see it in action:
my $iteration = 0; sub show-captures( Match $m ){ my Str $result-split; say "\n=== Iteration {++$iteration} ==="; for $m.list.kv -> $i, $capture { say "Capture $i = $capture"; $result-split ~= '[' ~ $capture ~ ']'; } say $result-split; } $string ~~ / (.+)(SQL) (.+) { show-captures( $/ ); } $1 /;
The output will be much more verbose and will show several iterations, with the last one being the winning. The following is an excerpt of the output:
=== Iteration 1 === Capture 0 = PostgreSQL is an Capture 1 = SQL Capture 2 = database! [PostgreSQL is an ][SQL][ database!] === Iteration 2 === Capture 0 = PostgreSQL is an Capture 1 = SQL Capture 2 = database [PostgreSQL is an ][SQL][ database] ... === Iteration 24 === Capture 0 = Postgre Capture 1 = SQL Capture 2 = is an [Postgre][SQL][ is an ]
In the first iteration the SQL part of PostgreSQL is kept within the word: that is not what the regular expression asks for, so there's the need for another iteration. The second iteration will move back, in particular one character back (removing thus the final !) and try to match again, resulting in a fail since again the SQL is still kept within PostgreSQL. After several iterations, the final result is match.
It is worth noting that the final iteration is number 24, and that such number is exactly the distance, in number of chars, from the end of the string to the first SQL occurrence:
say $string.chars - $string.index: 'SQL'; # OUTPUT: 23
Since there are 23 chars from the very end of the string to the very first S of SQL the backtracking engine will need 23 "useless" matches to find the right one, that is, it will need 24 steps to get the final result.
Backtracking is a costly machinery, therefore it is possible to disable it in those cases where the matching can be found forward only.
With regards to the above example, disabling backtracking means the regular expression will not have any chance to match:
say $string ~~ /(.+)(SQL) (.+) $1/; # OUTPUT: 「PostgreSQL is an SQL」 say $string ~~ / :r (.+)(SQL) (.+) $1/; # OUTPUT: Nil
The fact is that, as shown in the iteration 1 output, the first match of the regular expression engine will be PostgreSQL is an , SQL, database that does not leave out any room for matching another occurrence of the word SQL (as $1 in the regular expression). Since the engine is not able to get backward and change the path to match, the regular expression fails.
It is worth noting that disabling backtracking will not prevent the engine to try several ways to match the regular expression. Consider the following slightly changed example:
my $string = 'PostgreSQL is an SQL database!'; say $string ~~ / (SQL) (.+) $1 /; # OUTPUT: Nil
Since there is no specification for a character before the word SQL, the engine will match against the rightmost word SQL and go forward from there. Since there is no repetition of SQL remaining, the match fails. It is possible, again, to inspect what the engine performs introducing a dumping piece of code within the regular expression:
my $iteration = 0; sub show-captures( Match $m ){ my Str $result-split; say "\n=== Iteration {++$iteration} ==="; for $m.list.kv -> $i, $capture { say "Capture $i = $capture"; $result-split ~= '[' ~ $capture ~ ']'; } say $result-split; } $string ~~ / (SQL) (.+) { show-captures( $/ ); } $1 /;
that produces a rather simple output:
=== Iteration 1 === Capture 0 = SQL Capture 1 = is an SQL database! [SQL][ is an SQL database!] === Iteration 2 === Capture 0 = SQL Capture 1 = database! [SQL][ database!]
Even using the :r adverb to prevent backtracking will not change things:
my $iteration = 0; sub show-captures( Match $m ){ my Str $result-split; say "\n=== Iteration {++$iteration} ==="; for $m.list.kv -> $i, $capture { say "Capture $i = $capture"; $result-split ~= '[' ~ $capture ~ ']'; } say $result-split; } $string ~~ / :r (SQL) (.+) { show-captures( $/ ); } $1 /;
and the output will remain the same:
=== Iteration 1 === Capture 0 = SQL Capture 1 = is an SQL database! [SQL][ is an SQL database!] === Iteration 2 === Capture 0 = SQL Capture 1 = database! [SQL][ database!]
This demonstrates that disabling backtracking does not mean disabling possible multiple iterations of the matching engine, but rather disabling the backward matching tuning.
It is worth noting that each time a regular expression is used, the Match object returned (i.e., $/) is reset. In other words, $/ always refers to the very last regular expression matched:
my $answer = 'a lot of Stuff'; say 'Hit a capital letter!' if $answer ~~ / <[A..Z>]> /; say $/; # OUTPUT: 「S」 say 'hit an x!' if $answer ~~ / x /; say $/; # OUTPUT: Nil
The reset of $/ applies independently from the scope where the regular expression is matched:
my $answer = 'a lot of Stuff'; if $answer ~~ / <[A..Z>]> / { say 'Hit a capital letter'; say $/; # OUTPUT: 「S」 } say $/; # OUTPUT: 「S」 if True { say 'hit an x!' if $answer ~~ / x /; say $/; # OUTPUT: Nil } say $/; # OUTPUT: Nil
The very same concept applies to named captures:
my $answer = 'a lot of Stuff'; if $answer ~~ / $<capital>=<[A..Z>]> / { say 'Hit a capital letter'; say $/<capital>; # OUTPUT: 「S」 } say $/<capital>; # OUTPUT: 「S」 say 'hit an x!' if $answer ~~ / $<x>=x /; say $/<x>; # OUTPUT: Nil say $/<capital>; # OUTPUT: Nil
The Regexes: Best practices and gotchas provides useful information on how to avoid common pitfalls when writing regexes and grammars.
Unordered collections of unique and weighted objects in Perl 6
The six collection classes are Set, SetHash, Bag, BagHash, Mix and MixHash. They all share similar semantics.
In a nutshell, these classes hold, in general, unordered collections of objects, much like an object hash. The QuantHash role is the role that is implemented by all of these classes: therefore they are also referenced as QuantHashes.
Set and SetHash also implement the Setty role, Bag and BagHash implement the Baggy role, Mix and MixHash implement the Mixy role (which itself implements the Baggy role).
Sets only consider if objects in the collection are present or not, bags can hold several objects of the same kind, and mixes also allow fractional (and negative) weights. The regular versions are immutable, the Hash versions are mutable.
Let's elaborate on that. If you want to collect objects in a container but you do not care about the order of these objects, Perl 6 provides these unordered collection types. Being unordered, these containers can be more efficient than Lists or Arrays for looking up elements or dealing with repeated items.
On the other hand, if you want to get the contained objects (elements) without duplicates and you only care whether an element is in the collection or not, you can use a Set or SetHash.
If you want to get rid of duplicates but still preserve order, take a look at the unique routine for List.
=defn Set or SetHash Collection of distinct objectsIf you want to keep track of the number of times each object appeared, you can use a Bag or BagHash. In these Baggy containers each element has a weight (an unsigned integer) indicating the number of times the same object has been included in the collection.
The types Mix and MixHash are similar to Bag and BagHash, but they also allow fractional and negative weights.
Set, Bag, and Mix are immutable types. Use the mutable variants SetHash, BagHash, and MixHash if you want to add or remove elements after the container has been constructed.
For one thing, as far as they are concerned, identical objects refer to the same element – where identity is determined using the WHICH method (i.e. the same way that the === operator checks identity). For value types like Str, this means having the same value; for reference types like Array, it means referring to the same object instance.
Secondly, they provide a Hash-like interface where the actual elements of the collection (which can be objects of any type) are the 'keys', and the associated weights are the 'values':
type of $a | value of $a{$b} if $b is an element | value of $a{$b} if $b is not an element |
---|---|---|
Set / SetHash | True | False |
Bag / BagHash | a positive integer | 0 |
Mix / MixHash | a non-zero real number | 0 |
There are several infix operators devoted to performing common operations using QuantHash semantics. Since that is a mouthful, these operators are usually referred to as "set operators".
This does not mean that the parameters of these operators must always be Set, or even a more generic QuantHash. It just means that the logic that is applied to the operators, follows the logic of Set Theory.
These infixes can be written using the Unicode character that represents the function (like ∈ or ∪), or with an equivalent ASCII version (like (elem) or <(|)>.
So explicitly using Set (or Bag or Mix) objects with these infixes is unnecessary. All set operators work with all possible arguments. If necessary, a coercion will take place internally: but in many cases that is not actually needed.
However, if a Bag or Mix is one of the parameters to these set operators, then the semantics will be upgraded to that type (where Mix supersedes Bag if both types happen to be used).
Returns True if $a is an element of $b, else False. More information, Wikipedia definition.
Returns True if $a is not an element of $b, else False. More information, Wikipedia definition.
Returns True if $a contains $b as an element, else False. More information, Wikipedia definition.
Returns True if $a does not contain $b, else False. More information, Wikipedia definition.
Returns True if $a is a subset or is equal to $b, else False. More information, Wikipedia definition.
Returns True if $a is not a subset nor equal to $b, else False. More information, Wikipedia definition.
Returns True if $a is a strict subset of $b, else False. More information, Wikipedia definition.
Returns True if $a is not a strict subset of $b, else False. More information, Wikipedia definition.
Returns True if $a is a superset of or equal to $b, else False. More information, Wikipedia definition.
Returns True if $a is not a superset nor equal to $b, else False. More information, Wikipedia definition.
Returns True if $a is a strict superset of $b, else False. More information, Wikipedia definition.
Returns True if $a is not a strict superset of $b, else False. More information, Wikipedia definition.
Returns the union of all its arguments. More information, Wikipedia definition.
Returns the intersection of all of its arguments. More information, Wikipedia definition.
Returns the set difference of all its arguments. More information, Wikipedia definition.
Returns the symmetric set difference of all its arguments. More information, Wikipedia definition.
Returns the Baggy multiplication of its arguments. More information.
Returns the Baggy addition of its arguments. More information.
The empty set. More information, Wikipedia definition.
Prefixes that alter the behavior of a statement or a set of them
Statement prefixes are written in front of a statement, and change their meaning, their output, or the moment they are going to be run. Since they have a specific behavior, they are also sometimes specific to some statement or group of statements.
As a statement prefix, lazy acts in front of any statement, including for loops, saving the execution for when the variable they are assigned to is actually needed.
my $incremented = 0; my $var = lazy for <1 2 3 4> -> $d { $incremented++ }; say $incremented; # OUTPUT: «0» say eager $var; # OUTPUT: «(0 1 2 3)» say $incremented; # OUTPUT: «4»
The $incremented variable is only incremented, that is, the internal part of the loop is only run when we eagerly evaluate the variable $var that contains the lazy loop. Eagerness can be applied on a variable in other ways, such as calling the .eager method on it.
my @array = lazy { (^3).map( *² ) }; say @array; # OUTPUT: «[...]» say @array.eager; # OUTPUT: «[0 1 4]»
This prefix can also be used in front of gather to make the inner statements behave lazily; in general, any set of statements that returns a value will be made lazy using this.
The eager statement prefix will eagerly return the result of the statements behind, throwing away laziness and returning the result.
my $result := eager gather { for 1..3 { say "Hey"; take $_² } }; say $result[0]; # OUTPUT: «HeyHeyHey1»
gather is implicitly lazy when bound to a scalar. However, with eager as a statement prefix it will run all three iterations in the loop, as shown by the printed "Hey", even if we are just requesting the first one in a row.
hyper and race use (maybe simultaneous) threads to run different iterations in a loop:
my @a = hyper for ^100_000 { .is-prime }
This code is around 3x faster than the bare for. But there are a couple of caveats here:
The operation inside the loop should take enough time for threading to make sense.
There should be no read or write access to the same data structure inside the loop. Let the loop produce a result, and assign it.
If there's an I/O operation inside the loop, there might be some contention so please avoid it.
Main difference between hyper and race is the ordering of results. Use hyper if you need the loop results to be produced in order, race if you don't care.
As a statement prefix, quietly suppresses all warnings produced by the statement it precedes.
sub marine() {}; quietly say ~&marine; # OUTPUT: «marine»
Calling .Str on code produces a warning. Preceding the statement with quietly will just produce the output, the name of the routine.
If you use try in front of a statement, it will contain the exception produced in it and store it in the $! variable, just like when it's used in front of a block.
try [].pop; say $!; # OUTPUT: «Cannot pop from an empty Array..»
do can be used as an statement prefix to disambiguate the statement they precede; this is needed, for instance, if you want to assign the result of a for statement. A bare for will fail, but this will work:
my $counter = 0; my $result = do for ^5 { $counter++ }; say $counter; # OUTPUT: «5» say $result; # OUTPUT: «(0 1 2 3 4)»
do is equivalent, as in other cases, to surrounding a statement with a parenthesis. It can be used as an alternative with a (possibly more) straightforward syntax.
As in the case of the routine, sink will run the statement throwing away the result. Use it in case you want to run some statement for the side effects it produces.
my $counter = 0; my $result = sink for ^5 { $counter++ }; say $counter; # OUTPUT: «5» say $result; # OUTPUT: «(Any)»
Within a loop, runs the prefixed statement only once.
my $counter; my $result = do for ^5 { once $counter = 0; $counter++ }; say $result; # OUTPUT: «(0 1 2 3 4)»
gather can be used in front of a statement, receiving and gathering in a list all data structures emitted from a take run anywhere from that statement:
proto sub fact( Int ) {*} multi sub fact( 1 --> 1 ) {} multi sub fact( $x ) { take $x * fact( $x-1 ) } my @factors = gather say fact(13); # OUTPUT: «6227020800» say @factors; # OUTPUT: «[2 6 24 120 720 5040 40320 362880 3628800 ...]»
In this example, gather precedes say, which prints the first result of the factorial; at the same time, it's harvesting the result from every call to fact, which goes to @factor.
As a statement prefix, start behaves in the same way as in front of a block, that is, it runs the statement asynchronously, and returns a promise.
proto sub fact( Int ) {*} multi sub fact( 1 --> 1 ) {} multi sub fact( $x ) { $x * fact( $x-1 ) } my @promises = gather { for <3 4> { take start fact( 10 ** $_ ); } } say await @promises;
The Promise s created by start are gathered in an array, which returns the result of the operation once the promises have been fulfilled.
react can be used in concurrent programs to create blocks of code that run whenever some event occurs. It works with blocks, and also as a statement prefix.
my Channel $KXGA .= new; for ^100 { $KXGA.send( (100000..200000).pick ); } my @sums = ( start react whenever $KXGA -> $number { say "In thread ", $*THREAD.id; say "→ ", (^$number).sum; } ) for ^10; start { sleep 10; $KXGA.close(); } await @sums;
In this case react prefixes whenever, which makes a long sum with every number read from a channel.
The keyword supply creates on-demand supplies that you can tap. It pairs with emit, which can be used anywhere from within a supply prefixed statement.
my &cards = -> { my @cards = 1..10 X~ <♠ ♥ ♦ ♣>; emit($_) for @cards.pick(@cards.elems); } my $supply = supply cards; $supply.tap( -> $v { say "Drawing: $v" }); $supply.tap( -> $v { say "Drawing: $v" }, done => { say "No more cards" }); # OUTPUT: # [...] # Drawing: 1♥ # Drawing: 7♥ # Drawing: 9♥ # No more cards
In this example, supply acts as prefix of the previously defined cards routine. It would very well be defined as a block, but giving it a name in this case might increase legibility or simply give the responsibility of defining it to other module.
Accessing data structure elements by index or key
One often needs to refer to a specific element (or slice of elements) from a collection or data structure. Borrowing from mathematical notation where the components of a vector v would be referred to as v₁, v₂, v₃, this concept is called "subscripting" (or "indexing") in Perl 6.
Perl 6 provides two universal subscripting interfaces:
elements are identified by | interface name | supported by | |
---|---|---|---|
[ ] | zero-based indices | Positional | Array, List, Buf, Match, ... |
{ } | string or object keys | Associative | Hash, Bag, Mix, Match, ... |
Positional subscripting(via postcircumfix [ ]) addresses elements of an ordered collection by their position. Index 0 refers to the first element, index 1 to the second, and so on:
my @chores = "buy groceries", "feed dog", "wash car"; say @chores[0]; # OUTPUT: «buy groceries» say @chores[1]; # OUTPUT: «feed dog» say @chores[2]; # OUTPUT: «wash car»
Associative subscripting (via postcircumfix { }), does not require the collection to keep its elements in any particular order - instead, it uses a unique key to address each value. The nature of the keys depends on the collection in question: For example a standard Hash uses string keys, whereas a Mix allows arbitrary objects as keys, etc.:
my %grade = Zoe => "C", Ben => "B+"; say %grade{"Zoe"}; # OUTPUT: «C» say %grade{"Ben"}; # OUTPUT: «B+» my $stats = ( Date.today => 4.18, Date.new(2015, 4, 5) => 17.253 ).Mix; say $stats{ Date.new(2015, 4, 4) + 1 }; # OUTPUT: «17.253»
For passing single-word string keys to { }, you can also use the angle bracketed word quoting constructs as if they were postcircumfix operators:
my %grade = Zoe => "C", Ben => "B+"; say %grade<Zoe>; # OUTPUT: «C» say %grade<Ben>; # OUTPUT: «B+»
This is really just syntactic sugar that gets turned into the corresponding { } form at compile-time:
%hash<foo bar>; # same as %hash{ <foo bar> } %hash«foo "$var"»; # same as %hash{ «foo "$var"» } %hash<<foo "$var">>; # same as %hash{ <<foo "$var">> }
You may have noted above that we avoided having to quote Zoe by using the => operator, but that same operator did not just put invisible quotes around Date.new(2015, 4, 5), and we were able to find the same element using $stats{ Date.new(2015, 4, 4) + 1 }. This is because => only puts invisible quotes around single words, and by "word" we mean an identifier/name. The => operator is there to prevent us from accidentally calling functions or using constants with that name.
Hash subscripts do not do the same thing as =>. The default Hash has been made to behave the way new users have come to expect from using other languages, and for general ease of use. On a default Hash, subscripts coerce keys into strings, as long as those keys produce something Cool. You can use .perl on a collection to be sure whether the keys are strings or objects:
( 1 => 1 ).perl.say; # OUTPUT: «1 => 1» my %h; %h{1} = 1; say %h.perl; # OUTPUT: «{ "1" => 1 }» ( 1/2 => 1 ).perl.say; # OUTPUT: «0.5 => 1» my %h; %h{1/2} = 1; say %h.perl; # OUTPUT: «{ "0.5" => 1 }» ( pi => 1 ).perl.say; # OUTPUT: «:pi(1)» my %h; %h{pi} = 1; say %h.perl; # OUTPUT: «{ "3.14159265358979" => 1 }»
While the invisible quotes around single names is built into =>, string conversion is not built into the curly braces: it is a behavior of the default Hash. Not all types of hashes or collections do so:
my %h := MixHash.new; %h{pi} = 1; %h.perl.say; # OUTPUT: «(3.14159265358979e0=>1).MixHash»
(Any name that => would convert to a string can also be used to build a pair using "adverbial notation" and will appear that way when viewed through .perl, which is why we see :pi(1) above.)
Subscripts can be applied to any expression that returns a subscriptable object, not just to variables:
say "__Hello__".match(/__(.*)__/)[0]; # OUTPUT: «「Hello」» say "__Hello__".match(/__(.*)__/).[0]; # same, in method notation
Positional and associative subscripting are not mutually exclusive - for example, Match objects support both (each accessing a different set of data). Also, to make list processing more convenient, class Any provides a fallback implementation for positional subscripts which simply treats the invocant as a list of one element. (But there's no such fallback for associative subscripts, so they throw a runtime error when applied to an object that does not implement support for them.)
say 42[0]; # OUTPUT: «42» say 42<foo>; # ERROR: Type Int does not support associative indexing.
What happens when a nonexistent element is addressed by a subscript is up to the collection type in question. Standard Array and Hash collections return the type object of their value type constraint (which, by default, is Any) unless the collection has been declared with the is default trait in which case the returned value will be whatever the programmer declared it to be:
# no default values specified my @array1; say @array1[10]; # OUTPUT: «(Any)» my Int @array2; say @array2[10]; # OUTPUT: «(Int)» my %hash1; say %hash1<foo>; # OUTPUT: «(Any)» my Int %hash2; say %hash2<foo>; # OUTPUT: «(Int)» # default values specified my @array3 is default('--'); say @array3[10]; # OUTPUT: «--» my Int @array4 is default(17); say @array4[10]; # OUTPUT: «17» my %hash3 is default('Empty'); say %hash3<foo>; # OUTPUT: «Empty» my Int %hash4 is default(4711); say %hash4<foo>; # OUTPUT: «4711»
However, other types of collections may react differently to subscripts that address nonexistent elements:
say (0, 10, 20)[3]; # OUTPUT: «Nil» say bag(<a a b b b>)<c>; # OUTPUT: «0» say array[uint8].new(1, 2)[2] # OUTPUT: «0»
To silently skip nonexistent elements in a subscripting operation, see #Truncating slices and the #:v adverb.
Positional indices are counted from the start of the collection, but there's also a notation for addressing elements by their position relative to the end: *-1 refers to the last element, *-2 to the second-to-last element, and so on.
my @alphabet = 'A' .. 'Z'; say @alphabet[*-1]; # OUTPUT: «Z» say @alphabet[*-2]; # OUTPUT: «Y» say @alphabet[*-3]; # OUTPUT: «X»
Note: The asterisk is important. Passing a bare negative integer (e.g. @alphabet[-1]) like you would do in many other programming languages, throws an error in Perl 6.
What actually happens here, is that an expression like *-1 declares a code object via Whatever-currying - and the [ ] subscript reacts to being given a code object as an index, by calling it with the length of the collection as argument and using the result value as the actual index. In other words, @alphabet[*-1] becomes @alphabet[@alphabet.elems - 1].
This means that you can use arbitrary expressions which depend on the size of the collection:
say @array[* div 2]; # select the middlemost element say @array[$i % *]; # wrap around a given index ("modular arithmetic") say @array[ -> $size { $i % $size } ]; # same as previous
When multiple elements of a collection need to be accessed, there's a shortcut to doing multiple separate subscripting operations: Simply specify a list of indices/keys in the subscript, to get back a list of elements - also called a "slice" - in the same order.
For positional slices, you can mix normal indices with from-the-end ones:
my @alphabet = 'a' .. 'z'; say @alphabet[15, 4, *-9, 11].perl; # OUTPUT: «("p", "e", "r", "l")»
In the *-number construct above, * indicates the end of the array as explained above in the From the end section. So if you want to take the last N elements of the array, you will have to create a Range that includes it.
(5802..5830).map( {.chr} )[*-10..*-5] # OUTPUT: «(ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ)»
Using * as the last element of the range will, effectively, return the last elements of the collection.
For associative slices, the angle brackets form often comes in handy:
my %color = kiwi => "green", banana => "yellow", cherry => "red"; say %color{"cherry", "kiwi"}; # OUTPUT: «(red green)» say %color<cherry kiwi>; # OUTPUT: «(red green)» say %color{*}; # OUTPUT: «(red yellow green)»
Be aware that slices are controlled by the type of what is passed to (one dimension of) the subscript, not its length. In particular the type can be any of the following:
a lazy Iterable, that truncates in [ ]
accordingly, an infinite Range will truncate, but a finite one produces a normal slice
'*' (whatever-star), that returns the full slice (as if all keys/indices were specified)
any other object, that provides a single-element access rather than a slice
Callable, whatever is returned by the callable (this can lead to recursion)
empty, the full slice known as Zen slice
any iterable different from the above ones, normal slice
The notable difference between * and Zen slice (empty) is that the Whatever star will cause full reification or itemization, while Zen slice won't. Both versions also de-cont.
So even a one-element list returns a slice, whereas a bare scalar value doesn't:
say @alphabet[2,]; # OUTPUT: «(c)» say @alphabet[2,].^name; # OUTPUT: «List» say @alphabet[2]; # OUTPUT: «c» say @alphabet[2].^name; # OUTPUT: «Str»
(The angle bracket form for associative subscripts works out because word quoting conveniently returns a Str in case of a single word, but a List in case of multiple words.)
In fact, the list structure of (the current dimension of) the subscript is preserved across the slice operation (but the kind of Iterable is not – the result is always just lists.)
say @alphabet[0, (1..2, (3,))]; # OUTPUT: «(a ((b c) (d)))» say @alphabet[0, (1..2, [3,])]; # OUTPUT: «(a ((b c) (d)))» say @alphabet[flat 0, (1..2, (3,))]; # OUTPUT: «(a b c d)» say flat @alphabet[0, (1..2, (3,))]; # OUTPUT: «(a b c d)»
Referring to nonexistent elements in a slice subscript causes the output List to contain undefined values (or whatever else the collection in question chooses to return for nonexistent elements):
my @letters = <a b c d e f>; say @letters[3..7]; # OUTPUT: «(d e f (Any) (Any))»
This behavior, while at first glance may seem unintuitive, is desirable in instances when you want to assign a value at an index in which a value does not currently exist.
my @letters; say @letters; # OUTPUT: «[]» @letters[^10] = 'a'..'z'; say @letters; # OUTPUT: «[a b c d e f g h i j]»
If you want the resulting slice to only include existing elements, you can silently skip the non-existent elements using the #:v adverb.
my @letters = <a b c d e f>; say @letters[3..7]:v; # OUTPUT: «(d e f)»
The behavior when indexing a collection via lazy subscripts is different than when indexing with their eager counterparts. When accessing via a lazy subscript, the resulting slice will be truncated.
say @letters[lazy 3..7]; # OUTPUT: «(d e f)» say @letters[ 3..*]; # OUTPUT: «(d e f)»
This behavior exists as a precaution to prevent runaway generation of massive, potentially infinite Lists and the out-of-memory issues that occur as a result.
If you put the subscript operator behind an object without specifying any indices/keys at all, it simply returns the subscripted object itself. Since it is empty but returns everything, it is known as a Zen slice.
Zen slicing is different from passing a Whatever-star (which, like a normal slice, always returns a List of elements no matter the type of the original object) or an empty list (which returns an empty slice):
my %bag := (orange => 1, apple => 3).Bag; say %bag<>; # OUTPUT: «Bag(apple(3), orange)» say %bag{}; # OUTPUT: «Bag(apple(3), orange)» say %bag{*}; # OUTPUT: «(1 3)» say %bag{()}; # OUTPUT: «()»
Zen slicing does not reify or cache and merely returns the invocant. It is usually used to interpolate entire arrays / hashes into strings or to decont.
my @words = "cruel", "world"; say "Hello, @words[]!"; # OUTPUT: «Hello, cruel world!» my $list = <a b c>; .say for $list; # OUTPUT: «(a b c)» .say for $list<>; # OUTPUT: «abc» .say for $list[]; # OUTPUT: «abc»
Dimensions in subscripts are separated by a semicolon, allowing to mix lists of elements and dimensions.
my @twodim = (<a b c>, (1, 2, 3)); say @twodim; # OUTPUT: «[(a b c) (1 2 3)]» say @twodim[0,1;1]; # 2nd element of both lists # OUTPUT: «(b 2)» my %pantheon = %('Baldr' => 'consort' => 'Nanna' , 'Bragi' => 'consort' => 'Iðunn' , 'Nótt' => 'consort' => 'Dellingr' ); say %pantheon{'Bragi','Nótt';'consort'}; # 'consort' value for both keys # OUTPUT: «(Iðunn Dellingr)»
Multidimensional subscripts can be used to flatten nested lists when combined with Whatever.
my @toomany = [[<a b>], [1, 2]]; say @toomany; # OUTPUT: «[[a b] [1 2]]» say @toomany[*;*]; # OUTPUT: «(a b 1 2)»
You can use as many flattening semicolons as you want; there will be, at most, as many nesting levels flattened as the number of semicolons:
say [[1,2,[3,4]],[4,5]][*;*]; # OUTPUT: «(1 2 [3 4] 4 5)» say [[1,2,[3,4]],[4,5]][*;*;*;*]; # OUTPUT: «(1 2 3 4 4 5)»
In the first example, with one Whatever less than the number of levels, the deepest one will not be flattened; in the second case it is, since it's greater than the number of levels.
You can use Whatever to select ranges or "rows" in multidimensional subscripts.
my @a = [[1,2], [3,4]]; say @a[*;1]; # 2nd element of each sub list # OUTPUT: «(2 4)» my @a = (<1 c 6>, <2 a 4>, <5 b 3>); say @a.sort( { $_[1] } ); # sort by 2nd column # OUTPUT: «((2 a 4) (5 b 3) (1 c 6))»
Subscripts participate in "autovivification", i.e. the process by which arrays and hashes automatically spring into existence when needed, so that you can build nested data structures without having to pre-declare the collection type at each level:
my $beatles; $beatles{"White Album"}[0] = "Back in the U.S.S.R."; # autovivification! say $beatles.perl; # OUTPUT: «${"White Album" => $["Back in the U.S.S.R."]}»
$beatles started out undefined, but became a Hash object because it was subscripted with { } in the assignment. Similarly, $beatles{"White Album"} became an Array object due to being subscripted with [ ] in the assignment.
Note that the subscripting itself does not cause autovivification: It only happens when the result of the subscripting chain is assigned to (or otherwise mutated).
TODO: Add expanded documentation on autovivification (which affects more than just subscripts, i.e. also routines like C<push>), at /language/datastructures.html, and link to it from here.A subscripting expression may also be used as the left-hand-side of a binding statement. If supported by the subscripted collection's type, this replaces whatever value container would be naturally found at that "slot" of the collection, with the specified container.
The built-in Array and Hash types support this in order to allow building complex linked data structures:
my @a = 10, 11, 12, 13; my $x = 1; @a[2] := $x; # Bound! (@a[2] and $x refer to the same container now.) $x++; @a[2]++; say @a; # OUTPUT: «[10 11 3 13]» say $x; # OUTPUT: «3»
This can be specially useful when lazy data structures are part of a bigger one.
my @fib = 1,1, * + * … ∞; my @lucas = 1,3, * + * … ∞; my %sequences; %sequences<f> := @fib; %sequences<l> := @lucas; for %sequences.keys -> $s { for ^10 -> $n { say %sequences{$s}[100+$n*10]/%sequences{$s}[101+$n*10]; } } # OUTPUT: 0.6180339887498949 times 20.
In this case, hash keys are bound to lazily generated sequences. The fact that they are bound means that whatever state has been computed is shared by the hash value and the sequence it's bound to, making computations of subsequent elements faster.
TODO: Add expanded documentation on building complex data structures at /language/datastructures.html, and link to it from here.See #method BIND-POS and #method BIND-KEY for the underlying mechanism.
The return value and possible side-effect of a subscripting operation can be controlled using adverbs; these are defined on the relevant subscript operators.
Beware of the relatively loose precedence of operator adverbs, which may require you to add parentheses in compound expressions:
if $foo || %hash<key>:exists { ... } # WRONG, tries to adverb the || op
if $foo || (%hash<key>:exists) { ... } # correct if $foo or %hash<key>:exists { ... } # also correct
The supported adverbs are:
Returns whether or not the requested element exists, instead of returning the element's actual value. This can be used to distinguish between elements with an undefined value, and elements that aren't part of the collection at all:
my @foo = Any, 10; say @foo[0].defined; # OUTPUT: «False» say @foo[0]:exists; # OUTPUT: «True» say @foo[2]:exists; # OUTPUT: «False» say @foo[0, 2]:exists; # OUTPUT: «(True False)» my %fruit = apple => Any, orange => 10; say %fruit<apple>.defined; # OUTPUT: «False» say %fruit<apple>:exists; # OUTPUT: «True» say %fruit<banana>:exists; # OUTPUT: «False» say %fruit<apple banana>:exists; # OUTPUT: «(True False)»
May also be negated to test for non-existence:
say %fruit<apple banana>:!exists; # OUTPUT: «(False True)»
To check if all elements of a slice exist, use an all junction:
if all %fruit<apple orange banana>:exists { ... }
It can be used on multi-dimensional arrays and hashes:
my @multi-dim = 1, [2, 3, [4, 5]]; say @multi-dim[1;2;0]:exists; # OUTPUT: «True» say @multi-dim[1;2;5]:exists; # OUTPUT: «False» my %multi-dim = 1 => { foo => { 3 => 42 } }; say %multi-dim{1;'foo';3}:exists; # OUTPUT: «True» say %multi-dim{1;'bar';3}:exists; # OUTPUT: «False»
:exists can be combined with the #:delete and #:p/#:kv adverbs - in which case the behavior is determined by those adverbs, except that any returned element value is replaced with the corresponding Bool indicating element existence.
See #method EXISTS-POS and #method EXISTS-KEY for the underlying mechanism.
Delete the element from the collection or, if supported by the collection, creates a hole at the given index, in addition to returning its value.
my @tens = 0, 10, 20, 30; say @tens[3]:delete; # OUTPUT: «30» say @tens; # OUTPUT: «[0 10 20]» my %fruit = apple => 5, orange => 10, banana => 4, peach => 17; say %fruit<apple>:delete; # OUTPUT: «5» say %fruit<peach orange>:delete; # OUTPUT: «(17 10)» say %fruit; # OUTPUT: «{banana => 4}»
Note that assigning Nil will revert the container at the given index to its default value. It will not create a hole. The created holes can be tested for with :exists but iteration will not skip them and produce undefined values instead.
my @a = 1, 2, 3; @a[1]:delete; say @a[1]:exists; # OUTPUT: «False» .say for @a; # OUTPUT: «1(Any)3»
With the negated form of the adverb, the element is not actually deleted. This means you can pass a flag to make it conditional:
say %fruit<apple> :delete($flag); # deletes the element only if $flag is # true, but always returns the value.
Can be combined with the #:exists and #:p/#:kv/#:k/#:v adverbs - in which case the return value will be determined by those adverbs, but the element will at the same time also be deleted.
See #method DELETE-POS and #method DELETE-KEY for the underlying mechanism.
Return both the index/key and the value of the element, in the form of a Pair, and silently skip nonexistent elements:
my @tens = 0, 10, 20, 30; say @tens[1]:p; # OUTPUT: «1 => 10» say @tens[0, 4, 2]:p; # OUTPUT: «(0 => 0 2 => 20)» my %month = Jan => 1, Feb => 2, Mar => 3; say %month<Feb>:p; # OUTPUT: «Feb => 2» say %month<Jan Foo Mar>:p; # OUTPUT: «(Jan => 1 Mar => 3)»
If you don't want to skip nonexistent elements, use the negated form:
say %month<Jan Foo Mar>:!p; # OUTPUT: «(Jan => 1 Foo => (Any) Mar => 3)»
Can be combined with the #:exists and #:delete adverbs.
See also the pairs routine.
Return both the index/key and the value of the element, in the form of a List, and silently skip nonexistent elements. When used on a slice, the return value is a single flat list of interleaved keys and values:
my @tens = 0, 10, 20, 30; say @tens[1]:kv; # OUTPUT: «(1 10)» say @tens[0, 4, 2]:kv; # OUTPUT: «(0 0 2 20)» my %month = Jan => 1, Feb => 2, Mar => 3; say %month<Feb>:kv; # OUTPUT: «(Feb 2)» say %month<Jan Foo Mar>:kv; # OUTPUT: «(Jan 1 Mar 3)»
If you don't want to skip nonexistent elements, use the negated form:
say %month<Jan Foo Mar>:!kv; # OUTPUT: «(Jan 1 Foo (Any) Mar 3)»
This adverb is commonly used to iterate over slices:
for %month<Feb Mar>:kv -> $month, $i { say "$month had {Date.new(2015, $i, 1).days-in-month} days in 2015" }
Can be combined with the #:exists and #:delete adverbs.
See also the kv routine.
Return only the index/key of the element, rather than its value, and silently skip nonexistent elements:
my @tens = 0, 10, 20, 30; say @tens[1]:k; # OUTPUT: «1» say @tens[0, 4, 2]:k; # OUTPUT: «(0 2)» my %month = Jan => 1, Feb => 2, Mar => 3; say %month<Feb>:k; # OUTPUT: «Feb» say %month<Jan Foo Mar>:k; # OUTPUT: «(Jan Mar)»
If you don't want to skip nonexistent elements, use the negated form:
say %month<Jan Foo Mar>:!k; # OUTPUT: «(Jan Foo Mar)»
See also the keys routine.
Return the bare value of the element (rather than potentially returning a mutable value container), and silently skip nonexistent elements:
my @tens = 0, 10, 20, 30; say @tens[1]:v; # OUTPUT: «10» say @tens[0, 4, 2]:v; # OUTPUT: «(0, 20)» @tens[3] = 31; # OK @tens[3]:v = 31; # ERROR, Cannot modify an immutable Int (31) my %month = Jan => 1, Feb => 2, Mar => 3; say %month<Feb>:v; # OUTPUT: «2» say %month<Jan Foo Mar>:v; # OUTPUT: «(1 3)»
If you don't want to skip nonexistent elements, use the negated form:
say %month<Jan Foo Mar>:!v; # OUTPUT: «(1 (Any) 3)»
See also the values routine.
The subscripting interfaces described on this page are not meant to be exclusive to Perl 6's built-in collection types - you can (and should) reuse them for any custom type that wants to provide access to data by index or key.
You don't have to manually overload the postcircumfix [ ] and postcircumfix { } operators and re-implement all their magic, to achieve that - instead, you can rely on the fact that their standard implementation dispatches to a well-defined set of low-level methods behind the scenes. For example:
when you write: | this gets called behind the scenes: |
---|---|
%foo<aa> | %foo.AT-KEY("aa") |
%foo<aa>:delete | %foo.DELETE-KEY("aa") |
@foo[3, 4, 5] | @foo.AT-POS(3), @foo.AT-POS(4), @foo.AT-POS(5) |
@foo[*-1] | @foo.AT-POS(@foo.elems - 1) |
So in order to make subscripting work, you only have to implement or delegate those low-level methods (detailed below) for your custom type.
If you do, you should also let your type compose the Positional or Associative role, respectively. This doesn't add any functionality per se, but announces (and may be used to check) that the type implements the corresponding subscripting interface.
Imagine a HTTP::Header type which, despite being a custom class with special behavior, can be indexed like a hash:
my $request = HTTP::Request.new(GET => "perl6.org"); say $request.header.^name; # OUTPUT: «HTTP::Header» $request.header<Accept> = "text/plain"; $request.header{'Accept-' X~ <Charset Encoding Language>} = <utf-8 gzip en>; $request.header.push('Accept-Language' => "fr"); # like .push on a Hash say $request.header<Accept-Language>.perl; # OUTPUT: «["en", "fr"]» my $rawheader = $request.header.Str; # stringify according to HTTP spec
A simple way to implement this class would be to give it an attribute of type Hash, and delegate all subscripting and iterating related functionality to that attribute (using a custom type constraint to make sure users don't insert anything invalid into it):
class HTTP::Header does Associative { subset StrOrArrayOfStr where Str | ( Array & {.all ~~ Str} ); has %!fields of StrOrArrayOfStr handles <AT-KEY EXISTS-KEY DELETE-KEY push iterator list kv keys values>; method Str { #`[not shown, for brevity] } }
However, HTTP header field names are supposed to be case-insensitive (and preferred in camel-case). We can accommodate this by taking the *-KEY and push methods out of the handles list, and implementing them separately like this:
method AT-KEY ($key) is rw { %!fields{normalize-key $key} } method EXISTS-KEY ($key) { %!fields{normalize-key $key}:exists } method DELETE-KEY ($key) { %!fields{normalize-key $key}:delete } method push(*@_) { #`[not shown, for brevity] } sub normalize-key ($key) { $key.subst(/\w+/, *.tc, :g) }
Note that subscripting %!fields returns an appropriate rw container, which our AT-KEY can simply pass on.
However, we may prefer to be less strict about user input and instead take care of sanitizing the field values ourselves. In that case, we can remove the StrOrArrayOfStr type constraint on %!fields, and replace our AT-KEY implementation with one that returns a custom Proxy container which takes care of sanitizing values on assignment:
multi method AT-KEY (::?CLASS:D: $key) is rw { my $element := %!fields{normalize-key $key}; Proxy.new( FETCH => method () { $element }, STORE => method ($value) { $element = do given $value».split(/',' \s+/).flat { when 1 { .[0] } # a single value is stored as a string default { .Array } # multiple values are stored as an array } } ); }
Note that declaring the method as multi and restricting it to :D (defined invocants) makes sure that the undefined case is passed through to the default implementation provided by Any (which is involved in auto-vivification).
In order to make index-based subscripting via postcircumfix [ ] work for your custom type, you should implement at least elems, AT-POS and EXISTS-POS - and optionally others as detailed below.
multi method elems(::?CLASS:D:)
Expected to return a number indicating how many subscriptable elements there are in the object. May be called by users directly, and is also called by postcircumfix [ ] when indexing elements from the end, as in @foo[*-1].
If not implemented, your type will inherit the default implementation from Any that always returns 1 for defined invocants - which is most likely not what you want. So if the number of elements cannot be known for your positional type, add an implementation that fails or dies, to avoid silently doing the wrong thing.
multi method AT-POS (::?CLASS:D: $index)TODO: Cover the case of multi-dim indices (also for all the other methods below), after jnthn's ongoing refactor is finished.
Expected to return the element at position $index. This is what postcircumfix [ ] normally calls.
If you want an element to be mutable (like they are for the built-in Array type), you'll have to make sure to return it in the form of an item container that evaluates to the element's value when read, and updates it when assigned to. (Remember to use return-rw or the is rw routine trait to make that work; see the example.)
multi method EXISTS-POS (::?CLASS:D: $index)
Expected to return a Bool indicating whether or not there is an element at position $index. This is what postcircumfix [ ] calls when invoked like @foo[42]:exists.
What "existence" of an element means, is up to your type.
If you don't implement this, your type will inherit the default implementation from Any, which returns True for 0 and False for any other index - which is probably not what you want. So if checking for element existence cannot be done for your type, add an implementation that fails or dies, to avoid silently doing the wrong thing.
multi method DELETE-POS (::?CLASS:D: $index)
Expected to delete the element at position $index, and return the value it had. This is what postcircumfix [ ] calls when invoked like @foo[42]:delete.
What "deleting" an element means, is up to your type.
Implementing this method is optional; if you don't, users trying to delete elements from an object of this type will get an appropriate error message.
multi method ASSIGN-POS (::?CLASS:D: $index, $new)
Expected to set the element at position $index to the value $new. Implementing this is entirely optional; if you don't, self.AT-POS($index) = $new is used instead, and if you do, you should make sure it has the same effect.
This is meant as an opt-in performance optimization, so that simple assignments like @numbers[5] = "five" can operate without having to call AT-POS (which would have to create and return a potentially expensive container object).
Note that implementing ASSIGN-POS does not relieve you from making AT-POS an rw method though, because less trivial assignments/modifications such as @numbers[5]++ will still use AT-POS.
multi method BIND-POS (::?CLASS:D: $index, \new)
Expected to bind the value or container new to the slot at position $index, replacing any container that would be naturally found there. This is what is called when you write:
my $x = 10; @numbers[5] := $x;
The generic Array class supports this in order to allow building complex linked data structures, but for more domain-specific types it may not make sense, so don't feel compelled to implement it. If you don't, users will get an appropriate error message when they try to bind to a positional slot of an object of this type.
method STORE (::?CLASS:D: \values, :$initialize)
This method should only be supplied if you want to support this syntax:
my @a is Foo = 1,2,3;
Which is used for binding your implementation of the Positional role.
STORE should accept the values to (re-)initialize the object with. The optional named parameter will contain a True value when the method is called on the object for the first time. It should return the invocant.
class DNA { has $.chain is rw; method STORE ($chain where { $chain ~~ /^^ <[ACGT]>+ $$ / and $chain.chars %% 3 }, :$initialize --> DNA) { if $initialize { self= DNA.new( chain => $chain ) } else { self.chain = $chain; self } } method Str(::?CLASS:D:) { return $.chain.comb.rotor(3) } }; my @string is DNA = 'GAATCC'; say @string.Str; # OUTPUT: «((G A A) (T C C))» @string = 'ACGTCG'; say @string.Str; # OUTPUT: «((A C G) (T C G))»
This code takes into account the value of $initialize, which is set to True only if we are assigning a value to a variable declared using the is syntax for the first time. The STORE method should set the self variable and return it in all cases, including when the variable has already been initialized.
In order to make key-based subscripting via postcircumfix { } work for your custom type, you should implement at least AT-KEY and EXISTS-KEY - and optionally others as detailed below.
multi method AT-KEY (::?CLASS:D: $key)
Expected to return the element associated with $key. This is what postcircumfix { } normally calls.
If you want an element to be mutable (like they are for the built-in Hash type), you'll have to make sure to return it in the form of an item container that evaluates to the element's value when read, and updates it when assigned to. (Remember to use return-rw or the is rw routine trait to make that work; see the example.)
On the other hand if you want your collection to be read-only, feel free to return non-container values directly.
multi method EXISTS-KEY (::?CLASS:D: $key)
Expected to return a Bool indicating whether or not there is an element associated with $key. This is what postcircumfix { } calls when invoked like %foo<aa>:exists.
What "existence" of an element means, is up to your type.
If you don't implement this, your type will inherit the default implementation from Any, which always returns False - which is probably not what you want. So if checking for element existence cannot be done for your type, add an implementation that fails or dies, to avoid silently doing the wrong thing.
multi method DELETE-KEY (::?CLASS:D: $key)
Expected to delete the element associated with $key, and return the value it had. This is what postcircumfix { } calls when invoked like %foo<aa>:delete.
What "deleting" an element means, is up to your type - though it should usually cause EXISTS-KEY to become False for that key.
Implementing this method is optional; if you don't, users trying to delete elements from an object of this type will get an appropriate error message.
multi method ASSIGN-KEY (::?CLASS:D: $key, $new)
Expected to set the element associated with $key to the value $new. Implementing this is entirely optional; if you don't, self.AT-KEY($key) = $new is used instead, and if you do, you should make sure it has the same effect.
This is meant as an opt-in performance optimization, so that simple assignments %age<Claire> = 29 can operate without having to call AT-KEY (which would have to create and return a potentially expensive container object).
Note that implementing ASSIGN-KEY does not relieve you from making AT-KEY an rw method though, because less trivial assignments/modifications such as %age<Claire>++ will still use AT-KEY.
multi method BIND-KEY (::?CLASS:D: $key, \new)
Expected to bind the value or container new to the slot associated with $key, replacing any container that would be naturally found there. This is what is called when you write:
my $x = 10; %age<Claire> := $x;
The generic Hash class supports this in order to allow building complex linked data structures, but for more domain-specific types it may not make sense, so don't feel compelled to implement it. If you don't, users will get an appropriate error message when they try to bind to an associative slot of an object of this type.
method STORE (::?CLASS:D: \values, :$initialize)
This method should only be supplied if you want to support the:
my %h is Foo = a => 42, b => 666;
syntax for binding your implementation of the Associative role.
Should accept the values to (re-)initialize the object with, which either could consist of Pairs, or separate key/value pairs. The optional named parameter will contain a True value when the method is called on the object for the first time. Should return the invocant.
General rules of Perl 6 syntax
Perl 6 borrows many concepts from human language. Which is not surprising, considering it was designed by a linguist.
It reuses common elements in different contexts, has the notion of nouns (terms) and verbs (operators), is context-sensitive (in the every day sense, not necessarily in the Computer Science interpretation), so a symbol can have a different meaning depending on whether a noun or a verb is expected.
It is also self-clocking, so that the parser can detect most of the common errors and give good error messages.
Perl 6 code is Unicode text. Current implementations support UTF-8 as the input encoding.
See also Unicode versus ASCII symbols.
Perl 6 code is also free-form, in the sense that you are mostly free to chose the amount of whitespace you use, though in some cases, the presence or absence of whitespace carries meaning.
So you can write
if True { say "Hello"; }
or
if True { say "Hello"; # Bad indentation intended }
or
if True { say "Hello" }
or even
if True {say "Hello"}
though you can't leave out any of the remaining whitespace.
In many places where the compiler would not allow a space you can use any amount of whitespace, as long as it is quoted with a backslash. Unspaces in tokens are not supported. Newlines that are unspaced still count when the compiler produces line numbers. Use cases for unspace are separation of postfix operators and routine argument lists.
sub alignment(+@l) { +@l }; sub long-name-alignment(+@l) { +@l }; alignment\ (1,2,3,4).say; long-name-alignment(3,5)\ .say; say Inf+Inf\i;
In this case, our intention was to make the . of both statements, as well as the parentheses, align, so we precede the whitespace used for padding with a \.
A Perl 6 program is a list of statements, separated by semicolons ;.
say "Hello"; say "world";
A semicolon after the final statement (or after the final statement inside a block) is optional.
say "Hello"; say "world"
if True { say "Hello" } say "world"
Complete statements ending in bare blocks can omit the trailing semicolon, if no additional statements on the same line follow the block's closing curly brace }. This is called the "implied separator rule". For example, you don't need to write a semicolon after an if statement block as seen above, and below.
if True { say "Hello" } say "world";
However, semicolons are required to separate a block from trailing statements in the same line.
if True { say "Hello" }; say "world"; # ^^^ this ; is required
This implied statement separator rule applies in other ways, besides control statements, that could end with a bare block. For example, in combination with the colon : syntax for method calls.
my @names = <Foo Bar Baz>; my @upper-case-names = @names.map: { .uc } # OUTPUT: [FOO BAR BAZ]
For a series of blocks that are part of the same if/elsif/else (or similar) construct, the implied separator rule only applies at the end of the last block of that series. These three are equivalent:
if True { say "Hello" } else { say "Goodbye" }; say "world"; # ^^^ this ; is required
if True { say "Hello" } else { say "Goodbye" } # <- implied statement separator say "world";
if True { say "Hello" } # still in the middle of an if/else statement else { say "Goodbye" } # <- no semicolon required because it ends in a block # without trailing statements in the same line say "world";
Comments are parts of the program text which are only intended for human readers; the Perl 6 compilers do not evaluate them as program text.
Comments count as whitespace in places where the absence or presence of whitespace disambiguates possible parses.
The most common form of comments in Perl 6 starts with a single hash character # and goes until the end of the line.
if $age > 250 { # catch obvious outliers # this is another comment! die "That doesn't look right" }
Multi-line and embedded comments start with a hash character, followed by a backtick, and then some opening bracketing character, and end with the matching closing bracketing character. Only the paired characters (), {}, [], and <> are valid for bounding comment blocks. (Unlike matches and substitutions, where pairs such as !!, || or @ may be used.) The content can not only span multiple lines, but can also be embedded inline.
if #`( why would I ever write an inline comment here? ) True { say "something stupid"; }
These comments can extend multiple lines
#`[ And this is how a multi would work. That says why we do what we do below. ] say "No more";
Curly braces inside the comment can be nested, so in #`{ a { b } c }, the comment goes until the very end of the string. You may also use multiple curly braces, such as #`{{ double-curly-brace }}, which might help disambiguate from nested delimiters. You can embed these comments in expressions, as long as you don't insert them in the middle of keywords or identifiers.
Pod syntax can be used for multi-line comments
say "this is code"; =begin comment Here are several lines of comment =end comment say 'code again';
Identifiers are grammatical building blocks that may be used to give a name to entities/objects such as constants, variables (e.g. Scalars) and routines (e.g. Subs and Methods). In a variable name, any sigil (and twigil) precedes the identifier and does not form a part thereof.
constant c = 299792458; # identifier "c" names an Int my $a = 123; # identifier "a" in the name "$a" of a Scalar sub hello { say "Hello!" }; # identifier "hello" names a Sub
Identifiers come in different forms: ordinary, extended, and compound identifiers.
An ordinary identifier is composed of a leading alphabetic character which may be followed by one or more alphanumeric characters. It may also contain isolated, embedded apostrophes ' and/or hyphens -, provided that the next character is each time alphabetic.
The definitions of "alphabetic" and "alphanumeric" include appropriate Unicode characters. Which characters are "appropriate" depends on the implementation. In the Rakudo/MoarVM Perl 6 implementation alphabetic characters include characters with the Unicode General Category value Letter (L), and the underscore _. Alphanumeric characters additionally include characters with the Unicode General Category value Number, Decimal Digit (Nd).
# valid ordinary identifiers: x _snake_oil something-longer with-numbers1234 don't-do-that piece_of_π 駱駝道 # "Rakuda-dō", Japanese for "Way of the camel"
# invalid ordinary identifiers: 42 # identifier does not start with alphabetic character with-numbers1234-5 # embedded hyphen not followed by alphabetic character is-prime? # question mark is not alphanumeric x² # superscript 2 is not alphanumeric (explained above)
It is often convenient to have names that contain characters that are not allowed in ordinary identifiers. Use cases include situations where a set of entities shares a common "short" name, but still needs for each of its elements to be identifiable individually. For example, you might use a module whose short name is Dog, while its long name includes its naming authority and version:
Dog:auth<Somebody>:ver<1.0> # long module names including author and version Dog:auth<Somebody>:ver<2.0> use Dog:auth<Somebody>:ver<2.0>; # Selection of second module causes its full name to be aliased to the # short name for the rest of # the lexical scope, allowing a declaration # like this. my Dog $spot .= new("woof");
Similarly, sets of operators work together in various syntactic categories with names like prefix, infix and postfix. The official names of these operators often contain characters that are excluded from ordinary identifiers. The long name is what constitutes the extended identifier, and includes this syntactic category; the short name will be included in quotes in the definition:
infix:<+> # the official name of the operator in $a + $b infix:<*> # the official name of the operator in $a * $b infix:«<=» # the official name of the operator in $a <= $b
For all such uses, you can append one or more colon-separated strings to an ordinary identifier to create a so-called extended identifier. When appended to an identifier (that is, in postfix position), this colon-separated string generates unique variants of that identifier.
These strings have the form :key<value>, wherein key or value are optional; that is, after the colon that separates it from a regular identifier, there will be a key and/or a quoting bracketing construct such as < >, « » or [' '] which quotes one or more arbitrary characters value.
# exemplary valid extended identifiers: postfix:<²> # the official long name of the operator in $x² WOW:That'sAwesome WOW:That's<<🆒>> party:sweet<16> # exemplary invalid extended identifiers: party:16<sweet> # 16 is not an ordinary identifier party:16sweet party:!a # ...and neither is !a party:$a # ...nor $a
In an extended identifier, the postfix string is considered an integral part of the name, so infix:<+> and infix:<-> are two different operators. The bracketing characters used, however, do not count as part of it; only the quoted data matters. So these are all the same name:
infix:<+> infix:<<+>> infix:«+» infix:['+'] infix:('+')
Similarly, all of this works:
my $foo:bar<baz> = 'quux'; say $foo:bar«baz»; # OUTPUT: «quux» my $take-me:<home> = 'Where the glory has no end'; say $take-me:['home']; # OUTPUT: «Where [...]» my $foo:bar<2> = 5; say $foo:bar(1+1); # OUTPUT: «5»
Where an extended identifier comprises two or more colon pairs, their order is generally significant:
my $a:b<c>:d<e> = 100; my $a:d<e>:b<c> = 200; say $a:b<c>:d<e>; # OUTPUT: «100», NOT: «200»
An exception to this rule is module versioning; so these identifiers effectively name the same module:
use ThatModule:auth<Somebody>:ver<2.7.18.28.18> use ThatModule:ver<2.7.18.28.18>:auth<Somebody>
Furthermore, extended identifiers support compile-time interpolation; this requires the use of constants for the interpolation values:
constant $c = 42; # Constant binds to Int; $-sigil enables interpolation my $a:foo<42> = "answer"; say $a:foo«$c»; # OUTPUT: «answer»
Although quoting bracketing constructs are generally interchangeable in the context of identifiers, they are not identical. In particular, angle brackets < > (which mimic single quote interpolation characteristics) cannot be used for the interpolation of constant names.
constant $what = 'are'; my @we:<are>= <the champions>; say @we:«$what»; # OUTPUT: «[the champions]» say @we:<$what>; # Compilation error: Variable '@we:<$what>' is not declared
A compound identifier is an identifier that is composed of two or more ordinary and/or extended identifiers that are separated from one another by a double colon ::.
The double colon :: is known as the namespace separator or the package delimiter, which clarifies its semantic function in a name: to force the preceding portion of the name to be considered a package/namespace through which the subsequent portion of the name is to be located:
module MyModule { # declare a module package our $var = "Hello"; # declare package-scoped variable } say $MyModule::var # OUTPUT: «Hello»
In the example above, MyModule::var is a compound identifier, composed of the package name identifier MyModule and the identifier part of the variable name var. Altogether $MyModule::var is often referred to as a package-qualified name.
Separating identifiers with double colons causes the rightmost name to be inserted into existing (see above example) or automatically created packages:
my $foo::bar = 1; say OUR::.keys; # OUTPUT: «(foo)» say OUR::foo.HOW # OUTPUT: «Perl6::Metamodel::PackageHOW.new»
The last lines shows how the foo package was created automatically, as a deposit for variables in that namespace.
The double colon syntax enables runtime interpolation of a string into a package or variable name using ::($expr) where you'd ordinarily put a package or variable name:
my $buz = "quux"; my $bur::quux = 7; say $bur::($buz); # OUTPUT: «7»
You can use term:<> to introduce new terms, which is handy for introducing constants that defy the rules of normal identifiers:
use Test; plan 1; constant &term:<👍> = &ok.assuming(True); 👍 # OUTPUT: «1..1ok 1 - »
But terms don't have to be constant: you can also use them for functions that don't take any arguments, and force the parser to expect an operator after them. For instance:
sub term:<dice> { (1..6).pick }; say dice + dice;
can print any number between 2 and 12.
If instead we had declared dice as a regular
sub dice() {(1...6).pick }
, the expression dice + dice would be parsed as dice(+(dice())), resulting in an error since sub dice expects zero arguments.
Perl 6 programs are made of lists of statements. A special case of a statement is an expression, which returns a value. For example if True { say 42 } is syntactically a statement, but not an expression, whereas 1 + 2 is an expression (and thus also a statement).
The do prefix turns statements into expressions. So while
my $x = if True { 42 }; # Syntax error!
is an error,
my $x = do if True { 42 };
assigns the return value of the if statement (here 42) to the variable $x.
Terms are the basic nouns that, optionally together with operators, can form expressions. Examples for terms are variables ($x), barewords such as type names (Int), literals (42), declarations (sub f() { }) and calls (f()).
For example, in the expression 2 * $salary, 2 and $salary are two terms (an integer literal and a variable).
Variables typically start with a special character called the sigil, and are followed by an identifier. Variables must be declared before you can use them.
# declaration: my $number = 21; # usage: say $number * 2;
See the documentation on variables for more details.
Pre-declared identifiers can be terms on their own. Those are typically type names or constants, but also the term self which refers to an object that a method was called on (see objects), and sigilless variables:
say Int; # OUTPUT: «(Int)» # ^^^ type name (built in) constant answer = 42; say answer; # ^^^^^^ constant class Foo { method type-name { self.^name; # ^^^^ built-in term 'self' } } say Foo.type-name; # OUTPUT: «Foo» # ^^^ type name
Named entities, such as variables, constants, classes, modules or subs, are part of a namespace. Nested parts of a name use :: to separate the hierarchy. Some examples:
$foo # simple identifiers $Foo::Bar::baz # compound identifiers separated by :: $Foo::($bar)::baz # compound identifiers that perform interpolations Foo::Bar::bob(23) # function invocation given qualified name
See the documentation on packages for more details.
A literal is a representation of a constant value in source code. Perl 6 has literals for several built-in types, like strings, several numeric types, pairs and more.
String literals are surrounded by quotes:
say 'a string literal'; say "a string literal\nthat interprets escape sequences";
See quoting for many more options, including the escaping quoting q. Perl 6 uses the standard escape characters in literals: \a \b \t \n \f \r \e, with the same meaning as the ASCII escape codes, specified in the design document.
say "🔔\a"; # OUTPUT: «🔔␇»
Number literals are generally specified in base ten (which can be specified literally, if needed, via the prefix 0d), unless a prefix like 0x (hexadecimal, base 16), 0o (octal, base 8) or 0b (binary, base 2) or an explicit base in adverbial notation like :16<A0> specifies it otherwise. Unlike other programming languages, leading zeros do not indicate base 8; instead a compile-time warning is issued.
In all literal formats, you can use underscores to group digits, although they don't carry any semantic information; the following literals all evaluate to the same number:
1000000 1_000_000 10_00000 100_00_00
Integers default to signed base-10, but you can use other bases. For details, see Int.
# not a single literal, but unary - operator applied to numeric literal 2 -2 12345 0xBEEF # base 16 0o755 # base 8 :3<1201> # arbitrary base, here base 3
Rat literals (rationals) are very common, and take the place of decimals or floats in many other languages. Integer division also results in a Rat.
1.0 3.14159 -2.5 # Not actually a literal, but still a Rat :3<21.0012> # Base 3 rational ⅔ 2/3 # Not actually a literal, but still a Rat
Scientific notation with an integer exponent to base ten after an e produces floating point number:
1e0 6.022e23 1e-9 -2e48 2e2.5 # error
Complex numbers are written either as an imaginary number (which is just a rational number with postfix i appended), or as a sum of a real and an imaginary number:
1+2i 6.123e5i # note that this is 6.123e5 * i, not 6.123 * 10 ** (5i)
Pairs are made of a key and a value, and there are two basic forms for constructing them: key => 'value' and :key('value').
Arrow pairs can have an expression, a string literal or a "bare identifier", which is a string with ordinary-identifier syntax that does not need quotes on the left-hand side:
like-an-identifier-ain't-it => 42 "key" => 42 ('a' ~ 'b') => 1
Short forms without explicit values:
my $thing = 42; :$thing # same as thing => $thing :thing # same as thing => True :!thing # same as thing => False
The variable form also works with other sigils, like :&callback or :@elements. If the value is a number literal, it can also be expressed in this short form:
:42thing # same as thing => 42 :٤٢thing # same as thing => 42
This order is inverted if you use another alphabet
:٤٢ث # same as ث => ٤٢
the thaa letter precedes the number.
Long forms with explicit values:
:thing($value) # same as thing => $value :thing<quoted list> # same as thing => <quoted list> :thing['some', 'values'] # same as thing => ['some', 'values'] :thing{a => 'b'} # same as thing => { a => 'b' }
True and False are Boolean literals; they will always have initial capital letter.
A pair of square brackets can surround an expression to form an itemized Array literal; typically there is a comma-delimited list inside:
say ['a', 'b', 42].join(' '); # OUTPUT: «a b 42» # ^^^^^^^^^^^^^^ Array constructor
If the constructor is given a single Iterable, it'll clone and flatten it. If you want an Array with just 1 element that is an Iterable, ensure to use a comma after it:
my @a = 1, 2; say [@a].perl; # OUTPUT: «[1, 2]» say [@a,].perl; # OUTPUT: «[[1, 2],]»
The Array constructor does not flatten other types of contents. Use the Slip prefix operator (|) to flatten the needed items:
my @a = 1, 2; say [@a, 3, 4].perl; # OUTPUT: «[[1, 2], 3, 4]» say [|@a, 3, 4].perl; # OUTPUT: «[1, 2, 3, 4]»
List type can be explicitly created from an array literal declaration without a coercion from Array, using is trait on declaration.
my @a is List = 1, 2; # a List, not an Array # wrong: creates an Array of Lists my List @a;
A leading associative sigil and pair of parenthesis %( ) can surround a List of Pairs to form a Hash literal; typically there is a comma-delimited List of Pairs inside. If a non-pair is used, it is assumed to be a key and the next element is the value. Most often this is used with simple arrow pairs.
say %( a => 3, b => 23, :foo, :dog<cat>, "french", "fries" ); # OUTPUT: «a => 3, b => 23, dog => cat, foo => True, french => fries» say %(a => 73, foo => "fish").keys.join(" "); # OUTPUT: «a foo» # ^^^^^^^^^^^^^^^^^^^^^^^^^ Hash constructor
When assigning to a %-sigiled variable on the left-hand side, the sigil and parenthesis surrounding the right-hand side Pairs are optional.
my %ages = fred => 23, jean => 87, ann => 4;
By default, keys in %( ) are forced to strings. To compose a hash with non-string keys, use curly brace delimiters with a colon prefix :{ } :
my $when = :{ (now) => "Instant", (DateTime.now) => "DateTime" };
Note that with objects as keys, you cannot access non-string keys as strings:
say :{ -1 => 41, 0 => 42, 1 => 43 }<0>; # OUTPUT: «(Any)» say :{ -1 => 41, 0 => 42, 1 => 43 }{0}; # OUTPUT: «42»
Particular types that implement Associative role, Map (including Hash and Stash subclasses) and QuantHash (and its subclasses), can be explicitly created from a hash literal without a coercion, using is trait on declaration:
my %hash; # Hash my %hash is Hash; # explicit Hash my %map is Map; # Map my %stash is Stash; # Stash my %quant-hash is QuantHash; # QuantHash my %setty is Setty; # Setty my %set is Set; # Set my %set-hash is SetHash; # SetHash my %baggy is Baggy; # Baggy my %bag is Bag; # Bag my %bag-hash is BagHash; # BagHash my %mixy is Mixy; # Mixy my %mix is Mix; # Mix my %mix-hash is MixHash; # MixHash
Note that using a usual type declaration with a hash sigil creates a typed Hash, not a particular type:
# This is wrong: creates a Hash of Mixes, not Mix: my Mix %mix; # Works with $ sigil: my Mix $mix; # Can be typed: my Mix[Int] $mix-of-ints;
A Regex is declared with slashes like /foo/. Note that this // syntax is shorthand for the full rx// syntax.
/foo/ # Short version rx/foo/ # Longer version Q :regex /foo/ # Even longer version my $r = /foo/; # Regexes can be assigned to variables
Signatures can be used standalone for pattern matching, in addition to the typical usage in sub and block declarations. A standalone signature is declared starting with a colon:
say "match!" if 5, "fish" ~~ :(Int, Str); # OUTPUT: «match!» my $sig = :(Int $a, Str); say "match!" if (5, "fish") ~~ $sig; # OUTPUT: «match!» given "foo", 42 { when :(Str, Str) { "This won't match" } when :(Str, Int $n where $n > 20) { "This will!" } }
See the Signatures documentation for more about signatures.
my $x; # simple lexical variable my $x = 7; # initialize the variable my Int $x = 7; # declare the type my Int:D $x = 7; # specify that the value must be defined (not undef) my Int $x where { $_ > 3 } = 7; # constrain the value based on a function my Int $x where * > 3 = 7; # same constraint, but using Whatever shorthand
See Variable Declarators and Scope for more details on other scopes (our, has).
# The signature is optional sub foo { say "Hello!" } sub say-hello($to-whom) { say "Hello $to-whom!" }
You can also assign subroutines to variables.
my &f = sub { say "Hello!" } # Un-named sub my &f = -> { say "Hello!" } # Lambda style syntax. The & sigil indicates the variable holds a function my $f = -> { say "Hello!" } # Functions can also be put into scalars
There are several types of package, each declared with a keyword, a name, some optional traits, and a body of subroutines, methods, or rules.
package P { } module M { } class C { } role R { } grammar G { }
Several packages may be declared in a single file. However, you can declare a unit package at the start of the file (preceded only by comments or use statements), and the rest of the file will be taken as being the body of the package. In this case, the curly braces are not required.
unit module M; # ... stuff goes here instead of in {}'s
See also Multi-dispatch.
Subroutines can be declared with multiple signatures.
multi sub foo() { say "Hello!" } multi sub foo($name) { say "Hello $name!" }
Inside of a class, you can also declare multi-dispatch methods.
multi method greet { } multi method greet(Str $name) { }
Subroutines are created with the keyword sub followed by an optional name, an optional signature and a code block. Subroutines are lexically scoped, so if a name is specified at the declaration time, the same name can be used in the lexical scope to invoke the subroutine. A subroutine is an instance of type Sub and can be assigned to any container.
foo; # Invoke the function foo with no arguments foo(); # Invoke the function foo with no arguments &f(); # Invoke &f, which contains a function &f.(); # Same as above, needed to make the following work my @functions = ({say 1}, {say 2}, {say 3}); @functions>>.(); # hyper method call operator
When declared within a class, a subroutine is named "method": methods are subroutines invoked against an object (i.e., a class instance). Within a method the special variable self contains the object instance (see Methods).
# Method invocation. Object (instance) is $person, method is set-name-age $person.set-name-age('jane', 98); # Most common way $person.set-name-age: 'jane', 98; # Precedence drop set-name-age($person: 'jane', 98); # Invocant marker set-name-age $person: 'jane', 98; # Indirect invocation
For more information, see functions.
In the case of method invocation (i.e., when invoking a subroutine against a class instance) it is possible to apply the precedence drop, identified by a colon : just after the method name and before the argument list. The argument list takes precedence over the method call, that on the other hand "drops" its precedence. In order to better understand consider the following simple example (extra spaces have been added just to align method calls):
my $band = 'Foo Fighters'; say $band.substr( 0, 3 ) .substr( 0, 1 ); # F say $band.substr: 0, 3 .substr( 0, 1 ); # Foo
In the second method call the rightmost substr is applied to "3" and not to the result of the leftmost substr, which on the other hand yields precedence to the rightmost one.
See Operators for lots of details.
Operators are functions with a more symbol heavy and composable syntax. Like other functions, operators can be multi-dispatch to allow for context-specific usage.
There are five types (arrangements) for operators, each taking either one or two arguments.
++$x # prefix, operator comes before single input 5 + 3 # infix, operator is between two inputs $x++ # postfix, operator is after single input <the blue sky> # circumfix, operator surrounds single input %foo<bar> # postcircumfix, operator comes after first input and surrounds second
Operators can be composed. A common example of this is combining an infix (binary) operator with assignment. You can combine assignment with any binary operator.
$x += 5 # Adds 5 to $x, same as $x = $x + 5 $x min= 3 # Sets $x to the smaller of $x and 3, same as $x = $x min 3 $x .= child # Equivalent to $x = $x.child
Wrap an infix operator in [ ] to create a new reduction operator that works on a single list of inputs, resulting in a single value.
say [+] <1 2 3 4 5>; # OUTPUT: «15» (((1 + 2) + 3) + 4) + 5 # equivalent expanded version
Wrap an infix operator in « » (or the ASCII equivalent ) to create a new hyper operator that works pairwise on two lists.
say <1 2 3> «+» <4 5 6> # OUTPUT: «(5 7 9)»
The direction of the arrows indicates what to do when the lists are not the same size.
@a «+« @b # Result is the size of @b, elements from @a will be re-used @a »+» @b # Result is the size of @a, elements from @b will be re-used @a «+» @b # Result is the size of the biggest input, the smaller one is re-used @a »+« @b # Exception if @a and @b are different sizes
You can also wrap a unary operator with a hyper operator.
say -« <1 2 3> # OUTPUT: «(-1 -2 -3)»
Working with the underlying operating system and running applications
The simplest way is to use the @*ARGS variable to obtain arguments from the command line; this array will contain the strings that follow the program name. %*ENV will contain the environment variables, so that if you use:
export API_KEY=1967196417966160761fabc1511067 ./consume_api.p6
You can use them from your program this way:
my $api-key = %*ENV<API_KEY> // die "Need the API key";
This will fail if the environment variable API_KEY has not been defined previously.
Perl 6 has a better way to deal with command line arguments if they represent file names: the $*ARGFILES dynamic variable.
for $*ARGFILES.lines -> $l { say "Long lines in {$*ARGFILES.path}" if $l.chars > 72 ; }
You can run this program this way argfiles.p6 *.p6, for instance, and it will print a file name every time it finds a line longer than 72 characters. $*ARGFILES contains filehandles of all files described in the command lines- .lines will read in turn one line from every one of them, changing the value of $*ARGFILES.path every time a new handle is being processed. In general, it provides a very convenient API for scripts that deal with sets of files.
Use prompt to have a running program query the user for data:
my UInt $num-iters = prompt "How many iterations to run: ";
There are two routines to run external programs: run and shell. Both exist in the IO role and are thus included in all classes that mix that role in, like IO::Path. Both return a Proc object, but the main difference is that run will try to avoid the system shell, if possible, while shell will run the command through the default system shell.
The key class for running all external programs is Proc::Async, which runs processes asynchronously and allows concurrent interaction with the running processes. In general, it is a good practice to interact with the system through these high-level, abstract interfaces. However, Perl 6 provides with other ways of interacting with the system through a low-level interface.
The NativeCall API can be used to interact with system libraries, as well as any other accessible library. This short tutorial explains, for instance, how to call system functions such as getaddrinfo using that interface; some other functions like kill can also be accessed that way, via declaration using the NativeCall interface.
Fortunately, you do not have to do that for all native functions. As part of her Butterfly project porting Perl 5 functions to Perl 6 as part of the ecosystem, Elizabeth Mattijsen is porting many system functions that were part of that language to modules such as P5getprotobyname, which includes functions such as endprotoent, getprotoent, getprotobyname, getprotobynumber and setprotoent. Search and install P5 modules if you want to use those functions already in p6y form.
Compile-time specification of behavior made easy
In Perl 6, traits are compiler hooks attached to objects and classes that modify their default behavior, functionality or representation. As such compiler hooks, they are defined in compile time, although they can be used in runtime.
Several traits are already defined as part of the language or the Rakudo compiler by using the trait_mod keyword. They are listed, and explained, next.
Defined as
proto sub trait_mod:<is>(Mu $, |) {*}
is applies to any kind of scalar object, and can take any number of named or positional arguments. It is the most commonly used trait, and takes the following forms, depending on the type of the first argument.
The most common form, involving two classes, one that is being defined and the other existing, defines parenthood. A is B, if both are classes, defines A as a subclass of B.
is DEPRECATED can be applied to classes, Attributes or Routines, marks them as deprecated and issues a message, if provided.
Several instances of is are translated directly into attributes for the class they refer to: rw, nativesize, ctype, unsigned, hidden, array_type.
The Uninstantiable representation trait is not so much related to the representation as related to what can be done with a specific class; it effectively prevents the creation of instances of the class in any possible way.
constant @IMM = <Innie Minnie Moe>; class don't-instantiate is repr('Uninstantiable') { my $.counter; method imm () { return @IMM[ $.counter++ mod @IMM.elems ]; } } say don't-instantiate.imm for ^10;
Uninstantiable classes can still be used via their class variables and methods, as above. However, trying to instantiate them this way: my $do-instantiate = don't-instantiate.new; will yield the error You cannot create an instance of this type (don't-instantiate).
Since the is trait refers, in general, to the nature of the class or object they are applied to, they are used extensively in native calls to specify the representation of the data structures that are going to be handled by the native functions via the is repr suffix; at the same time, is native is used for the routines that are actually implemented via native functions. These are the representations that can be used:
CStruct corresponds to a struct in the C language. It is a composite data structure which includes different and heterogeneous lower-level data structures; see this for examples and further explanations.
CPPStruct, similarly, correspond to a struct in C++. However, this is Rakudo specific for the time being.
CPointer is a pointer in any of these languages. It is a dynamic data structure that must be instantiated before being used, can be used for classes whose methods are also native.
CUnion is going to use the same representation as an union in C; see this for an example.
On the other hand, P6opaque is the default representation used for all objects in Perl 6.
class Thar {}; say Thar.REPR; #OUTPUT: «P6opaque»
The meta object protocol uses it by default for every object and class unless specified otherwise; for that reason, it is in general not necessary unless you are effectively working with that interface.
The is trait can be used on the definition of methods and routines to establish precedence and associativity. They act as a sub defined using trait_mod which take as argument the types and names of the traits that are going to be added. In the case of subroutines, traits would be a way of adding functionality which cuts across class and role hierarchies, or can even be used to add behaviors to independently defined routines.
Introduction to the type system of Perl 6
A type defines a new object by creating a type object that provides an interface to create instances of objects or to check values against. Any type object is a subclass of Any or Mu. Introspection methods are provided via inheritance from those base classes and the introspection postfix .^. A new type is introduced to the current scope by one of the following type declarators at compile time or with the meta object protocol at runtime. All type names must be unique in their scope.
If no type is provided by the user Perl 6 assumes the type to be Any. This includes containers, base-classes, parameters and return types.
my $a = 1; $a = Nil; say $a.^name; # OUTPUT: «Any» class C {}; say C.^parents(:all); # OUTPUT: «((Any) (Mu))»
For containers the default type is Any but the default type constraint is Mu. Please note that binding replaces the container, not just the value. The type constraint may change in this case.
To test if an object is a type object, use smartmatch against a type constrained with a type smiley or .DEFINITE method:
my $a = Int; say $a ~~ Mu:U; # OUTPUT: «True» say not $a.DEFINITE; # OUTPUT: «True»
.DEFINITE will return True if the invocant is an instance. If it returns False, then the invocant is a type object.
Undefined objects maintain type information in Perl 6. Type objects are used to represent both undefinedness and the type of the undefined value. To provide a general undefined value use Any. If differentiation from Any, the default type for containers and arguments, is required use Mu.
Instances of objects created by .CREATE are by convention defined. The method .defined will return Bool::True to indicate definedness. The exceptions to that rule are Nil and Failure. Please note that any object is able to overload .defined and as such can carry additional information. Also, Perl 6 makes a clear distinction between definedness and trueness. Many values are defined even though they carry the meaning of wrongness or emptiness. Such values are 0, Bool::False, () (empty list) and NaN.
Values can become undefined at runtime via mixin.
my Int $i = 1 but role :: { method defined { False } }; say $i // "undefined"; # OUTPUT: «undefined»
To test for definedness call .defined, use //, with/without and signatures.
Turning one type into another is done with coercion methods that have the same name as the target type. This convention is made mandatory by Signatures. The source type has to know how to turn itself into the target type. To allow built-in types to turn themselves into user defined types use augment or the MOP.
class C { has $.int; method this-is-c { put 'oi' x $!int ~ '‽' } } use MONKEY-TYPING; augment class Int { method C { C.new(:int(self))} } my $i = 10; $i.=C; $i.this-is-c(); # OUTPUT: «oioioioioioioioioioi‽»
Perl 6 provides methods defined in Cool to convert to a target type before applying further operations. Most built-in types descend from Cool and as such may provide implicit coercion that may be undesired. It is the responsibility of the user to care about trap-free usage of those methods.
my $whatever = "123.6"; say $whatever.round; # OUTPUT: «124» say <a b c d>.starts-with("ab"); # OUTPUT: «False»
Type declarators introduce a new type into the given scope. Nested scopes can be separated by ::. New packages are created automatically if no such scope exists already.
class Foo::Bar::C {}; put Foo::Bar::.keys; # OUTPUT: «C»
Forward declarations can be provided with a block containing only .... The compiler will check at the end of the current scope if the type is defined.
class C {...} # many lines later class C { has $.attr }
The class declarator creates a compile time construct that is compiled into a type object. The latter is a simple Perl 6 object and provides methods to construct instances by executing initializers and sub methods to fill all attributes declared in a class, and any parent class, with values. Initializers can be provided with the declaration of attributes or in constructors. It's the responsibility of the Metamodel::ClassHOW to know how to run them. This is the only magic part of building objects in Perl 6. The default parent type is Any, which in turn inherits from Mu. The latter provides the default constructor .new which is named like this by convention. Aside from this, .new does not carry any special meaning nor is treated in any special way.
For more information how to use classes see the Classes and objects tutorial.
The type introduced by class can be extended with infix:<but> at runtime. The original type is not modified, instead a new type object is returned and can be stored in a container that type checks successful against the original type or the role that is mixed in.
class A {} role R { method m { say 'oi‽' } } my R $A = A but R; my $a1 = $A.new; $a1.m; say [$A ~~ R, $a1 ~~ R]; # OUTPUT: «oi‽[True True]»
To test if a given type object is a class, test the meta object method .HOW against Metamodel::ClassHOW.
class C {}; say C.HOW ~~ Metamodel::ClassHOW; # OUTPUT: «True»
Private attributes are addressed with any of the twigils $!, @! and %!. They do not have public accessor methods generated automatically. As such they can not be altered from outside the class they are defined in.
class C { has $!priv; submethod BUILD { $!priv = 42 } }; say (.name, .package, .has_accessor) for C.new.^attributes; # OUTPUT: «($!priv (C) False)»
The method declarator defines objects of type Method and binds them to the provided name in the scope of a class. Methods in a class are has scoped by default. Methods that are our scoped are not added to the method cache by default and as such can not be called with the accessor sigil $.. Call them with their fully qualified name and the invocant as the first argument.
A normal method in a subclass does not compete with multis of a parent class.
class A { multi method m(Int $i){ say 'Int' } multi method m(int $i){ say 'int' } } class B is A { method m(Int $i){ say 'B::Int' } } my int $i; B.new.m($i); # OUTPUT: «B::Int»
To explicitly state that a method is not a multi method use the only method declarator.
class C { only method m {}; multi method m {}; }; # OUTPUT: «X::Comp::AdHoc: Cannot have a multi candidate for 'm' when an only method is also in the package 'C'»
The submethod BUILD is (indirectly) called by .bless. It is meant to set private and public attributes of a class and receives all names attributes passed into .bless. The default constructor .new defined in Mu is the method that invokes it. Given that public accessor methods are not available in BUILD, you must use private attribute notation instead.
class C { has $.attr; submethod BUILD (:$attr = 42) { $!attr = $attr }; multi method new($positional) { self.bless(:attr($positional), |%_) } }; C.new.say; C.new('answer').say; # OUTPUT: «C.new(attr => 42) # C.new(attr => "answer")»
A method with the special name FALLBACK will be called when other means to resolve the name produce no result. The first argument holds the name and all following arguments are forwarded from the original call. Multi methods and sub-signatures are supported.
class Magic { method FALLBACK ($name, |c(Int, Str)) { put "$name called with parameters {c.perl}" } }; Magic.new.simsalabim(42, "answer"); # OUTPUT: «simsalabim called with parameters ⌈\(42, "answer")⌋»
Some built-in introspection methods are actually special syntax provided by the compiler, namely WHAT, WHO, HOW and VAR. Declaring methods with those names will silently fail. A dynamic call will work, what allows to call methods from foreign objects.
class A { method WHAT { "ain't gonna happen" } }; say A.new.WHAT; # OUTPUT: «(A)» say A.new."WHAT"() # OUTPUT: «ain't gonna happen»
Any our scoped method will be visible in the package scope of a class.
class C { our method packaged {}; method loose {} }; say C::.keys # OUTPUT: «(&packaged)»
Instead of writing attr => $attr or :attr($attr), you can save some typing if the variable (or method call) you're setting the attribute with shares the name with the attribute:
class A { has $.i = 42 }; class B { has $.i = "answer"; method m() { A.new(:$.i) } # ^^^^ Instead of i => $.i or :i($.i) }; my $a = B.new.m; say $a.i; # OUTPUT: «answer»
Since $.i method call is named i and the attribute is also named i, Perl 6 lets us shortcut. The same applies to :$var, :$!private-attribute, :&attr-with-code-in-it, and so on.
Marks a List method to indicate to hyperoperator to not descend into inner Iterables to call this method. This trait generally isn't something end users would be using, unless they're subclassing or augmenting core List type.
In order to demonstrate the difference consider the following examples, the first using a method (elems) that is nodal and the second using a method (Int) which is not nodal.
say ((1.0, "2", 3e0), [^4], '5')».elems; # OUTPUT: «(3, 4, 1)» say ((1.0, "2", 3e0), [^4], '5')».Int # OUTPUT: «((1 2 3) [0 1 2 3] 5)»
Defined as:
multi sub trait_mod:<handles>(Attribute:D $target, $thunk)
The trait handles applied to an attribute of a class will delegate all calls to the provided method name to the method with the same name of the attribute. The object referenced by the attribute must be initialized. A type constraint for the object that the call is delegated to can be provided.
class A { method m(){ 'A::m has been called.' } } class B is A { method m(){ 'B::m has been called.' } } class C { has A $.delegate handles 'm'; method new($delegate){ self.bless(delegate => $delegate) } }; say C.new(B.new).m(); # OUTPUT: «B::m has been called.»
Instead of a method name, a Pair (for renaming), a list of names or Pairs, a Regex or a Whatever can be provided. In the latter case existing methods, both in the class itself and its inheritance chain, will take precedence. If even local FALLBACKs should be searched, use a HyperWhatever.
class A { method m1(){} method m2(){} } class C { has $.delegate handles <m1 m2> = A.new() } C.new.m2; class D { has $.delegate handles /m\d/ = A.new() } D.new.m1; class E { has $.delegate handles (em1 => 'm1') = A.new() } E.new.em1;
Defined as:
multi sub trait_mod:<is>(Mu:U $child, Mu:U $parent)
The trait is accepts a type object to be added as a parent class of a class in its definition. To allow multiple inheritance the trait can be applied more than once. Adding parents to a class will import their methods into the target class. If the same method name occurs in multiple parents, the first added parent will win.
If no is trait is provided the default of Any will be used as a parent class. This forces all Perl 6 objects to have the same set of basic methods to provide an interface for introspection and coercion to basic types.
class A { multi method from-a(){ 'A::from-a' } } say A.new.^parents(:all).perl; # OUTPUT: «(Any, Mu)» class B { method from-b(){ 'B::from-b ' } multi method from-a(){ 'B::from-A' } } class C is A is B {} say C.new.from-a(); # OUTPUT: «A::from-a»
Defined as:
sub trait_mod:<is>(Mu:U $type, :$rw!)
The trait is rw on a class will create writable accessor methods on all public attributes of that class.
class C is rw { has $.a; }; my $c = C.new.a = 42; say $c; # OUTPUT: «42»
Defined as:
multi sub trait_mod:<is>(Attribute $attr, :$required!) multi sub trait_mod:<is>(Parameter:D $param, :$required!)
Marks a class or roles attribute as required. If the attribute is not initialized at object construction time throws X::Attribute::Required.
class Correct { has $.attr is required; submethod BUILD (:$attr) { $!attr = $attr } } say Correct.new(attr => 42); # OUTPUT: «Correct.new(attr => 42)» class C { has $.attr is required; } C.new; CATCH { default { say .^name => .Str } } # OUTPUT: «X::Attribute::Required => The attribute '$!attr' is required, but you did not provide a value for it.»
You can provide a reason why it's required as an argument to is required
class Correct { has $.attr is required("it's so cool") }; say Correct.new(); # OUTPUT: «The attribute '$!attr' is required because it's so cool,but you did not provide a value for it.»
The trait hides provides inheritance without being subject to re-dispatching.
class A { method m { say 'i am hidden' } } class B hides A { method m { nextsame } method n { self.A::m } }; B.new.m; B.new.n; # OUTPUT: «i am hidden»
The trait is hidden allows a class to hide itself from re-dispatching.
class A is hidden { method m { say 'i am hidden' } } class B is A { method m { nextsame } method n { self.A::m } } B.new.m; B.new.n; # OUTPUT: «i am hidden»
To allow one class to access the private methods of another class use the trait trusts. A forward declaration of the trusted class may be required.
class B {...}; class A { trusts B; has $!foo; method !foo { return-rw $!foo } method perl { "A.new(foo => $!foo)" } }; class B { has A $.a .= new; method change { $!a!A::foo = 42; self } }; say B.new.change; # OUTPUT: «B.new(a => A.new(foo => 42))»
To add methods and attributes to a class at compile time use augment in front of a class definition fragment. The compiler will demand the pragmas use MONKEY-TYPING or use MONKEY early in the same scope. Please note that there may be performance implications, hence the pragmas.
use MONKEY; augment class Str { method mark(Any :$set){ state $mark //= $set; $mark } }; my $s = "42"; $s.mark(set => "answer"); say $s.mark # OUTPUT: «answer»
There are few limitations of what can be done inside the class fragment. One of them is the redeclaration of a method or sub into a multi. Using added attributes is not yet implemented. Please note that adding a multi candidate that differs only in its named parameters will add that candidate behind the already defined one and as such it won't be picked by the dispatcher.
Versioning and authorship can be applied via the adverbs :ver<> and :auth<>. Both take a string as argument, for :ver the string is converted to a Version object. To query a class version and author use .^ver and ^.auth.
class C:ver<4.2.3>:auth<me@here.local> {} say [C.^ver, C.^auth]; # OUTPUT: «[v4.2.3 me@here.local]»
Roles are class fragments, which allow the definition of interfaces that are shared by classes. The role declarator also introduces a type object that can be used for type checks. Roles can be mixed into classes and objects at runtime and compile time. The role declarator returns the created type object thus allowing the definition of anonymous roles and in-place mixins.
role Serialize { method to-string { self.Str } method to-number { self.Num } } class A does Serialize {} class B does Serialize {} my Serialize @list; @list.push: A.new; @list.push: B.new; say @list».to-string; # OUTPUT: «[A<57192848> B<57192880>]»
Use ... as the only element of a method body to declare a method to be abstract. Any class getting such a method mixed in has to overload it. If the method is not overloaded before the end of the compilation unit X::Comp::AdHoc will be thrown.
EVAL 'role R { method overload-this(){...} }; class A does R {}; '; CATCH { default { say .^name, ' ', .Str } } # OUTPUT: «X::Comp::AdHoc Method 'overload-this' must be implemented by A because it is required by roles: R.»
A role can be used instead of a class to create objects. Since roles can't exist at runtime, a class of the same name is created that will type check successful against the role.
role R { method m { say 'oi‽' } }; R.new.^mro.say; # OUTPUT: «((R) (Any) (Mu))» say R.new.^mro[0].HOW.^name; # OUTPUT: «Perl6::Metamodel::ClassHOW» say R.new ~~ R; # OUTPUT: «True»
The trait does can be applied to roles and classes providing compile time mixins. To refer to a role that is not defined yet, use a forward declaration. The type name of the class with mixed in roles does not reflect the mixin, a type check does. If methods are provided in more than one mixed in role, the method that is defined first takes precedence. A list of roles separated by comma can be provided. In this case conflicts will be reported at compile time.
role R2 {...}; role R1 does R2 {}; role R2 {}; class C does R1 {}; say [C ~~ R1, C ~~ R2]; # OUTPUT: «[True True]»
For runtime mixins see but and does.
Roles can be provided with parameters in-between [] behind a roles name. Type captures are supported.
role R[$d] { has $.a = $d }; class C does R["default"] { }; my $c = C.new; say $c; # OUTPUT: «C.new(a => "default")»
Parameters can have type constraints, where clauses are not supported for types but can be implemented via subsets.
class A {}; class B {}; subset A-or-B where * ~~ A|B; role R[A-or-B ::T] {}; R[A.new].new;
Default parameters can be provided.
role R[$p = fail("Please provide a parameter to role R")] {}; my $i = 1 does R; CATCH { default { say .^name, ': ', .Str} } # OUTPUT: «X::AdHoc: Could not instantiate role 'R':Please provide a parameter to role R»
Roles can be used as type constraints wherever a type is expected. If a role is mixed in with does or but, its type-object is added to the type-object list of the object in question. If a role is used instead of a class (using auto-punning), the auto-generated class' type-object, of the same name as the role, is added to the inheritance chain.
role Unitish[$unit = fail('Please provide a SI unit quantifier as a parameter to the role Unitish')] { has $.SI-unit-symbol = $unit; method gist { given self { # ... when * < 1 { return self * 1000 ~ 'm' ~ $.SI-unit-symbol } when * < 1000 { return self ~ $.SI-unit-symbol } when * < 1_000_000 { return self / 1_000 ~ 'k' ~ $.SI-unit-symbol } # ... } } } role SI-second does Unitish[<s>] {} role SI-meter does Unitish[<m>] {} role SI-kilogram does Unitish[<g>] {} sub postfix:<s>(Numeric $num) { ($num) does SI-second } sub postfix:<m>(Numeric $num) { ($num) does SI-meter } sub postfix:<g>(Numeric $num) { ($num) does SI-kilogram } sub postfix:<kg>(Numeric $num){ ($num * 1000) does SI-kilogram } constant g = 9.806_65; role SI-Newton does Unitish[<N>] {} multi sub N(SI-kilogram $kg, SI-meter $m, SI-second $s --> SI-Newton ){ ($kg * ($m / $s²)) does SI-Newton } multi sub N(SI-kilogram $kg --> SI-Newton) { ($kg * g) does SI-Newton } say [75kg, N(75kg)]; # OUTPUT: «[75kg 735.49875kN]» say [(75kg).^name, N(75kg).^name]; # OUTPUT: «[Int+{SI-kilogram} Rat+{SI-Newton}]»
Versioning and authorship can be applied via the adverbs :ver<> and :auth<>. Both take a string as argument, for :ver the string is converted to a Version object. To query a role's version and author use .^ver and ^.auth.
role R:ver<4.2.3>:auth<me@here.local> {} say [R.^ver, R.^auth]; # OUTPUT: «[v4.2.3 me@here.local]»
Enumerations provide constant key-value-pairs with an associated type. Any key is of that type and injected as a symbol into the current scope. If the symbol is used, it is treated as a constant expression and the symbol is replaced with the value of the enum-pair. Any Enumeration inherits methods from the role Enumeration. Complex expressions for generating key-value pairs are not supported. In general, an enum is a Map whose elements have the Enumeration role mixed in; this role includes, for each element, an index which creates an order on the map.
Stringification of the symbol, which is done automatically in string context and is exactly equal to its name, which is also the key of the enum-pair.
enum Names ( name1 => 1, name2 => 2 ); say name1, ' ', name2; # OUTPUT: «name1 name2» say name1.value, ' ', name2.value; # OUTPUT: «1 2»
Comparing symbols will use type information and the value of the enum-pair. As value types Num and Str are supported.
enum Names ( name1 => 1, name2 => 2 ); sub same(Names $a, Names $b){ $a eqv $b } say same(name1, name1); # OUTPUT: «True» say same(name1, name2); # OUTPUT: «False» my $a = name1; say $a ~~ Names; # OUTPUT: «True» say $a.^name; # OUTPUT: «Names»
All keys have to be of the same type.
enum Mass ( mg => 1/1000, g => 1/1, kg => 1000/1 ); say Mass.enums; # OUTPUT: «Map.new((g => 1, kg => 1000, mg => 0.001))»
And you can use any kind of symbol:
enum Suit <♣ ♦ ♥ ♠>;
As long as you refer to that symbol using the full syntax:
say Suit::<♣>; # OUTPUT: «♣»
Attempting to access unicode enum keys without said syntax will result in an error:
say ♣ ; # OUTPUT: «(exit code 1) ===SORRY!===Argument to "say" seems to be malformed…
If no value is given Int will be assumed as the values type and incremented by one per key starting at zero. As enum key types Int, Num, Rat and Str are supported.
enum Numbers <one two three four>; say Numbers.enums; # OUTPUT: «Map.new((four => 3, one => 0, three => 2, two => 1))»
A different starting value can be provided.
enum Numbers «:one(1) two three four»; say Numbers.enums; # OUTPUT: «Map.new((four => 4, one => 1, three => 3, two => 2))»
You can also do this with the () form of the initializer, but will need to quote keys that do not have a value:
enum Numbers ( one => 1, 'two', 'three', 'four' );
Enums can also be anonymous, with the only difference with named enums being that you cannot use it in Signatures or to declare variables.
my $e = enum <one two three>; say two; # OUTPUT: «two» say one.^name; # OUTPUT: «» say $e.^name; # OUTPUT: «Map»
There are various methods to get access to the keys and values of the symbols that have been defined. All of them turn the values into Str, which may not be desirable. By treating the enum as a package, we can get a list of types for the keys.
enum E(<one two>); my @keys = E::.values; say @keys.map: *.enums; # OUTPUT: «(Map.new((one => 0, two => 1)) Map.new((one => 0, two => 1)))»
With the use of () parentheses, an enum can be defined using any arbitrary dynamically defined list. The list should consist of Pair objects:
For example, in file config we have:
a 1 b 2
We can create an enum using it with this code:
enum ConfigValues ('config'.IO.lines.map({ my ($key, $value) = $_.words; $key => $value })); say ConfigValues.enums; # OUTPUT: «Map.new((a => 1, b => 2))»
Firstly, we read lines from config file, split every line using words method and return resulting pair for every line, thus creating a List of Pairs.
To test if a given type object is an enum, test the meta object method .HOW against Metamodel::EnumHOW or simply test against the Enumeration role.
enum E(<a b c>); say E.HOW ~~ Metamodel::EnumHOW; # OUTPUT: «True» say E ~~ Enumeration; # OUTPUT: «True»
Defined as:
method enums()
Returns the list of enum-pairs.
enum Mass ( mg => 1/1000, g => 1/1, kg => 1000/1 ); say Mass.enums; # OUTPUT: «{g => 1, kg => 1000, mg => 0.001}»
If you want to coerce the value of an enum element to its proper enum object, use the coercer with the name of the enum:
my enum A (sun => 42, mon => 72); A(72).pair.say; # OUTPUT: «mon => 72» A(1000).say; # OUTPUT: «(A)»
The last example shows what happens if there is no enum-pair that includes that as a value.
Modules are usually one or more source files that expose Perl 6 constructs, such as classes, roles, grammars, subroutines and variables. Modules are usually used for distributing Perl 6 code as libraries which can be used in another Perl 6 program.
For a full explanation see Modules.
Versioning and authorship can be applied via the adverbs :ver<> and :auth<>. Both take a string as argument, for :ver the string is converted to a Version object. To query a modules version and author use .^ver and ^.auth.
module M:ver<4.2.3>:auth<me@here.local> {} say [M.^ver, M.^auth]; # OUTPUT: «[v4.2.3 me@here.local]»
Packages are nested namespaces of named program elements. Modules, classes and grammars are all types of package.
For a full explanation see Packages.
Grammars are a specific type of class intended for parsing text. Grammars are composed of rules, tokens and regexes which are actually methods, since grammars are classes.
For a full explanation see Grammars.
Versioning and authorship can be applied via the adverbs :ver<> and :auth<>. Both take a string as argument, for :ver the string is converted to a Version object. To query a grammars version and author use .^ver and ^.auth.
grammar G:ver<4.2.3>:auth<me@here.local> {} say [G.^ver, G.^auth]; # OUTPUT: «[v4.2.3 me@here.local]»
A subset declares a new type that will re-dispatch to its base type. If a where clause is supplied any assignment will be checked against the given code object.
subset Positive of Int where * > -1; my Positive $i = 1; $i = -42; CATCH { default { put .^name,': ', .Str } } # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $i; expected Positive but got Int (-42)»
Subsets can be used in signatures, e.g. by typing the output:
subset Foo of List where (Int,Str); sub a($a, $b, --> Foo) { $a, $b } # Only a List with the first element being an Int and the second a Str will pass the type check. a(1, "foo"); # passes a("foo", 1); # fails
Subsets can be anonymous, allowing inline placements where a subset is required but a name is neither needed nor desirable.
my enum E1 <A B>; my enum E2 <C D>; sub g(@a where { .all ~~ subset :: where E1|E2 } ) { say @a } g([A, C]); # OUTPUT: «[A C]»
Subsets can be used to check types dynamically, which can be useful in conjunction with require.
require ::('YourModule'); subset C where ::('YourModule::C');
Unicode support in Perl 6
Perl 6 has a high level of support of Unicode. This document aims to be both an overview as well as description of Unicode features which don't belong in the documentation for routines and methods.
For an overview on MoarVM's internal representation of strings, see the MoarVM string documentation.
Perl 6 applies normalization by default to all input and output except for file names, which are read and written as UTF8-C8; graphemes, which are user-visible forms of the characters, will use a normalized representation. For example, the grapheme á can be represented in two ways, either using one codepoint:
á (U+E1 "LATIN SMALL LETTER A WITH ACUTE")
Or two codepoints:
a + ́ (U+61 "LATIN SMALL LETTER A" + U+301 "COMBINING ACUTE ACCENT")
Perl 6 will turn both these inputs into one codepoint, as is specified for Normalization Form C (NFC). In most cases this is useful and means that two inputs that are equivalent are both treated the same. Unicode has a concept of canonical equivalence which allows us to determine the canonical form of a string, allowing us to properly compare strings and manipulate them, without having to worry about the text losing these properties. By default, any text you process or output from Perl 6 will be in this “canonical” form, even when making modifications or concatenations to the string (see below for how to avoid this). For more detailed information about Normalization Form C and canonical equivalence, see the Unicode Foundation's page on Normalization and Canonical Equivalence.
One case where we don't default to this, is for the names of files. This is because the names of files must be accessed exactly as the bytes are written on the disk.
To avoid normalization you can use a special encoding format called UTF8-C8. Using this encoding with any filehandle will allow you to read the exact bytes as they are on disk, without normalization. They may look funny when printed out, if you print it out using a UTF8 handle. If you print it out to a handle where the output encoding is UTF8-C8, then it will render as you would normally expect, and be a byte for byte exact copy. More technical details on UTF8-C8 on MoarVM are described below.
UTF-8 Clean-8 is an encoder/decoder that primarily works as the UTF-8 one. However, upon encountering a byte sequence that will either not decode as valid UTF-8, or that would not round-trip due to normalization, it will use NFG synthetics to keep track of the original bytes involved. This means that encoding back to UTF-8 Clean-8 will be able to recreate the bytes as they originally existed. The synthetics contain 4 codepoints:
The codepoint 0x10FFFD (which is a private use codepoint)
The codepoint 'x'
The upper 4 bits of the non-decodable byte as a hex char (0..9A..F)
The lower 4 bits as the non-decodable byte as a hex char (0..9A..F)
Under normal UTF-8 encoding, this means the unrepresentable characters will come out as something like ?xFF.
UTF-8 Clean-8 is used in places where MoarVM receives strings from the environment, command line arguments, and filesystem queries, for instance when decoding buffers:
say Buf.new(ord('A'), 0xFE, ord('Z')).decode('utf8-c8'); # OUTPUT: «AxFEZ»
You can see how the two initial codepoints used by UTF8-C8 show up here, right before the "FE". You can use this type of encoding to read files with unknown encoding:
my $test-file = "/tmp/test"; given open($test-file, :w, :bin) { .write: Buf.new(ord('A'), 0xFA, ord('B'), 0xFB, 0xFC, ord('C'), 0xFD); .close; } say slurp($test-file, enc => 'utf8-c8'); # OUTPUT: «(65 250 66 251 252 67 253)»
Reading with this type of encoding and encoding them back to UTF8-C8 will give you back the original bytes; this would not have been possible with the default UTF-8 encoding.
Please note that this encoding so far is not supported in the JVM implementation of Rakudo.
You can enter Unicode codepoints by number (decimal as well as hexadecimal). For example, the character named "latin capital letter ae with macron" has decimal codepoint 482 and hexadecimal codepoint 0x1E2:
say "\c[482]"; # OUTPUT: «Ǣ» say "\x1E2"; # OUTPUT: «Ǣ»
You can also access Unicode codepoints by name: Perl 6 supports all Unicode names.
say "\c[PENGUIN]"; # OUTPUT: «🐧» say "\c[BELL]"; # OUTPUT: «🔔» (U+1F514 BELL)
All Unicode codepoint names/named seq/emoji sequences are now case-insensitive: [Starting in Rakudo 2017.02]
say "\c[latin capital letter ae with macron]"; # OUTPUT: «Ǣ» say "\c[latin capital letter E]"; # OUTPUT: «E» (U+0045)
You can specify multiple characters by using a comma separated list with \c[]. You can combine numeric and named styles as well:
say "\c[482,PENGUIN]"; # OUTPUT: «Ǣ🐧»
In addition to using \c[] inside interpolated strings, you can also use the uniparse:
say "DIGIT ONE".uniparse; # OUTPUT: «1» say uniparse("DIGIT ONE"); # OUTPUT: «1»
Name Aliases are used mainly for codepoints without an official name, for abbreviations, or for corrections (Unicode names never change). For full list of them see here.
Control codes without any official name:
say "\c[ALERT]"; # Not visible (U+0007 control code (also accessible as \a)) say "\c[LINE FEED]"; # Not visible (U+000A same as "\n")
Corrections:
say "\c[LATIN CAPITAL LETTER GHA]"; # OUTPUT: «Ƣ» say "Ƣ".uniname; # OUTPUT: «LATIN CAPITAL LETTER OI» # This one is a spelling mistake that was corrected in a Name Alias: say "\c[PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRACKET]".uniname; # OUTPUT: «PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET»
Abbreviations:
say "\c[ZWJ]".uniname; # OUTPUT: «ZERO WIDTH JOINER» say "\c[NBSP]".uniname; # OUTPUT: «NO-BREAK SPACE»
You can also use any of the Named Sequences, these are not single codepoints, but sequences of them. [Starting in Rakudo 2017.02]
say "\c[LATIN CAPITAL LETTER E WITH VERTICAL LINE BELOW AND ACUTE]"; # OUTPUT: «É̩» say "\c[LATIN CAPITAL LETTER E WITH VERTICAL LINE BELOW AND ACUTE]".ords; # OUTPUT: «(201 809)»
Perl 6 supports Emoji sequences. For all of them see: Emoji ZWJ Sequences and Emoji Sequences. Note that any names with commas should have their commas removed, since Perl 6 uses commas to separate different codepoints/sequences inside the same \c sequence.
say "\c[woman gesturing OK]"; # OUTPUT: «🙆♀️» say "\c[family: man woman girl boy]"; # OUTPUT: «👨👩👧👦»
Unicode symbols and their ASCII equivalents
The following Unicode symbols can be used in Perl 6 without needing to load any additional modules. Some of them have equivalents which can be typed with ASCII-only characters.
Reference is made below to various properties of unicode codepoints. The definitive list can be found here: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt.
Any codepoint that has the Ll (Letter, lowercase), Lu (Letter, uppercase), Lt (Letter, titlecase), Lm (Letter, modifier), or the Lo (Letter, other) property can be used just like any other alphabetic character from the ASCII range.
my $Δ = 1; $Δ++; say $Δ;
Any codepoint that has the Nd (Number, decimal digit) property, can be used as a digit in any number. For example:
my $var = 19; # U+FF11 U+FF19 say $var + 2; # OUTPUT: «21»
Any codepoint that has the No (Number, other) or Nl (Number, letter) property can be used standalone as a numeric value, such as ½ and ⅓. (These aren't decimal digit characters, so can't be combined.) For example:
my $var = ⅒ + 2 + Ⅻ; # here ⅒ is No and Rat and Ⅻ is Nl and Int say $var; # OUTPUT: «14.1»
Besides spaces and tabs you can use any other unicode whitespace character that has the Zs (Separator, space), Zl (Separator, line), or Zp (Separator, paragraph) property.
This list contains the single codepoints [and their ASCII equivalents] that have a special meaning in Perl 6.
Symbol | Codepoint | ASCII | Remarks |
---|---|---|---|
« | U+00AB | << | as part of «» or .« or regex left word boundary |
» | U+00BB | >> | as part of «» or .» or regex right word boundary |
× | U+00D7 | * | |
÷ | U+00F7 | / | |
≤ | U+2264 | <= | |
≥ | U+2265 | >= | |
≠ | U+2260 | != | |
− | U+2212 | - | |
∘ | U+2218 | o | |
≅ | U+2245 | =~= | |
π | U+03C0 | pi | 3.14159_26535_89793_238e0 |
τ | U+03C4 | tau | 6.28318_53071_79586_476e0 |
𝑒 | U+1D452 | e | 2.71828_18284_59045_235e0 |
∞ | U+221E | Inf | |
… | U+2026 | ... | |
‘ | U+2018 | ' | as part of ‘’ or ’‘ |
’ | U+2019 | ' | as part of ‘’ or ‚’ or ’‘ |
‚ | U+201A | ' | as part of ‚‘ or ‚’ |
“ | U+201C | " | as part of “” or ”“ |
” | U+201D | " | as part of “” or ”“ or ”” |
„ | U+201E | " | as part of „“ or „” |
「 | U+FF62 | Q// | as part of 「」 (Note: Q// variant cannot be used bare in regexes) |
」 | U+FF63 | Q// | as part of 「」 (Note: Q// variant cannot be used bare in regexes) |
⁺ | U+207A | + | (must use explicit number) as part of exponentiation |
⁻ | U+207B | - | (must use explicit number) as part of exponentiation |
¯ | U+00AF | - | (must use explicit number) as part of exponentiation (macron is an alternative way of writing a minus) |
⁰ | U+2070 | **0 | can be combined with ⁰..⁹ |
¹ | U+00B9 | **1 | can be combined with ⁰..⁹ |
² | U+00B2 | **2 | can be combined with ⁰..⁹ |
³ | U+00B3 | **3 | can be combined with ⁰..⁹ |
⁴ | U+2074 | **4 | can be combined with ⁰..⁹ |
⁵ | U+2075 | **5 | can be combined with ⁰..⁹ |
⁶ | U+2076 | **6 | can be combined with ⁰..⁹ |
⁷ | U+2077 | **7 | can be combined with ⁰..⁹ |
⁸ | U+2078 | **8 | can be combined with ⁰..⁹ |
⁹ | U+2079 | **9 | can be combined with ⁰..⁹ |
∅ | U+2205 | set() | (empty set) |
∈ | U+2208 | (elem) | |
∉ | U+2209 | !(elem) | |
∋ | U+220B | (cont) | |
∌ | U+220C | !(cont) | |
⊆ | U+2286 | (<=) | |
⊈ | U+2288 | !(<=) | |
⊂ | U+2282 | (<) | |
⊄ | U+2284 | !(<) | |
⊇ | U+2287 | (>=) | |
⊉ | U+2289 | !(>=) | |
⊃ | U+2283 | (>) | |
⊅ | U+2285 | !(>) | |
∪ | U+222A | (|) | |
∩ | U+2229 | (&) | |
∖ | U+2216 | (-) | |
⊖ | U+2296 | (^) | |
⊍ | U+228D | (.) | |
⊎ | U+228E | (+) |
The atomic operators have U+269B ⚛ ATOM SYMBOL incorporated into them. Their ASCII equivalents are ordinary subroutines, not operators:
my atomicint $x = 42; $x⚛++; # Unicode version atomic-fetch-inc($x); # ASCII version
The ASCII alternatives are as follows:
Symbol | ASCII | Remarks |
---|---|---|
⚛= | atomic-assign | |
⚛ | atomic-fetch | this is the prefix:<⚛> operator |
⚛+= | atomic-add-fetch | |
⚛-= | atomic-sub-fetch | |
⚛−= | atomic-sub-fetch | this operator uses U+2212 minus sign |
++⚛ | atomic-inc-fetch | |
⚛++ | atomic-fetch-inc | |
--⚛ | atomic-dec-fetch | |
⚛-- | atomic-fetch-dec |
This list contains multiple-codepoint operators that require special composition for their ASCII equivalents. Note the codepoints are shown space-separated but should be entered as adjacent codepoints when used.
Symbol | Codepoints | ASCII | Since | Remarks |
---|---|---|---|---|
»=» | U+00BB = U+00BB | >>[=]>> | v6.c | uses ASCII '=' |
«=« | U+00AB = U+00AB | <<[=]<< | v6.c | uses ASCII '=' |
«=» | U+00AB = U+00BB | <<[=]>> | v6.c | uses ASCII '=' |
»=« | U+00BB = U+00AB | >>[=]<< | v6.c | uses ASCII '=' |
Variables in Perl 6
Variables are symbolic names for values or containers. Variable declarations or assignment of values may create a container on the fly. Variable names can start with or without a special character called a sigil, followed optionally by a second special character named twigil and then an identifier.
There are four sigils. The scalar-sigil $, the positional-sigil @, the associative-sigil % and the callable-sigil &.
Sigils provide a link between syntax, the type system and containers. They provide a shortcut for the most common type constraints when declaring variables and serve as markers for string interpolation. The positional-sigil and the associative-sigil provide type constraint that enforce a base type subscripts require to know what methods to dispatch to. The callable-sigil does the same for function calls. The latter also tells the compiler where parentheses for calls can be omitted. The positional and associative-sigil also simplify assignment by flattening by default.
Sigil | Type constraint | Default type | Assignment | Examples |
---|---|---|---|---|
$ | Mu (no type constraint) | Any | item | Int, Str, Array, Hash |
@ | Positional | Array | list | List, Array, Range, Buf |
% | Associative | Hash | list | Hash, Map, Pair |
& | Callable | Callable | item | Sub, Method, Block, Routine |
Examples:
my $square = 9 ** 2; my @array = 1, 2, 3; # Array variable with three elements my %hash = London => 'UK', Berlin => 'Germany';
The type to which the variable will be bound can be set with is in the declaration of the variable. Assuming we have a FailHash class:
class FailHash is Hash { has Bool $!final = False; multi method AT-KEY ( ::?CLASS:D: Str:D \key ){ fail X::OutOfRange.new(:what("Hash key"), :got(key), :range(self.keys)) if $!final && !self.EXISTS-KEY(key); callsame # still not final, so do normal action from Hash } method finalize() { $!final = True } }
One can then define a %h variable of this type using is:
my %h is FailHash = oranges => "round", bananas => "bendy";
And then run the following code:
say %h<oranges>; # OUTPUT: «round» %h.finalize; say %h<cherry>; CATCH { default { put .^name, ': ', .Str } } # OUTPUT: «X::OutOfRange: Hash key out of range. Is: cherry, should be in (oranges bananas)»
For information on variables without sigils, see sigilless variables.
There are two types of variable assignment, item assignment and list assignment. Both use the equal sign = as operator. The syntax of the left-hand side determines whether an = means item or list assignment.
Item assignment places the value from the right-hand side into the variable (container) on the left.
List assignment leaves the choice of what to do to the variable on the left.
For example, Array variables (@ sigil) empty themselves on list assignment and then put all the values from the right-hand side into themselves.
The type of assignment (item or list) is decided by the first context seen in the current expression or declarator:
my $foo = 5; # item assignment say $foo.perl; # OUTPUT: «5» my @bar = 7, 9; # list assignment say @bar.^name; # OUTPUT: «Array» say @bar.perl; # OUTPUT: «[7, 9]» (my $baz) = 11, 13; # list assignment say $baz.^name; # OUTPUT: «List» say $baz.perl; # OUTPUT: «$(11, 13)»
Thus, the behavior of an assignment contained within a list assignment depends on the expression that contains it or declarator that precedes it.
For instance, if the contained assignment is a declarator, item assignment is used, which has tighter precedence than both the comma and the list assignment:
my @array; @array = my $num = 42, "str"; # item assignment: uses declarator for $num say @array.perl; # OUTPUT: «[42, "str"]» (an Array) say $num.perl; # OUTPUT: «42» (a Num)
Similarly, if the internal or contained assignment is an expression that is being used as an initializer for a container declarator, the context of the internal expression determines the assignment type:
my $num; my @array = $num = 42, "str"; # item assignment for $num: uses expression say @array.perl; # OUTPUT: «[42, "str"]» (an Array) say $num.perl; # OUTPUT: «42» (a Num)
The same result would be obtained if @array is declared before the assignment; $num would be still item-assigned, @array list-assigned; the assignment expression is parsed as @array = (($num = 42), "str"), because item assignment has tighter precedence than the comma. However, let's see what happens if the internal variable assignment is in a list context:
my ( @foo, $bar ); @foo = ($bar) = 42, "str"; # list assignment for $bar: uses parentheses say @foo.perl; # OUTPUT: «[(42, "str"),]» (an Array) say $bar.perl; # OUTPUT: «$(42, "str")» (a List)#
In this case, () is the list contextualizer, putting the assignment to $bar in a list context; $bar then decides to include all the items to the right hand side of the = sign; this is still included in a list assignment to @foo, which then becomes an array with a single element, a List.
See operators for more details on precedence.
Using the \ prefix, it's possible to create variables that do not have a sigil:
my \degrees = pi / 180; my \θ = 15 * degrees;
Note that sigilless variable do not have associated containers. This means degrees and θ, above, actually directly represent Nums. To illustrate, try assigning to one after you've defined it:
θ = 3; # Dies with the error "Cannot modify an immutable Num"
Sigilless variables do not enforce context, so they can be used to pass something on as-is:
sub logged(&f, |args) { say('Calling ' ~ &f.name ~ ' with arguments ' ~ args.perl); my \result = f(|args); # ^^^^^^^ not enforcing any context here say(&f.name ~ ' returned ' ~ result.perl); return |result; }
Sigilless variables can also be used for binding. See Binding for more information.
Twigils influence the scoping of a variable; however, they have no influence over whether the primary sigil interpolates. That is, if $a interpolates, so do $^a, $*a, $=a, $?a, $.a, etc. It only depends on the $.
Twigil | Scope |
---|---|
none | Based only on declarator |
* | Dynamic |
? | Compile-time variable |
! | Attribute (class member) |
. | Method (not really a variable) |
< | Index into match object (not really a variable) |
^ | Self-declared formal positional parameter |
: | Self-declared formal named parameter |
= | Pod variables |
~ | The sublanguage seen by the parser at this lexical spot |
This twigil is used for dynamic variables which are looked up through the caller's, not through the outer, scope. Look at the example below.
Note: So far, if you use rakudo perl6, the example below cannot run correctly in the REPL. Please test it by copy-pasting it into a file, then run the file.
my $lexical = 1; my $*dynamic1 = 10; my $*dynamic2 = 100; sub say-all() { say "$lexical, $*dynamic1, $*dynamic2"; } say-all(); # OUTPUT: 1, 10, 100 { my $lexical = 2; my $*dynamic1 = 11; $*dynamic2 = 101; say-all(); # OUTPUT: 1, 11, 101 } say-all(); # OUTPUT: 1, 10, 101
The first time &say-all is called, it prints "1, 10, 100" just as one would expect. The second time though, it prints "1, 11, 101". This is because $lexical isn't looked up in the caller's scope but in the scope &say-all was defined in. The two dynamic variables are looked up in the caller's scope and therefore have the values 11 and 101. The third time &say-all is called $*dynamic1 isn't 11 anymore, but $*dynamic2 is still 101. This stems from the fact that we declared a new dynamic variable $*dynamic1 in the block and did not assign to the old variable as we did with $*dynamic2.
The dynamic variables differ from other variable types in that referring to an undeclared dynamic variable is not a compile time error but a runtime failure, so a dynamic variable can be used undeclared as long as it's checked for definedness or used in a boolean context before using it for anything else:
sub foo() { $*FOO // 'foo'; } say foo; # OUTPUT: «foo» my $*FOO = 'bar'; say foo; # OUTPUT: «bar»
Dynamic variables can have lexical scope when declared with my or package scope when declared with our. Dynamic resolution and resolution through symbol tables introduced with our are two orthogonal issues.
Compile-time variables may be addressed via the ? twigil. They are known to the compiler and may not be modified after being compiled in. A popular example for this is:
say "$?FILE: $?LINE"; # OUTPUT: "hello.p6: 23" # if this is the line 23 of a # file named "hello.p6"
For a list of these special variables, see compile-time variables.
Attributes are variables that exist per instance of a class. They may be directly accessed from within the class via !:
my class Point { has $.x; has $.y; method Str() { "($!x, $!y)" } }
Note how the attributes are declared as $.x and $.y but are still accessed via $!x and $!y. This is because in Perl 6 all attributes are private and can be directly accessed within the class by using $!attribute-name. Perl 6 may automatically generate accessor methods for you though. For more details on objects, classes and their attributes see object orientation.
The . twigil isn't really for variables at all. In fact, something along the lines of
my class Point { has $.x; has $.y; method Str() { "($.x, $.y)" # note that we use the . instead of ! this time } }
just calls the methods x and y on self, which are automatically generated for you because you used the . twigil when the attributes were declared. Note, however, that subclasses may override those methods. If you don't want this to happen, use $!x and $!y instead.
The fact that the . twigil does a method call implies that the following is also possible:
class SaySomething { method a() { say "a"; } method b() { $.a; } } SaySomething.b; # OUTPUT: «a»
For more details on objects, classes and their attributes and methods see object orientation.
The ^ twigil declares a formal positional parameter to blocks or subroutines; that is, variables of the form $^variable are a type of placeholder variable. They may be used in bare blocks to declare formal parameters to that block. So the block in the code
my @powers-of-three = 1,3,9…100; say reduce { $^b - $^a }, 0, |@powers-of-three; # OUTPUT: «61»
has two formal parameters, namely $a and $b. Note that even though $^b appears before $^a in the code, $^a is still the first formal parameter to that block. This is because the placeholder variables are sorted in Unicode order. If you have self-declared a parameter using $^a once, you may refer to it using only $a thereafter.
Although it is possible to use nearly any valid identifier as a placeholder variable, it is recommended to use short names or ones that can be trivially understood in the correct order, to avoid surprise on behalf of the reader.
Normal blocks and subroutines may also make use of placeholder variables but only if they do not have an explicit parameter list.
sub say-it { say $^a; } # valid sub say-it() { say $^a; } # invalid { say $^a; } # valid -> $x, $y, $x { say $^a; } # invalid
Placeholder variables cannot have type constraints or a variable name with a single upper-case letter (this is disallowed to enable catching some Perl5-isms).
The : twigil declares a formal named parameter to a block or subroutine. Variables declared using this form are a type of placeholder variable too. Therefore the same things that apply to variables declared using the ^ twigil also apply here (with the exception that they are not positional and therefore not ordered using Unicode order, of course). For instance:
say { $:add ?? $^a + $^b !! $^a - $^b }( 4, 5 ) :!add # OUTPUT: «-1»
See ^ for more details about placeholder variables.
The = twigil is used to access Pod variables. Every Pod block in the current file can be accessed via a Pod object, such as $=data, $=SYNOPSIS or =UserBlock. That is: a variable with the same name of the desired block and a = twigil.
=begin code =begin Foo ... =end Foo #after that, $=Foo gives you all Foo-Pod-blocks =end code
You may access the Pod tree which contains all Pod structures as a hierarchical data structure through $=pod.
Note that all those $=someBlockName support the Positional and the Associative roles.
The ~ twigil is for referring to sublanguages (called slangs). The following are useful:
$~MAIN | the current main language (e.g. Perl statements) |
$~Quote | the current root of quoting language |
$~Quasi | the current root of quasiquoting language |
$~Regex | the current root of regex language |
$~Trans | the current root of transliteration language |
$~P5Regex | the current root of the Perl 5 regex language |
You augment these languages in your current lexical scope.
use MONKEY-TYPING; augment slang Regex { # derive from $~Regex and then modify $~Regex token backslash:std<\Y> { YY }; }
Most of the time it's enough to create a new variable using the my keyword:
my $amazing-variable = "World"; say "Hello $amazing-variable!"; # OUTPUT: «Hello World!»
However, there are many declarators that change the details of scoping beyond what #Twigils can do.
Declarator | Effect |
---|---|
my | Introduces lexically scoped names |
our | Introduces package-scoped names |
has | Introduces attribute names |
anon | Introduces names that are private to the construct |
state | Introduces lexically scoped but persistent names |
augment | Adds definitions to an existing name |
supersede | Replaces definitions of an existing name |
There are also two prefixes that resemble declarators but act on predefined variables:
Prefix | Effect |
---|---|
temp | Restores a variable's value at the end of scope |
let | Restores a variable's value at the end of scope if the block exits unsuccessfully |
constant | Declares that a container value is not going to change during its lifetime |
Declaring a variable with my gives it lexical scope. This means it only exists within the current block. For example:
{ my $foo = "bar"; say $foo; # OUTPUT: «"bar"» } say $foo; # Exception! "Variable '$foo' is not declared"
This dies because $foo is only defined as long as we are in the same scope.
In order to create more than one variable with a lexical scope in the same sentence surround the variables with parentheses:
my ( $foo, $bar );
see also Declaring a list of variables with lexical or package scope.
Additionally, lexical scoping means that variables can be temporarily redefined in a new scope:
my $location = "outside"; sub outer-location { # Not redefined: say $location; } outer-location; # OUTPUT: «outside» sub in-building { my $location = "inside"; say $location; } in-building; # OUTPUT: «inside» outer-location; # OUTPUT: «outside»
If a variable has been redefined, any code that referenced the outer variable will continue to reference the outer variable. So here, &outer-location still prints the outer $location:
sub new-location { my $location = "nowhere"; outer-location; } new-location; # OUTPUT: «outside»
To make new-location() print nowhere, make $location a dynamic variable using the * twigil. This twigil makes the compiler look up the symbol in the calling scope instead of the outer scope after trying the local scope.
my is the default scope for subroutines, so my sub x() {} and sub x() {} do exactly the same thing.
our variables work just like my variables, except that they also introduce an alias into the symbol table.
module M { our $Var; # $Var available here } # Available as $M::Var here.
In order to create more than one variable with package scope, at the same time, surround the variables with parentheses:
our ( $foo, $bar );
see also the section on declaring a list of variables with lexical or package scope.
It is possible to scope more than one variable at a time, but both my and our require variables to be placed into parentheses:
my (@a, $s, %h); # same as my @a; my $s; my %h; our (@aa, $ss, %hh); # same as our @aa; our $ss; our %hh;
This can be used in conjunction with destructuring assignment. Any assignment to such a list will take the number of elements provided in the left list and assign corresponding values from the right list to them. Any missing elements are left will result in undefined values according to the type of the variables.
my (Str $a, Str $b, Int $c) = <a b>; say [$a, $b, $c].perl; # OUTPUT: «["a", "b", Int]»
To destructure a list into a single value, create a list literal with one element by using ($var,). When used with a variable declarator, providing parentheses around a single variable is sufficient.
sub f { 1,2,3 }; my ($a) = f; say $a.perl; # OUTPUT: «1»
To skip elements in the list use the anonymous state variable $.
my ($,$a,$,%h) = ('a', 'b', [1,2,3], {:1th}); say [$a, %h].perl; # OUTPUT: «["b", {:th(1)}]»
has scopes attributes to instances of a class or role, and methods to classes or roles. has is implied for methods, so has method x() {} and method x() {} do the same thing.
See object orientation for more documentation and some examples.
The anon declarator prevents a symbol from getting installed in the lexical scope, the method table and everywhere else.
For example, you can use it to declare subroutines which know their own name, but still aren't installed in a scope:
my %operations = half => anon sub half($x) { $x / 2 }, square => anon sub square($x) { $x * $x }, ; say %operations<square>.name; # square say %operations<square>(8); # 64
Since it is a declarator, it can be applied anywhere anything is declared, for instance for classes or even sigilless variables.
say anon class þ {}; # OUTPUT: «(þ)» say anon sub þ { 42 }; # OUTPUT: «&þ»
Since these symbols are not installed in the scope, they can't be used by name. They are useful, however, if they need to be assigned to an external variable and they need to know their own name, but this can be retrieved using introspection.
my $anon-class = anon class { has $.bar; method equal( ::?CLASS $foo ) { return $foo.bar == $.bar; } }; say $anon-class.new( :3bar).equal( $anon-class.new( :3bar ) );
state declares lexically scoped variables, just like my. However, initialization happens exactly once the first time the initialization is encountered in the normal flow of execution. Thus, state variables will retain their value across multiple executions of the enclosing block or routine.
Therefore, the subroutine
sub a { state @x; state $l = 'A'; @x.push($l++); }; say a for 1..6;
will continue to increment $l and append it to @x each time it is called. So it will output:
[A] [A B] [A B C] [A B C D] [A B C D E] [A B C D E F]
Since they have a lexical scope, they are tied to the block in which they are declared.
sub foo () { for 0..1 { state $foo = 1; say $foo++; } }; foo; # OUTPUT: «12» foo; # OUTPUT: «12»
In this case, a new state variable is created every time the block that runs the for loop is entered, which is why the state variable is reset in every call to foo.
This works per "clone" of the containing code object, as in this example:
({ state $i = 1; $i++.say; } xx 3).map: {$_(), $_()}; # says 1 then 2 thrice
Note that this is not a thread-safe construct when the same clone of the same block is run by multiple threads. Also remember that methods only have one clone per class, not per object.
As with my, a declaration of multiple state variables must be placed in parentheses which can be omitted for a single variable.
Many operators come with implicit binding which can lead to actions at a distance.
Use .clone or coercion to create a new container that can be bound to.
my @a; my @a-cloned; sub f() { state $i; $i++; @a\ .push: "k$i" => $i; @a-cloned.push: "k$i" => $i.clone; }; f for 1..3; say @a; # OUTPUT: «[k1 => 3 k2 => 3 k3 => 3]» say @a-cloned; # OUTPUT: «[k1 => 1 k2 => 2 k3 => 3]»
State variables are shared between all threads. The result can be unexpected.
sub code(){ state $i = 0; say ++$i; $i }; await start { loop { last if code() >= 5 } }, start { loop { last if code() >= 5 } }; # OUTPUT: «1234435» # OUTPUT: «21345» # many other more or less odd variations can be produced
In addition to explicitly declared named state variables, $ can be used as an anonymous state variable without an explicit state declaration.
say "1-a 2-b 3-c".subst(:g, /\d/, {<one two three>[$++]}); # OUTPUT: «one-a two-b three-c»
Furthermore, state variables can be used outside of subroutines. You could, for example, use $ in a one-liner to number the lines in a file.
perl6 -ne 'say ++$ ~ " $_"' example.txt
Each reference to $ within a lexical scope is in effect a separate variable.
perl6 -e '{ say ++$; say $++ } for ^5' # OUTPUT: «1021324354»
That is why, if you need to reference the same $ variable (or, for that matter, any of the other anon state variables @ and %) more than once, a possible solution is to bind another variable to it, although in this example it would be more straightforward to just declare state $x and not use the magical/anonymous $ variable:
sub foo () { my $x := $; $x++; say $x; $x = $x + 1; } foo() for ^3; # OUTPUT: «135»
In general, it is better style to declare a named state variable in case you have to refer to it several times.
Note that the implicit state declarator is only applied to the variable itself, not the expression that may contain an initializer. If the initializer has to be called exactly once, the state declarator has to be provided.
for ^3 { $ = .say } # OUTPUT: «012» for ^3 { state $ = .say } # OUTPUT: «0»
Similar to the $ variable, there is also a Positional anonymous state variable @.
sub foo($x) { say (@).push($x); } foo($_) for ^3; # OUTPUT: «[0] # [0 1] # [0 1 2]»
The @ here is parenthesized in order to disambiguate the expression from a class member variable named @.push. Indexed access doesn't require this disambiguation but you will need to copy the value in order to do anything useful with it.
sub foo($x) { my $v = @; $v[$x] = $x; say $v; } foo($_) for ^3; # OUTPUT: «[0] # [0 1] # [0 1 2]»
As with $, each mention of @ in a scope introduces a new anonymous array.
In addition, there's an Associative anonymous state variable %.
sub foo($x) { say (%).push($x => $x); } foo($_) for ^3; # OUTPUT: «{0 => 0} # {0 => 0, 1 => 1} # {0 => 0, 1 => 1, 2 => 2}»
The same caveat about disambiguation applies. As you may expect, indexed access is also possible (with copying to make it useful).
sub foo($x) { my $v = %; $v{$x} = $x; say $v; } foo($_) for ^3; # OUTPUT: «{0 => 0} # {0 => 0, 1 => 1} # {0 => 0, 1 => 1, 2 => 2}»
As with the other anonymous state variables, each mention of % within a given scope will effectively introduce a separate variable.
With augment, you can add attributes and methods to existing classes and grammars, provided you activated the MONKEY-TYPING pragma first.
Since classes are usually our scoped, and thus global, this means modifying global state, which is strongly discouraged. For almost all situations, there are better solutions.
# don't do this use MONKEY-TYPING; augment class Int { method is-answer { self == 42 } } say 42.is-answer; # OUTPUT: «True»
(In this case, the better solution would be to use a function).
Like my, temp restores the old value of a variable at the end of its scope. However, temp does not create a new variable.
my $in = 0; # temp will "entangle" the global variable with the call stack # that keeps the calls at the bottom in order. sub f(*@c) { (temp $in)++; "<f>\n" ~ @c».indent($in).join("\n") ~ (+@c ?? "\n" !! "") ~ '</f>' }; sub g(*@c) { (temp $in)++; "<g>\n" ~ @c».indent($in).join("\n") ~ (+@c ?? "\n" !! "") ~ "</g>" }; print g(g(f(g()), g(), f())); # OUTPUT: «<g> # <g> # <f> # <g> # </g> # </f> # <g> # </g> # <f> # </f> # </g> # </g>»
Restores the previous value if the block exits unsuccessfully. A successful exit means the block returned a defined value or a list.
my $answer = 42; { let $answer = 84; die if not Bool.pick; CATCH { default { say "it's been reset :(" } } say "we made it 84 sticks!"; } say $answer;
In the above case, if the Bool.pick returns true, the answer will stay as 84 because the block returns a defined value (say returns True). Otherwise the die statement will cause the block to exit unsuccessfully, resetting the answer to 42.
The constant prefix declares that a container value is not going to change during its lifetime.
constant $pi2 = pi * 2; $pi2 = 6; # OUTPUT: «(exit code 1) Cannot assign to an immutable value
The value is assigned at compile time. Please check the section on constants in the Terms page for additional information.
Variables have a type constraint via the container they are bound to, which goes between the declarator and the variable name. The default type constraint is Mu. You can also use the trait of to set a type constraint.
my Int $x = 42; $x = 'a string'; CATCH { default { put .^name, ': ', .Str } } # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $x; expected Int but got Str ("a string")»
If a scalar variable has a type constraint but no initial value, it's initialized with the type object of the default value of the container it's bound to.
my Int $x; say $x.^name; # OUTPUT: «Int» say $x.defined; # OUTPUT: «False»
Scalar variables without an explicit type constraint are typed as Mu but default to the Any type object.
Variables with the @ sigil are initialized with an empty Array; variables with the % sigil are initialized with an empty Hash.
The default value of a variable can be set with the is default trait, and re-applied by assigning Nil to it:
my Real $product is default(1); say $product; # OUTPUT: «1» $product *= 5; say $product; # OUTPUT: «5» $product = Nil; say $product; # OUTPUT: «1»
To force all variables to have a definiteness constraint, use the pragma use variables :D. The pragma is lexically scoped and can be switched off with use variables :_.
use variables :D; my Int $i; # OUTPUT: «===SORRY!=== Error while compiling <tmp>Variable definition of type Int:D (implicit :D by pragma) requires an initializer ... my Int $i = 1; # that works { use variables :_; my Int $i; } # switch it off in this block
Note that assigning Nil will revert the variable to its default value, which is often not a definite value and as such would fail the constraint:
use variables :D; my Int $x = 42; $x = Nil; # OUTPUT: «Type check failed in assignment to $x; expected type Int:D cannot be itself…»
As the name suggests, this pragma applies only to variables. To effect the same behavior on parameters, use the use parameters :D pragma (currently NYI in Rakudo).
Perl 6 attempts to use long, descriptive names for special variables. There are only three special variables that are extra short.
There are three special variables that are available in every block:
Variable | Meaning |
---|---|
$_ | topic variable |
$/ | regex match |
$! | exceptions |
$_ is the topic variable. It's the default parameter for blocks that do not have an explicit signature, so constructs like for @array { ... } and given $var { ... } bind the value or values of the variable to $_ by invoking the block.
for <a b c> { say $_ } # sets $_ to 'a', 'b' and 'c' in turn say $_ for <a b c>; # same, even though it's not a block given 'a' { say $_ } # sets $_ to 'a' say $_ given 'a'; # same, even though it's not a block
CATCH blocks set $_ to the exception that was caught. The ~~ smartmatch operator sets $_ on the right-hand side expression to the value of the left-hand side.
Calling a method on $_ can be shortened by leaving off the variable name:
.say; # same as $_.say
m/regex/ and /regex/ regex matches and s/regex/subst/ substitutions work on $_:
say "Looking for strings with non-alphabetic characters..."; for <ab:c d$e fgh ij*> { .say if m/<-alpha>/; } # OUTPUT: «Looking for strings with non-alphabetic characters... # ab:c # d$e # ij*»
$/ is the match variable. It stores the result of the last Regex match and so usually contains objects of type Match.
'abc 12' ~~ /\w+/; # sets $/ to a Match object say $/.Str; # OUTPUT: «abc»
The Grammar.parse method also sets the caller's $/ to the resulting Match object. For the following code:
use XML::Grammar; # zef install XML XML::Grammar.parse("<p>some text</p>"); say $/; # OUTPUT: «「<p>some text</p>」 # root => 「<p>some text</p>」 # name => 「p」 # child => 「some text」 # text => 「some text」 # textnode => 「some text」 # element => 「<p>some text</p>」 # name => 「p」 # child => 「some text」 # text => 「some text」 # textnode => 「some text」»
Prior to the 6.d version, you could use $() shortcut to get the ast value from $/ Match if that value is truthy, or the stringification of the Match object otherwise.
'test' ~~ /.../; # 6.c language only: say $(); # OUTPUT: «tes»; $/.make: 'McTesty'; say $(); # OUTPUT: «McTesty»;
This (non-)feature has been deprecated as of version 6.d.
$/ can have positional attributes if the Regex had capture-groups in it, which are just formed with parentheses.
'abbbbbcdddddeffg' ~~ / a (b+) c (d+ef+) g /; say $/[0]; # OUTPUT: «「bbbbb」» say $/[1]; # OUTPUT: «「dddddeff」»
These can also be accessed by the shortcuts $0, $1, $2, etc.
say $0; # OUTPUT: «「bbbbb」» say $1; # OUTPUT: «「dddddeff」»
To get all of the positional attributes, you can use $/.list or @$/. Before 6.d, you can also use the @() shortcut (no spaces inside the parentheses).
say @$/.join; # OUTPUT: «bbbbbdddddeff» # 6.c language only: say @().join; # OUTPUT: «bbbbbdddddeff»
This magic behavior of @() has been deprecated as of 6.d
$/ can have named attributes if the Regex had named capture-groups in it, or if the Regex called out to another Regex.
'I... see?' ~~ / \w+ $<punctuation>=[ <-[\w\s]>+ ] \s* $<final-word> = [ \w+ . ] /; say $/<punctuation>; # OUTPUT: «「....」» say $/<final-word>; # OUTPUT: «「see?」»
These can also be accessed by the shortcut $<named>.
say $<punctuation>; # OUTPUT: «「....」» say $<final-word>; # OUTPUT: «「see?」»
To get all of the named attributes, you can use $/.hash or %$/. Before 6.d language, you could also use the %() shortcut (no spaces inside the parentheses).
say %$/.join; # OUTPUT: «"punctuation ....final-word see?"» # 6.c language only say %().join; # OUTPUT: «"punctuation ....final-word see?"»
This behavior has been deprecated as of the 6.d version.
$! is the error variable. If a try block or statement prefix catches an exception, that exception is stored in $!. If no exception was caught, $! is set to the Any type object.
Note that CATCH blocks do not set $!. Rather, they set $_ inside the block to the caught exception.
All compile time variables have a question mark as part of the twigil. Being compile time they cannot be changed at runtime, however they are valuable in order to introspect the program. The most common compile time variables are the following:
$?FILE | Which file am I in? |
$?LINE | Which line am I at? [indexed from 1] |
::?CLASS | Which class am I in? |
%?RESOURCES | The files associated with the "Distribution" of the current compilation unit. |
$?FILE and $?LINE are also available from CallFrame as the file and line methods, respectively.
The following compile time variables allow for a deeper introspection:
$?PACKAGE | Which package am I in? |
$?MODULE | Which module am I in? |
$?CLASS | Which class am I in? (as variable) |
$?ROLE | Which role am I in? (as variable) |
$?TABSTOP | How many spaces is a tab in a heredoc or virtual margin? |
$?NL | What a vertical newline "\n" means: LF, CR or CRLF |
$?DISTRIBUTION | The Distribution of the current compilation unit. |
With particular regard to the $?NL, see the newline pragma.
These variables are Rakudo specific, with all the corresponding caveats:
$?BITS | Number of bits of the platform the program is being compiled |
The compile time variable &?ROUTINE provides introspection about which routine the program is actually within. It returns an instance of Sub attached to the current routine. It does support the method .name to obtain the name of the called routine, as well as .signature and others method related to Sub:
sub awesome-sub { say &?ROUTINE.name } awesome-sub # OUTPUT: awesome-sub
It also allows also for recursion:
my $counter = 10; sub do-work { say 'Calling myself other ' ~ $counter-- ~ ' times'; &?ROUTINE() if ( $counter > 0 ); } do-work;
The special compile variable ?&BLOCK behaves similarly to ?&ROUTINE but it allows to introspect a single block of code. It holds a Sub and allows for recursion within the same block:
for '.' { .Str.say when !.IO.d; .IO.dir()».&?BLOCK when .IO.d # lets recurse a little! }
$?DISTRIBUTION provides access to the Distribution of the current compilation unit. This gives module authors a way to reference other files in the distribution by their original relative path names, or to view the metadata (via the .meta method), without needing to know the underlying file structure (such as how CompUnit::Repository::Installation changes the file layout on installation).
unit module MyFoo; sub module-version { say "MyFoo is version:"; say $?DISTRIBUTION.meta<ver>; } sub module-source { say "MyFoo source code:"; say $?DISTRIBUTION.content('lib/MyFoo.pm6'); }
All dynamically scoped variables have the * twigil, and their name is (conventionally) written in uppercase.
These variables are related to the arguments passed to a script.
An IO::ArgFiles (an empty subclass of IO::CatHandle) that uses @*ARGS as source files, if it contains any files, or $*IN otherwise. When $*IN is used, its :nl-in, :chomp, :encoding, and :bin will be set on the IO::ArgFiles object.
As of the 6.d version, $*ARGFILES inside sub MAIN is always set to $*IN, even when @*ARGS is not empty. See the class documentation for examples and more context.
@*ARGS is an array of Str containing the arguments from the command line.
A dynamic variable available inside any custom ARGS-TO-CAPTURE subroutine that can be used to perform the default argument parsing. Takes the same parameters as are expected of the custom ARGS-TO-CAPTURE subroutine.
A dynamic variable available inside any custom GENERATE-USAGE subroutine that can be used to perform the default usage message creation. Takes the same parameters as are expected of the custom GENERATE-USAGE subroutine.
For more information about special filehandles please see also the Input and Output page and the IO::Special class. IO::Handle contains several examples of using $*IN for reading standard input.
$*IN Standard input filehandle, AKA STDIN.
$*OUT Standard output filehandle, AKA STDOUT.
$*ERR Standard error filehandle, AKA STDERR.
These dynamic variables contain information related to the environment the script or program is running in.
Operating system environment variables. Numeric values are provided as allomorphs.
This variable holds information about modules installed/loaded.
$*INIT-INSTANT is an Instant object representing program startup time. In particular, this is when the core code starts up, so the value of $*INIT-INSTANT may be a few milliseconds earlier than INIT now or even BEGIN now executed in your program.
$*TZ contains the system's local time zone offset, as the number of seconds from GMT.
It contains the Current Working Directory.
$*KERNEL contains a Kernel instance, the .gist of it being the current running kernel.
say $*KERNEL; # OUTPUT: «linux (4.4.92.31.default)»
This object (of type Distro) contains information about the current operating system distribution. For instance:
say "Some sort of Windows" if $*DISTRO.is-win;
$*DISTRO.name takes a set of values that depend on the operating system. These names will vary with version and implementation, so you should double-check and test before using them in your programs; since these names are implementation defined and not in the specification, they could vary and change at any moment.
The $*DISTRO gist is displayed by using say:
say $*DISTRO; # OUTPUT: «debian (9.stretch)»
This shows additional information on the operating system and version it's using, but as a matter of fact, this variable contains information which is useful to create portable programs, such as the path separator:
say $*DISTRO.perl; # OUTPUT: «Distro.new(release => "42.3", is-win => Bool::False, # path-sep => ":", name => "opensuse", # auth => "https://www.opensuse.org/", version => v42.3, # signature => Blob, desc => "2018-12-13T08:50:59.213619+01:00")»
This variable contains the current virtual machine running the code, as well as additional information on the inner workings of aforementioned VM.
say $*VM.precomp-ext, " ", $*VM.precomp-target; # OUTPUT: «moarvm mbc»
These two methods, for instance, will show the extension used in the precompiled bytecode scripts and the target used. This is what is found in the Moar Virtual Machine, but it could also vary with version and implementation. Other VM, such as Java, will show different values for them. $*VM.config includes all configuration values used to create the virtual machine, e.g.
say $*VM.config<versionmajor>, ".", $*VM.config<versionminor>; # OUTPUT: «2018.11»
which are the version of the virtual machine, generally the same one as the one used in the interpreter and the overall Perl 6 environment.
This object of the Perl class contains information on the current implementation of the Perl 6 language:
say $*PERL.compiler.version; # OUTPUT: «v2018.11.52.g.06156.a.7.ca»
but its gist includes the name of the language, followed by the major version of the compiler:
say $*PERL; # OUTPUT: «Perl 6 (6.d)»
It stringifies to Perl 6:
$*PERL.put; # OUTPUT: «Perl 6»
Object containing an integer describing the current Process IDentifier (operating system dependent).
This contains the path to the current executable as it was entered on the command line, or -e if perl was invoked with the -e flag.
Contains the location (in the form of an IO::Path object) of the Perl 6 program being executed.
This is a Callable that contains the code that will be executed when doing an exit() call. Intended to be used in situations where Perl 6 is embedded in another language runtime (such as Inline::Perl6 in Perl 5).
Contains an IO::Path absolute path of the perl executable that is currently running.
Contains the name of the Perl executable that is currently running. (e.g. perl6-p, perl6-m). Favor $*EXECUTABLE over this one, since it's not guaranteed that the perl executable is in PATH.
This is the default usage message generated from the signatures of MAIN subs available from inside sub MAIN and sub USAGE. The variable is read-only.
An Allomorph with information about the user that is running the program. It will evaluate to the username if treated as a string and the numeric user id if treated as a number.
An Allomorph with the primary group of the user who is running the program. It will evaluate to the groupname only if treated as a string and the numeric group id if treated as a number.
Contains information about the "home drive" of the user that is running the program on Windows. It's not defined in other operating systems.
Contains information about the path to the user directory that is running the program on Windows. It's not defined in other operating systems.
Contains an IO::Path object representing the "home directory" of the user that is running the program. Uses %*ENV<HOME> if set.
On Windows, uses %*ENV<HOMEDRIVE> ~ %*ENV<HOMEPATH>. If the home directory cannot be determined, it will be Any.
Contains the appropriate IO::Spec sub-class for the platform that the program is running on. This is a higher-level class for the operating system; it will return Unix, for instance, in the case of Linux (in the form of the IO::Spec class used for the current implementation).
This is an IO::Path object representing the "system temporary directory" as determined by .tmpdir IO::Spec::* method.
Contains a Thread object representing the currently executing thread.
This is a ThreadPoolScheduler object representing the current default scheduler.
By default this imposes a maximum of 64 threads on the methods .hyper, .race and other thread-pool classes that use that scheduler such as Promises or Supplys. This is, however, implementation, dependent and might be subject to change. To change the maximum number of threads, you can either set the environment variable RAKUDO_MAX_THREADS before running perl6 or create a scoped copy with the default changed before using them:
my $*SCHEDULER = ThreadPoolScheduler.new( max_threads => 128 );
This behavior is not tested in the spec tests and is subject to change.
The current Telemetry::Sampler used for making snapshots of system state. Only available if Telemetry has been loaded.
This is a Str object that holds value of the auto-generated USAGE message.
sub MAIN($a, :$b, UInt :$ehehe) { say $*USAGE; # OUTPUT: «Usage: perl6.pl6 [-a=<Int>] [-b=<Str>] [--<opts>=...]» }
It is accessible only inside of MAIN sub.
These variables affect the behavior of certain functions, and in some cases its value can be changed during runtime.
This is a Collation object that can be used to configure Unicode collation levels.
Variable used by the =~= operator, and any operations that depend on it, to decide if two values are approximately equal. Defaults to 1e-15.
Affects the number of bytes read by default by IO::Handle.read. Its default value is 65536.
It is helpful to know our naming conventions in order to understand what codes do directly. However, there is not yet (and might never be) an official list of; still, we list several conventions that are widely held.
Subs and methods from the built-ins library try to have single-word names when a good one could be found. In cases where there are two or more words making up a name, they are separated by a "-".
Compounds are treated as a single word, thus substr, subbuf, and deepmap (just like we write "starfish", not "star fish" in English).
Subs and methods that are automatically called for you at special times are written in uppercase. This includes the MAIN sub, the AT-POS and related methods for implementing container types, along with BUILD and DESTROY.
Type names are camel case, except for native types, which are lowercase. For the exception, you can remember it by: they are stored in a more compact way, so they names look smaller too.
Built-in dynamic variables and compile-time variables are always uppercase, such like $*OUT, $?FILE.
Methods from the MOP and other internals use "_" to separate multiple words, such like add_method.
Preview of upcoming new language features available for user evaluation
During Perl 6 development, new features are often made available for users as experimental before their design is completed. Eventually these features may be made part of the Perl 6 specification. To use these features, one uses the experimental pragma in program source code, for example, like this:
use experimental :macros;
These are the features that, for the time being, are experimental.
Pack is a feature that allows binary serialization of general data structures, and is inherited from Perl's pack. The pack order creates a Buf by packing data structures in a certain way given by a packing string with the options shown in the description of unpack. You turn it on by inserting this pragma at the beginning of your program:
use experimental :pack;
For instance, we can pack numbers interpreting them as hexadecimal (H) with the pattern repeating until there are no more elements (*):
use experimental :pack; say pack("H*", "414243").contents;# OUTPUT: «(65 66 67)»
There is a corresponding unpack routine that does exactly the opposite.
use experimental :pack; my $buf=Buf.new(65,66,67); say $buf.unpack("H*"); # OUTPUT: «414243»
Not all of the symbols above are guaranteed to be implemented, and the roadmap does not include a fixed date for getting out of that stage.
Please see also documentation for pack and unpack in the Blob page.
Macros are code-generating routines, that generate code in compile time, before the program is executed. In Perl 6 its use is still experimental and it needs to be turned on via the pragma
use experimental :macros;
Macro processing happens during parsing time. A macro generates an abstract syntax tree, which is grafted into the program syntax tree. quasi is the routine that performs this task.
macro does-nothing() { quasi {} }; does-nothing; # OUTPUT: «»
Macros are a kind of routine, so they can take arguments in exactly the same way, and act also in almost the same way.
macro is-mighty( $who ) { quasi { "$who is mighty!"} }; say is-mighty "Freija"; # OUTPUT: « "Freija" is mighty!»
"Almost" accounts for the fact that the argument is inserted as a literal, including the quotes. Please note that we can also eliminate the parentheses for a macro call, following the same rules as a routine. You can use the unquoting construct {{{}}} to get rid of this kind of thing:
macro is-mighty( $who ) { quasi { {{{$who}}} ~ " is mighty!"} }; say is-mighty "Freija"; # OUTPUT: «Freija is mighty!»
Since macro expansion happens at parse time, care must be taken when using external variables in them:
use experimental :macros; my $called; macro called() { $called++; quasi { "Called" } }; say called() ~ " $called times"; say called() ~ " $called times"; # OUTPUT: «Called 2 timesCalled 2 times»
Since macros are expanded at parse time, $called will be the result when runtime starts, which is already 2, as printed. Initializing $called with 0, however, will make this print Called 0 times since that initialization is run after the parse phase, when the macros are expanded.
Macros are terribly useful when complicated, computed initializations need to be done. However, they are still in the experimental nursery for a good reason. Although the features shown above are not very likely to change, anything, even their very presence, might change at any one time depending in necessities, so it would be best to keep them away from production code. Meanwhile, taking a look at this article by Masak as well as 007, a new macro language, might provide a glimpse into the things to come.
The following pragma:
use experimental :cached;
turns on the is cached trait, which stores the result of a routine call, returning the same value if called with the same arguments.
It can be used when heavy calculations are involved, as in this sample that uses amicable numbers, taken from the 2018 Advent Calendar:
use experimental :cached; sub aliquot-parts( $number ) is cached { (^$number).grep: $number %% *; } sub infix:<amic>( $m, $n ) { $m == aliquot-parts($n).sum && $n == aliquot-parts($m).sum; } # Taken from https://en.wikipedia.org/wiki/Amicable_numbers my @numbers = [2620, 2924, 5020, 5564, 6232, 6368, 66928, 66992]; say "Aliquot parts of $_ are ", aliquot-parts $_ for @numbers; for @numbers X @numbers -> @pair { say "@pair[0] and @pair[1] are ", @pair[0] amic @pair[1]??" "!!"not ", "amicable"; }
This code caches the computation of the aliquot parts, so that when the amic operator is called, it's only computed once; as a matter of fact, the first loop which prints these aliquot parts will be the only one that actually perform the computation.
See also the description of the trait for additional information and examples.
Native integer
class int is Int { }
This class is used to represent integers that are native to the compiler, operating system and architecture the interpreter is compiled in.
More information in the native types page as well as in the section on native numerics.
Modules and applications used to debug Perl 6 programs
There are at least two useful debuggers available for Rakudo, the Perl 6 compiler:
A command-line debugger frontend for Rakudo. This module installs the perl6-debug-m command-line utility, and is bundled with the Rakudo Star distributions. Please check its repository for instructions and a tutorial.
Simple tracing and debugging support for Perl 6 grammars.
Please see the documentation for these programs for further information.
Historically others have existed and others are likely to be written in the future, check the Perl 6 Modules website.
There are also environment variables that can be set to aid debugging various aspects of your program. See Perl 6 Environment Variables and Running rakudo from the command line for more information.
The trace pragma causes the program to print out step-by-step which lines get executed:
use trace; sub foo { say "hi" } foo; # OUTPUT: # 2 (/tmp/script.p6 line 2) # sub foo { say "hi" } # 5 (/tmp/script.p6 line 3) # foo # 3 (/tmp/script.p6 line 2) # say "hi" # hi
The Tiny Data Dumper: This function takes the input list of variables and notes them (on $*ERR) in an easy to read format, along with the name of the variable. Thus,
my $a = 42; my %hash = "a" => 1, "b" => 2, "c" => 3; dd %hash, $a; #`( OUTPUT: Hash %hash = {:a(1), :b(2), :c(3)} Int $a = 42 )
prints to the standard error stream the variables passed as argument.
Please note that dd will ignore named parameters. You can use a Capture or Array to force it to dump everything passed to it.
dd \((:a(1), :b(2)), :c(3)); dd [(:a(1), :b(2)), :c(3)];
If you don't specify any parameters at all, it will just print the type and name of the current subroutine / method to the standard error stream:
sub a { dd }; a # OUTPUT: «sub a()»
This can be handy as a cheap trace function.
The Backtrace class gets the current call stack, and can return it as a string:
my $trace = Backtrace.new; sub inner { say ~Backtrace.new; } sub outer { inner; } outer; # OUTPUT: # perl6 /tmp/script.p6 # in sub inner at /tmp/script.p6 line 2 # in sub outer at /tmp/script.p6 line 3 # in block <unit> at /tmp/script.p6 line 4
p6doc - the Perl 6 pod reader
Program p6doc is a command-line-interface (CLI) program that reads Perl 6 pod from installed modules' source code, in contrast to running perl6 --doc=MODULE programfile which reads Perl 6 pod from the named source file.
Note that p6doc may not be installed automatically depending upon how you installed Rakudo Perl 6. To install it use zef:
zef install p6doc
p6doc [switches] [arguments]
With no switches or arguments, p6doc lists its help to $*OUT (stdout):
You want to maintain the index? To build an index for 'p6doc -f' p6doc build To list the index keys p6doc list To display module name(s) containing key p6doc lookup To show where the index file lives p6doc path-to-index What documentation do you want to read? Examples: p6doc Str p6doc Str.split p6doc faq p6doc path/to/file You can list some top level documents: p6doc -l You can also look up specific method/routine/sub definitions: p6doc -f hyper p6doc -f Array.push You can bypass the pager and print straight to stdout: p6doc -n Str
The text output can be captured and converted to other forms if desired.
If you want to use ANSI escape sequences, which will apply boldface and other enhancements to the output, you will have to set POD_TO_TEXT_ANSI, which is unset by default
export POD_TO_TEXT_ANSI=1
Currently p6doc can only extract embedded Perl 6 pod from installed module source files (as listed in a distribution's META6.json file). It is planned to add a feature for p6doc (in conjunction with META6.json changes) to extract all Perl 6 pod in files included with the installed distribution.
The variables you can declare to alter its behavior or gather additional information.
The behavior of Rakudo, the Perl 6 interpreter, can be tweaked by a (growing) number of environment variables; this section attempts to document all those currently in use. They are interpreter specific in all cases, except where some use conventional names such as PATH.
The underlying virtual machine is also sensitive to a series of environment variables; they are listed in this wiki page.
RAKUDOLIB, PERL6LIB
RAKUDOLIB and PERL6LIB append a comma-delimited list of paths to the search list for modules. RAKUDOLIB is evaluated first.
RAKUDO_MODULE_DEBUG
If true, causes the module loader to print debugging information to standard error.
PERL6_EXCEPTIONS_HANDLER
If present, the print_exception routine will use a class of that name to process the exception for output. Rakudo currently ships with Exceptions::JSON (invoked by setting this variable to JSON), to override the default output. NOTE: this env var was added in version 6.d. Early implementation has been available in Rakudo compiler as of version 2018.08, and before that it was available as RAKUDO_EXCEPTIONS_HANDLER.
RAKUDO_NO_DEPRECATIONS
If true, suppresses deprecation warnings triggered by the is DEPRECATED trait.
RAKUDO_DEPRECATIONS_FATAL
If true, deprecation warnings become thrown exceptions.
RAKUDO_VERBOSE_STACKFRAME
Displays source code in stack frames surrounded by the specified number of lines of context; for instance RAKUDO_VERBOSE_STACKFRAME = 1 will use one context line.
RAKUDO_BACKTRACE_SETTING
Controls whether .setting files are included in backtraces.
RAKUDO_PREFIX
When this is set, Rakudo will look for the standard repositories (perl, vendor, site) in the specified directory. This is intended as an escape hatch for build-time bootstrapping issues, where Rakudo may be built as an unprivileged user without write access to the runtime paths in NQP's config.
RAKUDO_PRECOMP_DIST, RAKUDO_PRECOMP_LOADING RAKUDO_PRECOMP_WITH:
These are internal variables for passing serialized state to precompilation jobs in child processes. Please do not set them manually.
RAKUDO_LOG_PRECOMP
If set to 1, diagnostic information about the precompilation process is emitted.
RAKUDO_LINE_EDITOR
This specifies the preferred line editor to use; valid values are Readline, Linenoise, and none. A value of none is useful if you want to avoid the recommendation message upon REPL startup.
RAKUDO_DISABLE_MULTILINE
If set to 1, will disable multiline input for the REPL.
RAKUDO_HIST
This specifies the location of the history file used by the line editor; the default is ~/.perl6/rakudo-history.
RAKUDO_DEFAULT_READ_ELEMS
Is the default number of characters to read on an IO::Handle, defaults to 65536 (aka 64K).
RAKUDO_ERROR_COLOR
Controls whether to emit ANSI codes for error highlighting. Defaults to true if unset, except on Windows.
RAKUDO_MAX_THREADS
Indicates the maximum number of threads used by default when creating a ThreadPoolScheduler. Defaults to 64.
TMPDIR, TEMP, TMP:
The IO::Spec::Unix.tmpdir method will return $TMPDIR if it points to a directory with full access permissions for the current user, with a fallback default of '/tmp'.
IO::Spec::Cygwin and IO::Spec::Win32 use more Windows-appropriate lists which also include the %TEMP% and %TMP% environment variables.
PATH, Path
The IO::Spec::Unix.path method splits $PATH as a shell would; i.e. as a colon-separated list. IO::Spec::Cygwin inherits this from IO::Spec::Unix. IO::Spec::Win32.path will read the first defined of either %PATH% or %Path% as a semicolon-delimited list.
RAKUDO_SNAPPER
Indicates the period in which the telemetry snapper will take a snapshot. Defaults to .1 for 10 snapshots per second.
Initial version written by the Rakudo contributors, see the CREDITS file.
The initial version of this manual page was written by Reini Urban, Moritz Lenz and the Rakudo contributors.
Abstract representation of a piece of source code
class AST { }
An AST or Abstract Syntax Tree is a partially processed representation of a program. ASTs are return values of the quasi quoting construct, and are typically used within macros to generate code that is inserted in the calling location of the macro.
There is no API defined for ASTs yet. Hopefully that will emerge as part of the work on macros.
Thing/object
class Any is Mu {}
While Mu is the root of the Perl 6 class hierarchy, Any is the class that serves as a default base class for new classes, and as the base class for most built-in classes.
Since Perl 6 intentionally confuses items and single-element lists, most methods in Any are also present on class List, and coerce to List or a list-like type.
Defined as:
multi method ACCEPTS(Any:D: Mu $other)
Usage:
EXPR.ACCEPTS(EXPR);
Returns True if $other === self (i.e. it checks object identity).
Many built-in types override this for more specific comparisons.
Defined as:
method any(--> Junction:D)
Interprets the invocant as a list and creates an any-Junction from it.
say so 2 == <1 2 3>.any; # OUTPUT: «True» say so 5 == <1 2 3>.any; # OUTPUT: «False»
Defined as:
method all(--> Junction:D)
Interprets the invocant as a list and creates an all-Junction from it.
say so 1 < <2 3 4>.all; # OUTPUT: «True» say so 3 < <2 3 4>.all; # OUTPUT: «False»
Defined as:
method one(--> Junction:D)
Interprets the invocant as a list and creates a one-Junction from it.
say so 1 == (1, 2, 3).one; # OUTPUT: «True» say so 1 == (1, 2, 1).one; # OUTPUT: «False»
Defined as:
method none(--> Junction:D)
Interprets the invocant as a list and creates a none-Junction from it.
say so 1 == (1, 2, 3).none; # OUTPUT: «False» say so 4 == (1, 2, 3).none; # OUTPUT: «True»
Defined as:
multi method list(Any:U: --> List) multi method list(Any:D \SELF: --> List)
Applies the infix , operator to the invocant and returns the resulting List:
say 42.list.^name; # OUTPUT: «List» say 42.list.elems; # OUTPUT: «1»
Subclasses of Any may choose to return any core type that does the Positional role from .list. Use .List to coerce specifically to List.
@ can also be used as a list or Positional contextualizer:
my $not-a-list-yet = $[1,2,3]; say $not-a-list-yet.perl; # OUTPUT: «$[1, 2, 3]» my @maybe-a-list = @$not-a-list-yet; say @maybe-a-list.^name; # OUTPUT: «Array»
In the first case, the list is itemized. @ as a prefix puts the initial scalar in a list context by calling .list and turning it into an Array.
Defined as:
method push(|values --> Positional:D)
The method push is defined for undefined invocants and allows for autovivifying undefined to an empty Array, unless the undefined value implements Positional already. The argument provided will then be pushed into the newly created Array.
my %h; say %h<a>; # OUTPUT: «(Any)» <-- Undefined %h<a>.push(1); # .push on Any say %h; # OUTPUT: «{a => [1]}» <-- Note the Array
Defined as:
multi sub reverse(*@list --> Seq:D) multi method reverse(List:D: --> Seq:D)
Returns a Seq with the same elements in reverse order.
Note that reverse always refers to reversing elements of a list; to reverse the characters in a string, use flip.
Examples:
say <hello world!>.reverse; # OUTPUT: «(world! hello)» say reverse ^10; # OUTPUT: «(9 8 7 6 5 4 3 2 1 0)»
Defined as:
multi method sort() multi method sort(&custom-routine-to-use)
Sorts iterables with cmp or given code object and returns a new Seq. Optionally, takes a Callable as a positional parameter, specifying how to sort.
Examples:
say <b c a>.sort; # OUTPUT: «(a b c)» say 'bca'.comb.sort.join; # OUTPUT: «abc» say 'bca'.comb.sort({$^b cmp $^a}).join; # OUTPUT: «cba» say '231'.comb.sort(&infix:«<=>»).join; # OUTPUT: «123»
Defined as:
multi method map(Hash:D \hash) multi method map(Iterable:D \iterable) multi method map(|c) multi method map(\SELF: █; :$label, :$item) multi sub map(&code, +values)
map will iterate over the invocant and apply the number of positional parameters of the code object from the invocant per call. The returned values of the code object will become elements of the returned Seq.
The :$label and :$item are useful only internally, since for loops get converted to maps. The :$label takes an existing Label to label the .map's loop with and :$item controls whether the iteration will occur over (SELF,) (if :$item is set) or SELF.
In sub form, will apply the code block to the values, which will be used as invocant.
The form with \c, Iterable:D \iterable and Hash:D \hash as signatures will fail with X::Cannot::Map, and are mainly meant to catch common traps.
Defined as:
method deepmap(&block --> List) is nodal
deepmap will apply &block to each element and return a new List with the return values of &block, unless the element does the Iterable role. For those elements deepmap will descend recursively into the sublist.
say [[1,2,3],[[4,5],6,7]].deepmap(* + 1); # OUTPUT: «[[2 3 4] [[5 6] 7 8]]»
In the case of Associatives, it will be applied to its values:
{ what => "is", this => "thing", a => <real list> }.deepmap( *.flip ).say # OUTPUT: «{a => (laer tsil), this => gniht, what => si}»
Defined as:
method duckmap(&block) is rw is nodal
duckmap will apply &block on each element that behaves in such a way that &block can be applied. If it fails, it will descend recursively if possible, or otherwise return the item without any transformation. It will act on values if the object is Associative.
<a b c d e f g>.duckmap(-> $_ where <c d e>.any { .uc }).say; # OUTPUT: «(a b C D E f g)» (('d', 'e'), 'f').duckmap(-> $_ where <e f>.any { .uc }).say; # OUTPUT: «((d E) F)» { first => ('d', 'e'), second => 'f'}.duckmap(-> $_ where <e f>.any { .uc }).say; # OUTPUT: «{first => (d E), second => F}»
In the first case, it is applied to c, d and e which are the ones that meet the conditions for the block ({ .uc }) to be applied; the rest are returned as is.
In the second case, the first item is a list that does not meet the condition, so it's visited; that flat list will behave in the same way as the first one. In this case:
say [[1,2,3],[[4,5],6,7]].duckmap( *² ); # OUTPUT: «[9 9]»
You can square anything as long as it behaves like a number. In this case, there are two arrays with 3 elements each; these arrays will be converted into the number 3 and squared. In the next case, however
say [[1,2,3],[[4,5],6.1,7.2]].duckmap( -> Rat $_ { $_²} ); # OUTPUT: «[[1 2 3] [[4 5] 37.21 51.84]]»
3-item lists are not Rat, so it descends recursively, but eventually only applies the operation to those that walk (or slither, as the case may be) like a Rat.
Although on the surface (and name), duckmap might look similar to deepmap, the latter is applied recursively regardless of the type of the item.
Defined as:
method nodemap(&block --> List) is nodal
nodemap will apply &block to each element and return a new List with the return values of &block. In contrast to deepmap it will not descend recursively into sublists if it finds elements which do the Iterable role.
say [[1,2,3], [[4,5],6,7], 7].nodemap(*+1); # OUTPUT: «(4, 4, 8)» say [[2, 3], [4, [5, 6]]]».nodemap(*+1) # OUTPUT: «((3 4) (5 3))»
The examples above would have produced the exact same results if we had used map instead of nodemap. The difference between the two lies in the fact that map flattens out slips while nodemap doesn't.
say [[2,3], [[4,5],6,7], 7].nodemap({.elems == 1 ?? $_ !! slip}); # OUTPUT: «(() () 7)» say [[2,3], [[4,5],6,7], 7].map({.elems == 1 ?? $_ !! slip}); # OUTPUT: «(7)»
When applied to Associatives, it will act on the values:
{ what => "is", this => "thing" }.nodemap( *.flip ).say; # OUTPUT: «{this => gniht, what => si}»
Defined as:
method flat() is nodal
Interprets the invocant as a list, flattens non-containerized Iterables into a flat list, and returns that list. Keep in mind Map and Hash types are Iterable and so will be flattened into lists of pairs.
say ((1, 2), (3), %(:42a)); # OUTPUT: «((1 2) 3 {a => 42})» say ((1, 2), (3), %(:42a)).flat; # OUTPUT: «(1 2 3 a => 42)»
Note that Arrays containerize their elements by default, and so flat will not flatten them. You can use hyper method call to call .List method on all the inner Iterables and so de-containerize them, so that flat can flatten them:
say [[1, 2, 3], [(4, 5), 6, 7]] .flat; # OUTPUT: «([1 2 3] [(4 5) 6 7])» say [[1, 2, 3], [(4, 5), 6, 7]]».List.flat; # OUTPUT: «(1 2 3 4 5 6 7)»
For more fine-tuned options, see deepmap, duckmap, and signature destructuring
Defined as:
method eager() is nodal
Interprets the invocant as a List, evaluates it eagerly, and returns that List.
my $range = 1..5; say $range; # OUTPUT: «1..5» say $range.eager; # OUTPUT: «(1 2 3 4 5)»
Defined as:
multi method elems(Any:U: --> 1) multi method elems(Any:D:)
Interprets the invocant as a list, and returns the number of elements in the list.
say 42.elems; # OUTPUT: «1» say <a b c>.elems; # OUTPUT: «3» say Whatever.elems ; # OUTPUT: «1»
It will also return 1 for classes.
multi method end(Any:U: --> 0) multi method end(Any:D:)
Interprets the invocant as a list, and returns the last index of that list.
say 6.end; # OUTPUT: «0» say <a b c>.end; # OUTPUT: «2»
Defined as:
multi method pairup(Any:U:) multi method pairup(Any:D:)
Returns an empty Seq if the invocant is a type object
Range.pairup.say; # OUTPUT: «()»
Interprets the invocant as a list, and constructs a list of pairs from it, in the same way that assignment to a Hash does. That is, it takes two consecutive elements and constructs a pair from them, unless the item in the key position already is a pair (in which case the pair is passed through, and the next list item, if any, is considered to be a key again). It returns a Seq of Pairs.
say (a => 1, 'b', 'c').pairup.perl; # OUTPUT: «(:a(1), :b("c")).Seq»
Defined as:
multi item(\x) multi item(|c) multi item(Mu $a)
Forces given object to be evaluated in item context and returns the value of it.
say item([1,2,3]).perl; # OUTPUT: «$[1, 2, 3]» say item( %( apple => 10 ) ).perl; # OUTPUT: «${:apple(10)}» say item("abc").perl; # OUTPUT: «"abc"»
You can also use $ as item contextualizer.
say $[1,2,3].perl; # OUTPUT: «$[1, 2, 3]» say $("abc").perl; # OUTPUT: «"abc"»
Defined as:
method Array(--> Array:D) is nodal
Coerces the invocant to an Array.
Defined as:
method List(--> List:D) is nodal
Coerces the invocant to List, using the list method.
Defined as
multi method serial()
This method is Rakudo specific, and is not included in the Perl 6 spec.
The method returns the self-reference to the instance itself:
my $b; # defaults to Any say $b.serial.^name; # OUTPUT: «Any» say $b.^name; # OUTPUT: «Any» my $breakfast = 'food'; $breakfast.serial.say; # OUTPUT: «food»
This is apparently a no-op, as exemplified by the third example above. However, in HyperSeqs and RaceSeqs it returns a serialized Seq, so it can be considered the opposite of the hyper/race methods. As such, it ensures that we are in serial list-processing mode, as opposed to the autothreading mode of those methods.
Defined as:
multi method Hash( --> Hash:D)
Coerces the invocant to Hash.
Defined as:
multi method hash(Any:U:) multi method hash(Any:D:)
When called on a type object, returns an empty Hash. On instances, it is equivalent to assigning the invocant to a %-sigiled variable and returning that.
Subclasses of Any may choose to return any core type that does the Associative role from .hash. Use .Hash to coerce specifically to Hash.
my $d; # $d is Any say $d.hash; # OUTPUT: {} my %m is Map = a => 42, b => 666; say %m.hash; # Map.new((a => 42, b => 666)) say %m.Hash; # {a => 42, b => 666}
Defined as:
method Slip(--> Slip:D) is nodal
Coerces the invocant to Slip.
Defined as:
method Map(--> Map:D) is nodal
Coerces the invocant to Map.
Defined as:
method Bag(--> Bag:D) is nodal
Coerces the invocant to Bag, whereby Positionals are treated as lists of values.
Defined as:
method BagHash(--> BagHash:D) is nodal
Coerces the invocant to BagHash, whereby Positionals are treated as lists of values.
Defined as:
method Set(--> Set:D) is nodal
Coerces the invocant to Set, whereby Positionals are treated as lists of values.
Defined as:
method SetHash(--> SetHash:D) is nodal
Coerces the invocant to SetHash, whereby Positionals are treated as lists of values.
Defined as:
method Mix(--> Mix:D) is nodal
Coerces the invocant to Mix, whereby Positionals are treated as lists of values.
Defined as:
method MixHash(--> MixHash:D) is nodal
Coerces the invocant to MixHash, whereby Positionals are treated as lists of values.
Defined as:
method Supply(--> Supply:D) is nodal
First, it coerces the invocant to a list by applying its .list method, and then to a Supply.
Defined as:
multi method min() multi method min(&by) multi sub min(+args, :&by!) multi sub min(+args)
Coerces the invocant to Iterable and returns the numerically smallest element. In sub form, the invocant is passed as an argument.
If a Callable positional argument is provided, each value is passed into the filter, and its return value is compared instead of the original value. The original value is still the one returned from min.
say (1,7,3).min(); # OUTPUT:«1» say (1,7,3).min({1/$_}); # OUTPUT:«7» say min(1,7,3); # OUTPUT: «1» say min(1,7,3,:by( { 1/$_ } )); # OUTPUT: «7»
Defined as:
multi method max() multi method max(&by) multi sub max(+args, :&by!) multi sub max(+args)
Coerces the invocant to Iterable and returns the numerically largest element.
If a Callable positional argument is provided, each value is passed into the filter, and the return value is compared instead of the original value. The original value is still the one returned from max.
say (1,7,3).max(); # OUTPUT:«7» say (1,7,3).max({1/$_}); # OUTPUT:«1» say max(1,7,3,:by( { 1/$_ } )); # OUTPUT: «1» say max(1,7,3); # OUTPUT: «7»
Defined as:
multi method minmax() multi method minmax(&by) multi sub minmax(+args, :&by!) multi sub minmax(+args)
Returns a Range from the smallest to the largest element.
If a Callable positional argument is provided, each value is passed into the filter, and its return value is compared instead of the original value. The original values are still used in the returned Range.
say (1,7,3).minmax(); # OUTPUT:«1..7» say (1,7,3).minmax({-$_}); # OUTPUT:«7..1» say minmax(1,7,3); # OUTPUT: «1..7» say minmax(1,7,3,:by( -* )); # OUTPUT: «7..1»
Defined as:
multi method minpairs(Any:D:)
Calls .pairs and returns a Seq with all of the Pairs with minimum values, as judged by the cmp operator:
<a b c a b c>.minpairs.perl.put; # OUTPUT: «(0 => "a", 3 => "a").Seq» %(:42a, :75b).minpairs.perl.put; # OUTPUT: «(:a(42),).Seq»
Defined as:
multi method maxpairs(Any:D:)
Calls .pairs and returns a Seq with all of the Pairs with maximum values, as judged by the cmp operator:
<a b c a b c>.maxpairs.perl.put; # OUTPUT: «(2 => "c", 5 => "c").Seq» %(:42a, :75b).maxpairs.perl.put; # OUTPUT: «(:b(75),).Seq»
Defined as:
multi method keys(Any:U: --> List) multi method keys(Any:D: --> List)
For defined Any returns its keys after calling list on it, otherwise calls list and returns it.
my $setty = Set(<Þor Oðin Freija>); say $setty.keys; # OUTPUT: «(Þor Oðin Freija)»
See also List.keys.
Trying the same on a class will return an empty list, since most of them don't really have keys.
Defined as:
method flatmap(&block, :$label)
DEPRECATION NOTICE: This method is deprecated in 6.d and will be removed in 6.e. Use .map followed by .flat instead.
Applies map to every element with the block and Label used as an argument and flattens out the result using .flat.
say "aabbccc".comb.Mix.flatmap: "→ " ~ *; # OUTPUT: «(→ b␉2 → c␉3 → a␉2)»
In this case, the elements of the Mix are itemized to key␉value, and then mapped and flattened. Same result as
say "aabbccc".comb.Mix.map( "→ " ~ * ).flat
Which is why it is deprecated in 6.d and will be eventually eliminated in 6.e.
Defined as:
multi method roll(--> Any) multi method roll($n --> Seq)
Coerces the invocant to a list by applying its .list method and uses List.roll on it.
my Mix $m = ("þ" xx 3, "ð" xx 4, "ß" xx 5).Mix; say $m.roll; # OUTPUT: «ð» say $m.roll(5); # OUTPUT: «(ß ß þ ß þ)»
$m, in this case, is converted into a list and then a (weighted in this case) dice is rolled on it. See also List.roll for more information.
Defined as:
multi method iterator(Any:)
Returns the object as an iterator after converting it to a list. This is the function called from the for statement.
.say for 3; # OUTPUT: «3»
Most subclasses redefine this method for optimization, so it's mostly types that do not actually iterate the ones that actually use this implementation.
Defined as:
multi method pick(--> Any) multi method pick($n --> Seq)
Coerces the invocant to a list by applying its .list method and uses List.pick on it.
my Range $rg = 'α'..'ω'; say $rg.pick(3); # OUTPUT: «(β α σ)»
Defined as:
multi method skip() multi method skip(Whatever) multi method skip(Callable:D $w) multi method skip(Int() $n)
Creates a Seq from 1-item list's iterator and uses Seq.skip on it, please check that document for real use cases; calling skip without argument is equivalent to skip(1).
Calling it with Whatever will return an empty iterator:
say <1 2 3>.skip(*); # OUTPUT: «()»
The multi that uses a Callable is intended mainly to be used this way:
say <1 2 3>.skip(*-1); # OUTPUT: «(3)»
Instead of throwing away the first $n elements, it throws away everything but the elements indicated by the WhateverCode, in this case all but the last one.
Defined as:
multi method prepend(--> Array) multi method prepend(@values --> Array)
Called with no arguments on an empty variable, it initializes it as an empty Array; if called with arguments, it creates an array and then applies Array.prepend on it.
my $a; say $a.prepend; # OUTPUT: «[]» say $a; # OUTPUT: «[]» my $b; say $b.prepend(1,2,3); # OUTPUT: «[1 2 3]»
Defined as:
multi method unshift(--> Array) multi method unshift(@values --> Array)
Initializes Any variable as empty Array and calls Array.unshift on it.
my $a; say $a.unshift; # OUTPUT: «[]» say $a; # OUTPUT: «[]» my $b; say $b.unshift([1,2,3]); # OUTPUT: «[[1 2 3]]»
Defined as:
multi method first(Bool:D $t) multi method first(Regex:D $test, :$end, *%a) multi method first(Callable:D $test, :$end, *%a is copy) multi method first(Mu $test, :$end, *%a) multi method first(:$end, *%a) multi sub first(Bool:D $t, |) multi sub first(Mu $test, +values, *%a)
In general, coerces the invocant to a list by applying its .list method and uses List.first on it.
However, this is a multi with different signatures, which are implemented with (slightly) different behavior, although using it as a subroutine is equivalent to using it as a method with the second argument as the object.
For starters, using a Bool as the argument will always return a Failure. The form that uses a $test will return the first element that smartmatches it, starting from the end if :end is used.
say (3..33).first; # OUTPUT: «3» say (3..33).first(:end); # OUTPUT: «33» say (⅓,⅔…30).first( 0xF ); # OUTPUT: «15» say first 0xF, (⅓,⅔…30); # OUTPUT: «15» say (3..33).first( /\d\d/ ); # OUTPUT: «10»
The third and fourth examples use the Mu $test forms which smartmatches and returns the first element that does. The last example uses as a test a regex for numbers with two figures, and thus the first that meets that criterion is number 10. This last form uses the Callable multi:
say (⅓,⅔…30).first( * %% 11, :end, :kv ); # OUTPUT: «(65 22)»
Besides, the search for first will start from the :end and returns the set of key/values in a list; the key in this case is simply the position it occupies in the Seq. The :kv argument, which is part of the %a argument in the definitions above, modifies what first returns, providing it as a flattened list of keys and values; for a listy object, the key will always be the index.
From version 6.d, the test can also be a Junction:
say (⅓,⅔…30).first( 3 | 33, :kv ); # OUTPUT: «(8 3)»
Defined as:
multi method unique() multi method unique( :&as!, :&with! ) multi method unique( :&as! ) multi method unique( :&with! )
Creates a sequence of unique elements either of the object or of values in the case it's called as a sub.
<1 2 2 3 3 3>.unique.say; # OUTPUT: «(1 2 3)» say unique <1 2 2 3 3 3>; # OUTPUT: «(1 2 3)»
The :as and :with parameters receive functions that are used for transforming the item before checking equality, and for checking equality, since by default the === operator is used:
("1", 1, "1 ", 2).unique( as => Int, with => &[==] ).say; #OUTPUT: «(1 2)»
Please see unique for additional examples that use its sub form.
Defined as:
multi method repeated() multi method repeated( :&as!, :&with! ) multi method repeated( :&as! ) multi method repeated( :&with! )
Similarly to unique, finds repeated elements in values (as a routine) or in the object, using the :as associative argument as a normalizing function and :with as equality function.
<1 -1 2 -2 3>.repeated(:as(&abs),:with(&[==])).say; # OUTPUT: «(-1 -2)» (3+3i, 3+2i, 2+1i).repeated(as => *.re).say; # OUTPUT: «(3+2i)»
It returns the last repeated element before normalization, as shown in the example above. See repeated for more examples that use its sub form.
Defined as:
multi method squish( :&as!, :&with = &[===] ) multi method squish( :&with = &[===] )
Similar to .repeated, returns the sequence of first elements of contiguous sequences of equal elements, after normalization by the function :as, if present, and using as an equality operator the :with argument or === by default.
"aabbccddaa".comb.squish.say; # OUTPUT: «(a b c d a)» "aABbccdDaa".comb.squish( :as(&lc) ).say; # OUTPUT: «(a B c d a)» (3+2i,3+3i,4+0i).squish( as => *.re, with => &[==]).put; #OUTPUT: «3+2i 4+0i»
As shown in the last example, a sequence can contain a single element. See squish for additional sub examples.
Defined as:
method permutations(|c)
Coerces the invocant to a list by applying its .list method and uses List.permutations on it.
say <a b c>.permutations; # OUTPUT: «((a b c) (a c b) (b a c) (b c a) (c a b) (c b a))» say set(1,2).permutations; # OUTPUT: «((2 => True 1 => True) (1 => True 2 => True))»
Defined as
method join($separator = '') is nodal
Converts the object to a list by calling self.list, and calls .join on the list. Can take a separator, which is an empty string by default.
(1..3).join.say; # OUTPUT: «123» <a b c>.join("❧").put; # OUTPUT: «a❧b❧c»
Defined as:
multi method categorize() multi method categorize(Whatever) multi method categorize($test, :$into!, :&as) multi method categorize($test, :&as) multi sub categorize($test, +items, :$into!, *%named ) multi sub categorize($test, +items, *%named )
The two first forms fail with an error message.
In its simplest form, it uses a $test whose result will be used as a key; the values of the key will be an array of the elements that produced that key as a result of the test.
say (1..13).categorize( * %% 3); say categorize( * %% 3, 1..13) # OUTPUT: «{False => [1 2 4 5 7 8 10 11 13], True => [3 6 9 12]}»
The :as argument will normalize before categorizing
say categorize( * %% 3, -5..5, as => &abs ) # OUTPUT: «{False => [5 4 2 1 1 2 4 5], True => [3 0 3]}»
The $into associative argument can be used to put the result instead of returning a new Hash
my %leap-years; my @years = (2002..2009).map( { Date.new( $_~"-01-01" ) } ); @years.categorize( *.is-leap-year , into => %leap-years ); say %leap-years # OUTPUT: # «{ False # => [2002-01-01 2003-01-01 2005-01-01 2006-01-01 2007-01-01 2009-01-01], # True => [2004-01-01 2008-01-01]}»
The function used to categorize can return an array indicating all possible bins their argument can be put into:
sub divisible-by( Int $n --> Array(Seq) ) { gather { for <2 3 5 7> { take $_ if $n %% $_; } } } say (3..13).categorize( &divisible-by ); # OUTPUT: # «{2 => [4 6 8 10 12], 3 => [3 6 9 12], 5 => [5 10], 7 => [7]}»
In this case, every number in the range is classified in as many bins as it can be divided by.
Defined as:
multi method classify() multi method classify(Whatever) multi method classify($test, :$into!, :&as) multi method classify($test, :&as) multi sub classify($test, +items, :$into!, *%named ) multi sub classify($test, +items, *%named )
The two first forms will fail. The rest include a $test, which is a function that will return a scalar for every input; these will be used as keys of a hash whose values will be arrays with the elements that output that key for the test function.
my @years = (2003..2008).map( { Date.new( $_~"-01-01" ) } ); @years.classify( *.is-leap-year , into => my %leap-years ); say %leap-years; # OUTPUT: «{False => [2003-01-01 2005-01-01 2006-01-01 2007-01-01], # True => [2004-01-01 2008-01-01]}»
Similarly to .categorize, elements can be normalized by the Callable passed with the :as argument, and it can use the :into named argument to pass a Hash the results will be classified into; in the example above, it's defined on the fly.
From version 6.d, .classify will also work with Junctions.
Defined as:
multi method reduce(Any:U: & --> Nil) multi method reduce(Any:D: &with) multi sub reduce (&with, +list)
Applying it to a class will always produce Nil. Applies its argument (or first argument, in case it's a sub) as an operator to all the elements in the object (or second argument), producing a single result. The argument must be an infix operator or take, in any case, two positional arguments.
(1..13).reduce( &[*] ).say; # OUTPUT: «6227020800»
Defined as:
multi method produce(Any:U: & --> Nil) multi method produce(Any:D: &with) multi sub produce (&with, +list)
This is similar to reduce, but returns a list with the accumulated values instead of a single result.
<10 5 3>.reduce( &[*] ).say ; # OUTPUT: «150» <10 5 3>.produce( &[*] ).say; # OUTPUT: «(10 50 150)»
The last element of the produced list would be the output produced by the .reduce method.
If it's a class, it will simply return Nil.
Defined as:
multi method pairs(Any:U:) multi method pairs(Any:D:)
Returns an empty List if the invocant is a type object:
say Num.pairs; # OUTPUT: «()»
For a value object, it converts the invocant to a List via the list method and returns the result of List.pairs on it.
<1 2 2 3 3 3>.Bag.pairs.say;# OUTPUT: «(1 => 1 3 => 3 2 => 2)»
In this case, every element (with weight) in a bag is converted to a pair.
Defined as:
multi method antipairs(Any:U:) multi method antipairs(Any:D:)
Returns an empty List if the invocant is a type object
Range.antipairs.say; # OUTPUT: «()»
If it's a value object, it returns the inverted list of pairs after converting it to a list of pairs; the values will become keys and the other way round.
%(s => 1, t=> 2, u => 3).antipairs.say ;# OUTPUT: «(2 => t 1 => s 3 => u)»
Defined as:
multi method invert(Any:U:) multi method invert(Any:D:)
Applied to a type object will return an empty list; applied to an object will convert it to a list and apply List.invert to it, that is, interchange key with value in every Pair. The resulting list needs to be a list of Pairs.
"aaabbcccc".comb.Bag.invert.say; # OUTPUT: «(4 => c 3 => a 2 => b)»
In this case, a Bag can be converted to a list of Pairs. If the result of converting the object to a list is not a list of pairs, the method will fail.
Defined as:
multi method kv(Any:U:) multi method kv(Any:D:) multi sub kv($x)
Returns an empty List if the invocant is a type object:
Sub.kv.say ;# OUTPUT: «()»
It calls list on the invocant for value objects and returns the result of List.kv on it as a list where keys and values will be ordered and contiguous
<1 2 3>.kv.say; # OUTPUT: «(0 1 1 2 2 3)»
In the case of Positionals, the indices will be considered keys.
Defined as:
method toggle(Any:D: *@conditions where .all ~~ Callable:D, Bool :$off --> Seq:D)
Iterates over the invocant, producing a Seq, toggling whether the received values are propagated to the result on and off, depending on the results of calling Callables in @conditions:
say (1..15).toggle(* < 5, * > 10, * < 15); # OUTPUT: «(1 2 3 4 11 12 13 14)» say (1..15).toggle(:off, * > 2, * < 5, * > 10, * < 15); # OUTPUT: «(3 4 11 12 13 14)»
Imagine a switch that's either on or off (True or False), and values are produced if it's on. By default, the initial state of that switch is in "on" position, unless :$off is set to a true value, in which case the initial state will be "off".
A Callable from the head of @conditions is taken (if any are available) and it becomes the current tester. Each value from the original sequence is tested by calling the tester Callable with that value. The state of our imaginary switch is set to the return value from the tester: if it's truthy, set switch to "on", otherwise set it to "off".
Whenever the switch is toggled (i.e. switched from "off" to "on" or from "on" to "off"), the current tester Callable is replaced by the next Callable in @conditions, if available, which will be used to test any further values. If no more tester Callables are available, the switch will remain in its current state until the end of iteration.
# our original sequence of elements: say list ^10; # OUTPUT: «(0 1 2 3 4 5 6 7 8 9)» # toggled result: say ^10 .toggle: * < 4, * %% 2, &is-prime; # OUTPUT: «(0 1 2 3 6 7)» # First tester Callable is `* < 4` and initial state of switch is "on". # As we iterate over our original sequence: # 0 => 0 < 4 === True switch is on, value gets into result, switch is # toggled, so we keep using the same Callable: # 1 => 1 < 4 === True same # 2 => 2 < 4 === True same # 3 => 3 < 4 === True same # 4 => 4 < 4 === False switch is now off, "4" does not make it into the # result. In addition, our switch got toggled, so # we're switching to the next tester Callable # 5 => 5 %% 2 === False switch is still off, keep trying to find a value # 6 => 6 %% 2 === True switch is now on, take "6" into result. The switch # toggled, so we'll use the next tester Callable # 7 => is-prime(7) === True switch is still on, take value and keep going # 8 => is-prime(8) === False switch is now off, "8" does not make it into # the result. The switch got toggled, but we # don't have any more tester Callables, so it # will remain off for the rest of the sequence.
Since the toggle of the switch's state loads the next tester Callable, setting :$off to a True value affects when first tester is discarded:
# our original sequence of elements: say <0 1 2>; # OUTPUT: «(0 1 2)» # toggled result: say <0 1 2>.toggle: * > 1; # OUTPUT: «()» # First tester Callable is `* > 1` and initial state of switch is "on". # As we iterate over our original sequence: # 0 => 0 > 1 === False switch is off, "0" does not make it into result. # In addition, switch got toggled, so we change the # tester Callable, and since we don't have any more # of them, the switch will remain "off" until the end
The behavior changes when :off is used:
# our original sequence of elements: say <0 1 2>; # OUTPUT: «(0 1 2)» # toggled result: say <0 1 2>.toggle: :off, * > 1; # OUTPUT: «(2)» # First tester Callable is `* > 1` and initial state of switch is "off". # As we iterate over our original sequence: # 0 => 0 > 1 === False switch is off, "0" does not make it into result. # The switch did NOT get toggled this time, so we # keep using our current tester Callable # 1 => 1 > 1 === False same # 2 => 2 > 1 === True switch is on, "2" makes it into the result
Defined as:
multi method head(Any:D:) is raw multi method head(Any:D: Callable:D $w) multi method head(Any:D: $n)
Returns either the first element in the object, or the first $n if that's used.
"aaabbc".comb.Mix.head.put; # OUTPUT: «c␉1» "aaabbc".comb.Mix.head.put; # OUTPUT: «a␉3» say ^10 .head(5); # OUTPUT: «(0 1 2 3 4)» say ^∞ .head(5); # OUTPUT: «(0 1 2 3 4)» say ^10 .head; # OUTPUT: «0» say ^∞ .head; # OUTPUT: «0»
In the first two cases, the results are different since there's no defined order in Mixes. In the other cases, it returns a Seq. A Callable can be used to return all but the last elements:
say (^10).head( * - 3 );# OUTPUT: «(0 1 2 3 4 5 6)»
Defined as:
multi method tail() is raw multi method tail($n)
Returns the last or the list of the $n last elements of an object. $n can be a Callable, usually a WhateverCode, which will be used to get all but the first n elements of the object.
say (^12).reverse.tail ; # OUTPUT: «0» say (^12).reverse.tail(3); # OUTPUT: «(2 1 0)» say (^12).reverse.tail(*-7); # OUTPUT: «(4 3 2 1 0)»
Defined as:
multi method tree(Any:U:) multi method tree(Any:D:) multi method tree(Any:D: Whatever ) multi method tree(Any:D: Int(Cool) $count) multi method tree(Any:D: @ [&first, *@rest]) multi method tree(Any:D: &first, *@rest)
Returns the class if it's undefined or if it's not Iterable, returns the result of applying the tree method to its invocant otherwise.
say Any.tree; # OUTPUT: «Any»
.tree has different prototypes for Iterable elements.
my @floors = ( 'A', ('B','C', ('E','F','G'))); say @floors.tree(1).flat.elems; # OUTPUT: «6» say @floors.tree(2).flat.elems; # OUTPUT: «2» say @floors.tree( *.join("-"),*.join("—"),*.join("|"));# OUTPUT: «A-B—C—E|F|G»
With a number, it iteratively applies tree to every element in the lower level; the first instance will apply .tree(0) to every element in the array, and likewise for the next example.
The second prototype applies the Whatever code passed as arguments to every level in turn; the first argument will go to level 1 and so on. tree can, thus, be a great way to process complex all levels of complex, multi-level, data structures.
Defined as:
method nl-out(--> Str)
Returns Str with the value of "\n". See IO::Handle.nl-out for the details.
Num.nl-out.print; # OUTPUT: «» Whatever.nl-out.print;# OUTPUT: «» 33.nl-out.print; # OUTPUT: «»
Defined as:
method combinations(|c)
Coerces the invocant to a list by applying its .list method and uses List.combinations on it.
say (^3).combinations; # OUTPUT: «(() (0) (1) (2) (0 1) (0 2) (1 2) (0 1 2))»
Defined as:
method grep(Mu $matcher, :$k, :$kv, :$p, :$v --> Seq)
Coerces the invocant to a list by applying its .list method and uses List.grep on it.
Based on $matcher value can be either ((Any)) or empty List.
my $a; say $a.grep({ True }); # OUTPUT: «((Any))» say $a.grep({ $_ }); # OUTPUT: «()»
Defined as:
multi method append(Any:U \SELF: |values --> Array)
In the case the instance is not a positional-thing, it instantiates it as a new Array, otherwise clone the current instance. After that, it appends the values passed as arguments to the array obtained calling Array.append on it.
my $a; say $a.append; # OUTPUT: «[]» my $b; say $b.append((1,2,3)); # OUTPUT: «[1 2 3]»
Defined as:
multi method values(Any:U:) multi method values(Any:D:)
Will return an empty list for undefined or class arguments, and the object converted to a list otherwise.
say (1..3).values; # OUTPUT: «(1 2 3)» say List.values; # OUTPUT: «()»
Defined as:
method collate()
Collate sorts taking into account Unicode grapheme characteristics; that is, sorting more or less as one would expect instead of using the order in which their codepoints appear. collate will behave this way if the object it is applied to is Iterable.
say ('a', 'Z').sort; # (Z a) say ('a', 'Z').collate; # (a Z) say <ä a o ö>.collate; # (a ä o ö) my %hash = 'aa' => 'value', 'Za' => 'second'; say %hash.collate; # (aa => value Za => second);
This method is affected by the $*COLLATION variable, which configures the four collation levels. While the Primary, Secondary and Tertiary mean different things for different scripts, for the Latin script used in English they mostly correspond with Primary being Alphabetic, Secondary being Diacritics and Tertiary being Case.
In the example below you can see how when we disable tertiary collation which in Latin script generally is for case, and also disable quaternary which breaks any ties by checking the codepoint values of the strings, we get Same back for A and a:
$*COLLATION.set(:quaternary(False), :tertiary(False)); say 'a' coll 'A'; #OUTPUT: «Same» say ('a','A').collate == ('A','a').collate; # OUTPUT: «True»
The variable affects the coll operator as shown as well as this method.
Defined as:
method cache()
Provides a List representation of the object itself, calling the method list on the instance.
Defined as:
multi method batch(Int:D $batch) multi method batch(Int:D :$elems!)
Coerces the invocant to a list by applying its .list method and uses List.batch on it.
Defined as:
multi method rotor(Any:D: Int:D $batch, :$partial) multi method rotor(Any:D: *@cycle, :$partial)
Groups the elements of the object in lists of $batch elements.
say (3..9).rotor(3); # OUTPUT: «((3 4 5) (6 7 8))»
With the :partial named argument, it will also include lists that do not get to be the $batch size:
say (3..10).rotor(3, :partial); # OUTPUT: «((3 4 5) (6 7 8) (9 10))»
.rotor can be called with an array of integers and pairs, which will be applied in turn. While integers will establish the batch size, as above, Pairs will use the key as batch size and the value as number of elements to skip if it's positive, or overlap if it's negative.
say (3..11).rotor(3, 2 => 1, 3 => -2, :partial); # OUTPUT: «((3 4 5) (6 7) (9 10 11) (10 11))»
In this case, the first batch (ruled by an integer) has 3 elements; the second one has 2 elements (key of the pair), but skips one (the number 8); the third one has size 2 (because partials are allowed), and an overlap of 2 also.
Please see also list.rotor for examples applied to lists.
Defined as:
method sum() is nodal
If the content is iterable, it returns the sum of the values after pulling them one by one.
(3,2,1).sum; # OUTPUT: «6» say 3.sum; # OUTPUT: «3»
It will fail if any of the elements cannot be converted to a number.
Sequence of itemized values
class Array is List {}
An Array is a List which forces all its elements to be scalar containers, which means you can assign to array elements.
Array implements Positional and as such provides support for subscripts.
Note from version 6.d, .perl can be called on multi-dimensional arrays.
Exactly the same as List.gist, except using square brackets for surrounding delimiters.
Defined as:
multi sub pop(Array:D ) multi method pop(Array:D:)
Removes and returns the last item from the array. Fails for an empty array.
Example:
my @foo = <a b>; # a b @foo.pop; # b pop @foo; # a pop @foo; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Cannot::Empty: Cannot pop from an empty Array»
Defined as:
multi sub push(Array:D, **@values --> Array:D) multi method push(Array:D: **@values --> Array:D)
Adds the @values to the end of the array, and returns the modified array. Throws for lazy arrays.
Example:
my @foo = <a b c>; @foo.push: 'd'; say @foo; # OUTPUT: «[a b c d]»
Note that push does not attempt to flatten its argument list. If you pass an array or list as the thing to push, it becomes one additional element:
my @a = <a b c>; my @b = <d e f>; @a.push: @b; say @a.elems; # OUTPUT: «4» say @a[3].join; # OUTPUT: «def»
Only if you supply multiple values as separate arguments to push are multiple values added to the array:
my @a = '1'; my @b = <a b>; my @c = <E F>; @a.push: @b, @c; say @a.elems; # OUTPUT: «3»
See method append for when you want to append multiple values that are stored in a single array.
Defined as
sub append(\array, |elems) multi method append(Array:D: \values) multi method append(Array:D: **@values is raw)
Appends the argument list to the array passed as the first argument. This modifies the array in-place. Returns the modified array. Throws for lazy arrays.
The difference from method push is that if you append a single array or list argument, append will flatten that array / list, whereas push appends the list / array as just a single element.
Example:
my @a = <a b c>; my @b = <d e f>; @a.append: @b; say @a.elems; # OUTPUT: «6» say @a; # OUTPUT: «[a b c d e f]»
Defined as:
method elems(Array:D: --> Int:D)
Returns the number of elements in the invocant. Throws X::Cannot::Lazy exception if the invocant is lazy. For shaped arrays, returns the outer dimension; see shape if you need information for all dimensions.
say [<foo bar ber>] .elems; # OUTPUT: «3» say (my @a[42;3;70]).elems; # OUTPUT: «42» try [-∞...∞].elems; say $!.^name; # OUTPUT: «X::Cannot::Lazy»
Defined as:
method clone(Array:D: --> Array:D)
Clones the original Array. Modifications of elements in the clone are not propagated to the original and vice-versa:
my @a = <a b c>; my @b = @a.clone; @b[1] = 42; @a.push: 72; say @b; # OUTPUT: «[a 42 c]» say @a; # OUTPUT: «[a b c 72]»
However, note that the reifier is shared between the two Arrays, so both Arrays will have the same elements even when each is randomly-generated on reification and each element will be reified just once, regardless of whether the reification was done by the clone or the original Array. Note: just as reifying an Array from multiple threads is not safe, so is, for example, reifying the clone from one thread while reifying the original from another thread is not safe.
my @a = 1, {rand} … ∞; my @b = @a.clone; say @b[^3]; # OUTPUT: «(1 0.0216426755282736 0.567660896142156)» say @a[^3]; # OUTPUT: «(1 0.0216426755282736 0.567660896142156)»
Defined as:
multi sub shift(Array:D ) multi method shift(Array:D:)
Removes and returns the first item from the array. Fails for an empty arrays.
Example:
my @foo = <a b>; say @foo.shift; # OUTPUT: «a» say @foo.shift; # OUTPUT: «b» say @foo.shift; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Cannot::Empty: Cannot shift from an empty Array»
Defined as:
multi sub unshift(Array:D, **@values --> Array:D) multi method unshift(Array:D: **@values --> Array:D)
Adds the @values to the start of the array, and returns the modified array. Fails if @values is a lazy list.
Example:
my @foo = <a b c>; @foo.unshift: 1, 3 ... 11; say @foo; # OUTPUT: «[(1 3 5 7 9 11) a b c]»
The notes in the documentation for method push apply, regarding how many elements are added to the array.
#method prepend is the equivalent for adding multiple elements from one list or array.
Defined as
sub prepend(\array, |elems) multi method prepend(Array:D: \values) multi method prepend(Array:D: **@values is raw)
Adds the elements from LIST to the front of the array, modifying it in-place.
Example:
my @foo = <a b c>; @foo.prepend: 1, 3 ... 11; say @foo; # OUTPUT: «[1 3 5 7 9 11 a b c]»
The difference from method unshift is that if you prepend a single array or list argument, prepend will flatten that array / list, whereas unshift prepends the list / array as just a single element.
Defined as:
multi sub splice(@list, $start = 0, $elems?, *@replacement --> Array) multi method splice(Array:D: $start = 0, $elems?, *@replacement --> Array)
Deletes $elems elements starting from index $start from the Array, returns them and replaces them by @replacement. If $elems is omitted or is larger than the number of elements starting from $start, all the elements starting from index $start are deleted. If both $start and $elems are omitted, all elements are deleted from the Array and returned.
Each of $start and $elems can be specified as a Whatever or as a Callable that returns an int-compatible value.
A Whatever $start uses the number of elements of @list (or invocant). A Callable $start is called with one argument—the number of elements in @list—and its return value is used as $start.
A Whatever $elems deletes from $start to end of @list (same as no $elems). A Callable $elems is called with just one argument—the number of elements in @list minus the value of $start—and its return value is used the value of $elems.
Example:
my @foo = <a b c d e f g>; say @foo.splice(2, 3, <M N O P>); # OUTPUT: «[c d e]» say @foo; # OUTPUT: «[a b M N O P f g]»
Defined as:
method shape() { (*,) }
Returns the shape of the array as a list.
Example:
my @foo[2;3] = ( < 1 2 3 >, < 4 5 6 > ); # Array with fixed dimensions say @foo.shape; # OUTPUT: «(2 3)» my @bar = ( < 1 2 3 >, < 4 5 6 > ); # Normal array (of arrays) say @bar.shape; # OUTPUT: «(*)»
Defined as:
method default
Returns the default value of the invocant, i.e. the value which is returned when trying to access an element in the Array which has not been previously initialized or when accessing an element which has explicitly been set to Nil. Unless the Array is declared as having a default value by using the is default trait the method returns the type object (Any).
my @a1 = 1, "two", 2.718; say @a1.default; # OUTPUT: «(Any)» say @a1[4]; # OUTPUT: «(Any)» my @a2 is default(17) = 1, "two", 3; say @a2.default; # OUTPUT: «17» say @a2[4]; # OUTPUT: «17» @a2[1] = Nil; # (resets element to its default) say @a2[1]; # OUTPUT: «17»
Defined as:
method of
Returns the type constraint for the values of the invocant. By default, i.e. if no type constraint is given during declaration, the method returns (Mu).
my @a1 = 1, 'two', 3.14159; # (no type constraint specified) say @a1.of; # OUTPUT: «(Mu)» my Int @a2 = 1, 2, 3; # (values must be of type Int) say @a2.of; # OUTPUT: «(Int)» @a2.push: 'd'; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to @a2; expected Int but got Str ("d")»
Defined as:
method dynamic(Array:D: --> Bool:D)
Returns True if the invocant has been declared with the is dynamic trait.
my @a; say @a.dynamic; # OUTPUT: «False» my @b is dynamic; say @b.dynamic; # OUTPUT: «True»
If you declare a variable with the * twigil is dynamic is implied.
my @*b; say @*b.dynamic; # OUTPUT: «True»
Note that in the Scalar case you have to use the VAR method in order to get correct information.
my $s is dynamic = [1, 2, 3]; say $s.dynamic; # OUTPUT: «False» (wrong, don't do this) say $s.VAR.dynamic; # OUTPUT: «True» (correct approach)
Object that supports looking up values by key
role Associative[::TValue = Mu, ::TKey = Str(Any)] { }
A common role for types that support name-based lookup through postcircumfix:<{ }>, for example Hash and Map. It is used for type checks in operators that expect to find specific methods to call. See Subscripts for details.
The % sigil restricts variables to objects that do Associative, so you will have to mix in that role if you want to use it for your classes.
class Whatever {}; my %whatever := Whatever.new; # OUTPUT: «Type check failed in binding; expected Associative but got Whatever
Please note that we are using binding := here, since by default % assignments expect a Hash in the right-hand side. However, with the Associative role:
class Whatever is Associative {}; my %whatever := Whatever.new;
will be syntactically correct.
Defined as:
method of()
Associative is actually a parameterized role which can use different classes for keys and values. As seen at the top of the document, by default it coerces to Str for the key and uses a very generic Mu for value.
my %any-hash; say %any-hash.of;# OUTPUT: «(Mu)»
The value is the first parameter you use when instantiating Associative with particular classes:
class DateHash is Hash does Associative[Cool,DateTime] {}; my %date-hash := DateHash.new; say %date-hash.of; # OUTPUT: «(Cool)»
Defined as:
method keyof()
Returns the parameterized key used for the Associative role, which is Any coerced to Str by default. This is the class used as second parameter when you use the parameterized version of Associative.
my %any-hash; %any-hash.keyof; #OUTPUT: «(Str(Any))»
You need to provide these methods if you want your class to implement the Associative role.
method AT-KEY(\key)
Should return the value / container at the given key.
method EXISTS-KEY(\key)
Should return a Bool indicating whether the given key actually has a value.
method STORE(\values, :$initialize)
This method should only be supplied if you want to support the:
my %h is Foo = a => 42, b => 666;
syntax for binding your implementation of the Associative role.
Should accept the values to (re-)initialize the object with, which either could consist of Pairs, or separate key/value pairs. The optional named parameter will contain a True value when the method is called on the object for the first time. Should return the invocant.
See Methods to implement for positional subscripting for information about additional methods that can be implemented for the Associative role.
Member variable
class Attribute { }
In Perl 6 lingo, an attribute refers to a per-instance/object storage slot. An Attribute is used to talk about classes' and roles' attributes at the meta level.
Normal usage of attributes does not require the user to use this class explicitly.
An attribute that is assigned Nil will revert to its default value set with the trait is default. In the case of arrays or associatives, the argument of is default will set the default item value or hash value.
class C { has $.a is default(42) is rw = 666 } my $c = C.new; say $c; $c.a = Nil; say $c; # OUTPUT: «C.new(a => 666)C.new(a => 42)»
Defined as:
multi sub trait_mod:<is> (Attribute $attr, :$required!)
The trait is required will mark the attribute as to be filled with a value when the object is instantiated. Failing to do so will result in a runtime error.
class C { has $.a is required } my $c = C.new; CATCH{ default { say .^name, ': ', .Str } } # OUTPUT: «X::Attribute::Required: The attribute '$!a' is required, but you did not provide a value for it.»
Available as of 6.d language version (early implementation exists in Rakudo compiler 2018.08+): You can specify a reason why the attribute is required:
class D { has $.a is required("it is a good idea"); } my $d = D.new; CATCH{ default { say .^name, ': ', .Str } } # OUTPUT: «X::Attribute::Required: The attribute '$!a' is required because it is a good idea,but you did not provide a value for it.»
is required doesn't just affect the default constructor, it checks for the attribute at a lower level, so it will work for custom constructors written using bless.
multi sub trait_mod:<is>(Attribute:D $r, :$DEPRECATED!)
Marks an attribute as deprecated, optionally with a message what to use instead.
class C { has $.foo is DEPRECATED("'bar'"); } my $c = C.new( foo => 42 ); # doesn't trigger with initialization (yet) say $c.foo; # does trigger on usage
After the program is finished, this will show something like this on STDERR:
# Saw 1 occurrence of deprecated code. # ===================================== # Method foo (from C) seen at: # script.p6, line 5 # Please use 'bar' instead.
Defined as:
multi sub trait_mod:<is> (Attribute:D $attr, :$rw!)
Marks an attribute as read/write as opposed to the default readonly. The default accessor for the attribute will return a writable value.
class Boo { has $.bar is rw; has $.baz; }; my $boo = Boo.new; $boo.bar = 42; # works $boo.baz = 42; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Any»
The usual way to obtain an object of type Attribute is by introspection:
class Useless { has @!things; } my $a = Useless.^attributes(:local)[0]; say $a.perl; # OUTPUT: «Attribute.new» say $a.name; # OUTPUT: «@!things» say $a.package; # OUTPUT: «(Useless)» say $a.has_accessor; # OUTPUT: «False»
Modifying a private attribute from the outside is usually not possible, but since Attribute is at the level of the meta class, all is fair game.
Defined as:
method name(Attribute:D: --> Str:D)
Returns the name of the attribute. Note that this is always the private name, so if an attribute is declared as has $.a, the name returned is $!a.
class Foo { has @!bar; } my $a = Foo.^attributes(:local)[0]; say $a.name; # OUTPUT: «@!bar»
Defined as:
method package()
Returns the package (class/grammar/role) to which this attribute belongs.
class Boo { has @!baz; } my $a = Boo.^attributes(:local)[0]; say $a.package; # OUTPUT: «(Boo)»
Defined as:
method has_accessor(Attribute:D: --> Bool:D)
Returns True if the attribute has a public accessor method.
class Container { has $!private; has $.public; } my $private = Container.^attributes(:local)[0]; my $public = Container.^attributes(:local)[1]; say $private.has_accessor; # OUTPUT: «False» say $public.has_accessor; # OUTPUT: «True»
Defined as:
method rw(Attribute:D: --> Bool:D)
Returns True for attributes that have the "is rw" trait applied to them.
class Library { has $.address; # Read-only value has @.new-books is rw; } my $addr = Library.^attributes(:local)[0]; my $new-books = Library.^attributes(:local)[1]; say $addr.rw; # OUTPUT: «False» say $new-books.rw; # OUTPUT: «True»
Defined as:
method readonly(Attribute:D: --> Bool:D)
Returns True for readonly attributes, which is the default, or False for attributes marked as is rw.
class Library { has $.address; # Read-only value has @.new-books is rw; } my $addr = Library.^attributes(:local)[0]; my $new-books = Library.^attributes(:local)[1]; say $addr.readonly; # OUTPUT: «True» say $new-books.readonly; # OUTPUT: «False»
Defined as:
method required(Attribute:D: --> Any:D)
Returns 1 for attributes that have the "is required" trait applied, or Mu if the attribute did not have that trait applied. If the "is required" trait is applied with a string, then that string will be returned instead of 1.
class Library { has $.address is required; has @.new-books is required("we always need more books"); } my $addr = Library.^attributes(:local)[0]; my $new-books = Library.^attributes(:local)[1]; say $addr.required; # OUTPUT: «1» say $new-books.readonly; # OUTPUT: «"we always need more books"»
Defined as:
method type(Attribute:D: --> Mu)
Returns the type constraint of the attribute.
class TypeHouse { has Int @.array; has $!scalar; has @.mystery; } my @types = TypeHouse.^attributes(:local)[0..2]; for 0..2 { say @types[$_].type } # OUTPUT: «(Positional[Int]) # (Mu) # (Positional)»
Defined as:
method get_value(Mu $obj)
Returns the value stored in this attribute of object $obj.
class Violated { has $!private-thing = 5; } my $private = Violated.^attributes(:local)[0]; say $private.get_value(Violated.new); # OUTPUT: «5»
Note that this method violates encapsulation of the object, and should be used with care. Here be dragons.
Defined as:
method set_value(Mu $obj, Mu \new_val)
Binds the value new_val to this attribute of object $obj.
class A { has $!a = 5; method speak() { say $!a; } } my $attr = A.^attributes(:local)[0]; my $a = A.new; $a.speak; # OUTPUT: «5» $attr.set_value($a, 42); $a.speak; # OUTPUT: «42»
Note that this method violates encapsulation of the object, and should be used with care. Here be dragons.
Defined as
multi method gist(Attribute:D:)
Returns the name of the type followed by the name of the attribute.
class Hero { has @!inventory; has Str $.name; submethod BUILD( :$name, :@inventory ) { $!name = $name; @!inventory = @inventory } } say Hero.^attributes(:local)[0]; # OUTPUT: «Positional @!inventory»
Since say implicitly calls .gist, that is what produces the output here.
If an attribute is marked as DEPRECATED, then calling the DEPRECATED method is possible and will return "something else" (if no specific reason was specified) or the string that was specified with the DEPRECATED trait.
If an attribute is not marked as DEPRECATED, one cannot not call the DEPRECATED method. Therefore, the .?method syntax should be used.
class Hangout { has $.table; has $.bar is DEPRECATED("the patio"); } my $attr-table = Hangout.^attributes(:local)[0]; my $attr-bar = Hangout.^attributes(:local)[1]; with $attr-table.?DEPRECATED -> $text { # does not trigger say "Table is deprecated with '$text'"; # OUTPUT: } with $attr-table.?DEPRECATED -> $text { say "Bar is deprecated with '$text'"; # OUTPUT: «Bar is deprecated with 'the patio'"» }
Snapshot of the dynamic call stack
class Backtrace {}
A backtrace contains the dynamic call stack, usually leading up to a point where an exception was thrown, and is a List of Backtrace::Frame objects. Its default stringification excludes backtrace frames that are deemed unnecessary or confusing; for example routines like &die are hidden by default. Being a list, you can also access individual elements.
sub zipi { { { die "Something bad happened" }() }() }; try { zipi; } if ($!) { say $!.backtrace[*-1].perl; }
This will print the last frame in the list, pointing at the line where it's happened.
Defined as:
multi method new() multi method new(Int:D $offset) multi method new(Mu \ex) multi method new(Mu \ex, Int:D $offset) multi method new(List:D $bt) multi method new(List:D $bt, Int:D $offset)
Creates a new backtrace, using its calling location as the origin of the backtrace or the $offset that is passed as a parameter. If an object or a list (that will already contain a backtrace in list form) is passed, they will be used instead of the current code.
my $backtrace = Backtrace.new;
Defined as:
multi method gist(Backtrace:D:)
Returns string "Backtrace(42 frames)" where the number indicates the number of frames available via list method.
Defined as:
multi method Str(Backtrace:D:)
Returns a concise string representation of the backtrace, omitting routines marked as is hidden-from-backtrace, and at the discretion of the implementation, also some routines from the setting.
my $backtrace = Backtrace.new; say $backtrace.Str;
Defined as:
method next-interesting-index(Backtrace:D: Int $idx = 0, :$named, :$noproto, :$setting)
Returns the index of the next interesting frame, once hidden and other settings are taken into account. $named will decide whether to printed only those with a name, $noproto will hide protos, and $setting will hide those are considered setting.
sub zipi { { { die "Something bad happened" }() }() }; try zipi; say $!.backtrace.next-interesting-index; # OUTPUT: «2» say $!.backtrace.next-interesting-index( :named ); # OUTPUT: «4»
Defined as:
method outer-caller-idx(Backtrace:D: Int $startidx)
Returns as a list the index of the frames that called the current one.
sub zipi { { { die "Something bad happened" }() }() }; try zipi; say $!.backtrace.outer-caller-idx( 4 ); # OUTPUT: «[6]»
Defined as:
method nice(Backtrace:D: :$oneline)
Returns the backtrace as a list of interesting frames. If :$oneline is set, will stop after the first frame.
sub zipi { { { die "Something bad happened" }() }() }; try zipi; say $!.backtrace.nice( :oneline ) if $!; # OUTPUT: « in sub zipi at /tmp/... line 1»
Defined as:
multi method full(Backtrace:D:)
Returns a full string representation of the backtrace, including hidden frames, compiler-specific frames, and those from the setting.
my $backtrace = Backtrace.new; say $backtrace.full;
Defined as:
multi method list(Backtrace:D:)
Returns a list of Backtrace::Frame objects for this backtrace.
Defined as:
method summary(Backtrace:D: --> Str:D)
Returns a summary string representation of the backtrace, filtered by !.is-hidden && (.is-routine || !.is-setting).
This program:
sub inner { say Backtrace.new.summary } sub outer { inner; } outer;
results in:
in method new at SETTING::src/core/Backtrace.pm6 line 85 in sub inner at test.p6 line 1 in sub outer at test.p6 line 2 in block <unit> at test.p6 line 3
Defined as:
method concise(Backtrace:D:)
Returns a concise string representation of the backtrace, filtered by !.is-hidden && .is-routine && !.is-setting.
This program:
sub inner { say Backtrace.new.concise } sub outer { inner; } outer;
results in:
in sub inner at test.p6 line 1 in sub outer at test.p6 line 2
Defined as:
multi method map(Backtrace:D: &block --> Seq:D)
It invokes &block for each element and gathers the return values in a sequence and returns it.
This program:
sub inner { Backtrace.new.map({ say "{$_.file}: {$_.line}" }); } sub outer { inner; } outer;
results in:
SETTING::src/core/Backtrace.pm6: 85 SETTING::src/core/Backtrace.pm6: 85 test.p6: 1 test.p6: 2 test.p6: 3 test.p6: 1
Defined as:
multi method flat(Backtrace:D:)
Returns the backtrace same as list.
Single frame of a Backtrace
class Backtrace::Frame { }
A single backtrace frame. It identifies a location in the source code.
Defined as:
method file(Backtrace::Frame:D --> Str)
Returns the file name.
my $bt = Backtrace.new; my $btf = $bt[0]; say $btf.file;
Defined as:
method line(Backtrace::Frame:D --> Int)
Returns the line number (line numbers start counting from 1).
my $bt = Backtrace.new; my $btf = $bt[0]; say $btf.line;
Defined as:
method code(Backtrace::Frame:D)
Returns the code object into which .file and .line point, if available.
my $bt = Backtrace.new; my $btf = $bt[0]; say $btf.code;
Defined as:
method subname(Backtrace::Frame:D --> Str)
Returns the name of the enclosing subroutine.
my $bt = Backtrace.new; my $btf = $bt[0]; say $btf.subname;
Defined as:
method is-hidden(Backtrace::Frame:D --> Bool:D)
Returns True if the frame is marked as hidden with the is hidden-from-backtrace trait.
my $bt = Backtrace.new; my $btf = $bt[0]; say $btf.is-hidden;
Defined as:
method is-routine(Backtrace::Frame:D --> Bool:D)
Return True if the frame points into a routine (and not into a mere Block).
my $bt = Backtrace.new; my $btf = $bt[0]; say $btf.is-routine;
Defined as:
method is-setting(Backtrace::Frame:D --> Bool:D)
Returns True if the frame is part of a setting.
my $bt = Backtrace.new; my $btf = $bt[0]; say $btf.is-setting; # OUTPUT: «True»
Immutable collection of distinct objects with integer weights
class Bag does Baggy { }
A Bag is an immutable bag/multiset implementing Associative, meaning a collection of distinct elements in no particular order that each have an integer weight assigned to them signifying how many copies of that element are considered "in the bag". (For mutable bags, see BagHash instead.)
Bags are often used for performing weighted random selections - see .pick and .roll.
Objects/values of any type are allowed as bag elements. Within a Bag, items that would compare positively with the === operator are considered the same element, with the number of how many there are as its weight. But of course you can also easily get back the expanded list of items (without the order):
my $breakfast = bag <spam eggs spam spam bacon spam>; say $breakfast.elems; # OUTPUT: «3» say $breakfast.keys.sort; # OUTPUT: «bacon eggs spam» say $breakfast.total; # OUTPUT: «6» say $breakfast.kxxv.sort; # OUTPUT: «bacon eggs spam spam spam spam»
Bags can be treated as object hashes using the { } postcircumfix operator, or the < > operator for literal string keys, which returns the corresponding integer weight for keys that are elements of the bag, and 0 for keys that aren't:
my $breakfast = bag <spam eggs spam spam bacon spam>; say $breakfast<bacon>; # OUTPUT: «1» say $breakfast<spam>; # OUTPUT: «4» say $breakfast<sausage>; # OUTPUT: «0»
Bags can be composed using the bag subroutine (or Bag.new, for which it is a shorthand). Any positional parameters, regardless of their type, become elements of the bag:
my $n = bag "a" => 0, "b" => 1, "c" => 2, "c" => 2; say $n.keys.perl; # OUTPUT: «(:c(2), :b(1), :a(0)).Seq» say $n.keys.map(&WHAT); # OUTPUT: «((Pair) (Pair) (Pair))» say $n.values.perl; # OUTPUT: «(2, 1, 1).Seq»
Alternatively, the .Bag coercer (or its functional form, Bag()) can be called on an existing object to coerce it to a Bag. Its semantics depend on the type and contents of the object. In general it evaluates the object in list context and creates a bag with the resulting items as elements, although for Hash-like objects or Pair items, only the keys become elements of the bag, and the (cumulative) values become the associated integer weights:
my $n = ("a" => 0, "b" => 1, "c" => 2, "c" => 2).Bag; say $n.keys.perl; # OUTPUT: «("b", "c").Seq» say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Str))» say $n.values.perl; # OUTPUT: «(1, 4).Seq»
Furthermore, you can get a Bag by using bag operators (see next section) on objects of other types such as List, which will act like they internally call .Bag on them before performing the operation. Be aware of the tight precedence of those operators though, which may require you to use parentheses around arguments:
say (1..5) (+) 4; # OUTPUT: «bag(1, 2, 3, 4(2), 5)»
Of course, you can also create a Bag with the .new method.
my $breakfast = Bag.new( <spam eggs spam spam bacon spam> );
Since 6.d (2019.03 and later) you can also use this syntax for parameterization of the Bag, to specify which type of values are acceptable:
# only allow strings (Str) in the Bag my $breakfast = Bag[Str].new( <spam eggs spam spam bacon spam> ); # only allow whole numbers (Int) in the Bag my $breakfast = Bag[Int].new( <spam eggs spam spam bacon spam> ); # Type check failed in binding; expected Int but got Str ("spam")
Finally, you can create Bag masquerading as a hash by using the is trait:
my %b is Bag = <a b c>; say %b<a>; # True say %b<d>; # False
Since 6.d (2019.03 and later), this syntax also allows you to specify the type of values you would like to allow:
# limit to strings my %b is Bag[Str] = <a b c>; say %b<a>; # True say %b<d>; # False # limit to whole numbers my %b is Bag[Int] = <a b c>; # Type check failed in binding; expected Int but got Str ("a")
Perl 6 provides common set and bag operators, which can take Bags (or any other collections) as input, and return result as Bool, Set or Bag values. For example:
my ($a, $b) = bag(2, 2, 4), bag(2, 3, 3, 4); say $a (<) $b; # OUTPUT: «False» say $a (<+) $b; # OUTPUT: «False» say $a (^) $b; # OUTPUT: «bag(3(2), 2)» say $a (+) $b; # OUTPUT: «bag(2(3), 4(2), 3(2))» # Unicode versions: say $a ⊂ $b; # OUTPUT: «False» say $a ≼ $b; # OUTPUT: «False» say $a ⊖ $b; # OUTPUT: «bag(3(2), 2)» say $a ⊎ $b; # OUTPUT: «bag(2(3), 4(2), 3(2))»
See Set/Bag Operators for a complete list of set and bag operators with detailed explanations.
sub bag(*@args --> Bag)
Creates a new Bag from @args.
This method is inherited from Any, however, Mixes do not have an inherent order and you should not trust it returning a consistent output.
Mutable collection of distinct objects with integer weights
class BagHash does Baggy { }
A BagHash is a mutable bag/multiset, meaning a collection of distinct elements in no particular order that each have an integer weight assigned to them signifying how many copies of that element are considered "in the bag". (For immutable bags, see Bag instead.)
Objects/values of any type are allowed as bag elements. Within a BagHash, items that would compare positively with the === operator are considered the same element, with the number of how many there were as its weight. But of course you can also easily get back the expanded list of items (without the order):
my $breakfast = <spam eggs spam spam bacon spam>.BagHash; say $breakfast.elems; # OUTPUT: «3» say $breakfast.keys.sort; # OUTPUT: «bacon eggs spam» say $breakfast.total; # OUTPUT: «6» say $breakfast.kxxv.sort; # OUTPUT: «bacon eggs spam spam spam spam»
BagHashes can be treated as object hashes using the { } postcircumfix operator, which returns the corresponding integer weight for keys that are elements of the bag, and 0 for keys that aren't. It can also be used to modify weights; setting a weight to 0 automatically removes that element from the bag, and setting a weight to a positive number adds that element if it didn't already exist:
my $breakfast = <spam eggs spam spam bacon spam>.BagHash; say $breakfast<bacon>; # OUTPUT: «1» say $breakfast<spam>; # OUTPUT: «4» say $breakfast<sausage>; # OUTPUT: «0» $breakfast<sausage> = 2; $breakfast<bacon>--; say $breakfast.kxxv.sort; # OUTPUT: «eggs sausage sausage spam spam spam spam»
BagHashes can be composed using BagHash.new. Any positional parameters, regardless of their type, become elements of the bag:
my $n = BagHash.new: "a", "b", "c", "c"; say $n.perl; # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash» say $n.keys.perl; # OUTPUT: «("b", "a", "c").Seq» say $n.values.perl; # OUTPUT: «(1, 1, 2).Seq»
Besides, BagHash.new-from-pairs can create a BagHash with items and their occurrences.
my $n = BagHash.new-from-pairs: "a" => 0, "b" => 1, "c" => 2, "c" => 2; say $n.perl; # OUTPUT: «("b"=>1,"c"=>4).BagHash» say $n.keys.perl; # OUTPUT: «("b", "c").Seq» say $n.values.perl; # OUTPUT: «(1, 4).Seq»
Alternatively, the .BagHash coercer (or its functional form, BagHash()) can be called on an existing object to coerce it to a BagHash. Its semantics depend on the type and contents of the object. In general it evaluates the object in list context and creates a bag with the resulting items as elements, although for Hash-like objects or Pair items, only the keys become elements of the bag, and the (cumulative) values become the associated integer weights:
my $m = ("a", "b", "c", "c").BagHash; my $n = ("a" => 0, "b" => 1, "c" => 2, "c" => 2).BagHash; say $m.perl; # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash» say $n.perl; # OUTPUT: «("b"=>1,"c"=>4).BagHash»
You can also create BagHash masquerading as a hash by using the is trait:
my %bh is BagHash = <a b b c c c>; say %bh<b>; # 2 say %bh<d>; # 0
Since 6.d (2019.03 and later) it is also possible to specify the type of values you would like to allow in a BagHash. This can either be done when calling .new:
# only allow strings my $n = BagHash[Str].new: <a b b c c c>;
or using the masquerading syntax:
# only allow strings my %bh is BagHash[Str] = <a b b c c c>; say %bh<b>; # 2 say %bh<d>; # 0 # only allow whole numbers my %bh is BagHash[Int] = <a b b c c c>; # Type check failed in binding; expected Int but got Str ("a")
Perl 6 provides common set and bag operators, which can take BagHashes (or any other collections) as input, and return result as Bool, Set or Bag values. For example:
my ($a, $b) = BagHash.new(2, 2, 4), BagHash.new(2, 3, 3, 4); say $a (<) $b; # OUTPUT: «False» say $a (<+) $b; # OUTPUT: «False» say $a (^) $b; # OUTPUT: «Bag(3(2), 2)» say $a (+) $b; # OUTPUT: «Bag(2(3), 4(2), 3(2))» # Unicode versions: say $a ⊂ $b; # OUTPUT: «False» say $a ≼ $b; # OUTPUT: «False» say $a ⊖ $b; # OUTPUT: «Bag(3(2), 2)» say $a ⊎ $b; # OUTPUT: «Bag(2(3), 4(2), 3(2))»
See Set/Bag Operators for a complete list of set and bag operators with detailed explanations.
BagHash inherits reverse from Any, however, Bags do not have an inherent order and you should not trust it returning a consistent output.
If you sort a BagHash, the result is a list of pairs, at which point reverse makes perfect sense:
my $a = BagHash.new(2, 2, 18, 3, 4); say $a; # OUTPUT: «BagHash(18, 2(2), 3, 4)» say $a.sort; # OUTPUT: «(2 => 2 3 => 1 4 => 1 18 => 1)» say $a.sort.reverse; # OUTPUT: «(18 => 1 4 => 1 3 => 1 2 => 2)»
Collection of distinct weighted objects
role Baggy does QuantHash { }
A role for collections of weighted objects. See Bag, BagHash, and Mixy.
Defined as:
method new-from-pairs(*@pairs --> Baggy:D)
Constructs a Baggy objects from a list of Pair objects given as positional arguments:
say Mix.new-from-pairs: 'butter' => 0.22, 'sugar' => 0.1, 'sugar' => 0.02; # OUTPUT: «mix(butter(0.22), sugar(0.12))»
Note: be sure you aren't accidentally passing the Pairs as positional arguments; the quotes around the keys in the above example are significant.
Defined as:
multi method grab(Baggy:D: --> Any) multi method grab(Baggy:D: $count --> Seq:D)
Like pick, a grab returns a random selection of elements, weighted by the values corresponding to each key. Unlike pick, it works only on mutable structures, e.g. BagHash. Use of grab on an immutable structure results in an X::Immutable exception. If * is passed as $count, or $count is greater than or equal to the total of the invocant, then total elements from the invocant are returned in a random sequence; i.e. they are returned shuffled.
Grabbing decrements the grabbed key's weight by one (deleting the key when it reaches 0). By definition, the total of the invocant also decreases by one, so the probabilities stay consistent through subsequent grab operations.
my $cars = ('Ford' => 2, 'Rover' => 3).BagHash; say $cars.grab; # OUTPUT: «Ford» say $cars.grab(2); # OUTPUT: «(Rover Rover)» say $cars.grab(*); # OUTPUT: «(Rover Ford)» my $breakfast = ('eggs' => 2, 'bacon' => 3).Bag; say $breakfast.grab; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Immutable: Cannot call 'grab' on an immutable 'Bag'»
Defined as:
multi method grabpairs(Baggy:D: --> Any) multi method grabpairs(Baggy:D: $count --> Seq:D)
Returns a Pair or a Seq of Pairs depending on the version of the method being invoked. Each Pair returned has an element of the invocant as its key and the elements weight as its value. Unlike pickpairs, it works only on mutable structures, e.g. BagHash. Use of grabpairs on 'an immutable structure results in an X::Immutable exception. If * is passed as $count, or $count is greater than or equal to the number of elements of the invocant, then all element/weight Pairs from the invocant are returned in a random sequence.
What makes grabpairs different from pickpairs is that the 'grabbed' elements are in fact removed from the invocant.
my $breakfast = (eggs => 2, bacon => 3).BagHash; say $breakfast.grabpairs; # OUTPUT: «bacon => 3» say $breakfast; # OUTPUT: «BagHash.new(eggs(2))» say $breakfast.grabpairs(1); # OUTPUT: «(eggs => 2)» say $breakfast.grabpairs(*); # OUTPUT: «()» my $diet = ('eggs' => 2, 'bacon' => 3).Bag; say $diet.grabpairs; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Immutable: Cannot call 'grabpairs' on an immutable 'Bag'»
Defined as:
multi method pick(Baggy:D: --> Any) multi method pick(Baggy:D: $count --> Seq:D)
Like an ordinary list pick, but returns keys of the invocant weighted by their values, as if the keys were replicated the number of times indicated by the corresponding value and then list pick used. The underlying metaphor for picking is that you're pulling colored marbles out a bag. (For "picking with replacement" see roll instead). If * is passed as $count, or $count is greater than or equal to the total of the invocant, then total elements from the invocant are returned in a random sequence.
Note that each pick invocation maintains its own private state and has no effect on subsequent pick invocations.
my $breakfast = bag <eggs bacon bacon bacon>; say $breakfast.pick; # OUTPUT: «eggs» say $breakfast.pick(2); # OUTPUT: «(eggs bacon)» say $breakfast.total; # OUTPUT: «4» say $breakfast.pick(*); # OUTPUT: «(bacon bacon bacon eggs)»
Defined as:
multi method pickpairs(Baggy:D: --> Pair:D) multi method pickpairs(Baggy:D: $count --> Seq:D)
Returns a Pair or a Seq of Pairs depending on the version of the method being invoked. Each Pair returned has an element of the invocant as its key and the elements weight as its value. The elements are 'picked' without replacement. If * is passed as $count, or $count is greater than or equal to the number of elements of the invocant, then all element/weight Pairs from the invocant are returned in a random sequence.
Note that each pickpairs invocation maintains its own private state and has no effect on subsequent pickpairs invocations.
my $breakfast = bag <eggs bacon bacon bacon>; say $breakfast.pickpairs; # OUTPUT: «eggs => 1» say $breakfast.pickpairs(1); # OUTPUT: «(bacon => 3)» say $breakfast.pickpairs(*); # OUTPUT: «(eggs => 1 bacon => 3)»
Defined as:
multi method roll(Baggy:D: --> Any:D) multi method roll(Baggy:D: $count --> Seq:D)
Like an ordinary list roll, but returns keys of the invocant weighted by their values, as if the keys were replicated the number of times indicated by the corresponding value and then list roll used. The underlying metaphor for rolling is that you're throwing $count dice that are independent of each other, which (in bag terms) is equivalent to picking a colored marble out your bag and then putting it back, and doing this $count times. In dice terms, the number of marbles corresponds to the number of sides, and the number of marbles of the same color corresponds to the number of sides with the same color. (For "picking without replacement" see pick instead).
If * is passed to $count, returns a lazy, infinite sequence of randomly chosen elements from the invocant.
my $breakfast = bag <eggs bacon bacon bacon>; say $breakfast.roll; # OUTPUT: «bacon» say $breakfast.roll(3); # OUTPUT: «(bacon eggs bacon)» my $random_dishes := $breakfast.roll(*); say $random_dishes[^5]; # OUTPUT: «(bacon eggs bacon bacon bacon)»
Defined as:
method pairs(Baggy:D: --> Seq:D)
Returns all elements and their respective weights as a Seq of Pairs where the key is the element itself and the value is the weight of that element.
my $breakfast = bag <bacon eggs bacon>; my $seq = $breakfast.pairs; say $seq.sort; # OUTPUT: «(bacon => 2 eggs => 1)»
Defined as:
method antipairs(Baggy:D: --> Seq:D)
Returns all elements and their respective weights as a Seq of Pairs, where the element itself is the value and the weight of that element is the key, i.e. the opposite of method pairs.
my $breakfast = bag <bacon eggs bacon>; my $seq = $breakfast.antipairs; say $seq.sort; # OUTPUT: «(1 => eggs 2 => bacon)»
Defined as:
method invert(Baggy:D: --> Seq:D)
Returns all elements and their respective weights as a Seq of Pairs, where the element itself is the value and the weight of that element is the key, i.e. the opposite of method pairs. Except for some esoteric cases invert on a Baggy type returns the same result as antipairs.
my $breakfast = bag <bacon eggs bacon>; my $seq = $breakfast.invert; say $seq.sort; # OUTPUT: «(1 => eggs 2 => bacon)»
Defined as:
multi method classify-list(&mapper, *@list --> Baggy:D) multi method classify-list(%mapper, *@list --> Baggy:D) multi method classify-list(@mapper, *@list --> Baggy:D)
Populates a mutable Baggy by classifying the possibly-empty @list of values using the given mapper. The @list cannot be lazy.
say BagHash.new.classify-list: { $_ %% 2 ?? 'even' !! 'odd' }, ^10; # OUTPUT: BagHash.new(even(5), odd(5)) my @mapper = <zero one two three four five>; say MixHash.new.classify-list: @mapper, 1, 2, 3, 4, 4, 6; # OUTPUT: MixHash.new((Any), two, three, four(2), one)
The mapper can be a Callable that takes a single argument, an Associative, or an Iterable. With Associative and an Iterable mappers, the values in the @list represent the key and index of the mapper's value respectively. A Callable mapper will be executed once per each item in the @list, with that item as the argument and its return value will be used as the mapper's value.
The mapper's value is used as the key of the Baggy that will be incremented by 1. See .categorize-list if you wish to classify an item into multiple categories at once.
Note: unlike the Hash's .classify-list, returning an Iterable mapper's value will throw, as Baggy types do not support nested classification. For the same reason, Baggy's .classify-list does not accept :&as parameter.
Defined as:
multi method categorize-list(&mapper, *@list --> Baggy:D) multi method categorize-list(%mapper, *@list --> Baggy:D) multi method categorize-list(@mapper, *@list --> Baggy:D)
Populates a mutable Baggy by categorizing the possibly-empty @list of values using the given mapper. The @list cannot be lazy.
say BagHash.new.categorize-list: { gather { take 'largish' if $_ > 5; take .is-prime ?? 'prime' !! 'non-prime'; take $_ %% 2 ?? 'even' !! 'odd'; } }, ^10; # OUTPUT: BagHash.new(largish(4), even(5), non-prime(6), prime(4), odd(5)) my %mapper = :sugar<sweet white>, :lemon<sour>, :cake('sweet', 'is a lie'); say MixHash.new.categorize-list: %mapper, <sugar lemon cake>; # OUTPUT: MixHash.new(is a lie, sour, white, sweet(2))
The mapper can be a Callable that takes a single argument, an Associative, or an Iterable. With Associative and an Iterable mappers, the values in the @list represent the key and index of the mapper's value respectively. A Callable mapper will be executed once per each item in the @list, with that item as the argument and its return value will be used as the mapper's value.
The mapper's value is used as a possibly-empty list of keys of the Baggy that will be incremented by 1.
Note: unlike the Hash's .categorize-list, returning a list of Iterables as mapper's value will throw, as Baggy types do not support nested categorization. For the same reason, Baggy's .categorize-list does not accept :&as parameter.
Defined as:
method keys(Baggy:D: --> Seq:D)
Returns a Seq of all keys in the Baggy object without taking their individual weights into account as opposed to kxxv.
my $breakfast = bag <eggs spam spam spam>; say $breakfast.keys.sort; # OUTPUT: «(eggs spam)» my $n = ("a" => 5, "b" => 2).BagHash; say $n.keys.sort; # OUTPUT: «(a b)»
Defined as:
method values(Baggy:D: --> Seq:D)
Returns a Seq of all values, i.e. weights, in the Baggy object.
my $breakfast = bag <eggs spam spam spam>; say $breakfast.values.sort; # OUTPUT: «(1 3)» my $n = ("a" => 5, "b" => 2, "a" => 1).BagHash; say $n.values.sort; # OUTPUT: «(2 6)»
Defined as:
method kv(Baggy:D: --> Seq:D)
Returns a Seq of keys and values interleaved.
my $breakfast = bag <eggs spam spam spam>; say $breakfast.kv; # OUTPUT: «(spam 3 eggs 1)» my $n = ("a" => 5, "b" => 2, "a" => 1).BagHash; say $n.kv; # OUTPUT: «(a 6 b 2)»
Defined as:
method kxxv(Baggy:D: --> Seq:D)
Returns a Seq of the keys of the invocant, with each key multiplied by its weight. Note that kxxv only works for Baggy types which have integer weights, i.e. Bag and BagHash.
my $breakfast = bag <spam eggs spam spam bacon>; say $breakfast.kxxv.sort; # OUTPUT: «(bacon eggs spam spam spam)» my $n = ("a" => 0, "b" => 1, "b" => 2).BagHash; say $n.kxxv; # OUTPUT: «(b b b)»
Defined as:
method elems(Baggy:D: --> Int:D)
Returns the number of elements in the Baggy object without taking the individual elements weight into account.
my $breakfast = bag <eggs spam spam spam>; say $breakfast.elems; # OUTPUT: «2» my $n = ("b" => 9.4, "b" => 2).MixHash; say $n.elems; # OUTPUT: «1»
Defined as:
method total(Baggy:D:)
Returns the sum of weights for all elements in the Baggy object.
my $breakfast = bag <eggs spam spam bacon>; say $breakfast.total; # OUTPUT: «4» my $n = ("a" => 5, "b" => 1, "b" => 2).BagHash; say $n.total; # OUTPUT: «8»
Defined as:
method default(Baggy:D: --> Int:D)
Returns zero.
my $breakfast = bag <eggs bacon>; say $breakfast.default; # OUTPUT: «0»
Defined as:
method hash(Baggy:D: --> Hash:D)
Returns a Hash where the elements of the invocant are the keys and their respective weights the values.
my $breakfast = bag <eggs bacon bacon>; my $h = $breakfast.hash; say $h.^name; # OUTPUT: «Hash[Any,Any]» say $h; # OUTPUT: «{bacon => 2, eggs => 1}»
Defined as:
method Bool(Baggy:D: --> Bool:D)
Returns True if the invocant contains at least one element.
my $breakfast = ('eggs' => 1).BagHash; say $breakfast.Bool; # OUTPUT: «True (since we have one element)» $breakfast<eggs> = 0; # weight == 0 will lead to element removal say $breakfast.Bool; # OUTPUT: «False»
Defined as:
method Set(--> Set:D)
Returns a Set whose elements are the keys of the invocant.
my $breakfast = (eggs => 2, bacon => 3).BagHash; say $breakfast.Set; # OUTPUT: «set(bacon, eggs)»
Defined as:
method SetHash(--> SetHash:D)
Returns a SetHash whose elements are the keys of the invocant.
my $breakfast = (eggs => 2, bacon => 3).BagHash; my $sh = $breakfast.SetHash; say $sh.^name; # OUTPUT: «SetHash» say $sh.elems; # OUTPUT: «2»
Defined as:
method ACCEPTS($other --> Bool:D)
Used in smartmatching if the right-hand side is a Baggy.
If the right-hand side is the type object, i.e. Baggy, the method returns True if $other does Baggy otherwise False is returned.
If the right-hand side is a Baggy object, True is returned only if $other has the same elements, with the same weights, as the invocant.
my $breakfast = bag <eggs bacon>; say $breakfast ~~ Baggy; # OUTPUT: «True» say $breakfast.does(Baggy); # OUTPUT: «True» my $second-breakfast = (eggs => 1, bacon => 1).Mix; say $breakfast ~~ $second-breakfast; # OUTPUT: «True» my $third-breakfast = (eggs => 1, bacon => 2).Bag; say $second-breakfast ~~ $third-breakfast; # OUTPUT: «False»
Immutable buffer for binary data ('Binary Large OBject')
role Blob[::T = uint8] does Positional[T] does Stringy { }
The Blob role is an immutable interface to binary types, and offers a list-like interface to lists of integers, typically unsigned integers.
Defined as:
multi method new(Blob:) multi method new(Blob: Blob:D $blob) multi method new(Blob: int @values) multi method new(Blob: @values) multi method new(Blob: *@values)
Creates an empty Blob, or a new Blob from another Blob, or from a list of integers or values (which will have to be coerced into integers):
my $blob = Blob.new([1, 2, 3]); say Blob.new(<1 2 3>); # OUTPUT: «Blob:0x<01 02 03>»
Defined as:
multi method Bool(Blob:D:)
Returns False if and only if the buffer is empty.
my $blob = Blob.new(); say $blob.Bool; # OUTPUT: «False» $blob = Blob.new([1, 2, 3]); say $blob.Bool; # OUTPUT: «True»
Defined as:
method Capture(Blob:D)
Equivalent to calling .List.Capture on the invocant.
Defined as:
multi method elems(Blob:D:) multi method elems(Blob:U: --> 1)
Returns the number of elements of the buffer.
my $blob = Blob.new([1, 2, 3]); say $blob.elems; # OUTPUT: «3»
It will also return 1 on the class object.
Defined as:
method bytes(Blob:D: --> Int:D)
Returns the number of bytes used by the elements in the buffer.
say Blob.new([1, 2, 3]).bytes; # OUTPUT: «3» say blob16.new([1, 2, 3]).bytes; # OUTPUT: «6» say blob64.new([1, 2, 3]).bytes; # OUTPUT: «24»
Defined as:
method chars(Blob:D:)
Throws X::Buf::AsStr with chars as payload.
Defined as:
multi method Str(Blob:D:)
Throws X::Buf::AsStr with Str as payload. In order to convert to a Str you need to use .decode.
Defined as:
multi method Stringy(Blob:D:)
Throws X::Buf::AsStr with Stringy as payload.
Defined as:
multi method decode(Blob:D: $encoding = self.encoding // "utf-8")
multi method decode(Blob:D: $encoding, Str :$replacement!, Bool:D :$strict = False)
multi method decode(Blob:D: $encoding, Bool:D :$strict = False)
Applies an encoding to turn the blob into a Str; the encoding will be UTF-8 by default.
my Blob $blob = "string".encode('utf-8'); say $blob.decode('utf-8'); # OUTPUT: «string»
On malformed utf-8 .decode will throw X::AdHoc. To handle sloppy utf-8 use utf8-c8.
Defined as:
multi method list(Blob:D:)
Returns the list of codepoints:
say "zipi".encode("ascii").list; # OUTPUT: «(122 105 112 105)»
Defined as:
method gist(Blob:D: --> Str:D)
Returns the string containing the "gist" of the Blob, listing up to the first 100 elements, separated by space, appending an ellipsis if the Blob has more than 100 elements.
put Blob.new(1, 2, 3).gist; # OUTPUT: «Blob:0x<01 02 03>» put Blob.new(1..2000).gist; # OUTPUT: # Blob:0x<01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 # 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C # 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 # 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A # 5B 5C 5D 5E 5F 60 61 62 63 64 ...>
Defined as:
multi method subbuf(Int $from, Int $len = self.elems --> Blob:D) multi method subbuf(Range $range --> Blob:D)
Extracts a part of the invocant buffer, starting from the index with elements $from, and taking $len elements (or less if the buffer is shorter), and creates a new buffer as the result.
say Blob.new(1..10).subbuf(2, 4); # OUTPUT: «Blob:0x<03 04 05 06>» say Blob.new(1..10).subbuf(*-2); # OUTPUT: «Blob:0x<09 0a>» say Blob.new(1..10).subbuf(*-5,2); # OUTPUT: «Blob:0x<06 07>»
For convenience, also allows a Range to be specified to indicate which part of the invocant buffer you would like:
say Blob.new(1..10).subbuf(2..5); # OUTPUT: «Blob:0x<03 04 05 06>»
Defined as:
multi method allocate(Blob:U: Int:D $elements) multi method allocate(Blob:U: Int:D $elements, int $value) multi method allocate(Blob:U: Int:D $elements, Int:D \value) multi method allocate(Blob:U: Int:D $elements, Mu:D $got) multi method allocate(Blob:U: Int:D $elements, int @values) multi method allocate(Blob:U: Int:D $elements, Blob:D $blob) multi method allocate(Blob:U: Int:D $elements, @values)
Returns a newly created Blob object with the given number of elements. Optionally takes a second argument that indicates the pattern with which to fill the Blob: this can be a single (possibly native) integer value, or any Iterable that generates integer values, including another Blob. The pattern will be repeated if not enough values are given to fill the entire Blob.
my Blob $b0 = Blob.allocate(10,0); $b0.say; # OUTPUT: «Blob:0x<00 00 00 00 00 00 00 00 00 00>»
If the pattern is a general Mu value, it will fail.
This method is considered experimental, in order to use it you will need to do:
use experimental :pack;
Defined as:
multi method unpack(Blob:D: Str:D $template) multi method unpack(Blob:D: @template) multi sub unpack(Blob:D \blob, Str:D $template) multi sub unpack(Blob:D \blob, @template)
Extracts features from the blob according to the template string, and returns them as a list.
The template string consists of zero or more units that begin with an ASCII letter, and are optionally followed by a quantifier. The quantifier can be * (which typically stands for "use up the rest of the Blob here"), or a positive integer (without a +).
Whitespace between template units is ignored.
Examples of valid templates include "A4 C n*" and "A*".
The following letters are recognized:
Letter | Meaning |
---|---|
A | Extract a string, where each element of the Blob maps to a codepoint |
a | Same as A |
C | Extract an element from the blob as an integer |
H | Extracts a hex string |
L | Extracts four elements and returns them as a single unsigned integer |
n | Extracts two elements and combines them in "network" (BigEndian) byte order into a single integer |
N | Extracts four elements and combines them in "network" (BigEndian) byte order into a single integer |
S | Extracts two elements and returns them as a single unsigned integer |
v | Same as S |
V | Same as L |
x | Drop an element from the blob (that is, ignore it) |
Z | Same as A |
Example:
use experimental :pack; say Blob.new(1..10).unpack("C*"); # OUTPUT: «(1 2 3 4 5 6 7 8 9 10)»
This subroutine is considered experimental, in order to use it you will need to do:
use experimental :pack;
multi sub pack(Str $template, *@items) multi sub pack(@template, *@items)
Packs the given items according to the template and returns a buffer containing the packed bytes.
The template string consists of zero or more units that begin with an ASCII letter, and are optionally followed by a quantifier. For details, see unpack.
Defined as:
method reverse(Blob:D: --> Blob:D)
Returns a Blob with all elements in reversed order.
say Blob.new([1, 2, 3]).reverse; # OUTPUT: «Blob:0x<03 02 01>» say blob16.new([2]).reverse; # OUTPUT: «Blob[uint16]:0x<02>» say buf32.new([16, 32]).reverse; # OUTPUT: «Buf[uint32]:0x<20 10>»
These methods are available on the blob8 (and buf8) types only. They allow low level access to reading bytes from the underlying data and interpreting them in different ways with regards to type (integer or floating point (num)), size (8, 16, 32, 64 or 128 bits), signed or unsigned (for integer values) and endianness (native, little and big endianness). The returned values are always expanded to a 64 bit native value where possible, and to a (big) integer value if that is not possible.
Endianness must be indicated by using values of the Endian enum as the second parameter to these methods. If no endianness is specified, NativeEndian will be assumed. Other values are LittleEndian and BigEndian.
Defined as:
method read-uint8(blob8:D: uint $pos, $endian = NativeEndian --> uint)
Returns an unsigned native integer value for the byte at the given position. The $endian parameter has no meaning, but is available for consistency.
Defined as:
method read-int8(blob8:D: uint $pos, $endian = NativeEndian --> int)
Returns a native int value for the byte at the given position. The $endian parameter has no meaning, but is available for consistency.
Defined as:
method read-uint16(blob8:D: uint $pos, $endian = NativeEndian --> uint)
Returns a native uint value for the two bytes starting at the given position.
Defined as:
method read-int16(blob8:D: uint $pos, $endian = NativeEndian --> int)
Returns a native int value for the two bytes starting at the given position.
Defined as:
method read-uint32(blob8:D: uint $pos, $endian = NativeEndian --> uint)
Returns a native uint value for the four bytes starting at the given position.
Defined as:
method read-int32(blob8:D: uint $pos, $endian = NativeEndian --> int)
Returns a native int value for the four bytes starting at the given position.
Defined as:
method read-uint64(blob8:D: uint $pos, $endian = NativeEndian --> UInt:D)
Returns an unsigned integer value for the eight bytes starting at the given position.
Defined as:
method read-int64(blob8:D: uint $pos, $endian = NativeEndian --> int)
Returns a native int value for the eight bytes starting at the given position.
Defined as:
method read-uint128(blob8:D: uint $pos, $endian = NativeEndian --> UInt:D)
Returns an unsigned integer value for the sixteen bytes starting at the given position.
Defined as:
method read-int128(blob8:D: uint $pos, $endian = NativeEndian --> Int:D)
Returns an integer value for the sixteen bytes starting at the given position.
Defined as:
method read-num32(blob8:D: uint $pos, $endian = NativeEndian --> int)
Returns a native num value for the four bytes starting at the given position.
Defined as:
method read-num64(blob8:D: uint $pos, $endian = NativeEndian --> int)
Returns a native num value for the eight bytes starting at the given position.
Defined as:
method read-ubits(blob8:D: uint $pos, uint $bits --> UInt:D)
Returns an unsigned integer value for the bits from the given bit offset and given number of bits. The endianness of the bits is assumed to be BigEndian.
Defined as:
method read-bits(blob8:D: uint $pos, uint $bits --> Int:D)
Returns a signed integer value for the bits from the given bit offset and given number of bits. The endianness of the bits is assumed to be BigEndian.
Code object with its own lexical scope
class Block is Code { }
A Block is a code object meant for small-scale code reuse. A block is created syntactically by a list of statements enclosed in curly braces.
Without an explicit signature or placeholder arguments, a block has $_ as a positional argument
my $block = { uc $_; }; say $block.^name; # OUTPUT: «Block» say $block('hello'); # OUTPUT: «HELLO»
A block can have a Signature between -> or <-> and the block:
my $add = -> $a, $b = 2 { $a + $b }; say $add(40); # OUTPUT: «42»
If the signature is introduced with <-> , then the parameters are marked as rw by default:
my $swap = <-> $a, $b { ($a, $b) = ($b, $a) }; my ($a, $b) = (2, 4); $swap($a, $b); say $a; # OUTPUT: «4»
Blocks that aren't of type Routine (which is a subclass of Block) are transparent to return.
sub f() { say <a b c>.map: { return 42 }; # ^^^^^^ exits &f, not just the block }
The last statement is the implicit return value of the block.
say {1}.(); # OUTPUT: «1»
Bare blocks are automatically executed in the order they appear:
say 1; # OUTPUT: «1» { say 2; # OUTPUT: «2»; executed directly, not a Block object } say 3; # OUTPUT: «3»
Logical boolean
enum Bool <False True>
An enum for boolean true/false decisions.
method ACCEPTS(Bool:D: --> Bool:D)
Used for smartmatch comparison. When the right side is True returns always True, when the right side of the match is False returns always False. In particular, ACCEPTS returns always the instance on which it is invoked, that is the right side of a smartmatch. As an example:
my $b = Bool.new( True ); # when True on the right side returns # always True True ~~ $b; # True False ~~ $b; # True $b = Bool.new( False ); # when False on the right side # returns always False False ~~ $b; # False True ~~ $b; # False
method succ(--> Bool:D)
Returns True.
say True.succ; # OUTPUT: «True» say False.succ; # OUTPUT: «True»
succ is short for "successor"; it returns the next enum value. Bool is a special enum with only two values, False and True. When sorted, False comes first, so True is its successor. And since True is the "highest" Bool enum value, its own successor is also True.
method pred(--> Bool:D)
Returns False.
say True.pred; # OUTPUT: «False» say False.pred; # OUTPUT: «False»
pred is short for "predecessor"; it returns the previous enum value. Bool is a special enum with only two values, False and True. When sorted, False comes first, so False is the predecessor to True. And since False is the "lowest" Bool enum value, its own predecessor is also False.
method enums(--> Hash:D)
Returns a Hash of enum-pairs. Works on both the Bool type and any key.
say Bool.enums; # OUTPUT: «{False => 0, True => 1}» say False.enums; # OUTPUT: «{False => 0, True => 1}»
multi method pick(Bool:U --> Bool:D) multi method pick(Bool:U $count --> Seq:D)
Returns True or False if called without any argument. Otherwise returns $count elements chosen at random (without repetition) from the enum. If * is passed as $count, or $count is greater than or equal to two, then both elements are returned in random order.
say Bool.pick; # OUTPUT: «True» say Bool.pick(1); # OUTPUT: «(False)» say Bool.pick(*); # OUTPUT: «(False True)»
multi method roll(Bool:U --> Bool:D) multi method roll(Bool:U $count --> Seq:D)
Returns True or False if called without any argument. Otherwise returns $count elements chosen at random. Note that each random choice from the enum is made independently, like a separate coin toss where each side of the coin represents one of the two values of the enum. If * is passed as $count an infinite Seq of Bools is returned.
say Bool.roll; # OUTPUT: «True» say Bool.roll(3); # OUTPUT: «(True False False)» say Bool.roll(*); # OUTPUT: «(...)»
multi method Int(Bool:D --> Int:D)
Returns the value part of the enum pair.
say False.Int; # OUTPUT: «0» say True.Int; # OUTPUT: «1»
multi method Numeric(Bool:D --> Int:D)
Returns the value part of the enum pair.
say False.Numeric; # OUTPUT: «0» say True.Numeric; # OUTPUT: «1»
multi sub prefix:<?>(Mu --> Bool:D)
Coerces its argument to Bool.
multi sub prefix:<so>(Mu --> Bool:D)
Coerces its argument to Bool, has looser precedence than prefix:<?> .
Mutable buffer for binary data
role Buf[::T = uint8] does Blob[T] is repr('VMArray') is array_type(T){ ... }
A Buf does the role of a mutable sequence of (usually unsigned) integers.
my $b = Buf.new(1, 2, 3); $b[1] = 42;
However, it's a parameterized type, and you can instantiate with several integer types:
my $b = Buf[int32].new( 3, -3, 0xff32, -44) # OUTPUT: «Buf[int32]:0x<03 -3 FF32 -2C>»
By default, Buf uses 8-bit unsigned integers, that is, it is equivalent to Buf[uint8]. Some other types of Bufs which are used often get their own class name.
buf8 | Buf[uint8] |
buf16 | Buf[uint16] |
buf32 | Buf[uint32] |
buf64 | Buf[uint64] |
You can use these in pretty much the same way you would with Buf:
my $buf = buf8.new(3,6, 254); say $buf; # OUTPUT: «Buf[uint8]:0x<03 06 fe>»
Plus there are some object methods, like encode that might return a buf8 in some cases where it is the best representation for a particular encoding.
method subbuf-rw($from = 0, $elems = self.elems - $from) is rw
A mutable version of subbuf that returns a Proxy functioning as a writable reference to a part of a buffer. Its first argument, $from specifies the index in the buffer from which a substitution should occur, and its last argument, $elems specifies how many elements are to be replaced.
For example, to replace one element at index 3 with two elements, 100 and 101:
my Buf $b .= new(0..5); $b.subbuf-rw(3,1) = Buf.new(100, 101); say $b.perl; # OUTPUT: «Buf.new(0,1,2,100,101,4,5)»
In the case the $elems argument is not specified, the substitution happens at the specified index $from removing all trailing elements:
my Buf $b .= new(0..5); $b.subbuf-rw(3) = Buf.new(200); say $b.perl; # OUTPUT: «Buf.new(0,1,2,200)»
In the case the $from argument is not specified, the substitution happens from the very beginning of the buffer:
my Buf $b .= new(0..5); $b.subbuf-rw = Buf.new(123, 123); say $b.perl; # OUTPUT: «Buf.new(123, 123)»
Declared as
multi sub subbuf-rw(Buf:D \b) is rw multi sub subbuf-rw(Buf:D \b, Int() $from) is rw multi sub subbuf-rw(Buf:D \b, $from, $elems) is rw
Returns a writable reference to a part of a buffer. Invokes the subbuf-rw method on the specified Buf:
my Buf $b .= new(1,2,3); subbuf-rw($b,2,1) = Buf.new(42); say $b.perl; # OUTPUT: «Buf.new(1,2,42)»
method reallocate($elems)
Change the number of elements of the Buf, returning the changed Buf. The size of Buf will be adapted depending on the number of $elems specified: if it is smaller than the actual size of the Buf the resulting Buf will be shrunk down, otherwise it will be enlarged to fit the number of $elems. In the case the Buf is enlarged, newly created items will be assigned a Virtual Machine specific null value, therefore you should not rely upon their value since it could be inconsistent across different virtual machines.
my Buf $b .= new(^10); $b.reallocate(5); say $b.perl; # OUTPUT: «Buf.new(0,1,2,3,4)» $b = Buf.new( 1..3 ); $b.reallocate( 10 ); $b.perl.say; # OUTPUT: «Buf.new(1,2,3,0,0,0,0,0,0,0)»
Defined as:
multi method list(Buf:D:)
Returns a Seq of codepoints.
say Buf.new(122,105,112,205).list; # OUTPUT: «(122 105 112 205)»
method push( $elems )
Adds elements at the end of the buffer
my @φ = 1,1, * + * … ∞; my $bú = Buf.new( @φ[^5] ); $bú.push( @φ[5] ); say $bú.perl; # OUTPUT: «Buf.new(1,1,2,3,5,8)»
method pop()
Extracts the last element of the buffer
say $bú.pop(); # OUTPUT: «8» say $bú.perl; # OUTPUT: «Buf.new(1,1,2,3,5)»
method append( $elems )
Appends at the end of the buffer
$bú.append( @φ[5..10] ); say $bú.perl; # OUTPUT: «Buf.new(1,1,2,3,5,8,13,21,34,55,89)»
method prepend( $elems )
Adds elements at the beginning of the buffer
$bú.prepend( 0 ); say $bú.perl; # OUTPUT: «Buf.new(0,1,1,2,3,5,8,13,21,34,55,89)»
method shift()
Takes out the first element of the buffer
$bú.shift(); say $bú.perl; # OUTPUT: «Buf.new(1,1,2,3,5,8,13,21,34,55,89)»
method unshift()
Adds elements at the beginning of the buffer
$bú.unshift( 0 ); say $bú.perl; # OUTPUT: «Buf.new(0,1,1,2,3,5,8,13,21,34,55,89)»
method splice( Buf:D: $start = 0, $elems?, *@replacement --> Buf)
Substitutes elements of the buffer by other elements
$bú.splice: 0, 3, <3 2 1>; say $bú.perl; # OUTPUT: «Buf.new(3,2,1,2,3,5,8,13,21,34,55,89)»
These methods are available on the buf8 type only. They allow low level access to writing bytes to the underlying data and in different ways with regards to type (integer or floating point (num)), size (8, 16, 32, 64 or 128 bits), signed or unsigned (for integer values) and endianness (native, little and big endianness). These methods always return Nil.
Endianness must be indicated by using values of the Endian enum as the third parameter to these methods. If no endianness is specified, NativeEndian will be assumed. Other values are LittleEndian and BigEndian.
The buffer will be automatically resized to support any bytes being written if it is not large enough yet.
Defined as:
method write-uint8(buf8:D: uint $pos, uint8 $value, $endian = NativeEndian --> Nil)
Writes an unsigned 8-bit integer value at the given position. The $endian parameter has no meaning, but is available for consistency.
Defined as:
method write-int8(buf8:D: uint $pos, int8 $value, $endian = NativeEndian --> Nil)
Writes a signed 8-bit integer value at the given position. The $endian parameter has no meaning, but is available for consistency.
Defined as:
method write-uint16(buf8:D: uint $pos, uint16 $value, $endian = NativeEndian --> Nil)
Writes an unsigned 16-bit integer value at the given position with the given endianness.
Defined as:
method write-int16(buf8:D: uint $pos, int16 $value, $endian = NativeEndian --> Nil)
Writes a signed 16-bit integer value at the given position with the given endianness.
Defined as:
method write-uint32(buf8:D: uint $pos, uint32 $value, $endian = NativeEndian --> Nil)
Writes an unsigned 32-bit integer value at the given position with the given endianness.
Defined as:
method write-int32(buf8:D: uint $pos, int32 $value, $endian = NativeEndian --> Nil)
Writes a signed 32-bit integer value at the given position with the given endianness.
Defined as:
method write-uint64(buf8:D: uint $pos, uint64 $value, $endian = NativeEndian --> Nil)
Writes an unsigned 64-bit integer value at the given position with the given endianness.
Defined as:
method write-int64(buf8:D: uint $pos, Int:D $value, $endian = NativeEndian --> Nil)
Writes a signed 64-bit integer value at the given position with the given endianness.
Defined as:
method write-uint128(buf8:D: uint $pos, UInt:D $value, $endian = NativeEndian --> Nil)
Writes an unsigned 128-bit integer value at the given position with the given endianness.
Defined as:
method write-int128(buf8:D: uint $pos, Int:D $value, $endian = NativeEndian --> Nil)
Writes a signed 128-bit integer value at the given position with the given endianness.
Defined as:
method write-num32(buf8:D: uint $pos, num32 $value, $endian = NativeEndian --> Nil)
Writes a native num32 IEEE floating point value at the given position with the given endianness.
Defined as:
method write-num64(buf8:D: uint $pos, num64 $value, $endian = NativeEndian --> Nil)
Writes a native num64 IEEE floating point value at the given position with the given endianness.
Defined as:
method write-ubits(buf8:D: uint $pos, uint $bits, UInt:D $value --> Nil)
Writes an unsigned integer value to the bits from the given bit offset and given number of bits. The endianness of the bits is assumed to be BigEndian. Always returns Nil.
Defined as:
method write-bits(buf8:D: uint $pos, uint $bits, Int:D $value --> Nil)
Writes a signed integer value for the bits from the given bit offset and given number of bits. The endianness of the bits is assumed to be BigEndian. Always returns Nil.
Done control exception
role CX::Done does X::Control { }
A control exception to be used to indicate a supply block is finished by calling done.
Defined as:
method message()
Returns "<done control exception>"
Emit control exception
role CX::Emit does X::Control { }
A control exception to be used when emit is used inside a Supply block.
Defined as:
method message()
Returns "<emit control exception>"
Last control exception
role CX::Last does X::Control { }
A control exception that is thrown when last is called.
Defined as:
method message()
Returns "<last control exception>". Since this type of exception is to be consumed by type and not really by the content of the message, this is a generic message, similar to all other CX::* exceptions.
Next control exception
role CX::Next does X::Control { }
A control exception that is triggered when next is called.
for ^10 { CONTROL { when CX::Next { say "We're next" }; } next if $_ %% 2; say "We're in $_"; }
This will print:
We're next We're in 1 We're next We're in 3 We're next We're in 5 We're next We're in 7 We're next We're in 9
Defined as:
method message()
Returns "<next control exception>"
Proceed control exception
role CX::Proceed does X::Control { }
A control exception to be used when proceed is used within when or default blocks.
Defined as:
method message()
Returns "<proceed control exception>"
Redo control exception
role CX::Redo does X::Control { }
A control exception thrown when redo is called.
Defined as:
method message()
Returns "<redo control exception>".
Return control exception
role CX::Next does X::Control { }
A control exception to be used when return is called from within a sub.
Defined as:
method message()
Returns "<return control exception>"
Succeed control exception
role CX::Succeed does X::Control { }
A control exception thrown when succeed is called from a when or default block.
Defined as:
method message()
Returns "<next control exception>"
Take control exception
role CX::Take does X::Control { }
A control exception triggered by take.
Defined as:
method message()
Returns "<take control exception>".
Control exception warning
role CX::Warn does X::Control { }
A control exception triggered when warn is called to warn about any incidence.
CX::Warn objects are created when a warning is thrown in any block.
Captures the current frame state
class CallFrame {}
A CallFrame will be usually captured from the current state of a program using the callframe subroutine.
my $frame = callframe; say "The above line of code ran at {$frame.file}:{$frame.line}.";
With no arguments the callframe will give you frame information for the line calling callframe. The file and line annotations will be identical to those in $?FILE and $?LINE.
You may, however, pass a number to callframe to specify a different frame level. A positive number will move upward through the levels of frame. A negative number will move downward into the callframe method and class itself at the point at which they are running to construct this information for you.
The frames themselves do not necessarily match only method or subroutine calls. Perl constructs a frames for blocks and such as well, so if you need a callframe for a particular method call, do not assume it is a fixed number of levels up.
Each frame stores annotations, including the file and line annotations, which have convenience methods for accessing them directly. You can also retrieve a reference to the code block of the currently executing frame using the code method. The frame also captures all lexical variables stored with the frame, which are available by calling my on the frame object.
Here's a short example that will find the calling routine and print the package of the caller using the callframe interface.
sub calling-frame() { for 1..* -> $level { given callframe($level) -> $frame { when $frame ~~ CallFrame { next unless $frame.code ~~ Routine; say $frame.code.package; last; } default { say "no calling routine or method found"; last; } } } } calling-frame;
If you just need to trace caller information, Backtrace may provide a better means of getting it. CallFrame contains more information about a specific frame, but provides a tedious interface for enumerating a call stack.
Note From version 6.d, .perl can be called on CallFrame.
method code()
Return the callable code for the current block. When called on the object returned by callframe(0), this will be the same value found in &?BLOCK.
my $frame; for ^3 { FIRST $frame = callframe; say $_ * 3 }; say $frame.code()
The $frame variable will hold the Code for the block inside the loop in this case.
method file()
This is a shortcut for looking up the file annotation. Therefore, the following code prints True.
my $frame = callframe(0); say $frame.file eq $frame.annotations<file>;
method line()
This is a shortcut for looking up the line annotation. For example, the following two calls are identical.
say callframe(1).line; say callframe(1).annotations<line>;
method annotations()
Returns a Map containing the invocants annotations, i.e. line and file. An easier way to get hold of the annotation information is to use one of the convenience methods instead.
say callframe.annotations.^name; # OUTPUT: «Map» say callframe.annotations<file> eq callframe.file; # OUTPUT: «True»
method my()
Return a Hash that names all the variables and their values associated with the lexical scope of the frame.
sub some-value { my $the-answer = 42; callframe(0); } my $frame = some-value(); say $frame.my<$the-answer>; # OUTPUT: «42»
sub callframe(Int:D $level = 0)
Returns a CallFrame object for the given level. If no level is given, the default level is 0. Positive levels move up the frame stack and negative levels move down (into the call to callframe and deeper).
Returns Mu if there is no call information for the given level. Negative levels may result in an exception.
Invocable code object
role Callable { ... }
Role for objects which support calling them. It's used in Block, Routine, Sub, Method, Submethod and Macro types.
Callables can be stored in &-sigiled containers, the default type constraint of such a container is Callable.
A signature object can be used to force a check against the signature of the Callable to be stored into the container.my &a = {;}; # Empty block needs a semicolon my &b = -> {}; my &c = sub () {}; sub foo() {}; my &d = &foo;commented out until it's implemented for code :skip-test my &f:(Int) = sub bar(Int) {}; # Not yet implemented my &f:(Str) = -> Str {}; # Not yet implemented
method CALL-ME(Callable:D $self: |arguments)
This method is required for postfix:«( )» and postfix:«.( )». It's what makes an object actually call-able and needs to be overloaded to let a given object act like a routine. If the object needs to be stored in a &-sigiled container, is has to implement Callable.
class A does Callable { submethod CALL-ME(|c){ 'called' } } my &a = A; say a(); # OUTPUT: «called»
Defined as:
method Capture()
Throws X::Cannot::Capture.
Removal of a task from a Scheduler before normal completion
my class Cancellation {}
A low level part of the Perl 6 concurrency system. Some Scheduler objects return a Cancellation with the .cue method which can be used to cancel the scheduled execution before normal completion. Cancellation.cancelled is a boolean that is true after #cancel is called.
Defined as:
method cancel()
Usage:
Cancellation.cancel
Cancels the scheduled execution of a task before normal completion.
Argument list suitable for passing to a Signature
class Capture { }
A Capture is a container for passing arguments to a code object. Captures are the flip-side of Signatures – Captures are the caller defined arguments, while Signatures are the callee defined parameters.
When you call print $a, $b, the $a, $b part is a Capture.
Captures contain a list-like part for positional arguments and a hash-like part for named arguments, thus behaving as Positional and Associative, although it does not actually mixes in those roles. For the named arguments, Captures use a slightly different syntax than a normal List. There are two easy ways to make a named argument: 1) use an unquoted key naming a parameter, followed by =>, followed by the argument and 2) use a colon-pair literal named after the parameter:
say unique 1, -2, 2, 3, as => { abs $_ }; # OUTPUT: «(1 -2 3)» # ... is the same thing as: say unique 1, -2, 2, 3, :as({ abs $_ }); # OUTPUT: «(1 -2 3)» # Be careful not to quote the name of a named parameter: say unique 1, -2, 2, 3, 'as' => { abs $_ }; # OUTPUT: «(1 -2 2 3 as => -> ;; $_? is raw { #`(Block|78857320) ... })»
A stand-alone Capture can also be made, stored, and used later. A literal Capture can be created by prefixing a term with a backslash \. Commonly, this term will be a List of terms, from which any Pair literal will be placed in the named part, and all other terms will be placed in the positional part.
my $c = \(42); # Capture with one positional part $c = \(1, 2, a => 'b'); # Capture with two positional and one named parts
To use such a Capture, you may use '|' before it in a function call, and it will be as if the values in the Capture were passed directly to the function as arguments – named arguments will be passed as named arguments and positional arguments will be passed as positional arguments. You may re-use the Capture as many times as you want, even with different functions.
my $c = \(4, 2, 3); reverse(|$c).say; # OUTPUT: «3 2 4» sort(5,|$c).say; # OUTPUT: «2 3 4 5»
Inside a Signature, a Capture may be created by prefixing a sigilless parameter with a vertical bar |. This packs the remainder of the argument list into that parameter.
f(1, 2, 3, a => 4, b => 5); sub f($a, |c) { # c is \(2, 3, a => 4, b => 5) }
Note that Captures are still Lists in that they may contain containers, not just values:
my $b = 1; my $c = \(4, 2, $b, 3); sort(|$c).say; # OUTPUT: «1 2 3 4» $b = 6; sort(|$c).say; # OUTPUT: «2 3 4 6»
Defined as:
method list(Capture:D:)
Returns the positional part of the Capture.
my Capture $c = \(2, 3, 5, apples => (red => 2)); say $c.list; # OUTPUT: «(2 3 5)»
Defined as:
method hash(Capture:D:)
Returns the named/hash part of the Capture.
my Capture $c = \(2, 3, 5, apples => (red => 2)); say $c.hash; # OUTPUT: «Map.new((:apples(:red(2))))»
Defined as:
method elems(Capture:D: --> Int:D)
Returns the number of positional elements in the Capture.
my Capture $c = \(2, 3, 5, apples => (red => 2)); say $c.elems; # OUTPUT: «3»
Defined as:
multi method keys(Capture:D: --> Seq:D)
Returns a Seq containing all positional keys followed by all named keys. For positional arguments the keys are the respective arguments ordinal position starting from zero.
my $capture = \(2, 3, 5, apples => (red => 2)); say $capture.keys; # OUTPUT: «(0 1 2 apples)»
Defined as:
multi method values(Capture:D: --> Seq:D)
Returns a Seq containing all positional values followed by all named argument values.
my $capture = \(2, 3, 5, apples => (red => 2)); say $capture.values; # OUTPUT: «(2 3 5 red => 2)»
Defined as:
multi method kv(Capture:D: --> Seq:D)
Returns a Seq of alternating keys and values. The positional keys and values, if any, comes first followed by the named keys and values.
my $capture = \(2, 3, apples => (red => 2)); say $capture.kv; # OUTPUT: «(0 2 1 3 apples red => 2)»
Defined as:
multi method pairs(Capture:D: --> Seq:D)
Returns all arguments, the positional followed by the named, as a Seq of Pairs. Positional arguments have their respective ordinal value, starting at zero, as key while the named arguments have their names as key.
my Capture $c = \(2, 3, apples => (red => 2)); say $c.pairs; # OUTPUT: «(0 => 2 1 => 3 apples => red => 2)»
Defined as:
multi method antipairs(Capture:D: --> Seq:D)
Returns all arguments, the positional followed by the named, as a Seq of pairs where the keys and values have been swapped, i.e. the value becomes the key and the key becomes the value. This behavior is the opposite of the pairs method.
my $capture = \(2, 3, apples => (red => 2)); say $capture.antipairs; # OUTPUT: «(2 => 0 3 => 1 (red => 2) => apples)»
Defined as:
method Bool(Capture:D: --> Bool:D)
Returns True if the Capture contains at least one named or one positional argument.
say \(1,2,3, apples => 2).Bool; # OUTPUT: «True» say \().Bool; # OUTPUT: «False»
Defined as:
method Capture(Capture:D: --> Capture:D)
Returns itself, i.e. the invocant.
say \(1,2,3, apples => 2).Capture; # OUTPUT: «\(1, 2, 3, :apples(2))»
Defined as:
method Numeric(Capture:D: --> Int:D)
Returns the number of positional elements in the Capture.
say \(1,2,3, apples => 2).Numeric; # OUTPUT: «3»
Thread-safe queue for sending values from producers to consumers
class Channel {}
A Channel is a thread-safe queue that helps you to send a series of objects from one or more producers to one or more consumers. Each object will arrive at only one such consumer, selected by the scheduler. If there is only one consumer and one producer, the order of objects is guaranteed to be preserved. Sending on a Channel is non-blocking.
my $c = Channel.new; await (^10).map: { start { my $r = rand; sleep $r; $c.send($r); } } $c.close; say $c.list;
Further examples can be found in the concurrency page
Defined as:
method send(Channel:D: \item)
Enqueues an item into the Channel. Throws an exception of type X::Channel::SendOnClosed if the channel has been closed already. This call will not block waiting for a consumer to take the object. There is no set limit on the number of items that may be queued, so care should be taken to prevent runaway queueing.
my $c = Channel.new; $c.send(1); $c.send([2, 3, 4, 5]); $c.close; say $c.list; # OUTPUT: «(1 [2 3 4 5])»
Defined as:
method receive(Channel:D:)
Receives and removes an item from the channel. It blocks if no item is present, waiting for a send from another thread.
Throws an exception of type X::Channel::ReceiveOnClosed if the channel has been closed, and the last item has been removed already, or if close is called while receive is waiting for an item to arrive.
If the channel has been marked as erratic with method fail, and the last item has been removed, throws the argument that was given to fail as an exception.
See method poll for a non-blocking version that won't throw exceptions.
my $c = Channel.new; $c.send(1); say $c.receive; # OUTPUT: «1»
Defined as:
method poll(Channel:D:)
Receives and removes an item from the channel. If no item is present, returns Nil instead of waiting.
my $c = Channel.new; Promise.in(2).then: { $c.close; } ^10 .map({ $c.send($_); }); loop { if $c.poll -> $item { $item.say }; if $c.closed { last }; sleep 0.1; }
See method receive for a blocking version that properly responds to channel closing and failure.
Defined as:
method close(Channel:D:)
Close the Channel, normally. This makes subsequent send calls die with X::Channel::SendOnClosed. Subsequent calls of .receive may still drain any remaining items that were previously sent, but if the queue is empty, will throw an X::Channel::ReceiveOnClosed exception. Since you can produce a Seq from a Channel by contextualizing to array with @() or by calling the .list method, these methods will not terminate until the channel has been closed. A whenever-block will also terminate properly on a closed channel.
my $c = Channel.new; $c.close; $c.send(1); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Channel::SendOnClosed: Cannot send a message on a closed channel»
Please note that any exception thrown may prevent .close from being called, this may hang the receiving thread. Use a LEAVE phaser to enforce the .close call in this case.
Defined as:
method list(Channel:D: --> List:D)
Returns a list based on the Seq which will iterate items in the queue and remove each item from it as it iterates. This can only terminate once the close method has been called.
my $c = Channel.new; $c.send(1); $c.send(2); $c.close; say $c.list; # OUTPUT: «(1 2)»
Defined as:
method closed(Channel:D: --> Promise:D)
Returns a promise that will be kept once the channel is closed by a call to method close.
my $c = Channel.new; $c.closed.then({ say "It's closed!" }); $c.close; sleep 1;
Defined as:
method fail(Channel:D: $error)
Closes the Channel (that is, makes subsequent send calls die), and enqueues the error to be thrown as the final element in the channel. Method receive will throw that error as an exception. Does nothing if the channel has already been closed or .fail has already been called on it.
my $c = Channel.new; $c.fail("Bad error happens!"); $c.receive; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::AdHoc: Bad error happens!»
Defined as:
method Capture(Channel:D --> Capture:D)
Equivalent to calling .List.Capture on the invocant.
Defined as:
method Supply(Channel:D:)
This returns an on-demand Supply that emits a value for every value received on the Channel. done will be called on the Supply when the Channel is closed.
my $c = Channel.new; my Supply $s1 = $c.Supply; my Supply $s2 = $c.Supply; $s1.tap(-> $v { say "First $v" }); $s2.tap(-> $v { say "Second $v" }); ^10 .map({ $c.send($_) }); sleep 1;
Multiple calls to this method produce multiple instances of Supply, which compete over the values from the Channel.
Defined as:
multi sub await(Channel:D) multi sub await(*@)
Waits until all of one or more channels has a value available, and returns those values (it calls .receive on the channel). Also works with promises.
my $c = Channel.new; Promise.in(1).then({$c.send(1)}); say await $c;
Since 6.d, it no longer blocks a thread while waiting.
Code object
class Code is Any does Callable {}
Code is the ultimate base class of all code objects in Perl 6. It exposes functionality that all code objects have. While thunks are directly of type Code, most code objects (such as those resulting from blocks, subroutines or methods) will belong to some subclass of Code.
multi method ACCEPTS(Code:D: Mu $topic)
Usually calls the code object and passes $topic as an argument. However, when called on a code object that takes no arguments, the code object is invoked with no arguments and $topic is dropped. The result of the call is returned.
Defined as:
method arity(Code:D: --> Int:D)
Returns the minimum number of positional arguments that must be passed in order to call the code object. Any optional or slurpy parameters in the code object's Signature do not contribute, nor do named parameters.
sub argless() { } sub args($a, $b?) { } sub slurpy($a, $b, *@c) { } say &argless.arity; # OUTPUT: «0» say &args.arity; # OUTPUT: «1» say &slurpy.arity; # OUTPUT: «2»
method assuming(Callable:D $self: |primers)
Returns a Callable that implements the same behavior as the original, but has the values passed to .assuming already bound to the corresponding parameters.
my sub slow($n){ my $i = 0; $i++ while $i < $n; $i }; # takes only one parameter and as such wont forward $n sub bench(&c){ c, now - ENTER now }; say &slow.assuming(10000000).&bench; # OUTPUT: «(10000000 7.5508834)»
For a sub with arity greater than one, you can use Whatever * for all of the positional parameters that are not "assumed".
sub first-and-last ( $first, $last ) { say "Name is $first $last"; } my &surname-smith = &first-and-last.assuming( *, 'Smith' ); &surname-smith.( 'Joe' ); # OUTPUT: «Name is Joe Smith»
You can handle any combination of assumed and not assumed positional parameters:
sub longer-names ( $first, $middle, $last, $suffix ) { say "Name is $first $middle $last $suffix"; } my &surname-public = &longer-names.assuming( *, *, 'Public', * ); &surname-public.( 'Joe', 'Q.', 'Jr.'); # OUTPUT: «Name is Joe Q. Public Jr.»
Named parameters can be assumed as well:
sub foo { say "$^a $^b $:foo $:bar" } &foo.assuming(13, :42foo)(24, :72bar); # OUTPUT: «13 24 42 72»
And you can use .assuming on all types of Callables, including Methods and Blocks:
# We use a Whatever star for the invocant: my &comber = Str.^lookup('comb').assuming: *, /P \w+/; say comber 'Perl is awesome! Python is great! And PHP is OK too'; # OUTPUT: «(Perl Python PHP)» my &learner = { "It took me $:months months to learn $^lang" }.assuming: 'Perl 6'; say learner :6months; # OUTPUT: «It took me 6 months to learn Perl 6»
Defined as:
method count(Code:D: --> Real:D)
Returns the maximum number of positional arguments that may be passed when calling the code object. For code objects that can accept any number of positional arguments (that is, they have a slurpy parameter), count will return Inf. Named parameters do not contribute.
sub argless() { } sub args($a, $b?) { } sub slurpy($a, $b, *@c) { } say &argless.count; # OUTPUT: «0» say &args.count; # OUTPUT: «2» say &slurpy.count; # OUTPUT: «Inf»
Defined as:
method of(Code:D: --> Mu)
Returns the return type constraint of the Code:
say -> () --> Int {}.of; # OUTPUT: «(Int)»
Defined as:
multi method signature(Code:D: --> Signature:D)
Returns the Signature object for this code object, which describes its parameters.
sub a(Int $one, Str $two) {}; say &a.signature; # OUTPUT: «(Int $one, Str $two)»
method cando(Capture $c)
Returns a list of candidates that can be called with the given Capture. Since Code objects do not have any multiple dispatch, this either returns a list with the object, or an empty list.
my $single = \'a'; # a single argument Capture my $plural = \('a', 42); # a two argument Capture my &block = { say $^a }; # a Block object, that is a subclass of Code, taking one argument say &block.cando($single); # OUTPUT: «(-> $a { #`(Block|94212856419136) ... })» say &block.cando($plural); # OUTPUT: «()»
Defined as:
multi method Str(Code:D: --> Str:D)
Will output the method name, but also produce a warning. Use .perl or .gist instead.
sub marine() { } say ~&marine; # OUTPUT: «Sub object coerced to string (please use .gist or .perl to do that)marine» say &marine.Str; # OUTPUT: «Sub object coerced to string (please use .gist or .perl to do that)marine» say &marine.perl; # OUTPUT: «sub marine { #`(Sub|94280758332168) ... }»
Defined as:
method file(Code:D: --> Str:D)
Returns the name of the file in which the code object was declared.
say &infix:<+>.file;
Defined as
method line(Code:D: --> Int:D)
Returns the line number in which the code object was declared.
say &infix:<+>.line;
Encapsulates how strings are sorted
class Collation { }
Collation is the class that allows proper sorting, taking into account all Unicode characteristics. It's the class the object $*COLLATION is instantiated to, and thus includes collation levels, that is, what kind of features should be looked up when comparing two strings and in which order.
Defined as:
method set ( Int :$primary = 1, Int :$secondary = 1, Int :$tertiary = 1, Int :$quaternary = 1)
Sets if the different levels should be used in ascending or descending order, or if they are going to be ignored (when set to 0).
my $*COLLATION = Collation.new; say 'a' coll 'z'; # OUTPUT: «Less» $*COLLATION.set(:primary(-1)); say 'a' coll 'z'; # OUTPUT: «More»
Defined as:
method primary
Returns the state of the primary collation level.
Defined as:
method secondary
Returns the state of the secondary collation level.
Defined as:
method tertiary
Returns the state of the tertiary collation level.
Defined as:
method quaternary
Returns the state of the quaternary collation level.
CompUnit
class CompUnit {}
The CompUnit represents the meta-information about a compilation unit. This usually relates to source code that resides in a file on a filesystem, rather than code that is executed using an EVAL statement.
method auth(--> Str:D)
Returns the authority information with which the CompUnit object was created (if any).
method distribution(--> Distribution:D)
Returns the Distribution object with which the CompUnit object was created (if any).
method from(--> Str:D)
Returns the name of the language with which the CompUnit object was created (if any). It will be Perl6 by default.
method precompiled(--> Bool:D)
Returns whether the CompUnit object originated from a precompiled source.
method repo(--> CompUnit::Repository:D)
Returns the CompUnit::Repository object with which the CompUnit object was created.
method repo-id(--> Str:D)
Returns the identification string with which the CompUnit object can be identified in the associated repo.
method short-name(--> Str:D)
Returns The short name with which the CompUnit object was created (if any).
method version(--> Version:D)
Returns the version information with which the CompUnit object was created (if any).
CompUnit::Repository
The CompUnit::Repository role defines the interface of the implementation of CompUnit::Repositories such as CompUnit::Repository::Installation and CompUnit::Repository::FileSystem.
method resolve(CompUnit::DependencySpecification $spec --> CompUnit:D)
Returns a CompUnit mapped to the highest version distribution matching $spec from the first repository in the repository chain that contains any version of a distribution matching $spec.
Loads and returns a CompUnit which is mapped to the highest version distribution matching $spec from the first repository in the repository chain that contains any version of a distribution matching $spec.
method load(IO::Path:D $file --> CompUnit:D)
Load the $file and return a CompUnit object representing it.
method loaded(--> Iterable:D)
Returns all CompUnits this repository has loaded.
CompUnit::Repository::FileSystem
class CompUnit::Repository::FileSystem does CompUnit::Repository::Locally does CompUnit::Repository { }
A CompUnit::Repository implementation backed by the filesystem typically used in development situations. This is what is used by -I . / -I lib (which are actually -I file#. and -I file#lib) or use lib "." / use lib "lib". Unlike CompUnit::Repository::Installation, this represents a single distribution.
multi method candidates(Str:D $name, :$auth, :$ver, :$api) multi method candidates(CompUnit::DependencySpecification $spec)
Return all distributions that contain a module matching the specified $name, auth, ver, and api.
# assuming one is cloned into the zef git repository... my $repo = CompUnit::Repository::FileSystem.new(prefix => $*CWD); with $repo.candidates("Zef").head -> $dist { say "Zef version: " ~ $dist.meta<version>; } else { say "No candidates for 'Zef' found"; }
multi method files(Str:D $name, :$auth, :$ver, :$api) multi method files(CompUnit::DependencySpecification $spec)
Return all distributions that match the specified auth ver and api, and contains a non-module file matching the specified $name.
# assuming one is cloned into the zef git repository... my $repo = CompUnit::Repository::FileSystem.new(prefix => $*CWD); say $repo.files('bin/zef', :ver<419.0+>).head.<name> // "Nada"; # OUTPUT: «Nada» say $repo.files('resources/config.txt', :ver<419.0+>).head.<name> // "Nada"; # OUTPUT: «Nada» say $repo.files('bin/zef', :ver<0.4.0+>).head.<name>; # OUTPUT: «zef» say $repo.files('resources/config.txt', :ver<0.4.0+>).head.<name>; # OUTPUT: «zef»
method resolve(CompUnit::DependencySpecification $spec --> CompUnit:D)
Returns a CompUnit mapped to the highest version distribution matching $spec from the first repository in the repository chain that contains any version of a distribution matching $spec.
method need( CompUnit::DependencySpecification $spec, CompUnit::PrecompilationRepository $precomp = self.precomp-repository(), CompUnit::PrecompilationStore :@precomp-stores = self!precomp-stores(), --> CompUnit:D)
Loads and returns a CompUnit which is mapped to the highest version distribution matching $spec from the first repository in the repository chain that contains any version of a distribution matching $spec.
method load(IO::Path:D $file --> CompUnit:D)
Load the $file and return a CompUnit object representing it.
method loaded(--> Iterable:D)
Returns all CompUnits this repository has loaded.
method short-id()
Returns the repo short-id, which for this repository is file.
CompUnit::Repository::Installation
class CompUnit::Repository::Installation does CompUnit::Repository::Locally does CompUnit::Repository::Installable { }
A CompUnit::Repository implementation backed by the filesystem, but uses an internal storage format to:
Handle case sensitivity issues on filesystems that may conflict as a CompUnit::Repository::FileSystem.
Handle allowable filename issues (e.g. unicode) on filesystems that don't support them.
Allow multiple distributions with the same name, but with different ver and/or auth and/or api values, to be installed and separately accessible in a single repository.
Enable faster module loading by providing module precompilation.
Because of the internal storage format the usual way to add a distribution is not by copying files but by calling CompUnit::Repository::Installation#method_install.
method install(Distribution $distribution, Bool :$force)
Copies modules into a special location so that they can be loaded afterwards.
:$force will allow installing over an existing distribution that has the same name, auth, api, and ver. Otherwise such a situation will result in Failure.
my $inst-repo = CompUnit::RepositoryRegistry.repository-for-name("site"); my $dist = Distribution::Path.new(...); $inst-repo.install($dist);
method uninstall(Distribution $distribution)
Removes the $distribution from the repository. $distribution should be obtained from the repository it is being removed from:
my $inst-repo = CompUnit::RepositoryRegistry.repository-for-name("site"); my $dist = $inst-repo.candidates("Acme::Unused").head; $inst-repo.uninstall($dist);
multi method candidates(Str:D $name, :$auth, :$ver, :$api) multi method candidates(CompUnit::DependencySpecification $spec)
Return all distributions that contain a module matching the specified $name, auth, ver, and api.
my $inst-repo-path = CompUnit::RepositoryRegistry.repository-for-name("perl").prefix; my $inst-repo = CompUnit::Repository::Installation.new(prefix => $inst-repo-path); my $dist = $inst-repo.candidates("Test").head; say "Test version: " ~ $dist.meta<ver>; # OUTPUT: «6.d»
multi method files(Str:D $name, :$auth, :$ver, :$api) multi method files(CompUnit::DependencySpecification $spec)
Return all distributions that match the specified auth ver and api, and contains a non-module file matching the specified $name.
# assuming Zef is installed to the default location... my $repo = CompUnit::RepositoryRegistry.repository-for-name("site"); say $repo.files('bin/zef', :ver<419.0+>).head.<name> // "Nada"; # OUTPUT: «Nada» say $repo.files('resources/config.txt', :ver<419.0+>).head.<name> // "Nada"; # OUTPUT: «Nada» say $repo.files('bin/zef', :ver<0.4.0+>).head.<name>; # OUTPUT: «zef» say $repo.files('resources/config.txt', :ver<0.4.0+>).head.<name>; # OUTPUT: «zef»
method resolve(CompUnit::DependencySpecification $spec --> CompUnit:D)
Returns a CompUnit mapped to the highest version distribution matching $spec from the first repository in the repository chain that contains any version of a distribution matching $spec.
method need( CompUnit::DependencySpecification $spec, CompUnit::PrecompilationRepository $precomp = self.precomp-repository(), CompUnit::PrecompilationStore :@precomp-stores = self!precomp-stores(), --> CompUnit:D)
Loads and returns a CompUnit which is mapped to the highest version distribution matching $spec from the first repository in the repository chain that contains any version of a distribution matching $spec.
method load(IO::Path:D $file --> CompUnit:D)
Load the $file and return a CompUnit object representing it.
method loaded(--> Iterable:D)
Returns all CompUnits this repository has loaded.
method short-id()
Returns the repo short-id, which for this repository is inst.
Information related to the compiler that is being used
class Compiler does Systemic {}
Built-in class for providing compiler related information. Usually accessed through the compiler attribute of the $*PERL dynamic variable.
say $*PERL.compiler; # OUTPUT: «rakudo (2019.03.1.385.ga.643.b.8.be.1)»
Returns an unique identifier, a long hexadecimal string
It's empty, but it might contain the release number for specific releases.
It's empty, but it might contain the codename for specific releases.
method build-date()
Up to version 2019.03.1, it returns the date when it was built.
say $*PERL.compiler.build-date; #OUTPUT: «2018-05-05T21:49:43Z»
method verbose-config(:$say)
If $say is True, it prints the different items included in the configuration of the compiler; if it is not, returns a Hash with the same information.
say $*PERL.compiler.verbose-config; # OUTPUT: «distro::auth=https://www.opensuse.org/distro::desc=2018-05-06T09:19:17.571307+02:00» ... And the rest of the configuration
See Also: Systemic
Complex number
class Complex is Cool does Numeric {}
Represents a number in the complex plane.
Complex objects are immutable.
Adding a trailing i to a number literal makes it a Complex, for example:
say 2i; # same as Complex.new(0, 2); say 1-2e3i; # same as Complex.new(1, -2e3);
Defined as:
multi method new(Real $re, Real $im --> Complex:D)
Creates a new Complex object from real and imaginary parts.
my $complex = Complex.new(1, 1); say $complex; # OUTPUT: «1+1i»
When created without arguments, both parts are considered to be zero.
say Complex.new; # OUTPUT: «0+0i»
Defined as:
method re(Complex:D: --> Real:D)
Returns the real part of the complex number.
say (3+5i).re; # OUTPUT: «3»
Defined as:
method im(Complex:D: --> Real:D)
Returns the imaginary part of the complex number.
say (3+5i).im; # OUTPUT: «5»
Defined as:
method reals(Complex:D: --> Positional:D)
Returns a two-element list containing the real and imaginary parts for this value.
say (3+5i).reals; # OUTPUT: «(3 5)»
Defined as:
method isNaN(Complex:D: --> Bool:D)
Returns true if the real or imaginary part is NaN (not a number).
say (NaN+5i).isNaN; # OUTPUT: «True» say (7+5i).isNaN; # OUTPUT: «False»
Defined as:
method polar(Complex:D: --> Positional:D)
Returns a two-element list of the polar coordinates for this value, i.e. magnitude and angle in radians.
say (10+7i).polar; # OUTPUT: «(12.2065556157337 0.610725964389209)»
Defined as:
method floor(Complex:D: --> Complex:D)
Returns self.re.floor + self.im.floor. That is, each of the real and imaginary parts is rounded to the highest integer not greater than the value of that part.
say (1.2-3.8i).floor; # OUTPUT: «1-4i»
Defined as:
method ceiling(Complex:D: --> Complex:D)
Returns self.re.ceiling + self.im.ceiling. That is, each of the real and imaginary parts is rounded to the lowest integer not less than the value of that part.
say (1.2-3.8i).ceiling; # OUTPUT: «2-3i»
Defined as:
multi method round(Complex:D: --> Complex:D) multi method round(Complex:D: Real() $scale --> Complex:D)
With no arguments, rounds both the real and imaginary parts to the nearest integer and returns a new Complex number. If $scale is given, rounds both parts of the invocant to the nearest multiple of $scale. Uses the same algorithm as Real.round on each part of the number.
say (1.2-3.8i).round; # OUTPUT: «1-4i» say (1.256-3.875i).round(0.1); # OUTPUT: «1.3-3.9i»
Defined as:
method truncate(Complex:D: --> Complex:D)
Removes the fractional part of both the real and imaginary parts of the number, using Real.truncate, and returns the result as a new Complex.
say (1.2-3.8i).truncate; # OUTPUT: «1-3i»
Defined as:
method abs(Complex:D: --> Num:D) multi sub abs(Complex:D $z --> Num:D)
Returns the absolute value of the invocant (or the argument in sub form). For a given complex number $z the absolute value |$z| is defined as sqrt($z.re * $z.re + $z.im * $z.im).
say (3+4i).abs; # OUTPUT: «5» # sqrt(3*3 + 4*4) == 5
Defined as:
method conj(Complex:D: --> Complex:D)
Returns the complex conjugate of the invocant (that is, the number with the sign of the imaginary part negated).
say (1-4i).conj; # OUTPUT: «1+4i»
Defined as:
method sqrt(Complex:D: --> Complex:D)
Returns the complex square root of the invocant, i.e. the root where the real part is ≥ 0 and the imaginary part has the same sign as the imaginary part of the invocant.
say (3-4i).sqrt; # OUTPUT: «2-1i» say (-3+4i).sqrt; # OUTPUT: «1+2i»
Defined as:
method gist(Complex:D: --> Str:D)
Returns a string representation of the form "1+2i", without internal spaces. (Str coercion also returns this.)
say (1-4i).gist; # OUTPUT: «1-4i»
Defined as:
method perl(Complex:D: --> Str:D)
Returns an implementation-specific string that produces an equivalent object when given to EVAL.
say (1-3i).perl; # OUTPUT: «<1-3i>»
Defined as:
multi method Real(Complex:D: --> Num:D) multi method Real(Complex:U: --> Num:D)
Coerces the invocant to Num. If the imaginary part isn't approximately zero, coercion fails with X::Numeric::Real.
The :D variant returns the result of that coercion. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value 0e0.
Declared as
multi sub infix:<**>(Complex:D \a, Complex:D \b --> Complex:D) multi sub infix:<**>(Num(Real) \a, Complex:D \b --> Complex:D) multi sub infix:<**>(Complex:D \a, Num(Real) \b --> Complex:D)
The exponentiation operator coerces the second argument to Complex and calculates the left-hand-side raised to the power of the right-hand side. Since 6.d, either argument can be equal to zero.
say i ** i; # OUTPUT: «0.20787957635076193+0i» say 2 ** i; # OUTPUT: «0.7692389013639721+0.6389612763136348i» say i ** 2; # OUTPUT: «-1+1.2246467991473532e-16i» say 0 ** 1; # OUTPUT: «0+0i»
Dual value complex number and string
class ComplexStr is Complex is Str {}
The dual value types (often referred to as allomorphs) allow for the representation of a value as both a string and a numeric type. Typically they will be created for you when the context is "stringy" but they can be determined to be numbers, such as in some quoting constructs:
my $f = <42+0i>; say $f.^name; # OUTPUT: «ComplexStr»
As a subclass of both Complex and Str, a ComplexStr will be accepted where either is expected. However, ComplexStr does not share object identity with Complex- or Str-only variants:
my $complex-str = < 42+0i >; my Complex $complex = $complex-str; # OK! my Str $str = $complex-str; # OK! say 42+0i ∈ <42+0i 55 1>; # False; ∈ operator cares about object identity
method new(Complex $i, Str $s)
The constructor requires both the Complex and the Str value, when constructing one directly the values can be whatever is required:
my $f = ComplexStr.new(42+0i, "forty two (but complicated)"); say +$f; # OUTPUT: «42+0i» say ~$f; # OUTPUT: «"forty two (but complicated)"»
Defined as:
multi method Bool(ComplexStr:D: --> Bool:D)
This method may be provided by the parent classes and not implemented in ComplexStr directly.
Returns False if the invocant is numerically ±0±0i, otherwise returns True. String portion is not considered.
Defined as:
method Capture(ComplexStr:D --> Capture:D)
Equivalent to Mu.Capture.
method Complex
Returns the Complex value of the ComplexStr.
Defined as:
multi method Numeric(ComplexStr:D: --> Complex:D) multi method Numeric(ComplexStr:U: --> Complex:D)
The :D variant returns the numeric portion of the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value <0+0i>.
Defined as:
multi method Real(ComplexStr:D: --> Num:D) multi method Real(ComplexStr:U: --> Num:D)
Coerces the numeric portion of the invocant to Num. If the imaginary part isn't approximately zero, coercion fails with X::Numeric::Real.
The :D variant returns the result of that coercion. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value 0e0.
Returns the string value of the ComplexStr.
Defined as:
multi method ACCEPTS(ComplexStr:D: Any:D $value)
If $value is Numeric (including another allomorph), checks if invocant's Numeric part ACCEPTS the $value. If $value is Str, checks if invocant's Str part ACCEPTS the $value. If value is anything else, checks if both Numeric and Str parts ACCEPTS the $value.
say < 5+0i> ~~ "5.0"; # OUTPUT: «False» say < 5+0i> ~~ 5.0 ; # OUTPUT: «True» say < 5+0i> ~~ <5.0>; # OUTPUT: «True»
multi sub infix:<cmp>(ComplexStr:D $a, ComplexStr:D $b)
Compare two ComplexStr objects. The comparison is done on the Complex value first and then on the Str value. If you want to compare in a different order then you would coerce to the Complex or Str values first:
my $f = ComplexStr.new(42+0i, "smaller"); my $g = ComplexStr.new(43+0i, "larger"); say $f cmp $g; # OUTPUT: «Less» say $f.Str cmp $g.Str; # OUTPUT: «More»
Object that can be treated as both a string and number
class Cool is Any { }
Cool, also known as the Convenient OO Loop, is a base class employed by a number of built-in classes whose instances can be meaningfully coerced to a string and a number. For example, an Array can be used in mathematical operations, where its numerical representation is the number of elements it contains. At the same time, it can be concatenated to a string, where its stringy representation is all of its elements joined by a space. Because Array is Cool, the appropriate coercion happens automatically.
Methods in Cool coerce the invocant to a more specific type, and then call the same method on that type. For example both Int and Str inherit from Cool, and calling method substr on an Int converts the integer to Str first.
123.substr(1, 1); # '2', same as 123.Str.substr(1, 1)
The following built-in types inherit from Cool: Array Bool Complex Cool Duration Map FatRat Hash Instant Int List Match Nil Num Range Seq Stash Str.
The following table summarizes the methods that Cool provides, and what type they coerce to:
method | coercion type |
---|---|
abs | Numeric |
conj | Numeric |
sqrt | Numeric |
sign | Real |
rand | Numeric |
sin | Numeric |
asin | Numeric |
cos | Numeric |
acos | Numeric |
tan | Numeric |
tanh | Numeric |
atan | Numeric |
atan2 | Numeric |
atanh | Numeric |
sec | Numeric |
asec | Numeric |
cosec | Numeric |
acosec | Numeric |
cotan | Numeric |
cotanh | Numeric |
acotan | Numeric |
sinh | Numeric |
asinh | Numeric |
cosh | Numeric |
acosh | Numeric |
sech | Numeric |
asech | Numeric |
cosech | Numeric |
acosech | Numeric |
acotanh | Numeric |
cis | Numeric |
log | Numeric |
exp | Numeric |
roots | Numeric |
log10 | Numeric |
unpolar | Numeric |
round | Numeric |
floor | Numeric |
ceiling | Numeric |
truncate | Numeric |
chr | Int |
ord | Str |
chars | Str |
fmt | Str |
uniname | Str |
uninames | Seq |
unival | Str |
univals | Str |
uniprop | Str |
unimatch | Str |
uc | Str |
lc | Str |
fc | Str |
tc | Str |
tclc | Str |
flip | Str |
trans | Str |
contains | Str |
index | Str |
rindex | Str |
ords | Str |
split | Str |
match | Str |
comb | Str |
subst | Str |
sprintf | Str |
printf | Str |
samecase | Str |
trim | Str |
trim-leading | Str |
trim-trailing | Str |
EVAL | Str |
chomp | Str |
chop | Str |
codes | Str |
Defined as:
sub abs(Numeric() $x) method abs()
Coerces the invocant (or in the sub form, the argument) to Numeric and returns the absolute value (that is, a non-negative number).
say (-2).abs; # OUTPUT: «2» say abs "6+8i"; # OUTPUT: «10»
Defined as:
method conj()
Coerces the invocant to Numeric and returns the complex conjugate (that is, the number with the sign of the imaginary part negated).
say (1+2i).conj; # OUTPUT: «1-2i»
Defined as:
method EVAL(*%_)
It calls the subroutine form with the invocant as the first argument, $code, passing along named args, if any.
Defined as:
sub sqrt(Numeric(Cool) $x) method sqrt()
Coerces the invocant to Numeric (or in the sub form, the argument) and returns the square root, that is, a non-negative number that, when multiplied with itself, produces the original number.
say 4.sqrt; # OUTPUT: «2» say sqrt(2); # OUTPUT: «1.4142135623731»
Defined as:
method sign()
Coerces the invocant to Numeric and returns its sign, that is, 0 if the number is 0, 1 for positive and -1 for negative values.
say 6.sign; # OUTPUT: «1» say (-6).sign; # OUTPUT: «-1» say "0".sign; # OUTPUT: «0»
Defined as:
method rand()
Coerces the invocant to Num and returns a pseudo-random value between zero and the number.
say 1e5.rand; # OUTPUT: «33128.495184283»
Defined as:
sub sin(Numeric(Cool)) method sin()
Coerces the invocant (or in the sub form, the argument) to Numeric, interprets it as radians, returns its sine.
say sin(0); # OUTPUT: «0» say sin(pi/4); # OUTPUT: «0.707106781186547» say sin(pi/2); # OUTPUT: «1»
Note that Perl 6 is no computer algebra system, so sin(pi) typically does not produce an exact 0, but rather a very small floating-point number.
Defined as:
sub asin(Numeric(Cool)) method asin()
Coerces the invocant (or in the sub form, the argument) to Numeric, and returns its arc-sine in radians.
say 0.1.asin; # OUTPUT: «0.10016742116156» say asin(0.1); # OUTPUT: «0.10016742116156»
Defined as:
sub cos(Numeric(Cool)) method cos()
Coerces the invocant (or in sub form, the argument) to Numeric, interprets it as radians, returns its cosine.
say 0.cos; # OUTPUT: «1» say pi.cos; # OUTPUT: «-1» say cos(pi/2); # OUTPUT: «6.12323399573677e-17»
Defined as:
sub acos(Numeric(Cool)) method acos()
Coerces the invocant (or in sub form, the argument) to Numeric, and returns its arc-cosine in radians.
say 1.acos; # OUTPUT: «0» say acos(-1); # OUTPUT: «3.14159265358979»
Defined as:
sub tan(Numeric(Cool)) method tan()
Coerces the invocant (or in sub form, the argument) to Numeric, interprets it as radians, returns its tangent.
say tan(3); # OUTPUT: «-0.142546543074278» say 3.tan; # OUTPUT: «-0.142546543074278»
Defined as:
sub atan(Numeric(Cool)) method atan()
Coerces the invocant (or in sub form, the argument) to Numeric, and returns its arc-tangent in radians.
say atan(3); # OUTPUT: «1.24904577239825» say 3.atan; # OUTPUT: «1.24904577239825»
Defined as:
method atan2($y = 1e0)
Coerces self and argument to Numeric, using them to compute the two-argument arc-tangent in radians.
say 3.atan2; # OUTPUT: «1.24904577239825» say ⅔.atan2(⅓); # OUTPUT: «1.1071487177940904»
The first argument defaults to 1, so in the first case the function will return the angle θ in radians between a vector that goes from origin to the point (3, 1) and the x axis.
Defined as:
sub sec(Numeric(Cool)) method sec()
Coerces the invocant (or in sub form, its argument) to Numeric, interprets it as radians, returns its secant, that is, the reciprocal of its cosine.
say 45.sec; # OUTPUT: «1.90359440740442» say sec(45); # OUTPUT: «1.90359440740442»
Defined as:
sub asec(Numeric(Cool)) method asec()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its arc-secant in radians.
say 1.asec; # OUTPUT: «0» say sqrt(2).asec; # OUTPUT: «0.785398163397448»
Defined as:
sub cosec(Numeric(Cool)) method cosec()
Coerces the invocant (or in sub form, its argument) to Numeric, interprets it as radians, returns its cosecant, that is, the reciprocal of its sine.
say 0.45.cosec; # OUTPUT: «2.29903273150897» say cosec(0.45); # OUTPUT: «2.29903273150897»
Defined as:
sub acosec(Numeric(Cool)) method acosec()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its arc-cosecant in radians.
say 45.acosec; # OUTPUT: «0.0222240516182672» say acosec(45) # OUTPUT: «0.0222240516182672»
Defined as:
sub cotan(Numeric(Cool)) method cotan()
Coerces the invocant (or in sub form, its argument) to Numeric, interprets it as radians, returns its cotangent, that is, the reciprocal of its tangent.
say 45.cotan; # OUTPUT: «0.617369623783555» say cotan(45); # OUTPUT: «0.617369623783555»
Defined as:
sub acotan(Numeric(Cool)) method acotan()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its arc-cotangent in radians.
say 45.acotan; # OUTPUT: «0.0222185653267191» say acotan(45) # OUTPUT: «0.0222185653267191»
Defined as:
sub sinh(Numeric(Cool)) method sinh()
Coerces the invocant (or in method form, its argument) to Numeric, and returns its Sine hyperbolicus.
say 1.sinh; # OUTPUT: «1.1752011936438» say sinh(1); # OUTPUT: «1.1752011936438»
Defined as:
sub asinh(Numeric(Cool)) method asinh()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Inverse Sine hyperbolicus.
say 1.asinh; # OUTPUT: «0.881373587019543» say asinh(1); # OUTPUT: «0.881373587019543»
Defined as:
sub cosh(Numeric(Cool)) method cosh()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Cosine hyperbolicus.
say cosh(0.5); # OUTPUT: «1.12762596520638»
Defined as:
sub acosh(Numeric(Cool)) method acosh()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Inverse Cosine hyperbolicus.
say acosh(45); # OUTPUT: «4.4996861906715»
Defined as:
sub tanh(Numeric(Cool)) method tanh()
Coerces the invocant (or in sub form, its argument) to Numeric, interprets it as radians and returns its Tangent hyperbolicus.
say tanh(0.5); # OUTPUT: «0.46211715726001» say tanh(atanh(0.5)); # OUTPUT: «0.5»
Defined as:
sub atanh(Numeric(Cool)) method atanh()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Inverse tangent hyperbolicus.
say atanh(0.5); # OUTPUT: «0.549306144334055»
Defined as:
sub sech(Numeric(Cool)) method sech()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Secant hyperbolicus.
say 0.sech; # OUTPUT: «1»
Defined as:
sub asech(Numeric(Cool)) method asech()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Inverse hyperbolic secant.
say 0.8.asech; # OUTPUT: «0.693147180559945»
Defined as:
sub cosech(Numeric(Cool)) method cosech()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Hyperbolic cosecant.
say cosech(pi/2); # OUTPUT: «0.434537208094696»
Defined as:
sub acosech(Numeric(Cool)) method acosech()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Inverse hyperbolic cosecant.
say acosech(4.5); # OUTPUT: «0.220432720979802»
Defined as:
sub cotanh(Numeric(Cool)) method cotanh()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Hyperbolic cotangent.
say cotanh(pi); # OUTPUT: «1.00374187319732»
Defined as:
sub acotanh(Numeric(Cool)) method acotanh()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns its Inverse hyperbolic cotangent.
say acotanh(2.5); # OUTPUT: «0.423648930193602»
Defined as:
sub cis(Numeric(Cool)) method cis()
Coerces the invocant (or in sub form, its argument) to Numeric, and returns cos(argument) + i*sin(argument).
say cis(pi/4); # OUTPUT: «0.707106781186548+0.707106781186547i»
Defined as:
multi sub log(Numeric(Cool) $number, Numeric(Cool) $base?) multi method log(Cool:D: Cool:D $base?)
Coerces the arguments (including the invocant in the method form) to Numeric, and returns its Logarithm to base $base, or to base e (Euler's Number) if no base was supplied (Natural logarithm). Returns NaN if $base is negative. Throws an exception if $base is 1.
say (e*e).log; # OUTPUT: «2»
Defined as:
multi sub log10(Cool(Numeric)) multi method log10()
Coerces the invocant (or in the sub form, the invocant) to Numeric, and returns its Logarithm to base 10, that is, a number that approximately produces the original number when raised to the power of 10. Returns NaN for negative arguments and -Inf for 0.
say log10(1001); # OUTPUT: «3.00043407747932»
Defined as:
multi sub exp(Cool:D $pow, Cool:D $base?) multi method exp(Cool:D: Cool:D $base?)
Coerces the arguments (including the invocant in the method from) to Numeric, and returns $base raised to the power of the first number. If no $base is supplied, e (Euler's Number) is used.
say 0.exp; # OUTPUT: «1» say 1.exp; # OUTPUT: «2.71828182845905» say 10.exp; # OUTPUT: «22026.4657948067»
Defined as:
method unpolar(Numeric(Cool))
Coerces the arguments (including the invocant in the method form) to Numeric, and returns a complex number from the given polar coordinates. The invocant (or the first argument in sub form) is the magnitude while the argument (i.e. the second argument in sub form) is the angle. The angle is assumed to be in radians.
say sqrt(2).unpolar(pi/4); # OUTPUT: «1+1i»
Defined as:
multi sub round(Numeric(Cool)) multi method round(Cool:D: $unit = 1)
Coerces the invocant (or in sub form, its argument) to Numeric, and rounds it to the unit of $unit. If $unit is 1, rounds to the nearest integer.
say 1.7.round; # OUTPUT: «2» say 1.07.round(0.1); # OUTPUT: «1.1» say 21.round(10); # OUTPUT: «20»
Always rounds up if the number is at mid-point:
say (−.5 ).round; # OUTPUT: «0» say ( .5 ).round; # OUTPUT: «1» say (−.55).round(.1); # OUTPUT: «-0.5» say ( .55).round(.1); # OUTPUT: «0.6»
Pay attention to types when using this method, as ending up with the wrong type may affect the precision you seek to achieve. For Real types, the type of the result is the type of the argument (Complex argument gets coerced to Real, ending up a Num). If rounding a Complex, the result is Complex as well, regardless of the type of the argument.
9930972392403501.round(1) .perl.say; # OUTPUT: «9930972392403501» 9930972392403501.round(1e0) .perl.say; # OUTPUT: «9.9309723924035e+15» 9930972392403501.round(1e0).Int.perl.say; # OUTPUT: «9930972392403500»
Defined as:
multi sub floor(Numeric(Cool)) multi method floor
Coerces the invocant (or in sub form, its argument) to Numeric, and rounds it downwards to the nearest integer.
say "1.99".floor; # OUTPUT: «1» say "-1.9".floor; # OUTPUT: «-2» say 0.floor; # OUTPUT: «0»
Defined as:
method fmt($format = '%s')
Uses $format to return a formatted representation of the invocant; equivalent to calling sprintf with $format as format and the invocant as the second argument. The $format will be coerced to Stringy and defaults to '%s'.
For more information about formats strings, see sprintf.
say 11.fmt('This Int equals %03d'); # OUTPUT: «This Int equals 011» say '16'.fmt('Hexadecimal %x'); # OUTPUT: «Hexadecimal 10»
Defined as:
multi sub ceiling(Numeric(Cool)) multi method ceiling
Coerces the invocant (or in sub form, its argument) to Numeric, and rounds it upwards to the nearest integer.
say "1".ceiling; # OUTPUT: «1» say "-0.9".ceiling; # OUTPUT: «0» say "42.1".ceiling; # OUTPUT: «43»
Defined as:
multi sub truncate(Numeric(Cool)) multi method truncate()
Coerces the invocant (or in sub form, its argument) to Numeric, and rounds it towards zero.
say 1.2.truncate; # OUTPUT: «1» say truncate -1.2; # OUTPUT: «-1»
Defined as:
sub ord(Str(Cool)) method ord()
Coerces the invocant (or in sub form, its argument) to Str, and returns the Unicode code point number of the first code point.
say 'a'.ord; # OUTPUT: «97»
The inverse operation is chr.
Mnemonic: returns an ordinal number
Defined as:
method path()
DEPRECATED. It's been deprecated as of the 6.d version. Will be removed in the next ones.
Stringifies the invocant and converts it to IO::Path object. Use the .IO method instead.
Defined as:
sub chr(Int(Cool)) method chr()
Coerces the invocant (or in sub form, its argument) to Int, interprets it as a Unicode code points, and returns a string made of that code point.
say '65'.chr; # OUTPUT: «A»
The inverse operation is ord.
Mnemonic: turns an integer into a character.
Defined as:
multi sub chars(Cool $x) multi sub chars(Str:D $x) multi sub chars(str $x --> int) method chars(--> Int:D)
Coerces the invocant (or in sub form, its argument) to Str, and returns the number of characters in the string. Please note that on the JVM, you currently get codepoints instead of graphemes.
say 'møp'.chars; # OUTPUT: «3» say 'ã̷̠̬̊'.chars; # OUTPUT: «1» say '👨👩👧👦🏿'.chars; # OUTPUT: «1»
If the string is native, the number of chars will be also returned as a native int.
Graphemes are user visible characters. That is, this is what the user thinks of as a “character”.
Graphemes can contain more than one codepoint. Typically the number of graphemes and codepoints differs when Prepend or Extend characters are involved (also known as Combining characters), but there are many other cases when this may happen. Another example is \c[ZWJ] (Zero-width joiner).
You can check Grapheme_Cluster_Break property of a character in order to see how it is going to behave:
say ‘ã̷̠̬̊’.uniprops(‘Grapheme_Cluster_Break’); # OUTPUT: «(Other Extend Extend Extend Extend)» say ‘👨👩👧👦🏿’.uniprops(‘Grapheme_Cluster_Break’); # OUTPUT: «(E_Base_GAZ ZWJ E_Base_GAZ ZWJ E_Base_GAZ ZWJ E_Base_GAZ E_Modifier)»
You can read more about graphemes in the Unicode Standard, which Perl 6 tightly follows, using a method called NFG, normal form graphemes for efficiently representing them.
Defined as:
sub codes(Str(Cool)) method codes()
Coerces the invocant (or in sub form, its argument) to Str, and returns the number of Unicode code points.
say 'møp'.codes; # OUTPUT: «3»
The same result will be obtained with
say +'møp'.ords; # OUTPUT: «3»
ords first obtains the actual codepoints, so there might be a difference in speed.
Defined as:
sub flip(Cool $s --> Str:D) method flip()
Coerces the invocant (or in sub form, its argument) to Str, and returns a reversed version.
say 421.flip; # OUTPUT: «124»
Defined as:
sub trim(Str(Cool)) method trim()
Coerces the invocant (or in sub form, its argument) to Str, and returns the string with both leading and trailing whitespace stripped.
my $stripped = ' abc '.trim; say "<$stripped>"; # OUTPUT: «<abc>»
Defined as:
sub trim-leading(Str(Cool)) method trim-leading()
Coerces the invocant (or in sub form, its argument) to Str, and returns the string with leading whitespace stripped.
my $stripped = ' abc '.trim-leading; say "<$stripped>"; # OUTPUT: «<abc >»
Defined as:
sub trim-trailing(Str(Cool)) method trim-trailing()
Coerces the invocant (or in sub form, its argument) to Str, and returns the string with trailing whitespace stripped.
my $stripped = ' abc '.trim-trailing; say "<$stripped>"; # OUTPUT: «< abc>»
Defined as:
sub lc(Str(Cool)) method lc()
Coerces the invocant (or in sub form, its argument) to Str, and returns it case-folded to lower case.
say "ABC".lc; # OUTPUT: «abc»
Defined as:
sub uc(Str(Cool)) method uc()
Coerces the invocant (or in sub form, its argument) to Str, and returns it case-folded to upper case (capital letters).
say "Abc".uc; # OUTPUT: «ABC»
Defined as:
sub fc(Str(Cool)) method fc()
Coerces the invocant (or in sub form, its argument) to Str, and returns the result a Unicode "case fold" operation suitable for doing caseless string comparisons. (In general, the returned string is unlikely to be useful for any purpose other than comparison.)
say "groß".fc; # OUTPUT: «gross»
Defined as:
sub tc(Str(Cool)) method tc()
Coerces the invocant (or in sub form, its argument) to Str, and returns it with the first letter case-folded to title case (or where not available, upper case).
say "abC".tc; # OUTPUT: «AbC»
Defined as:
sub tclc(Str(Cool)) method tclc()
Coerces the invocant (or in sub form, its argument) to Str, and returns it with the first letter case-folded to title case (or where not available, upper case), and the rest of the string case-folded to lower case.
say 'abC'.tclc; # OUTPUT: «Abc»
Defined as:
sub wordcase(Str(Cool) $input, :&filter = &tclc, Mu :$where = True) method wordcase(:&filter = &tclc, Mu :$where = True)
Coerces the invocant (or in sub form, the first argument) to Str, and filters each word that smartmatches against $where through the &filter. With the default filter (first character to upper case, rest to lower) and matcher (which accepts everything), this title-cases each word:
say "perl 6 programming".wordcase; # OUTPUT: «Perl 6 Programming»
With a matcher:
say "have fun working on perl".wordcase(:where({ .chars > 3 })); # Have fun Working on Perl
With a customer filter too:
say "have fun working on perl".wordcase(:filter(&uc), :where({ .chars > 3 })); # HAVE fun WORKING on PERL
Defined as:
sub samecase(Cool $string, Cool $pattern) method samecase(Cool:D: Cool $pattern)
Coerces the invocant (or in sub form, the first argument) to Str, and returns a copy of $string with case information for each individual character changed according to $pattern.
Note: The pattern string can contain three types of characters, i.e. uppercase, lowercase and caseless. For a given character in $pattern its case information determines the case of the corresponding character in the result.
If $string is longer than $pattern, the case information from the last character of $pattern is applied to the remaining characters of $string.
say "perL 6".samecase("A__a__"); # OUTPUT: «Perl 6» say "pERL 6".samecase("Ab"); # OUTPUT: «Perl 6»
Defined as:
multi sub uniprop(Str:D, |c) multi sub uniprop(Int:D $code) multi sub uniprop(Int:D $code, Stringy:D $propname) multi method uniprop(|c)
Returns the unicode property of the first character. If no property is specified returns the General Category. Returns a Bool for Boolean properties. A uniprops routine can be used to get the property for every character in a string.
say 'a'.uniprop; # OUTPUT: «Ll» say '1'.uniprop; # OUTPUT: «Nd» say 'a'.uniprop('Alphabetic'); # OUTPUT: «True» say '1'.uniprop('Alphabetic'); # OUTPUT: «False»
Defined as:
sub uniprops(Str:D $str, Stringy:D $propname = "General_Category")
Interprets the invocant as a Str, and returns the unicode property for each character as a Seq. If no property is specified returns the General Category. Returns a Bool for Boolean properties. Similar to uniprop, but for each character in the passed string.
Defined as:
sub uniname(Str(Cool) --> Str) method uniname(--> Str)
Interprets the invocant or first argument as a Str, and returns the Unicode codepoint name of the first codepoint of the first character. See uninames for a routine that works with multiple codepoints, and uniparse for the opposite direction.
# Camelia in Unicode say ‘»ö«’.uniname; # OUTPUT: «"RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK"» say "Ḍ̇".uniname; # Note, doesn't show "COMBINING DOT ABOVE" # OUTPUT: «"LATIN CAPITAL LETTER D WITH DOT BELOW"» # Find the char with the longest Unicode name. say (0..0x1FFFF).sort(*.uniname.chars)[*-1].chr.uniname; # OUTPUT: ««ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM»»
Defined as:
sub uninames(Str:D) method uninames()
Returns of a Seq of Unicode names for the all the codepoints in the Str provided.
say ‘»ö«’.uninames.perl; # OUTPUT: «("RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK", "LATIN SMALL LETTER O WITH DIAERESIS", "LEFT-POINTING DOUBLE ANGLE QUOTATION MARK").Seq»
Note this example, which gets a Seq where each element is a Seq of all the codepoints in that character.
say "Ḍ̇'oh".comb>>.uninames.perl; # OUTPUT: «(("LATIN CAPITAL LETTER D WITH DOT BELOW", "COMBINING DOT ABOVE").Seq, ("APOSTROPHE",).Seq, ("LATIN SMALL LETTER O",).Seq, ("LATIN SMALL LETTER H",).Seq)»
See uniparse for the opposite direction.
Defined as:
multi sub unimatch(Str:D $str, |c) multi unimatch(Int:D $code, Stringy:D $pvalname, Stringy:D $propname = $pvalname)
Checks if the given integer codepoint or the first letter of the string given have a unicode property equal to the value you give. If you supply the Unicode property to be checked it will only return True if that property matches the given value.
say unimatch 'A', 'Latin'; # OUTPUT: «True» say unimatch 'A', 'Latin', 'Script'; # OUTPUT: «True» say unimatch 'A', 'Ll'; # OUTPUT: «True»
Defined as:
sub chop(Str(Cool)) method chop()
Coerces the invocant (or in sub form, its argument) to Str, and returns it with the last character removed.
say 'perl'.chop; # OUTPUT: «per»
Defined as:
sub chomp(Str(Cool)) method chomp()
Coerces the invocant (or in sub form, its argument) to Str, and returns it with the last character removed, if it is a logical newline.
say 'ab'.chomp.chars; # OUTPUT: «2» say "a\n".chomp.chars; # OUTPUT: «1»
Defined as:
sub substr(Str(Cool) $str, |c) method substr(|c)
Coerces the invocant (or in the sub form, the first argument) to Str, and calls Str.substr with the arguments.
Defined as:
multi method substr-rw(|) is rw multi sub substr-rw(|) is rw
Coerces the invocant (or in the sub form, the first argument) to Str, and calls Str.substr-rw with the arguments.
Defined as:
sub ords(Str(Cool) $str) method ords()
Coerces the invocant (or in the sub form, the first argument) to Str, and returns a list of Unicode codepoints for each character.
say "Camelia".ords; # OUTPUT: «67 97 109 101 108 105 97» say ords 10; # OUTPUT: «49 48»
This is the list-returning version of ord. The inverse operation in chrs. If you are only interested in the number of codepoints, codes is a possibly faster option.
Defined as:
sub chrs(*@codepoints --> Str:D) method chrs()
Coerces the invocant (or in the sub form, the argument list) to a list of integers, and returns the string created by interpreting each integer as a Unicode codepoint, and joining the characters.
say <67 97 109 101 108 105 97>.chrs; # OUTPUT: «Camelia»
This is the list-input version of chr. The inverse operation is ords.
Defined as:
multi sub split( Str:D $delimiter, Str(Cool) $input, $limit = Inf, :$k, :$v, :$kv, :$p, :$skip-empty) multi sub split(Regex:D $delimiter, Str(Cool) $input, $limit = Inf, :$k, :$v, :$kv, :$p, :$skip-empty) multi sub split(@delimiters, Str(Cool) $input, $limit = Inf, :$k, :$v, :$kv, :$p, :$skip-empty) multi method split( Str:D $delimiter, $limit = Inf, :$k, :$v, :$kv, :$p, :$skip-empty) multi method split(Regex:D $delimiter, $limit = Inf, :$k, :$v, :$kv, :$p, :$skip-empty) multi method split(@delimiters, $limit = Inf, :$k, :$v, :$kv, :$p, :$skip-empty)
Coerces the invocant (or in the sub form, the second argument) to Str, and splits it into pieces based on delimiters found in the string.
If $delimiter is a string, it is searched for literally and not treated as a regex. You can also provide multiple delimiters by specifying them as a list; mixing Cool and Regex objects is OK.
say split(';', "a;b;c").perl; # OUTPUT: «("a", "b", "c")» say split(';', "a;b;c", 2).perl; # OUTPUT: «("a", "b;c").Seq» say split(';', "a;b;c,d").perl; # OUTPUT: «("a", "b", "c,d")» say split(/\;/, "a;b;c,d").perl; # OUTPUT: «("a", "b", "c,d")» say split(/<[;,]>/, "a;b;c,d").perl; # OUTPUT: «("a", "b", "c", "d")» say split(['a', /b+/, 4], '1a2bb345').perl; # OUTPUT: «("1", "2", "3", "5")»
By default, split omits the matches, and returns a list of only those parts of the string that did not match. Specifying one of the :k, :v, :kv, :p adverbs changes that. Think of the matches as a list that is interleaved with the non-matching parts.
The :v interleaves the values of that list, which will be either Match objects, if a Regex was used as a matcher in the split, or Str objects, if a Cool was used as matcher. If multiple delimiters are specified, Match objects will be generated for all of them, unless all of the delimiters are Cool.
say 'abc'.split(/b/, :v); # OUTPUT: «(a 「b」 c)» say 'abc'.split('b', :v); # OUTPUT: «(a b c)»
:k interleaves the keys, that is, the indexes:
say 'abc'.split(/b/, :k); # OUTPUT: «(a 0 c)»
:kv adds both indexes and matches:
say 'abc'.split(/b/, :kv); # OUTPUT: «(a 0 「b」 c)»
and :p adds them as Pairs, using the same types for values as :v does:
say 'abc'.split(/b/, :p); # OUTPUT: «(a 0 => 「b」 c)» say 'abc'.split('b', :p); # OUTPUT: «(a 0 => b c)»
You can only use one of the :k, :v, :kv, :p adverbs in a single call to split.
Note that empty chunks are not removed from the result list. For that behavior, use the :skip-empty named argument:
say ("f,,b,c,d".split: /","/ ).perl; # OUTPUT: «("f", "", "b", "c", "d")» say ("f,,b,c,d".split: /","/, :skip-empty).perl; # OUTPUT: «("f", "b", "c", "d")»
Defined as:
sub lines(Str(Cool)) method lines()
Coerces the invocant (and in sub form, the argument) to Str, decomposes it into lines (with the newline characters stripped), and returns the list of lines.
say lines("a\nb\n").join('|'); # OUTPUT: «a|b» say "some\nmore\nlines".lines.elems; # OUTPUT: «3»
This method can be used as part of an IO::Path to process a file line-by-line, since IO::Path objects inherit from Cool, e.g.:
for 'huge-csv'.IO.lines -> $line { # Do something with $line } # or if you'll be processing later my @lines = 'huge-csv'.IO.lines;
Without any arguments, sub lines operates on $*ARGFILES, which defaults to $*IN in the absence of any filenames.
To modify values in place use is copy to force a writable container.
for $*IN.lines -> $_ is copy { s/(\w+)/{$0 ~ $0}/; .say }
Defined as:
method words(Cool:D: |c)
Coerces the invocant (or first argument, if it is called as a subroutine) to Str, and returns a list of words that make up the string. Check Str.words for additional arguments and its meaning.
say <The quick brown fox>.words.join('|'); # OUTPUT: «The|quick|brown|fox» say <The quick brown fox>.words(2).join('|'); # OUTPUT: «The|quick»
Cool is the base class for many other classes, and some of them, like Match, can be converted to a string. This is what happens in this case:
say ( "easy come, easy goes" ~~ m:g/(ea\w+)/).words(Inf); # OUTPUT: «(easy easy)» say words( "easy come, easy goes" ~~ m:g/(ea\w+)/ , ∞); # OUTPUT: «(easy easy)»
The example above illustrates two of the ways words can be invoked, with the first argument turned into invocant by its signature. Of course, Inf is the default value of the second argument, so in both cases (and forms) it can be simply omitted.
Only whitespace (including no-break space) counts as word boundaries
say <Don't we ♥ Perl 6>.words.join('|'); # OUTPUT: «Don't|we|♥|Perl|6»
In this case, Perl 6 includes an (visible only in the source) no-break space; words still splits the (resulting) Str on it, even if the original array only had 4 elements:
say <Don't we ♥ Perl 6>.join("|"); # OUTPUT: «Don't|we|♥|Perl 6»
Please see Str.words for more examples and ways to invoke it.
Defined as:
multi sub comb(Regex $matcher, Cool $input, $limit = *) multi sub comb(Str $matcher, Cool $input, $limit = *) multi sub comb(Int:D $size, Cool $input, $limit = *) multi method comb(|c)
Returns a Seq of all (or if supplied, at most $limit) matches of the invocant (method form) or the second argument (sub form) against the Regex, string or defined number.
say "6 or 12".comb(/\d+/).join(", "); # OUTPUT: «6, 12» say comb(/\d <[1..9]> /,(11..30)).join("--"); # OUTPUT: # «11--12--13--14--15--16--17--18--19--21--22--23--24--25--26--27--28--29»
The second statement exemplifies the first form of comb, with a Regex that excludes multiples of ten, and a Range (which is Cool) as $input. comb stringifies the Range before applying .comb on the resulting string. Check Str.comb for its effect on different kind of input strings. When the first argument is an integer, it indicates the (maximum) size of the chunks the input is going to be divided in
say comb(3,[3,33,333,3333]).join("*"); # OUTPUT: «3 3*3 3*33 *333*3»
In this case the input is a list, which after transformation to Str (which includes the spaces) is divided in chunks of size 3.
Defined as:
method contains(Cool:D: |c)
Coerces the invocant Str, and calls Str.contains on it. Please refer to that version of the method for arguments and general syntax.
say 123.contains("2")# OUTPUT: «True»
Since Int is a subclass of Cool, 123 is coerced to a Str and then contains is called on it.
say (1,1, * + * … * > 250).contains(233)# OUTPUT: «True»
Seqs are also subclasses of Cool, and they are stringified to a comma-separated form. In this case we are also using an Int, which is going to be stringified also; "233" is included in that sequence, so it returns True. Please note that this sequence is not lazy; the stringification of lazy sequences does not include each and every one of their components for obvious reasons.
Defined as:
multi sub index(Cool $s, Cool $needle, Cool $pos = 0) method index(Cool:D: |c)
Coerces the first two arguments (in method form, also counting the invocant) to a Str, and searches for $needle in the string $s starting from $startpos. It returns the offset into the string where $needle was found, and an undefined value if it was not found.
See the documentation in type Str for examples.
Defined as:
multi sub rindex(Str(Cool) $haystack, Str(Cool) $needle, Int(Cool) $startpos = $haystack.chars) multi method rindex(Str(Cool) $haystack: Str(Cool) $needle, Int(Cool) $startpos = $haystack.chars)
Coerces the first two arguments (including the invocant in method form) to Str and $startpos to Int, and returns the last position of $needle in $haystack not after $startpos. Returns an undefined value if $needle wasn't found.
See the documentation in type Str for examples.
Defined as:
multi method match(Cool:D: $target, *%adverbs)
Coerces the invocant to Str and calls the method match on it.
Defined as:
multi sub roots(Numeric(Cool) $x, Int(Cool) $n) multi method roots(Int(Cool) $n)
Coerces the first argument (and in method form, the invocant) to Numeric and the second ($n) to Int, and produces a list of $n Complex $n-roots, which means numbers that, raised to the $nth power, approximately produce the original number.
For example
my $original = 16; my @roots = $original.roots(4); say @roots; for @roots -> $r { say abs($r ** 4 - $original); } # OUTPUT:«2+0i 1.22464679914735e-16+2i -2+2.44929359829471e-16i -3.67394039744206e-16-2i» # OUTPUT:«1.77635683940025e-15» # OUTPUT:«4.30267170434156e-15» # OUTPUT:«8.03651692704705e-15» # OUTPUT:«1.04441561648202e-14»
Defined as:
method match(|)
Coerces the invocant to Stringy and calls Str.match.
Defined as:
method subst(|)
Coerces the invocant to Stringy and calls Str.subst.
Defined as:
method trans(|)
Coerces the invocant to Str and calls Str.trans
Defined as:
method IO(--> IO::Path:D)
Coerces the invocant to IO::Path.
.say for '.'.IO.dir; # gives a directory listing
Scheduler that synchronously executes code on the current thread
class CurrentThreadScheduler does Scheduler {}
CurrentThreadScheduler executes tasks on the current threads. This means that method cue blocks until the code has finished executing.
Synonym of Match
my constant Cursor = Match
Initially, it was used to keep track of initial position in regex matches. In current versions, it's an alias for Match.
Calendar date
class Date { }
A Date is an immutable object identifying a day in the Gregorian calendar.
Date objects support addition and subtraction of integers, where an integer is interpreted as the number of days. You can compare Date objects with the numeric comparison operators ==, <, <=, >, >=, != . Their stringification in YYYY-MM-DD format means that comparing them with the string operators eq, lt, le etc. also gives the right result.
Date.today creates an object the current day according to the system clock.
my $d = Date.new(2015, 12, 24); # Christmas Eve! say $d; # OUTPUT: «2015-12-24» say $d.year; # OUTPUT: «2015» say $d.month; # OUTPUT: «12» say $d.day; # OUTPUT: «24» say $d.day-of-week; # OUTPUT: «4» (Thursday) say $d.later(days => 20); # OUTPUT: «2016-01-13» my $n = Date.new('2015-12-31'); # New Year's Eve say $n - $d; # OUTPUT: «7», 7 days between New Years/Christmas Eve say $n + 1; # OUTPUT: «2016-01-01»
Note since version 6.d, .perl can be called on Date.
Defined as:
multi method new($year, $month, $day, :&formatter --> Date:D) multi method new(:$year!, :$month = 1, :$day = 1 --> Date:D) multi method new(Str $date --> Date:D) multi method new(Instant:D $dt --> Date:D) multi method new(DateTime:D $dt --> Date:D)
Creates a new Date object, either from a triple of (year, month, day) that can be coerced to integers, or from a string of the form YYYY-MM-DD (ISO 8601), or from an Instant or DateTime object. Optionally accepts a formatter as a named parameter.
my $date = Date.new(2042, 1, 1); $date = Date.new(year => 2042, month => 1, day => 1); $date = Date.new("2042-01-01"); $date = Date.new(Instant.from-posix: 1482155532); $date = Date.new(DateTime.now);
Defined as:
method new-from-daycount($daycount,:&formatter --> Date:D)
Creates a new Date object given $daycount which is the number of days from epoch Nov. 17, 1858, i.e. the Modified Julian Day. Optionally accepts a formatter as a named parameter.
say Date.new-from-daycount(49987); # OUTPUT: «1995-09-27»
Defined as:
method clone(:$year, :$month, :$day, :&formatter)
Creates a new Date object based on the invocant, but with the given arguments overriding the values from the invocant.
say Date.new('2015-11-24').clone(month => 12); # OUTPUT: «2015-12-24»
Defined as:
method today(:&formatter --> Date:D)
Returns a Date object for the current day. Optionally accepts a formatter named parameter.
say Date.today;
Defined as:
method later(Date:D: *%unit)
Returns a Date object based on the current one, but with a date delta applied. The date delta can be passed as a named argument where the argument name is the unit.
Allowed units are day, days, week, weeks, month, months, year, years. Please note that the plural forms can only be used with the later method.
Please note that the special ":2nd" named parameter syntax can be a compact and self-documenting way of specifying the delta
say Date.new('2015-12-24').later(:2years); # OUTPUT: «2017-12-24»
Since addition of several different time units is not commutative, only one unit may be passed.
my $d = Date.new('2015-02-27'); say $d.later(month => 1).later(:2days); # OUTPUT: «2015-03-29» say $d.later(days => 2).later(:1month); # OUTPUT: «2015-04-01» say $d.later(days => 2).later(:month); # same, as +True === 1
Negative offsets are allowed, though #method earlier is more idiomatic for that.
Defined as:
method earlier(Date:D: *%unit)
Returns a Date object based on the current one, but with a date delta towards the past applied. See #method later for usage.
my $d = Date.new('2015-02-27'); say $d.earlier(month => 5).earlier(:2days); # OUTPUT: «2014-09-25»
Defined as:
method truncated-to(Date:D: Cool $unit)
Returns a Date truncated to the first day of its year, month or week. For example
my $c = Date.new('2012-12-24'); say $c.truncated-to('year'); # OUTPUT: «2012-01-01» say $c.truncated-to('month'); # OUTPUT: «2012-12-01» say $c.truncated-to('week'); # OUTPUT: «2012-12-24», because it's Monday already
Defined as:
method succ(Date:D: --> Date:D)
Returns a Date of the following day. "succ" is short for "successor".
say Date.new("2016-02-28").succ; # OUTPUT: «2016-02-29»
Defined as:
method pred(Date:D: --> Date:D)
Returns a Date of the previous day. "pred" is short for "predecessor".
say Date.new("2016-01-01").pred; # OUTPUT: «2015-12-31»
Defined as:
multi method Str(Date:D: --> Str:D)
Returns a string representation of the invocant, as specified by the formatter. If no formatter was specified, an (ISO 8601) date will be returned.
say Date.new('2015-12-24').Str; # OUTPUT: «2015-12-24» my $fmt = { sprintf "%02d/%02d/%04d", .month, .day, .year }; say Date.new('2015-12-24', formatter => $fmt).Str; # OUTPUT: «12/24/2015»
Defined as:
multi method gist(Date:D: --> Str:D)
Returns the date in YYYY-MM-DD format (ISO 8601)
say Date.new('2015-12-24').gist; # OUTPUT: «2015-12-24»
Defined as:
method Date(--> Date)
Returns the invocant.
say Date.new('2015-12-24').Date; # OUTPUT: «2015-12-24» say Date.Date; # OUTPUT: «(Date)»
Defined as:
multi method DateTime(Date:U --> DateTime:U) multi method DateTime(Date:D --> DateTime:D)
Converts the invocant to DateTime
say Date.new('2015-12-24').DateTime; # OUTPUT: «2015-12-24T00:00:00Z» say Date.DateTime; # OUTPUT: «(DateTime)»
sub sleep($seconds = Inf --> Nil)
Attempt to sleep for the given number of $seconds. Returns Nil on completion. Accepts Int, Num, Rat, or Duration types as an argument since all of these also do Real.
sleep 5; # Int sleep 5.2; # Num sleep (5/2); # Rat sleep (now - now + 5); # Duration
It is thus possible to sleep for a non-integer amount of time. For instance, the following code shows that sleep (5/2) sleeps for 2.5 seconds and sleep 5.2 sleeps for 5.2 seconds:
my $before = now; sleep (5/2); my $after = now; say $after-$before; # OUTPUT: «2.502411561» $before = now; sleep 5.2; $after = now; say $after-$before; # OUTPUT: «5.20156987»
sub sleep-timer(Real() $seconds = Inf --> Duration:D)
This function is implemented like sleep, but unlike the former it does return a Duration instance with the number of seconds the system did not sleep.
In particular, the returned Duration will handle the number of seconds remaining when the process has been awakened by some external event (e.g., Virtual Machine or Operating System events). Under normal condition, when sleep is not interrupted, the returned Duration has a value of 0, meaning no extra seconds remained to sleep. Therefore, in normal situations:
say sleep-timer 3.14; # OUTPUT: «0»
The same result applies to edge cases, when a negative or zero time to sleep is passed as argument:
say sleep-timer -2; # OUTPUT: 0 say sleep-timer 0; # OUTPUT: 0
See also sleep-until.
sub sleep-until(Instant $until --> Bool)
Works similar to sleep but checks the current time and keeps sleeping until the required instant in the future has been reached. It uses internally the sleep-timer method in a loop to ensure that, if accidentally woken up early, it will wait again for the specified amount of time remaining to reach the specified instant. goes back to sleep
Returns True if the Instant in the future has been achieved (either by mean of sleeping or because it is right now), False in the case an Instant in the past has been specified.
To sleep until 10 seconds into the future, one could write something like this:
say sleep-until now+10; # OUTPUT: «True»
Trying to sleep until a time in the past doesn't work:
my $instant = now - 5; say sleep-until $instant; # OUTPUT: «False»
However if we put the instant sufficiently far in the future, the sleep should run:
my $instant = now + 30; # assuming the two commands are run within 30 seconds of one another... say sleep-until $instant; # OUTPUT: «True»
To specify an exact instant in the future, first create a DateTime at the appropriate point in time, and cast to an Instant.
my $instant = DateTime.new( year => 2020, month => 9, day => 1, hour => 22, minute => 5); say sleep-until $instant.Instant; # True (eventually...)
This could be used as a primitive kind of alarm clock. For instance, say you need to get up at 7am on the 4th of September 2015, but for some reason your usual alarm clock is broken and you only have your laptop. You can specify the time to get up (being careful about time zones, since DateTime.new uses UTC by default) as an Instant and pass this to sleep-until, after which you can play an mp3 file to wake you up instead of your normal alarm clock. This scenario looks roughly like this:
# DateTime.new uses UTC by default, so get time zone from current time my $timezone = DateTime.now.timezone; my $instant = DateTime.new( year => 2015, month => 9, day => 4, hour => 7, minute => 0, timezone => $timezone ).Instant; sleep-until $instant; qqx{mplayer wake-me-up.mp3};
multi sub infix:<-> (Date:D, Int:D --> Date:D) multi sub infix:<-> (Date:D, Date:D --> Int:D)
Takes a date to subtract from and either an Int, representing the number of days to subtract, or another Date object. Returns a new Date object or the number of days between the two dates, respectively.
say Date.new('2016-12-25') - Date.new('2016-12-24'); # OUTPUT: «1» say Date.new('2015-12-25') - Date.new('2016-11-21'); # OUTPUT: «-332» say Date.new('2016-11-21') - 332; # OUTPUT: «2015-12-25»
multi sub infix:<+> (Date:D, Int:D --> Date:D) multi sub infix:<+> (Int:D, Date:D --> Date:D)
Takes an Int and adds that many days to the given Date object.
say Date.new('2015-12-25') + 332; # OUTPUT: «2016-11-21» say 1 + Date.new('2015-12-25'); # OUTPUT: «2015-12-26»
Calendar date with time
class DateTime does Dateish {}
For handling points in civil time, a DateTime object stores year, month, day, hour, minute (all Int), second (potentially fractional) and a time zone.
It provides methods for calculating with date and time.
DateTime methods are immutable; if you are tempted to modify one, create a modified copy instead.
Time zones are handled as Integers in seconds offset from UTC, not by time zone name.
my $dt = DateTime.new( year => 2015, month => 11, day => 21, hour => 16, minute => 1, ); say $dt; # OUTPUT: «2015-11-21T16:01:00Z» say $dt.later(days => 20); # OUTPUT: «2015-12-11T16:01:00Z» say $dt.truncated-to('hour'); # OUTPUT: «2015-11-21T16:00:00Z» say $dt.in-timezone(-8 * 3600); # OUTPUT: «2015-11-21T08:01:00-0800» my $now = DateTime.now(formatter => { sprintf "%02d:%02d", .hour, .minute }); say $now; # 12:45 (or something like that)
Defined as:
multi method new(Int :$year!, Int :$month = 1, Int :$day = 1, Int :$hour = 0, Int :$minute = 0, :$second = 0, Int :$timezone = 0, :&formatter) multi method new(Date :$date!, Int :$hour = 0, Int :$minute = 0, :$second = 0, Int :$timezone = 0, :&formatter) multi method new(Int() $year, Int() $month, Int() $day, Int() $hour, Int $minute, $second, Int() :$timezone = 0, :&formatter) multi method new(Instant:D $i, :$timezone=0, :&formatter) multi method new(Int:D $posix, :$timezone=0, :&formatter) multi method new(Str:D $format, :$timezone=0, :&formatter)
Creates a new DateTime object. One option for creating a new DateTime object is from the components (year, month, day, hour, ...) separately. Another is to pass a Date object for the date component, and specify the time component-wise. Yet another is to obtain the time from an Instant, and only supply the time zone and formatter. Or instead of an Instant you can supply an Int as a UNIX timestamp.
You can also supply a Str formatted in ISO 8601 timestamp notation or as a full RFC 3339 date and time. Strings should be formatted as yyyy-mm-ddThh:mm:ssZ or yyyy-mm-ddThh:mm:ss+0100. We are somewhat less restrictive than the ISO 8601 standard, as we allow Unicode digits and mixing of condensed and extended time formats.
An invalid input string throws an exception of type X::Temporal::InvalidFormat. If you supply a string that includes a time zone and supply the timezone named argument, an exception of type X::DateTime::TimezoneClash is thrown.
my $datetime = DateTime.new(year => 2015, month => 1, day => 1, hour => 1, minute => 1, second => 1, timezone => 1); $datetime = DateTime.new(date => Date.new('2015-12-24'), hour => 1, minute => 1, second => 1, timezone => 1); $datetime = DateTime.new(2015, 1, 1, # First January of 2015 1, 1, 1); # Hour, minute, second with default time zone $datetime = DateTime.new(now); # Instant. # from a Unix timestamp say $datetime = DateTime.new(1470853583); # OUTPUT: «2016-08-10T18:26:23Z» $datetime = DateTime.new("2015-01-01T03:17:30+0500") # Formatted string
Defined as:
method now(:$timezone = $*TZ, :&formatter --> DateTime:D)
Creates a new DateTime object from the current system time. A custom formatter and timezone can be provided. The :$timezone is the offset in seconds from GMT and defaults to the value of $*TZ variable.
say DateTime.now; # OUTPUT: «2018-01-08T13:05:32.703292-06:00»
Note that one may use the methods shown below chained to the .now to easily express current values, e.g.,
say DateTime.now.year; # OUTPUT: «2018»
Defined as:
method clone(:$year, :$month, :$day, :$hour, :$minute, :$second, :$timezone, :&formatter)
Creates a new DateTime object based on the invocant, but with the given arguments overriding the values from the invocant.
say DateTime.new('2015-12-24T12:23:00Z').clone(hour => 0); # OUTPUT: «2015-12-24T00:23:00Z»
Note that this can lead to invalid dates in some circumstances:
say DateTime.new("2012-02-29T12:34:56Z").clone(year => 2015); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::OutOfRange: Day out of range. Is: 29, should be in 1..28»
Defined as:
method hh-mm-ss(DateTime:D: --> Str:D)
Returns the time represented by the object as a string in 24-hour HH:MM:SS format:
say DateTime.new("2052-02-29T22:34:56Z").hh-mm-ss; # OUTPUT: «22:34:56»
Defined as:
method hour(DateTime:D: --> Int:D)
Returns the hour component.
say DateTime.new('2012-02-29T12:34:56Z').hour; # OUTPUT: «12»
Defined as:
method minute(DateTime:D: --> Int:D)
Returns the minute component.
say DateTime.new('2012-02-29T12:34:56Z').minute; # OUTPUT: «34»
Defined as:
method second(DateTime:D:)
Returns the second component, including potentially fractional seconds.
say DateTime.new('2012-02-29T12:34:56Z').second; # OUTPUT: «56» say DateTime.new('2012-02-29T12:34:56.789Z').second; # OUTPUT: «56.789» say DateTime.new('2012-02-29T12:34:56,789Z').second; # comma also ok
Defined as:
method whole-second(DateTime:D:)
Returns the second component, rounded down to an Int.
say DateTime.new('2012-02-29T12:34:56.789Z').whole-second; # OUTPUT: «56»
Defined as:
method timezone(DateTime:D: --> Int:D)
Returns the time zone in seconds as an offset from UTC.
say DateTime.new('2015-12-24T12:23:00+0200').timezone; # OUTPUT: «7200»
Defined as:
method offset(DateTime:D: --> Int:D)
Returns the time zone in seconds as an offset from UTC. This is an alias for #method timezone.
say DateTime.new('2015-12-24T12:23:00+0200').offset; # OUTPUT: «7200»
Defined as:
method offset-in-minutes(DateTime:D: --> Real:D)
Returns the time zone in minutes as an offset from UTC.
say DateTime.new('2015-12-24T12:23:00+0200').offset-in-minutes; # OUTPUT: «120»
Defined as:
method offset-in-hours(DateTime:D: --> Real:D)
Returns the time zone in hours as an offset from UTC.
say DateTime.new('2015-12-24T12:23:00+0200').offset-in-hours; # OUTPUT: «2»
Defined as:
method Str(DateTime:D: --> Str:D)
Returns a string representation of the invocant, as done by the formatter. If no formatter was specified, an ISO 8601 timestamp will be returned.
say DateTime.new('2015-12-24T12:23:00+0200').Str; # OUTPUT: «2015-12-24T12:23:00+02:00»
Defined as:
method Instant(DateTime:D: --> Instant:D)
Returns an Instant object based on the invocant.
say DateTime.new('2015-12-24T12:23:00+0200').Instant; # OUTPUT: «Instant:1450952616»
Defined as:
method posix(Bool:D: $ignore-timezone = False --> Int:D)
Returns the date and time as a POSIX/UNIX timestamp (seconds since the Epoch, 1st January 1970 UTC).
If $ignore-timezone is True, the DateTime object will be treated as if the time zone offset is zero.
say DateTime.new('2015-12-24T12:23:00Z').posix; # OUTPUT: «1450959780»
Defined as:
method later(DateTime:D: *%unit)
Returns a DateTime object based on the current one, but with a time delta applied. The time delta can be passed as a named argument where the argument name is the unit.
Unless the given unit is second or seconds, the given value will be converted to an Int.
Allowed units are second, seconds, minute, minutes, hour, hours, day, days, week, weeks, month, months, year, years. Please note that the plural forms can only be used with the later and earlier methods.
The :2nd form of colonpairs can be used as a compact and self-documenting way of specifying the delta:
say DateTime.new('2015-12-24T12:23:00Z').later(:2years); # OUTPUT: «2017-12-24T12:23:00Z»
Since addition of several different time units is not commutative, only one unit may be passed.
my $d = DateTime.new(date => Date.new('2015-02-27')); say $d.later(month => 1).later(:2days); # OUTPUT: «2015-03-29T00:00:00Z» say $d.later(days => 2).later(:1month); # OUTPUT: «2015-04-01T00:00:00Z» say $d.later(days => 2).later(:month); # same, as +True === 1
If the resultant time has value 60 for seconds, yet no leap second actually exists for that time, seconds will be set to 59:
say DateTime.new('2008-12-31T23:59:60Z').later: :1day; # OUTPUT: «2009-01-01T23:59:59Z»
Negative offsets are allowed, though earlier is more idiomatic for that.
Defined as:
method earlier(DateTime:D: *%unit)
Returns a DateTime object based on the current one, but with a time delta towards the past applied. Unless the given unit is second or seconds, the given value will be converted to an Int. See #method later for usage.
my $d = DateTime.new(date => Date.new('2015-02-27')); say $d.earlier(month => 1).earlier(:2days); # OUTPUT: «2015-01-25T00:00:00Z»
If the resultant time has value 60 for seconds, yet no leap second actually exists for that time, seconds will be set to 59:
say DateTime.new('2008-12-31T23:59:60Z').earlier: :1day; # OUTPUT: «2008-12-30T23:59:59Z»
Negative offsets are allowed, though later is more idiomatic for that.
Defined as:
method truncated-to(DateTime:D: Cool $unit)
Returns a copy of the invocant, with everything smaller than the specified unit truncated to the smallest possible value.
my $d = DateTime.new("2012-02-29T12:34:56.946314Z"); say $d.truncated-to('second'); # OUTPUT: «2012-02-29T12:34:56Z» say $d.truncated-to('minute'); # OUTPUT: «2012-02-29T12:34:00Z» say $d.truncated-to('hour'); # OUTPUT: «2012-02-29T12:00:00Z» say $d.truncated-to('day'); # OUTPUT: «2012-02-29T00:00:00Z» say $d.truncated-to('month'); # OUTPUT: «2012-02-01T00:00:00Z» say $d.truncated-to('year'); # OUTPUT: «2012-01-01T00:00:00Z»
DateTimes with fractional seconds can be truncated to whole seconds with .truncated-to('second').
Defined as:
multi method Date(DateTime:U --> Date:U) multi method Date(DateTime:D --> Date:D)
Converts the invocant to Date.
say DateTime.new("2012-02-29T12:34:56.946314Z").Date; # OUTPUT: «2012-02-29» say DateTime.Date; # OUTPUT: «(Date)»
Defined as:
method DateTime(--> DateTime)
Returns the invocant.
say DateTime.new("2012-02-29T12:34:56.946314Z").DateTime; # OUTPUT: «2012-02-29T12:34:56.946314Z» say DateTime.DateTime; # OUTPUT: «(DateTime)»
Defined as:
method utc(DateTime:D: --> DateTime:D)
Returns a DateTime object for the same time, but in time zone UTC.
say DateTime.new('2015-12-24T12:23:00+0200').utc; # OUTPUT: «2015-12-24T10:23:00Z»
Defined as:
method in-timezone(DateTime:D: Int(Cool) $timezone = 0 --> DateTime:D)
Returns a DateTime object for the same time, but in the specified $timezone, which is the offset in seconds from GMT.
say DateTime.new('2015-12-24T12:23:00Z').in-timezone(3600 + 1800); # OUTPUT: «2015-12-24T13:53:00+0130»
Per RFC 7164, leap seconds do not respect local time and always occur at the end of the UTC day:
say DateTime.new: '2017-01-01T00:59:60+01:00' # OUTPUT: «2017-01-01T00:59:60+01:00»
Defined as:
method local(DateTime:D: --> DateTime:D)
Returns a DateTime object for the same time, but in the local time zone ($*TZ).
my $*TZ = -3600; say DateTime.new('2015-12-24T12:23:00+0200').local; # OUTPUT: «2015-12-24T09:23:00-0100»
multi sub infix:<-> (DateTime:D, Duration:D --> DateTime:D) multi sub infix:<-> (DateTime:D, DateTime:D --> Duration:D)
Takes a DateTime to subtract from and either a Duration or another DateTime object. Returns a new DateTime object or the Duration between the two dates, respectively. When subtracting Duration, time zone of the original DateTime is preserved in the returned DateTime object.
say perl DateTime.new(:2016year) - DateTime.new(:2015year):; # OUTPUT: «Duration.new(31536001.0)» say DateTime.new(:2016year, :3600timezone) - Duration.new(31536001.0); # OUTPUT: «2015-01-01T00:00:00+01:00»
multi sub infix:<+> (DateTime:D, Duration:D --> DateTime:D) multi sub infix:<+> (Duration:D, DateTime:D --> DateTime:D)
Takes a DateTime and increases it by the given Duration, preserving the time zone.
say DateTime.new(:2015year) + Duration.new(31536001.0); # OUTPUT: «2016-01-01T00:00:00Z» say Duration.new(42) + DateTime.new(:2015year, :3600timezone); # OUTPUT: «2015-01-01T00:00:42+01:00»
multi sub infix:«<=>»(DateTime:D \a, DateTime:D \b --> Order:D)
Compares the equivalent instant, returns the Order.
say DateTime.now <=> DateTime.now; # OUTPUT: «Less»
multi sub infix:«cmp»(DateTime:D \a, DateTime:D \b --> Order:D)
Compares the equivalent instant, returns the Order.
multi sub infix:«<»(DateTime:D \a, DateTime:D \b --> Bool:D)
Compares the equivalent instant, returns a Bool
multi sub infix:«>»(DateTime:D \a, DateTime:D \b --> Bool:D)
Compares the equivalent instant, returns a Bool
multi sub infix:«<=»(DateTime:D \a, DateTime:D \b --> Bool:D)
Compares the equivalent instant, returns a Bool
multi sub infix:«>=»(DateTime:D \a, DateTime:D \b --> Bool:D)
Compares the equivalent instant, returns a Bool
multi sub infix:«==»(DateTime:D \a, DateTime:D \b --> Bool:D)
Compares the equivalent instant, returns a Bool
multi sub infix:«!=»(DateTime:D \a, DateTime:D \b --> Bool:D)
Compares the equivalent instant, returns a Bool
Object that can be treated as a date
role Dateish { ... }
Both Date and DateTime support accessing a year, month and day-of-month, as well as related functionality such as calculating the day of the week.
Defined as:
method year(Date:D: --> Int:D)
Returns the year of the date.
say Date.new('2015-12-31').year; # OUTPUT: «2015» say DateTime.new(date => Date.new('2015-12-24'), hour => 1).year; # OUTPUT: «2015»
Defined as:
method month(Date:D: --> Int:D)
Returns the month of the date (1..12).
say Date.new('2015-12-31').month; # OUTPUT: «12» say DateTime.new(date => Date.new('2015-12-24'), hour => 1).month; # OUTPUT: «12»
Defined as:
method day(Date:D: --> Int:D)
Returns the day of the month of the date (1..31).
say Date.new('2015-12-31').day; # OUTPUT: «31» say DateTime.new(date => Date.new('2015-12-24'), hour => 1).day; # OUTPUT: «24»
Defined as:
method formatter(Dateish:D:)
Returns the formatting function which is used for conversion to Str. If none was provided at object construction, a default formatter is used. In that case the method will return a Callable type object.
The formatting function is called by DateTime method Str with the invocant as its only argument.
my $dt = Date.new('2015-12-31'); # (no formatter specified) say $dt.formatter.^name; # OUTPUT: «Callable» my $us-format = sub ($self) { sprintf "%02d/%02d/%04d", .month, .day, .year given $self; }; $dt = Date.new('2015-12-31', formatter => $us-format); say $dt.formatter.^name; # OUTPUT: «Sub» say $dt; # OUTPUT: «12/31/2015»
Defined as:
method is-leap-year(--> Bool:D)
Returns True if the year of the Dateish object is a leap year.
say DateTime.new(:year<2016>).is-leap-year; # OUTPUT: «True» say Date.new("1900-01-01").is-leap-year; # OUTPUT: «False»
Defined as:
method day-of-month(Date:D: --> Int:D)
Returns the day of the month of the date (1..31). Synonymous to the day method.
say Date.new('2015-12-31').day-of-month; # OUTPUT: «31» say DateTime.new(date => Date.new('2015-12-24'), hour => 1).day-of-month; # OUTPUT: «24»
Defined as:
method day-of-week(Date:D: --> Int:D)
Returns the day of the week, where 1 is Monday, 2 is Tuesday and Sunday is 7.
say Date.new('2015-12-31').day-of-week; # OUTPUT: «4» say DateTime.new(date => Date.new('2015-12-24'), hour => 1).day-of-week; # OUTPUT: «4»
Defined as:
method day-of-year(Date:D: --> Int:D)
Returns the day of the year (1..366).
say Date.new('2015-12-31').day-of-year; # OUTPUT: «365» say DateTime.new(date => Date.new('2015-03-24'), hour => 1).day-of-year; # OUTPUT: «83»
Defined as:
method days-in-month(Dateish:D: --> Int:D)
Returns the number of days in the month represented by the Dateish object:
say Date.new("2016-01-02").days-in-month; # OUTPUT: «31» say DateTime.new(:year<10000>, :month<2>).days-in-month; # OUTPUT: «29»
Defined as:
method week()
Returns a list of two integers: the year, and the week number. This is because at the start or end of a year, the week may actually belong to the other year.
my ($year, $week) = Date.new("2014-12-31").week; say $year; # OUTPUT: «2015» say $week; # OUTPUT: «1» say Date.new('2015-01-31').week; # OUTPUT: «(2015 5)»
Defined as:
method week-number(Date:D: --> Int:D)
Returns the week number (1..53) of the date specified by the invocant. The first week of the year is defined by ISO as the one which contains the fourth day of January. Thus, dates early in January often end up in the last week of the prior year, and similarly, the final few days of December may be placed in the first week of the next year.
say Date.new("2014-12-31").week-number; # 1 (first week of 2015) say Date.new("2016-01-02").week-number; # 53 (last week of 2015)
Defined as:
method week-year(Date:D: --> Int:D)
Returns the week year of the date specified by the invocant. Normally week-year is equal to Date.year. Note however that dates early in January often end up in the last week of the prior year, and similarly, the final few days of December may be placed in the first week of the next year.
say Date.new("2015-11-15").week-year; # 2015 say Date.new("2014-12-31").week-year; # 2015 (date belongs to the first week of 2015) say Date.new("2016-01-02").week-year; # 2015 (date belongs to the last week of 2015)
Defined as:
method weekday-of-month(Date:D: --> Int:D)
Returns a number (1..5) indicating the number of times a particular day-of-week has occurred so far during that month, the day itself included.
say Date.new("2003-06-09").weekday-of-month; # 2 (second Monday of the month)
Defined as:
method yyyy-mm-dd(Date:D: --> Str:D)
Returns the date in YYYY-MM-DD format (ISO 8601)
say Date.new("2015-11-15").yyyy-mm-dd; # OUTPUT: «2015-11-15» say DateTime.new(1470853583).yyyy-mm-dd; # OUTPUT: «2016-08-10»
Defined as:
method daycount(Dateish:D: --> Int:D)
Returns the number of days from the epoch Nov. 17, 1858 to the day of the invocant. The daycount returned by this method is the MJD, i.e. the Modified Julian Day, which is used routinely by e.g. astronomers, geodesists, scientists and others. The MJD convention is designed to facilitate simplified chronological calculations.
say Date.new('1995-09-27').daycount; # OUTPUT: «49987»
Defined as:
method IO(Dateish:D: --> IO::Path:D)
Returns an IO::Path object representing the stringified value of the Dateish object:
Date.today.IO.say; # OUTPUT: «"2016-10-03".IO» DateTime.now.IO.say; # OUTPUT: «"2016-10-03T11:14:47.977994-04:00".IO»
PORTABILITY NOTE: some operating systems (e.g. Windows) do not permit colons (:) in filenames, which would be present in IO::Path created from a DateTime object.
Distribution
role Distribution { }
Interface for objects that provide API access mapping META6 data to the files its represents. Objects that fulfill the Distribution role can be read by e.g. CompUnit::Repository::Installation. Generally a Distribution provides read access to a set of modules and metadata. These may be backed by the filesystem (Distribution::Path, Distribution::Hash) but could also read from an e.g. tar file or socket.
method meta(--> Hash:D) { ... }
Returns a Hash with the representation of the metadata. Please note that an actual META6.json file does not need to exist, just a representation in that format.
method content($name-path --> IO::Handle:D) { ... }
Returns an IO::Handle to the file represented by $name-path. $name-path is a relative path as it would be found in the metadata such as lib/Foo.pm6 or resources/foo.txt.
Distribution::Hash
class Distribution::Hash does Distribution::Locally { }
A Distribution implementation backed by the filesystem. It does not require a META6.json file, essentially providing a lower level Distribution::Path.
method new($hash, :$prefix)
Creates a new Distribution::Hash instance from the metadata contained in $hash. All paths in the metadata will be prefixed with :$prefix.
method meta()
Returns a Hash with the representation of the metadata.
Please check the content method in Distribution::Locally.
Returns an IO::Handle to the file represented by $name-path. $name-path is a relative path as it would be found in the metadata such as lib/Foo.pm6 or resources/foo.txt.
Distribution::Locally
role Distribution::Locally does Distribution { }
Provides read access to specific files pointed at by a distributions metadata, providing the Distribution#method_content method for Distribution::Path and Distribution::Hash.
A prefix path to be used in conjuncture with the paths found in the metadata.
Provides Distribution#method_content
Returns an IO::Handle to the file represented by $name-path. $name-path is a relative path as it would be found in the metadata such as lib/Foo.pm6 or resources/foo.txt, and these paths will be prefixed with Distribution#method_prefix.
Distribution::Path
class Distribution::Path does Distribution::Locally { }
A Distribution implementation backed by the filesystem. It requires a META6.json file at its root.
method new(IO::Path $prefix, IO::Path :$meta-file = IO::Path)
Creates a new Distribution::Path instance from the META6.json file found at the given $prefix, and from which all paths in the metadata will be prefixed with. :$meta-file may optionally be passed if a filename other than META6.json needs to be used.
method meta()
Returns a Hash with the representation of the metadata.
Distribution::Locally#method_content
Returns an IO::Handle to the file represented by $name-path. $name-path is a relative path as it would be found in the metadata such as lib/Foo.pm6 or resources/foo.txt.
Distribution related information
class Distro does Systemic { }
Built-in class for providing distribution related information. Usually accessed through the $*DISTRO dynamic variable.
Instance method returning a Bool indicating whether the distribution is a version of the Windows operating system.
Instance method returning the string that can be used to delimit elements in a path specification.
Instance method returning the release information of the Distro object. Dies if the release information could not be established.
Length of time
class Duration is Cool does Real { }
A Duration represents a length of time in atomic seconds, with fractions. Like an Instant, it is epoch-agnostic.
Durations can be subtracted from or added to Instants to yield another, new Instant. Subtracting one Instant from another yields a Duration. A Duration can also result from mathematical operations between two Durations when it makes sense (namely, the addition, subtraction, or modulus of two Durations). It can also be added, subtracted or divided modulo Real numbers.
The type of object returned for other numeric operations is currently unspecified.
Support for character encodings.
role Encoding { ... }
The Encoding role is implemented by classes that provide a character encoding, such as ASCII or UTF-8. Besides being used by the built-in character encodings, it may also be implemented by users to provide new encodings. Instances of objects doing this role are typically obtained using Encoding::Registry. For a list of supported encodings, see IO::Handle.
All methods provided by this role are stubs; they should be implemented by consumers of the role.
method name(--> Str)
Abstract method that would return the primary name of the encoding.
method alternative-names()
Abstract methods that should get a list of alternative names for the encoding.
method decoder(*%options --> Encoding::Decoder)
Should get a character decoder instance for this encoding, configured with the provided options. Options vary by encoding. The built-in encodings all support translate-nl, which if True will translate \r\n into \n while decoding.
Defined as:
method encoder(*%options --> Encoding::Encoder)
Gets a character encoder instance for this encoding, configured with the provided options. Options vary by encoding. The built-in encodings all support both replacement (either a Str replacement sequence or True to use a default replacement sequence for unencodable characters) and translate-nl (when set to True, turns \n into \r\n if the current platform is Windows).
Management of available encodings
class Encoding::Registry {}
Encoding::Registry is initialized with a list of encoding that is available for any Perl 6 application, namely:
utf8
utf8-c8
utf16
utf16le
utf16be
utf32, utf-32
ascii
iso-8859-1, iso_8859-1:1987, iso_8859-1, iso-ir-100, latin1, latin-1, csisolatin1, l1, ibm819, cp819
windows-1251
windows-1252
windows-932
method register(Encoding $enc --> Nil)
Register a new Encoding.
method find(Str() $name)
Finds an encoding by its name. Returns an Encoding::Encoder or Encoding::Decoder, depending on what had been registered.
Indicate endianness (6.d, 2018.12 and later)
enum Endian <NativeEndian LittleEndian BigEndian>;
An enum for indicating endianness, specifically with methods on blob8 and buf8. Consists of NativeEndian, LittleEndian and BigEndian.
multi method Numeric(Endian:D --> Int:D)
Returns the value part of the enum pair.
say NativeEndian.Numeric; # OUTPUT: «0» say LittleEndian.Numeric; # OUTPUT: «1» say BigEndian.Numeric; # OUTPUT: «2»
Note that the actual numeric values are subject to change. So please use the named values instead.
Working with the role behind the enum type
role Enumeration { }
This is the role implemented by the enum-pairs in the enum type. In general, it is used to create constant sets, the elements of which become also constant symbols in the current namespace and to establish a relationship between the symbols belonging to the same set. In general, you will find Enumeration in enum types:
enum norse-gods <Þor Oðin Loki>; my $one-of-them = norse-gods.pick; say $one-of-them ~~ Enumeration; # OUTPUT: «True»
but nothing prevents you from using it in your own programs if you want to restrict somehow the relationship between the key and the value:
class DNA does Enumeration { my %pairings = %( A => "T", T => "A", C => "G", G => "C" ); method new( $base-pair where "A" | "C" | "G" | "T" ) { self.bless( key => $base-pair, value => %pairings{$base-pair}); } multi method gist(::?CLASS:D:) { return "$!key → $!value"; } } enum Chain (); constant length = 16; for <A C G T>.roll( length ) -> $letter { my DNA $base = DNA.new( $letter ); Chain.HOW.add_enum_value( Chain, $base ); } for ^length { my $base = Chain.pick; say "{$base.key} and {$base.value}"; }
In this code, DNA consumes the Enumeration role, which is from this point of view a pair of key and value; we can use the generated DNA objects to compose an enum type from which elements can be picked one by one, with the output shown below.
T and A C and G T and A # and so on...
These are the methods included in this role:
An Enumeration property.
enum Norse-gods <Þor Oðin Freija>; say Freija.key; # OUTPUT: «Freija»
These are Enumeration properties.
enum Norse-gods <Þor Oðin Freija>; say Oðin.value; # OUTPUT: «1»
The value is assigned automatically by the enum type starting at 0. Oðin gets 1 since it is the second in the enum.
Defined as:
method enums()
Returns a Map of enum values. Works both on the enum type and any key.
enum Mass ( mg => 1/1000, g => 1/1, kg => 1000/1 ); say Mass.enums; # OUTPUT: «Map.new((g => 1, kg => 1000, mg => 0.001))» say g.enums; # OUTPUT: «Map.new((g => 1, kg => 1000, mg => 0.001))»
Defined as:
multi method kv(::?CLASS:D:)
Returns a list with key and value of the enum-pair.
say g.kv; # OUTPUT: «(g 1)»
Defined as:
method pair(::?CLASS:D:)
Returns it as a Pair.
say g.pair; # OUTPUT: «g => 1»
Defined as:
multi method CALL-ME(|)
Returns an Enumeration instance given an enum value.
enum Mass ( mg => 1/1000, g => 1/1, kg => 1000/1 ); say Mass(1/1000); # OUTPUT: mg
Defined as:
multi method pick(::?CLASS:U:) multi method pick(::?CLASS:U: \n) multi method pick(::?CLASS:D: *@pos)
It works on the defined class, selecting one element and eliminating it.
say Norse-gods.pick() for ^3; # OUTPUT: «ÞorFreijaOðin»
Defined as:
multi method roll(::?CLASS:U:) multi method roll(::?CLASS:U: \n) multi method roll(::?CLASS:D: *@pos)
They work on the defined class selecting one or n elements without eliminating them.
say Norse-gods.roll() for ^3; # OUTPUT: «FreijaFreijaOðin»
Defined as:
method pred(::?CLASS:D:)
say Freija.pred; # OUTPUT: «Oðin»
Defined as:
method succ(::?CLASS:D:)
say Oðin.succ; # OUTPUT: «Freija»
Defined as:
multi method Numeric(::?CLASS:D:)
Takes a value of an enum and returns it after coercion to Numeric:
enum Numbers ( cool => '42', almost-pi => '3.14', sqrt-n-one => 'i' ); say cool.Numeric; # OUTPUT: «42» say almost-pi.Numeric; # OUTPUT: «3.14» say sqrt-n-one.Numeric; # OUTPUT: «0+1i»
Note that if the value cannot be coerced to Numeric, an exception will be thrown.
Defined as:
multi method Int(::?CLASS:D:)
Takes a value of an enum and returns it after coercion to Int:
enum Numbers ( cool => '42', almost-pi => '3.14', sqrt-n-one => 'i' ); say cool.Int; # OUTPUT: «42» say almost-pi.Int; # OUTPUT: «3» try say sqrt-n-one.Int; say $!.message if $!; # OUTPUT: «Cannot convert 0+1i to Int: imaginary part not zero»
Note that if the value cannot be coerced to Int, an exception will be thrown.
Defined as:
multi method Real(::?CLASS:D:)
Takes a value of an enum and returns it after coercion to Real:
enum Numbers ( cool => '42', almost-pi => '3.14', sqrt-n-one => 'i' ); say cool.Real; # OUTPUT: «42» say almost-pi.Real; # OUTPUT: «3.14» try say sqrt-n-one.Real; say $!.message if $!; # OUTPUT: «Cannot convert 0+1i to Real: imaginary part not zero»
Note that if the value cannot be coerced to Real, an exception will be thrown.
Defined as
multi infix:<===> (Enumeration:D \a, Enumeration:D \b)
Equality of Enumeration symbols:
say Norse-gods.pick() === Freija for ^3; # OUTPUT: «FalseFalseTrue»
Anomalous event capable of interrupting normal control-flow
class Exception {}
All exceptions that are placed into the $! variable (or into $_ in CATCH blocks) inherit from Exception. When you call die or fail with a non-Exception argument, it is wrapped into an X::AdHoc object, which also inherits from Exception.
User-defined exception classes should inherit from Exception too, and define at least a method message.
class X::YourApp::SomeError is Exception { method message() { "A YourApp-Specific error occurred: out of coffee!"; } }
Defined as:
method message(Exception:D: --> Str:D)
This is a stub that must be overwritten by subclasses, and should return the exception message.
Special care should be taken that this method does not produce an exception itself.
try die "Something bad happened"; if ($!) { say $!.message; # OUTPUT: «Something bad happened.» }
Defined as:
method backtrace(Exception:D:)
Returns the backtrace associated with the exception in a Backtrace object or an empty string if there is none. Only makes sense on exceptions that have been thrown at least once.
try die "Something bad happened"; with $! { .backtrace.print ; }
Defined as:
method throw(Exception:D:)
Throws the exception.
my $exception = X::AdHoc.new; # Totally fine try $exception.throw; # Throws if ($!) { #`( some handling ) }; # Suppress the exception
Defined as:
method resume(Exception:D:)
Resumes control flow where .throw left it when handled in a CATCH block.
# For example, resume control flow for any exception CATCH { default { .resume } }
Defined as:
method rethrow(Exception:D:)
Rethrows an exception that has already been thrown at least once. This is different from throw in that it preserves the original backtrace.
my $e = X::AdHoc.new(payload => "Bad situation"); sub f() { die 'Bad' }; sub g() { try f; CATCH { default { .rethrow } } }; g; CATCH { default { say .backtrace.full } };
Defined as:
multi sub fail(*@text) multi sub fail(Exception $e) method fail(Exception:D:)
Exits the calling Routine and returns a Failure object wrapping the exception $e - or, for the *@text form, an X::AdHoc exception constructed from the concatenation of @text. If the caller activated fatal exceptions via the pragma use fatal;, the exception is thrown instead of being returned as a Failure.
# A custom exception defined class ForbiddenDirectory is Exception { has Str $.name; method message { "This directory is forbidden: '$!name'" } } sub copy-directory-tree ($dir) { # We don't allow for non-directories to be copied fail "$dir is not a directory" if !$dir.IO.d; # We don't allow 'foo' directory to be copied too fail ForbiddenDirectory.new(:name($dir)) if $dir eq 'foo'; # or above can be written in method form as: # ForbiddenDirectory.new(:name($dir)).fail if $dir eq 'foo'; # Do some actual copying here ... } # A Failure with X::AdHoc exception object is returned and # assigned, so no throwing Would be thrown without an assignment my $result = copy-directory-tree("cat.jpg"); say $result.exception; # OUTPUT: «cat.jpg is not a directory» # A Failure with a custom Exception object is returned $result = copy-directory-tree('foo'); say $result.exception; # OUTPUT: «This directory is forbidden: 'foo'»
Defined as:
multi method gist(Exception:D:)
Returns whatever the exception printer should produce for this exception. The default implementation returns message and backtrace separated by a newline.
my $e = X::AdHoc.new(payload => "This exception is pretty bad"); try $e.throw; if ($!) { say $!.gist; }; # OUTPUT: «This exception is pretty bad # in block <unit> at <unknown file> line 1»
Defined as:
multi sub die() multi sub die(*@message) multi sub die(Exception:D $e) method die(Exception:D:)
Throws a fatal Exception. The default exception handler prints each element of the list to $*ERR (STDERR).
die "Important reason";
If the subroutine form is called without arguments, the value of $! variable is checked. If it is set to a .DEFINITE value, its value will be used as the Exception to throw if it's of type Exception, otherwise, it will be used as payload of X::AdHoc exception. If $! is not .DEFINITE, X::AdHoc with string "Died" as payload will be thrown.
die will print by default the line number where it happens
die "Dead"; # OUTPUT: «(exit code 1) Dead # in block <unit> at /tmp/dead.p6 line 1»
However, that default behavior is governed at the Exception level and thus can be changed to anything we want by capturing the exception using CATCH. This can be used, for instance, to suppress line numbers.
CATCH { default { .payload.say } }; die "Dead" # OUTPUT: «Dead»
Defined as:
multi sub warn(*@message)
Throws a resumable warning exception, which is considered a control exception, and hence is invisible to most normal exception handlers. The outermost control handler will print the warning to $*ERR. After printing the warning, the exception is resumed where it was thrown. To override this behavior, catch the exception in a CONTROL block. A quietly {...} block is the opposite of a try {...} block in that it will suppress any warnings but pass fatal exceptions through.
To simply print to $*ERR, please use note instead. warn should be reserved for use in threatening situations when you don't quite want to throw an exception.
warn "Warning message";
Delayed exception
class Failure is Nil { }
A Failure is a soft or unthrown Exception, usually generated by calling &fail. It acts as a wrapper around an Exception object.
Sink (void) context causes a Failure to throw, i.e. turn into a normal exception. The use fatal pragma causes this to happen in all contexts within the pragma's scope. Inside try blocks, use fatal is automatically set, and you can disable it with no fatal.
That means that Failures are generally only useful in cases of code that normally would produce an rvalue; Failures are more or less equivalent to Exceptions in code that will frequently be called in sink context (i.e., for its side-effects, such as with say).
Similarly, you should generally use &fail only inside code that is normally expected to return something.
Checking a Failure for truth (with the Bool method) or definedness (with the defined method) marks the failure as handled, and causes it not to throw in sink context anymore.
You can call the handled method to check if a failure has been handled.
Calling methods on unhandled failures propagates the failure. The specification says the result is another Failure, in Rakudo it causes the failure to throw.
Because a Failure is Nil, which is undefined, a common idiom for safely executing code that may fail uses a with/else statement:
sub may_fail( --> Numeric:D ) { my $value = (^10).pick || fail "Zero is unacceptable"; fail "Odd is also not okay" if $value % 2; return $value; } with may_fail() -> $value { # defined, so didn't fail say "I know $value isn't zero or odd." } else { # undefined, so failed, and the Failure is the topic say "Uh-oh: {.exception.message}." }
Defined as:
method new(Failure:D: $payload --> Failure)
Returns a new Failure instance with the given payload. The latter can be either an Exception or a payload for an Exception. A typical payload would be a Str with an error message. A list of payloads is also accepted.
my $e = Failure.new(now.DateTime, 'WELP‼'); say $e; CATCH{ default { say .^name, ': ', .Str } } # OUTPUT: «X::AdHoc: 2017-09-10T11:56:05.477237ZWELP‼»
Defined as:
method handled(Failure:D: --> Bool:D)
Returns True for handled failures, False otherwise.
sub f() { fail }; my $v = f; say $v.handled; # OUTPUT: «False»
The handled method is an lvalue, which means you can also use it to set the handled state:
sub f() { fail } my $v = f; $v.handled = True; say $v.handled; # OUTPUT: «True»
Defined as:
method exception(Failure:D: --> Exception)
Returns the Exception object that the failure wraps.
sub failer() { fail }; my $failure = failer; my $ex = $failure.exception; put "$ex.^name(): $ex"; # OUTPUT: «X::AdHoc: Failed»
Defined as:
method self(Failure:D: --> Failure:D)
If the invocant is a handled Failure, returns it as is. If not handled, throws its Exception. Since Mu type provides .self for every class, calling this method is a handy way to explosively filter out Failures:
my $num1 = '♥'.Int; # $num1 now contains a Failure object, which may not be desirable my $num2 = '♥'.Int.self; # .self method call on Failure causes an exception to be thrown my $num3 = '42'.Int.self; # Int type has a .self method, so here $num3 has `42` in it (my $stuff = '♥'.Int).so; say $stuff.self; # OUTPUT: «(HANDLED) Cannot convert string to number…» # Here, Failure is handled, so .self just returns it as is
Defined as:
multi method Bool(Failure:D: --> Bool:D)
Returns False, and marks the failure as handled.
sub f() { fail }; my $v = f; say $v.handled; $v.Bool; say $v.handled; # OUTPUT: «False # True»
Defined as:
method Capture()
Throws X::Cannot::Capture if the invocant is a type object or a handled Failure. Otherwise, throws the invocant's exception.
Defined as:
multi method defined(Failure:D: --> Bool:D)
Returns False (failures are officially undefined), and marks the failure as handled.
sub f() { fail }; my $v = f; say $v.defined; # OUTPUT: «False»
Rational number (arbitrary-precision)
class FatRat is Cool does Rational[Int, Int] {}
A FatRat is a rational number stored with arbitrary size numerator and denominator. Arithmetic operations involving a FatRat and optionally Int or Rat objects return a FatRat, avoiding loss of precision.
Since, unlike Rat, FatRat arithmetics do not fall back Num at some point, there is a risk that repeated arithmetic operations generate pathologically large numerators and denominators.
There are two common ways to generate FatRat objects: through the FatRat.new(Int, Int) constructor, which generates them from numerator and denominator, or by calling the .FatRat method on an Int or Rat object.
multi method perl(FatRat:D: --> Str:D)
Returns an implementation-specific string that produces an equivalent object when given to EVAL.
say FatRat.new(1, 2).perl; # OUTPUT: «FatRat.new(1, 2)»
Rakudo-specific class that wraps around code in other languages (generally NQP)
class ForeignCode does Callable {}
ForeignCode is a Perl 6 wrapper around code that is not written originally in that language; its intention is to use these blocks of code in Callable contexts easily. For instance, subs have some anonymous functions that are actually ForeignCode.
sub does-nothing(){}; say $_.name ~ ' → ' ~ $_.^name for &does-nothing.^methods; # OUTPUT: «<anon> → ForeignCode<anon> → ForeignCodesoft → Method…»
This script will map method names to their class, and it shows that routines, in particular, have several methods that are actually ForeignCode instead of Method s.
method arity()
Returns the arity of the enclosed code.
method count()
Returns the number of arguments the enclosed code needs.
method signature( ForeignCode:D: )
Returns the signature of the enclosed code.
method name()
Returns the name of the enclosed code, or <anon> if it has not received any.
method gist( ForeignCode:D: )
Returns the name of the code by calling name.
method Str( ForeignCode:D: )
Returns the name of the code by calling name.
Formal grammar made up of named regexes
class Grammar is Cursor {}
Every type declared with grammar and not explicitly stating its superclass, becomes a subclass of Grammar.
grammar Identifier { token TOP { <initial> <rest>* } token initial { <+myletter +[_]> } token rest { <+myletter +mynumber +[_]> } token myletter { <[A..Za..z]> } token mynumber { <[0..9]> } } say Identifier.isa(Grammar); # OUTPUT: «True» my $match = Identifier.parse('W4anD0eR96'); say ~$match; # OUTPUT: «W4anD0eR96»
More documentation on grammars is available.
Defined as:
method parse($target, :$rule = 'TOP', Capture() :$args = \(), Mu :$actions = Mu, *%opt)
Parses the $target, which will be coerced to Str if it isn't one, using $rule as the starting rule. Additional $args will be passed to the starting rule if provided.
grammar RepeatChar { token start($character) { $character+ } } say RepeatChar.parse('aaaaaa', :rule('start'), :args(\('a'))); say RepeatChar.parse('bbbbbb', :rule('start'), :args(\('b'))); # OUTPUT: # 「aaaaaa」 # 「bbbbbb」
If the action named argument is provided, it will be used as an action object, that is, for each successful regex match, a method of the same name, if it exists, is called on the action object, passing the match object as the sole positional argument.
my $actions = class { method TOP($/) { say "7" } }; grammar { token TOP { a { say "42" } b } }.parse('ab', :$actions); # OUTPUT : «427»
Additional named arguments are used as options for matching, so you can specify things like :pos(4) to start parsing from the fourth (zero-base) character. All matching adverbs are allowed, but not all of them take effect. There are several types of adverbs that a regex can have, some of which apply at compile time, like :s and :i. You cannot pass those to .parse, because the regexes have already been compiled. But, you can pass those adverbs that affect the runtime behavior, such as :pos and :continue.
say RepeatChar.parse('bbbbbb', :rule('start'), :args(\('b')), :pos(4)).Str; # OUTPUT : «bb»
Method parse only succeeds if the cursor has arrived at the end of the target string when the match is over. Use method subparse if you want to be able to stop in the middle.
Returns a Match object on success, and Nil on failure.
Defined as:
method subparse($target, :$rule = 'TOP', Capture() :$args = \(), Mu :$actions = Mu, *%opt)
Does exactly the same as method parse, except that cursor doesn't have to reach the end of the string to succeed. That is, it doesn't have to match the whole string.
Note that unlike method parse, subparse always returns a Match object, which will be a failed match (and thus falsy), if the grammar failed to match.
grammar RepeatChar { token start($character) { $character+ } } say RepeatChar.subparse('bbbabb', :rule('start'), :args(\('b'))); say RepeatChar.parse('bbbabb', :rule('start'), :args(\('b'))); say RepeatChar.subparse('bbbabb', :rule('start'), :args(\('a'))); say RepeatChar.subparse('bbbabb', :rule('start'), :args(\('a')), :pos(3)); # OUTPUT: # 「bbb」 # Nil # #<failed match> # 「a」
Defined as:
method parsefile(Str(Cool) $filename, :$enc, *%opts)
Reads file $filename encoding by $enc, and parses it. All named arguments are passed on to method parse.
grammar Identifiers { token TOP { [<identifier><.ws>]+ } token identifier { <initial> <rest>* } token initial { <+myletter +[_]> } token rest { <+myletter +mynumber +[_]> } token myletter { <[A..Za..z]> } token mynumber { <[0..9]> } } say Identifiers.parsefile('users.txt', :enc('UTF-8')) .Str.trim.subst(/\n/, ',', :g); # users.txt : # TimToady # lizmat # jnthn # moritz # zoffixznet # MasterDuke17 # OUTPUT : «TimToady,lizmat,jnthn,moritz,zoffixznet,MasterDuke17»
Mapping from strings to itemized values
class Hash is Map { }
A Hash is a mutable Map; it implements Associative through its inheritance of Map and as such provides support for looking up values using keys, providing support for associative subscripting.
Although the order of the hashes is guaranteed to be random in every single call, still successive calls to .keys and .values are guaranteed to return them in the same order:
my %orig = :1a, :2b; my %new = :5b, :6c; %orig{ %new.keys } = %new.values; say %orig.perl; # OUTPUT: «{:a(1), :b(5), :c(6)}»
In this case, b will always be associated to 5 and c to 6; even if two successive calls to keys will return them in different order. Successive calls to any of them separately and repeatedly will always return the same order in any program invocation.
Please see the section on hash literals for different ways to declare a hash. Additionally, they can be declared using curly braces as long as these rules are followed:
Empty curly braces will always declare an empty hash.
A reference to $_ (even implicit) will instead declare a block.
A Pair or variable with % as the first element will declare a hash.
given 3 { say WHAT {3 => 4, :b} }; # OUTPUT: «(Hash)» given 3 { say WHAT {3 => 4, :b($_)} }; # OUTPUT: «(Block)» given 3 { say WHAT {3 => 4, :b(.Num)} };# OUTPUT: «(Block)» say { 'a',:b(3), 'c' }.^name; # OUTPUT: «Block»
The next-to-last two cases are examples of the generation of Blocks in the presence of the topic variable $_. The last case does not meet the third criterium for generating a hash, and thus generates a Block.
A % in front of parentheses or square brackets will generate a Hash as long as the elements can be paired.
say %( 'a', 3, :b(3), 'c', 3 ).^name; # OUTPUT: «Hash»
Elements in this hash can be paired both sides of the Pair :b(3).
say %(«a b c 1 2 3»).^name; # OUTPUT: «Hash»
An empty hash can be initialized either with empty curly braces or, since 6.d, %().
say %().^name; # OUTPUT: «Hash» say {}.^name; # OUTPUT: «Hash»
Defined as:
multi method classify-list(&mapper, *@list, :&as --> Hash:D) multi method classify-list(%mapper, *@list, :&as --> Hash:D) multi method classify-list(@mapper, *@list, :&as --> Hash:D)
Populates a Hash by classifying the possibly-empty @list of values using the given mapper, optionally altering the values using the :&as Callable. The @list cannot be lazy.
The mapper can be a Callable that takes a single argument, an Associative, or an Iterable. With Associative and an Iterable mappers, the values in the @list represent the key and index of the mapper's value respectively. A Callable mapper will be executed once per each item in the @list, with that item as the argument and its return value will be used as the mapper's value.
In simple classification mode, each mapper's value is any non-Iterable and represents a key to classify @list's item under:
say % .classify-list: { $_ %% 2 ?? 'even' !! 'odd' }, ^10; # OUTPUT: «{even => [0 2 4 6 8], odd => [1 3 5 7 9]}» my @mapper = <zero one two three four five>; my %hash = foo => 'bar'; say %hash.classify-list: @mapper, 1, 2, 3, 4, 4; # OUTPUT: «{foo => bar, four => [4 4], one => [1], three => [3], two => [2]}»
The mapper's value is used as the key of the Hash to which the @list's item will be push ed. See .categorize-list if you wish to classify an item into multiple categories at once.
In multi-level classification mode, each mapper's value is an Iterable that represents a tree of hash keys to classify @list's item under:
say % .classify-list: { [ (.is-prime ?? 'prime' !! 'non-prime'), ($_ %% 2 ?? 'even' !! 'odd' ), ] }, ^10; # OUTPUT: # { # non-prime => { # even => [0 4 6 8], # odd => [1 9] # }, # prime => { # even => [2], # odd => [3 5 7] # } # }
NOTE: each of those Iterables must have the same number of elements, or the method will throw an exception. This restriction exists to avoid conflicts when the same key is a leaf of one value's classification but a node of another value's classification.
If :&as Callable argument is specified, it will be called once per each item of @list, with the value as the argument, and its return value will be used instead of the original @list's item:
say % .classify-list: :as{"Value is $_"}, { $_ %% 2 ?? 'even' !! 'odd' }, ^5; # OUTPUT (slightly altered manually, for clarity): # { # even => ['Value is 0', 'Value is 2', 'Value is 4'], # odd => ['Value is 1', 'Value is 3'] # }
Defined as:
multi method categorize-list(&mapper, *@list, :&as --> Hash:D) multi method categorize-list(%mapper, *@list, :&as --> Hash:D) multi method categorize-list(@mapper, *@list, :&as --> Hash:D)
Populates a Hash by classifying the possibly-empty @list of values using the given mapper, optionally altering the values using the :&as Callable. The @list cannot be lazy.
The mapper can be a Callable that takes a single argument, an Associative, or an Iterable. With Associative and an Iterable mappers, the values in the @list represent the key and index of the mapper's value respectively. A Callable mapper will be executed once per each item in the @list, with that item as the argument and its return value will be used as the mapper's value.
The mapper's value is expected to be a possibly empty list of non-Iterables that represent categories to place the value into:
say % .categorize-list: { gather { take 'prime' if .is-prime; take 'largish' if $_ > 5; take $_ %% 2 ?? 'even' !! 'odd'; } }, ^10; # OUTPUT: # { # prime => [2 3 5 7] # even => [0 2 4 6 8], # odd => [1 3 5 7 9], # largish => [6 7 8 9], # }
Notice how some items, e.g. 6 and 7, are present in several categories.
In multi-level categorization, the categories produced by the mapper can are Iterables and categorization combines features of classify, by producing nested hashes of classifications for each category.
say % .categorize-list: { [ $_ > 5 ?? 'largish' !! 'smallish', .is-prime ?? 'prime' !! 'non-prime', ], }, ^10; # OUTPUT: # { # largish => { # non-prime => [6 8 9], # prime => [7] # }, # smallish => { # non-prime => [0 1 4], # prime => [2 3 5] # } # }
The mapper in above snippet produces single-item list (note the significant trailing comma) with a two-item Array in it. The first item in that array indicates the first level of classification: the largish/smallish categories the routine produces. The second item in that array indicates further levels of classification, in our case the classification into prime/non-prime inside of each category.
NOTE: each of category Iterables must have the same number of elements, or the method will throw an exception. This restriction exists to avoid conflicts when the same key is a leaf of one value's classification but a node of another value's classification.
If :&as Callable argument is specified, it will be called once per each item of @list, with the value as the argument, and its return value will be used instead of the original @list's item:
say % .categorize-list: :as{"Value is $_"}, { $_ %% 2 ?? 'even' !! 'odd' }, ^5; # OUTPUT (slightly altered manually, for clarity): # { # even => ['Value is 0', 'Value is 2', 'Value is 4'], # odd => ['Value is 1', 'Value is 3'] # }
Defined as:
multi method push(Hash:D: *@new)
Adds the @new elements to the hash with the same semantics as hash assignment, but with three exceptions:
The hash isn't emptied first, i.e. old pairs are not deleted.
If a key already exists in the hash, and the corresponding value is an Array, the new value is pushed onto the array (instead of replacing it).
If a key already exists in the hash, and the corresponding value is not an Array, old and new value are both placed into an array in the place of the old value.
Example:
my %h = a => 1; %h.push: (a => 1); # a => [1,1] %h.push: (a => 1) xx 3 ; # a => [1,1,1,1,1] %h.push: (b => 3); # a => [1,1,1,1,1], b => 3 %h.push('c' => 4); # a => [1,1,1,1,1], b => 3, c => 4 push %h, 'd' => 5; # a => [1,1,1,1,1], b => 3, c => 4, d => 5
Please note that Pairs or colon pairs as arguments to push will be treated as extra named arguments and as such wont end up the Hash. The same applies to the sub push.
my %h .= push(e => 6); push %h, f => 7; say %h.perl; # OUTPUT: «{}»
Also note that push can be used as a replacement for assignment during hash initialization very useful ways. Take for instance the case of an inverted index:
my %wc = 'hash' => 323, 'pair' => 322, 'pipe' => 323; (my %inv).push: %wc.invert; say %inv; # OUTPUT: «{322 => pair, 323 => [pipe hash]}»
Note that such an initialization could also be written as
my %wc = 'hash' => 323, 'pair' => 322, 'pipe' => 323; my %inv .= push: %wc.invert;
Note: Compared to append, push will add the given value as is, whereas append will slip it in:
my %ha = :a[42, ]; %ha.push: "a" => <a b c a>; say %ha; # OUTPUT: «{a => [42 (a b c a)]}» my %hb = :a[42, ]; %hb.append: "a" => <a b c a>; say %hb; # OUTPUT: «{a => [42 a b c a]}»
Defined as:
method append(+@values)
Append the provided Pairs or even sized list to the Hash. If a key already exists, turn the existing value into an Array and push new value onto that Array. Please note that you can't mix even sized lists and lists of Pairs. Also, bare Pairs or colon pairs will be treated as named arguments to .append.
my %h = a => 1; %h.append('b', 2, 'c', 3); %h.append( %(d => 4) ); say %h; # OUTPUT: «{a => 1, b => 2, c => 3, d => 4}» %h.append('a', 2); # OUTPUT: «{{a => [1 2], b => 2, c => 3, d => 4}»
Note: Compared to push, append will slip in the given value, whereas push will add it as is:
my %hb = :a[42, ]; %hb.append: "a" => <a b c a>; say %hb; # OUTPUT: «{a => [42 a b c a]}» my %ha = :a[42, ]; %ha.push: "a" => <a b c a>; say %ha; # OUTPUT: «{a => [42 (a b c a)]}»
Defined as:
method default()
Returns the default value of the invocant, i.e. the value which is returned when a non existing key is used to access an element in the Hash. Unless the Hash is declared as having a default value by using the is default trait the method returns the type object (Any).
my %h1 = 'apples' => 3, 'oranges' => 7; say %h1.default; # OUTPUT: «(Any)» say %h1{'bananas'}; # OUTPUT: «(Any)» my %h2 is default(1) = 'apples' => 3, 'oranges' => 7; say %h2.default; # OUTPUT: «1» say %h2{'apples'} + %h2{'bananas'}; # OUTPUT: «4»
Defined as:
method keyof()
Returns the type constraint for the keys of the invocant. For normal hashes the method returns the coercion type (Str(Any)) while for non-string keys hashes the type used in the declaration of the Hash is returned.
my %h1 = 'apples' => 3, 'oranges' => 7; # (no key type specified) say %h1.keyof; # OUTPUT: «(Str(Any))» my %h2{Str} = 'oranges' => 7; # (keys must be of type Str) say %h2.keyof; # (Str) %h2{3} = 'apples'; # throws exception CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Binding: Type check failed in binding to key; expected Str but got Int (3)» my %h3{Int}; # (this time, keys must be of type Int) %h3{42} = 4096; say %h3.keyof; # (Int)
Defined as:
method of()
Returns the type constraint for the values of the invocant. By default, i.e. if no type constraint is given during declaration, the method returns (Mu).
my %h1 = 'apples' => 3, 'oranges' => 7; # (no type constraint specified) say %h1.of; # OUTPUT: «(Mu)» my Int %h2 = 'oranges' => 7; # (values must be of type Int) say %h2.of; # OUTPUT: «(Int)»
Defined as:
method dynamic(--> Bool:D)
Returns True if the invocant has been declared with the is dynamic trait.
my %a; say %a.dynamic; # OUTPUT: «False» my %b is dynamic; say %b.dynamic; # OUTPUT: «True»
If you declare a variable with the * twigil is dynamic is implied.
my %*b; say %*b.dynamic; # OUTPUT: «True»
Note that in the Scalar case you have to use the VAR method in order to get correct information.
my $s is dynamic = %('apples' => 5); say $s.dynamic; # OUTPUT: «False» (wrong, don't do this) say $s.VAR.dynamic; # OUTPUT: «True» (correct approach)
Some methods are implemented as adverbs on subscripts (consult the operators documentation for more information).
The adverb :exists returns Bool::True if a key exists in the Hash. If more than one key is supplied it returns a List of Bool.
my %h = a => 1, b => 2; say %h<a>:exists; # OUTPUT: «True» say %h<a b>:exists; # OUTPUT: «(True True)»
Use :delete to remove a Pair from the Hash.
my %h = a => 1; say %h; # OUTPUT: «{a => 1}» say %h.elems; # OUTPUT: «1» %h<a>:delete; say %h; # OUTPUT: «{}» say %h.elems; # OUTPUT: «0»
The adverb :p returns a Pair or a List of Pair instead of just the value.
my %h = a => 1, b => 2; say %h<a>:p; # OUTPUT: «a => 1» say %h<a b>:p; # OUTPUT: «(a => 1 b=> 2)»
The adverbs :v and :k return the key or value or a list thereof.
my %h = a => 1, b => 2; say %h<a>:k; # OUTPUT: «a» say %h<a b>:k; # OUTPUT: «(a b)»
The adverb :kv returns a list of keys and values.
my %h = a => 1, b => 2, c => 3; say %h<a c>:kv; # OUTPUT: «(a 1 c 3)»
You can also use the adverbs without knowing anything about the hash by using empty angle brackets in which case all the keys and values will be listed:
my %h1 = a => 1; my %h2 = a => 1, b => 2; say %h1<>:k; # OUTPUT: «(a)» say %h1<>:v; # OUTPUT: «(1)» say %h2<>:k; # OUTPUT: «(a b)» say %h2<>:v; # OUTPUT: «(1 2)»
An object for performing batches of work in parallel with ordered output
class HyperSeq does Iterable does Sequence { }
An HyperSeq is the intermediate object used when the operator hyper is invoked on a Seq. In general, it's not intended for direct consumption by the developer.
method iterator(HyperSeq:D: --> Iterator:D)
Returns the underlying iterator.
method grep(HyperSeq:D: $matcher, *%options)
Applies grep to the HyperSeq similarly to how it would do it on a Seq.
my @hyped = (^10000).map(*²).hyper; @hyped.grep( * %% 3 ).say; # OUTPUT: «(0 9 36 81 144…»
When you use hyper on a Seq, this is the method that is actually called.
method map(HyperSeq:D: $matcher, *%options)
Uses maps on the HyperSeq, generally created by application of hyper to a preexisting Seq.
method invert(HyperSeq:D:)
Inverts the HyperSeq created from a Seq by .hyper.
method hyper(HyperSeq:D:)
Returns the object.
method race(HyperSeq:D:)
Creates a RaceSeq object out of the current one.
multi method serial(HyperSeq:D:)
Converts the object to a Seq and returns it.
method is-lazy(--> False )
Returns False.
Defined as:
method sink(--> Nil)
Sinks the underlying data structure, producing any side effects.
Placeholder for multiple unspecified values/arguments
class HyperWhatever { }
HyperWhatever is very similar in functionality to Whatever. The difference lies in HyperWhatever standing in for multiple values, rather than a single one.
Just like with Whatever, if a HyperWhatever is used as a term on its own, no currying is done and the HyperWhatever object will be used as-is:
sub foo ($arg) { say $arg.^name } foo **; # OUTPUT: «HyperWhatever»
You can choose to interpret such a value as standing for multiple values in your own routines. In core, a HyperWhatever can be used with this meaning when smartmatching with Lists:
say (1, 8) ~~ (1, **, 8); # OUTPUT: «True» say (1, 2, 4, 5, 6, 7, 8) ~~ (1, **, 8); # OUTPUT: «True» say (1, 2, 8, 9) ~~ (1, **, 8); # OUTPUT: «False»
Wherever a HyperWhatever appears in the list on the right-hand side means any number of elements can fill that space in the list being smartmatched.
When it comes to currying, the HyperWhatever follows the same rules as Whatever. The only difference is HyperWhatever produces a Callable with a *@ slurpy as a signature:
say (**²)(1, 2, 3, 4, 5); # OUTPUT: «(1 4 9 16 25)»
A HyperWhatever closure can be imagined as a Whatever closure with another sub wrapped around it that simply maps each element in the arguments over:
my &hyper-whatever = sub (*@args) { map *², @args } say hyper-whatever(1, 2, 3, 4, 5); # OUTPUT: «(1 4 9 16 25)»
When currying, mixing HyperWhatever with Whatever is not permitted.
Input/output related routines
The role provides no methods, but exists so that IO() coercers, which coerce to IO::Path, correctly type-check the resultant value. The role is implemented by IO::Path and IO::Special.
See also the related classes IO::Handle and IO::Path.
Iterate over contents of files specified on command line
class IO::ArgFiles is IO::CatHandle { }
This class exists for backwards compatibility reasons and provides no additional methods to IO::CatHandle, so it can be used in the same way as it, for instance, in this way:
my $argfiles = IO::ArgFiles.new(@*ARGS); .say for $argfiles.lines;
If invoked with perl6 io-argfiles.p6 *.p6 it will print the contents of all the files with that extension in the directory. However, that is totally equivalent to:
my $argfiles = IO::CatHandle.new(@*ARGS); .say for $argfiles.lines;
This class is the magic behind the $*ARGFILES variable, which provides a way to iterate over files passed in to the program on the command line (i.e. elements of @*ARGS). Thus the examples above can be simplified like so:
.say for $*ARGFILES.lines; # or while ! $*ARGFILES.eof { say $*ARGFILES.get; } # or say $*ARGFILES.slurp;
Save one of the variations above in a file, say argfiles.p6. Then create another file (named, say sonnet18.txt with the contents:
Shall I compare thee to a summer's day?
Running the command
$ perl6 argfiles.p6 sonnet18.txt
will then give the output
Shall I compare thee to a summer's day?
As of 6.d language, $*ARGFILES inside sub MAIN is always set to $*IN, even when @*ARGS is not empty. That means that
sub MAIN () { .say for $*ARGFILES.lines; }
which can be used as cat *.p6 | perl6 argfiles-main.p6, for instance, is totally equivalent to:
sub MAIN () { .say for $*IN.lines; }
and, in fact, can't be used to process the arguments in the command line, since, in this case, it would result in an usage error.
Bear in mind that the object $*ARGFILES is going to contain a handle for every argument in a command line, even if that argument is not a valid file. You can retrieve them via the .handles method.
for $*ARGFILES.handles -> $fh { say $fh; }
That code will fail if any of the arguments is not the valid name of a file. You will have to deal with that case at another level, checking that @*ARGS contains valid file names, for instance.
Use multiple IO handles as if they were one
class IO::CatHandle is IO::Handle { }
This class has been available in Rakudo since version 2017.06.
The IO::CatHandle|/type/IO::CatHandle class provides a means to create an IO::Handle that seamlessly gathers input from multiple IO::Handle and IO::Pipe sources.
All of the IO::Handle's methods are implemented, and while attempt to use write methods will (currently) throw and exception, an IO::CatHandle is usable anywhere a read-only IO::Handle can be used.
Defined as:
method new(*@handles, :&on-switch, :$chomp = True, :$nl-in = ["\n", "\r\n"], Str :$encoding, Bool :$bin)
Creates a new IO::CatHandle object.
The @handles positional argument indicates a source of handles for the IO::CatHandle to read from and can deal with a mixed collection of Cool, IO::Path, and IO::Handle (including IO::Pipe) objects. As input from IO::CatHandle is processed (so operations won't happen during .new call, but only when @handles' data is needed), it will walk through the @handles list, processing each argument as follows:
IO::Path objects will be opened for reading using the IO::CatHandle's (invocant's) attributes for open calls;
un-opened IO::Handle objects will be opened in the same fashion as IO::Path objects;
and already opened IO::Handle objects will have all of their attributes set to the attributes of the invocant IO::CatHandle.
In short, all the @handles end up as IO::Handle objects opened in the same mode and with the same attributes as the invocant IO::CatHandle.
See .on-switch method for details on the :&on-switch named argument, which by default is not set.
The :$encoding named argument specifies the handle's encoding and accepts the same values as IO::Handle.encoding. Set :$bin named argument to True if you wish the handle to be in binary mode. Attempting to specify both a defined :$encoding and a True :$bin is a fatal error resulting in X::IO::BinaryAndEncoding exception thrown. If neither :$encoding is set nor :$bin set to a true value, the handle will default to utf8 encoding.
The :$chomp and :$nl-in arguments have the same meaning as in IO::Handle and take and default to the same values.
Defined as:
method chomp(IO::CatHandle:D:) is rw
Sets the invocant's $.chomp attribute to the assigned value. All source handles, including the active one will use the provided $.chomp value.
(my $f1 = 'foo'.IO).spurt: "A\nB\nC\n"; (my $f2 = 'bar'.IO).spurt: "D\nE\n"; with IO::CatHandle.new: $f1, $f2 { # .chomp is True by default: (.get xx 2).perl.say; # OUTPUT: «("A", "B").Seq» .chomp = False; (.get xx 3).perl.say; # OUTPUT: «("C\n", "D\n", "E\n").Seq» .close }
Defined as:
method nl-in(IO::CatHandle:D:) is rw
Sets the invocant's $.nl-in attribute to the assigned value, which can be a Str or a List of Str, where each Str object represents the end-of-line string. All source handles, including the active one will use the provided $.nl-in value. Note that source handle boundary is always counted as a new line break.
(my $f1 = 'foo'.IO).spurt: "A\nB\nC"; (my $f2 = 'bar'.IO).spurt: "DxEx"; with IO::CatHandle.new: $f1, $f2 { # .nl-in is ["\n", "\r\n"] by default: (.get xx 2).perl.say; # OUTPUT: «("A", "B").Seq» .nl-in = 'x'; (.get xx 3).perl.say; # OUTPUT: «("C", "D", "E").Seq» .close }
Defined as:
method close(IO::CatHandle:D: --> True)
Closes the currently active source handle, as well as any already-open source handles, and empties the source handle queue. Unlike a regular IO::Handle, an explicit call to .close is often not necessary on a CatHandle, as merely exhausting all the input closes all the handles that need to be closed.
with IO::CatHandle.new: @bunch-of-handles { say .readchars: 42; .close; # we are done; close all the open handles }
Defined as:
method comb(IO::CatHandle:D: |args --> Seq:D)
Read the handle and processes its contents the same way Str.comb does, taking the same arguments. Implementations may slurp the contents of all the source handles in their entirety when this method is called.
(my $f1 = 'foo'.IO).spurt: 'foo'; (my $f2 = 'bar'.IO).spurt: 'bar'; IO::CatHandle.new($f1, $f2).comb(2).perl.say; # OUTPUT: «("fo", "ob", "ar").Seq»
Defined as:
method DESTROY(IO::CatHandle:D:)
Calls .close. This method isn't to be used directly, but is something that's called during garbage collection.
Defined as:
multi method encoding(IO::CatHandle:D:) multi method encoding(IO::CatHandle:D: $new-encoding)
Sets the invocant's $.encoding attribute to the provided value. Valid values are the same as those accepted by IO::Handle.encoding (use value Nil to switch to binary mode). All source handles, including the active one will use the provided $.encoding value.
(my $f1 = 'foo'.IO).spurt: 'I ♥ Perl'; (my $f2 = 'bar'.IO).spurt: 'meow'; with IO::CatHandle.new: $f1, $f2 { # .encoding is 'utf8' by default: .readchars(5).say; # OUTPUT: «I ♥ P» .encoding: Nil; # switch to binary mode .slurp.say; # OUTPUT: «Buf[uint8]:0x<72 6c 6d 65 6f 77>» }
Defined as:
method eof(IO::CatHandle:D: --> Bool:D)
Returns True if the read operations have exhausted the source handle queue, including the contents of the last handle. Note: calling this method may cause one or more .on-switch calls, while the source handle queue is examined, and the source handle queue may get exhausted.
(my $f1 = 'foo'.IO).spurt: 'foo'; (my $f2 = 'bar'.IO).spurt: 'bar'; with IO::CatHandle.new: :on-switch{ print 'SWITCH! ' }, $f1, $f2 { # OUTPUT: «SWITCH! » .eof.say; # OUTPUT: «False» .readchars(3); .eof.say; # OUTPUT: «SWITCH! False» .slurp; # OUTPUT: «SWITCH! » .eof.say; # OUTPUT: «True» }
The same caveats for non-seekable handles and empty files that apply to IO::Handle.eof apply here.
Defined as:
method get(IO::CatHandle:D: --> Bool:D)
Returns a single line of input from the handle, with the new line string defined by the value(s) of $.nl-in attribute, which will be removed from the line if $.chomp attribute is set to True. Returns Nil when there is no more input. It is an error to call this method when the handle is in binary mode, resulting in X::IO::BinaryMode exception being thrown.
(my $f1 = 'foo'.IO).spurt: "a\nb\nc"; (my $f2 = 'bar'.IO).spurt: "d\ne"; my $cat = IO::CatHandle.new: $f1, $f2; .say while $_ = $cat.get; # OUTPUT: «abcde»
Defined as:
method getc(IO::CatHandle:D: --> Bool:D)
Returns a single character of input from the handle. All the caveats described in IO::Handle.getc apply. Returns Nil when there is no more input. It is an error to call this method when the handle is in binary mode, resulting in X::IO::BinaryMode exception being thrown.
(my $f1 = 'foo'.IO).spurt: 'I ♥ Perl'; (my $f2 = 'bar'.IO).spurt: 'meow'; my $cat = IO::CatHandle.new: $f1, $f2; .say while $_ = $cat.getc; # OUTPUT: «I ♥ Perlmeow»
Defines as:
method handles(IO::CatHandle:D: --> Seq:D)
Returns a Seq containing the currently-active handle, as well as all the remaining source handles produced by calling next-handle. If the invocant has already been fully-consumed, returns an empty Seq.
This method is especially handy when working with IO::ArgFiles, where you want to treat each filehandle separately:
# print at most the first 2 lines of each file in $*ARGFILES: .say for flat $*ARGFILES.handles.map: *.lines: 2
It is acceptable to call this method multiple times; .handles.head is a valid idiom for obtaining the currently-active handle. If, between reification of the elements of the returned Seq the handles get switched by some other means, the next element produced by the Seq would be the next handle of the invocant, not the handle that would've been produced if no switching occurred:
(my $file1 := 'file1'.IO).spurt: "1a\n1b\n1c"; (my $file2 := 'file2'.IO).spurt: "2a\n2b\n2c"; (my $file3 := 'file3'.IO).spurt: "3a\n3b\n3c"; my $cat := IO::CatHandle.new: $file1, $file2, $file3; for $cat.handles { say .lines: 2; $cat.next-handle; } # OUTPUT: «(1a 1b)(3a 3b)»
Likewise, reifying the returned Seq consumes the invocant's source handles and once it is fully reified the invocant becomes fully-consumed.
Defined as:
method IO(IO::CatHandle:D:)
Alias for .path
Defined as:
method lines(IO::CatHandle:D: $limit = Inf, :$close --> Seq:D)
Same as IO::Handle.lines. Note that a boundary between source handles is considered to be a newline break.
(my $f1 = 'foo'.IO).spurt: "foo\nbar"; (my $f2 = 'bar'.IO).spurt: 'meow'; IO::CatHandle.new($f1, $f2).lines.perl.say; # OUTPUT: «("foo", "bar", "meow").Seq»
Note: if :$close is False, fully-consumed handles are still going to be closed.
Defined as:
method lock(IO::CatHandle:D: Bool:D :$non-blocking = False, Bool:D :$shared = False --> True)
Same as IO::Handle.lock. Returns Nil if the source handle queue has been exhausted.
Locks only the currently active source handle. The .on-switch Callable can be used to conveniently lock/unlock the handles as they're being processed by the CatHandle.
Defined as:
method native-descriptor(IO::CatHandle:D: --> Int:D)
Returns the native-descriptor of the currently active source handle or Nil if the source handle queue has been exhausted.
Since the CatHandle closes a source handle, once it's done with it, it's possible for successive source handles to have the same native descriptor, if they were passed to .new as Cool or IO::Path objects.
(my $f1 = 'foo'.IO).spurt: 'foo'; (my $f2 = 'bar'.IO).spurt: 'bar'; with IO::CatHandle.new: $f1, $f2, $*IN { repeat { .native-descriptor.say } while .next-handle; # OUTPUT: «13139» }
Defined as:
method next-handle(IO::CatHandle:D: --> IO::Handle:D)
Switches the active source handle to the next handle in the source handle queue, which is the sources given in @handles attribute to .new. The return value is the currently active source handle or Nil if the source handle queue has been exhausted.
Coerces Cool source "handles" to IO::Path; opens IO::Path and unopened IO::Handle source handles for reading using the invocant's $.nl-in, $.chomp, and $.encoding attributes; those same attributes of already-opened IO::Handle objects will be changed to the values of the invocant's attributes.
This method is called automatically whenever CatHandle's methods require a switch to the next source handle, triggers .on-switch Callable to be called, and is called once during .new call. The .on-switch will continue to be triggered each time this method is called, even after the source handle queue has been exhausted. Note that generally reaching the EOF of the currently active source handle does not trigger the .next-handle call, but rather further read operations that need more data do.
(my $f1 = 'foo'.IO).spurt: "a\nb"; (my $f2 = 'bar'.IO).spurt: "c\nd"; with IO::CatHandle.new: :on-switch{ say '▸ Switching' }, $f1, $f2 { say 'one'; .next-handle.^name.say; say 'two'; .next-handle.^name.say; say 'three'; .next-handle.^name.say; # OUTPUT: # ▸ Switching # one # ▸ Switching # IO::Handle # two # ▸ Switching # Nil # three # ▸ Switching # Nil }
Defined as:
has &.on-switch is rw
One of the attributes that can be set during .new call and changed later by assigning to. By default is not specified. Takes a Callable with .count of 0, 1, 2, or Inf. Gets called every time .next-handle is, which happens once during .new call and then each time a source handle is switched to the next one in the queue, or when the .next-handle method is called manually.
If the .count of &.on-switch is 0, it receives no arguments; if it's 1, it receives the currently active handle, and if it's 2 or Inf, it receives the currently active handle, and the last active handle as positional arguments (in that order). On the very first &.on-switch execution, the "last active handle" argument is Nil. Upon source handle queue exhaustion the "currently active handle" argument is Nil, and all the executions made afterwards have both arguments as Nil.
(my $f1 = 'foo'.IO).spurt: "A\nB\nC"; (my $f2 = 'bar'.IO).spurt: "D\nE"; my $line; my $cat = IO::CatHandle.new: :on-switch{ $line = 1 }, $f1, $f2; say "{$cat.path}:{$line++} $_" for $cat.lines; # OUTPUT: # foo:1 A # foo:2 B # foo:3 C # bar:1 D # bar:2 E
my @old-stuff; sub on-switch ($new, $old) { $new and $new.seek: 1, SeekFromBeginning; $old and @old-stuff.push: $old.open.slurp: :close; } (my $f1 = 'foo'.IO).spurt: "A\nB\nC"; (my $f2 = 'bar'.IO).spurt: "D\nE"; my $cat = IO::CatHandle.new: :&on-switch, $f1, $f2; $cat.lines.perl.say; # OUTPUT: «("", "B", "C", "", "E").Seq» @old-stuff.perl.say; # OUTPUT: «["A\nB\nC", "D\nE"]»
Defined as:
method open(IO::CatHandle:D: --> IO::CatHandle:D)
Returns the invocant. The intent of this method is to merely make CatHandle workable with things that open IO::Handle. You never have to call this method intentionally.
Defined as:
method opened(IO::CatHandle:D: --> Bool:D)
Returns True if the invocant has any source handles, False otherwise.
say IO::CatHandle.new .opened; # OUTPUT: «False» say IO::CatHandle.new($*IN).opened; # OUTPUT: «True» (my $f1 = 'foo'.IO).spurt: "A\nB\nC"; with IO::CatHandle.new: $f1 { .opened.say; # OUTPUT: «True» .slurp; .opened.say; # OUTPUT: «False» }
Defined as:
method path(IO::CatHandle:D:)
Returns the value of .path attribute of the currently active source handle, or Nil if the source handle queue has been exhausted. Basically, if your CatHandle is based on files, this is the way to get the path of the file the CatHandle is currently reading from.
(my $f1 = 'foo'.IO).spurt: "A\nB\nC"; (my $f2 = 'bar'.IO).spurt: "D\nE"; my $line; my $cat = IO::CatHandle.new: :on-switch{ $line = 1 }, $f1, $f2; say "{$cat.path}:{$line++} $_" for $cat.lines; # OUTPUT: # foo:1 A # foo:2 B # foo:3 C # bar:1 D # bar:2 E
Defined as:
method read(IO::CatHandle:D: Int(Cool:D) $bytes = 65536 --> Buf:D)
Reads up to $bytes bytes from the handle and returns them in a Buf. $bytes defaults to an implementation-specific value (in Rakudo, the value of $*DEFAULT-READ-ELEMS, which by default is set to 65536). It is permitted to call this method on handles that are not in binary mode.
(my $f1 = 'foo'.IO).spurt: 'meow'; (my $f2 = 'bar'.IO).spurt: Blob.new: 4, 5, 6; with IO::CatHandle.new: :bin, $f1, $f2 { say .read: 2; # OUTPUT: «Buf[uint8]:0x<6d 65>» say .read: 2000; # OUTPUT: «Buf[uint8]:0x<6f 77 04 05 06>» } # Non-binary mode is OK too: with IO::CatHandle.new: $f1, $f2 { say .get; # OUTPUT: «meow» say .read: 2000; # OUTPUT: «Buf[uint8]:0x<04 05 06>» }
Defined as:
method readchars(IO::CatHandle:D: Int(Cool:D) $chars = 65536 --> Str:D)
Returns a Str of up to $chars characters read from the handle. $chars defaults to an implementation-specific value (in Rakudo, the value of $*DEFAULT-READ-ELEMS, which by default is set to 65536). It is NOT permitted to call this method on handles opened in binary mode and doing so will result in X::IO::BinaryMode exception being thrown.
(my $f1 = 'foo'.IO).spurt: 'Perl loves to'; (my $f2 = 'bar'.IO).spurt: ' meow'; with IO::CatHandle.new: $f1, $f2 { say .readchars: 11; # OUTPUT: «Perl loves » say .readchars: 1000; # OUTPUT: «to meow» }
Defined as:
method seek(IO::CatHandle:D: |c)
Calls .seek on the currently active source handle, forwarding it all the arguments, and returns the result. Returns Nil if the source handle queue has been exhausted. NOTE: this method does NOT perform any source handle switching, so seeking past the end of the current source handle will NOT seek to the next source handle in the queue and seeking past the beginning of the current source handle is a fatal error. Also see .next-handle, to learn the details on when source handles are switched.
(my $f1 = 'foo'.IO).spurt: 'foo'; (my $f2 = 'bar'.IO).spurt: 'bar'; with IO::CatHandle.new: $f1, $f2 { .get.say; # OUTPUT: «foo» .seek: -2, SeekFromCurrent; .readchars(2).say; # OUTPUT: «oo» .seek: 1000, SeekFromCurrent; # this doesn't switch to second handle! .readchars(3).say; # OUTPUT: «bar» try .seek: -4; # this won't seek to previous handle! say ~$!; # OUTPUT: «Failed to seek in filehandle: 22» }
Defined as:
method tell(IO::CatHandle:D: --> Int:D)
Calls .tell on the currently active source handle and returns the result. Returns Nil if the source handle queue has been exhausted.
(my $f1 = 'foo'.IO).spurt: 'foo'; (my $f2 = 'bar'.IO).spurt: 'bar'; with IO::CatHandle.new: $f1, $f2 { .get.say; # OUTPUT: «foo» .tell.say; # OUTPUT: «3» .seek: -2, SeekFromCurrent; .tell.say; # OUTPUT: «1» say .readchars: 3; # OUTPUT: «oob» .tell.say; # OUTPUT: «2» }
Defined as:
method slurp(IO::CatHandle:D:)
Reads all of the available input from all the source handles and returns it as a Buf if the handle is in binary mode or as a Str otherwise. Returns Nil if the source handle queue has been exhausted.
(my $f1 = 'foo'.IO).spurt: 'foo'; (my $f2 = 'bar'.IO).spurt: 'bar'; IO::CatHandle.new( $f1, $f2).slurp.say; # OUTPUT: «foobar» IO::CatHandle.new(:bin, $f1, $f2).slurp.say; # OUTPUT: «Buf[uint8]:0x<66 6f 6f 62 61 72>» IO::CatHandle.new .slurp.say; # OUTPUT: «Nil»
Defined as:
method split(IO::CatHandle:D: |args --> Seq:D)
Read the handle and processes its contents the same way Str.split does, taking the same arguments. Implementations may slurp the contents of all the source handles in their entirety when this method is called.
(my $f1 = 'foo'.IO).spurt: 'foo'; (my $f2 = 'bar'.IO).spurt: 'bar'; IO::CatHandle.new($f1, $f2).split(/o+/).perl.say; # OUTPUT: «("f", "bar").Seq»
Defined as:
method Str(IO::CatHandle:D: --> Str:D)
Calls .Str on the currently active source handle and returns the result. If the source handle queue has been exhausted, returns an implementation-defined string ('<closed IO::CatHandle>' in Rakudo).
Defined as:
method Supply(IO::CatHandle:D: :$size = 65536 --> Supply:D)
Returns a Supply fed with either .read, if the handle is in binary mode, or with .readchars, if it isn't, with reads of :$size bytes or characters. :$size defaults to an implementation-specific value (in Rakudo, the value of $*DEFAULT-READ-ELEMS, which by default is set to 65536).
(my $f1 = 'foo'.IO).spurt: 'foo'; (my $f2 = 'bar'.IO).spurt: 'bar'; react whenever IO::CatHandle.new($f1, $f2).Supply: :2size {.say} # OUTPUT: «foobar» react whenever IO::CatHandle.new(:bin, $f1, $f2).Supply: :2size {.say} # OUTPUT: «Buf[uint8]:0x<66 6f>Buf[uint8]:0x<6f 62>Buf[uint8]:0x<61 72>»
Defined as:
method t(IO::CatHandle:D: --> Bool:D)
Calls .t, which tells if the handle is a TTY, on the currently active source handle and returns the result. If the source handle queue has been exhausted, returns False.
(my $f1 = 'foo'.IO).spurt: 'foo'; with IO::CatHandle.new: $f1, $*IN { repeat { .t.say } while .next-handle; # OUTPUT: «FalseTrue» }
Defined as:
method unlock(IO::CatHandle:D:)
Same as IO::Handle.unlock. Returns Nil if the source handle queue has been exhausted.
Unlocks only the currently active source handle. The .on-switch Callable can be used to conveniently lock/unlock the handles as they're being processed by the CatHandle.
Defined as:
method words(IO::CatHandle:D: $limit = Inf, :$close --> Seq:D)
Same as IO::Handle.words (including the caveat about more data read than needed to make some number of words). Note that a boundary between source handles is considered to be word boundary.
(my $f1 = 'foo'.IO).spurt: 'foo bar'; (my $f2 = 'bar'.IO).spurt: 'meow'; IO::CatHandle.new($f1, $f2).words.perl.say; # OUTPUT: «("foo", "bar", "meow").Seq»
Note: if :$close is False, fully-consumed handles are still going to be closed.
The IO::CatHandle type overrides these methods to throw a X::NYI exception.
Defined as:
multi method flush(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method nl-out(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method out-buffer(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method print(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method printf(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method print-nl(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method put(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method say(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method write(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method WRITE(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method EOF(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Defined as:
multi method EOF(|)
The IO::CatHandle type overrides this method to throw a X::NYI exception. If you have a good idea for how this method should behave, tell Rakudo developers about it!
Opened file or stream
class IO::Handle { }
Instances of IO::Handle encapsulate an handle to manipulate input/output resources. Usually there is no need to create directly an IO::Handle instance, since it will be done by other roles and methods. For instance, an IO::Path object provides an open method that returns an IO::Handle:
my $fh = '/tmp/log.txt'.IO.open; say $fh.^name; # OUTPUT: IO::Handle
The first line is pretty much equivalent to the following piece of code:
my $fh = IO::Handle.new( :path( '/tmp/log.txt'.IO.path ) ).open;
Defined as:
method open(IO::Handle:D: :$bin, :$enc, :$chomp, :$nl-in, Str:D :$nl-out, Str :$mode, :$r, :$w, :$a, :$x, :$update, :$rw, :$rx, :$ra, :$create, :$append, :$truncate, :$exclusive, :$out-buffer, --> IO::Handle:D )
Opens the handle in one of the modes. Fails with appropriate exception if the open fails.
See description of individual methods for the accepted values and behavior of :$chomp, :$nl-in, :$nl-out, and :$enc. The values for parameters default to the invocant's attributes and if any of them are provided, the attributes will be updated to the new values. Specify :$bin set to True instead of :$enc to indicate the handle should be opened in binary mode. Specifying undefined value as :$enc is equivalent to not specifying :$enc at all. Specifying both a defined encoding as :$enc and :$bin set to true will cause X::IO::BinaryAndEncoding exception to be thrown.
The open mode defaults to non-exclusive, read only (same as specifying :r) and can be controlled by a mix of the following arguments:
:r same as specifying :mode<ro> same as specifying nothing :w same as specifying :mode<wo>, :create, :truncate :a same as specifying :mode<wo>, :create, :append :x same as specifying :mode<wo>, :create, :exclusive :update same as specifying :mode<rw> :rw same as specifying :mode<rw>, :create :ra same as specifying :mode<rw>, :create, :append :rx same as specifying :mode<rw>, :create, :exclusive
Support for combinations of modes other than what is listed above is implementation-dependent and should be assumed unsupported. That is, specifying, for example, .open(:r :create) or .open(:mode<wo> :append :truncate) might work or might cause the Universe to implode, depending on a particular implementation. This applies to reads/writes to a handle opened in such unsupported modes as well.
The mode details are:
:mode<ro> means "read only" :mode<wo> means "write only" :mode<rw> means "read and write" :create means the file will be created, if it does not exist :truncate means the file will be emptied, if it exists :exclusive means .open will fail if the file already exists :append means writes will be done at the end of file's current contents
Attempts to open a directory, write to a handle opened in read-only mode or read from a handle opened in write-only mode, or using text-reading methods on a handle opened in binary mode will fail or throw.
In 6.c language, it's possible to open path '-', which will cause open to open (if closed) the $*IN handle if opening in read-only mode or to open the $*OUT handle if opening in write-only mode. All other modes in this case will result in exception being thrown.
As of 6.d language version, use path '-' is deprecated and it will be removed in future language versions entirely.
The :out-buffer controls output buffering and by default behaves as if it were Nil. See method out-buffer for details.
Note (Rakudo versions before 2017.09): Filehandles are NOT flushed or closed when they go out of scope. While they will get closed when garbage collected, garbage collection isn't guaranteed to get run. This means you should use an explicit close on handles opened for writing, to avoid data loss, and an explicit close is recommended on handles opened for reading as well, so that your program does not open too many files at the same time, triggering exceptions on further open calls.
Note (Rakudo versions 2017.09 and after): Open filehandles are automatically closed on program exit, but it is still highly recommended that you close opened handles explicitly.
Defined as:
method comb(IO::Handle:D: Bool :$close, |args --> Seq:D)
Read the handle and processes its contents the same way Str.comb does, taking the same arguments, closing the handle when done if $close is set to a true value. Implementations may slurp the file in its entirety when this method is called.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
my $fh = 'path/to/file'.IO.open; say "The file has {+$fh.comb: '♥', :close} ♥s in it";
Defined as:
has $.chomp is rw = True
One of the attributes that can be set via .new or open. Defaults to True. Takes a Bool specifying whether the line separators (as defined by .nl-in) should be removed from content when using .get or .lines methods.
Defined as:
method get(IO::Handle:D: --> Str:D) multi sub get (IO::Handle $fh = $*ARGFILES --> Str:D)
Reads a single line of input from the handle, removing the trailing newline characters (as set by .nl-in) if the handle's .chomp attribute is set to True. Returns Nil, if no more input is available. The subroutine form defaults to $*ARGFILES if no handle is given.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
$*IN.get.say; # Read one line from the standard input my $fh = open 'filename'; $fh.get.say; # Read one line from a file $fh.close; say get; # Read one line from $*ARGFILES
Defined as:
method getc(IO::Handle:D: --> Str:D) multi sub getc (IO::Handle $fh = $*ARGFILES --> Str:D)
Reads a single character from the input stream. Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown. The subroutine form defaults to $*ARGFILES if no handle is given. Returns Nil, if no more input is available, otherwise operation will block, waiting for at least one character to be available; these caveats apply:
Using getc to get a single keypress from a terminal will only work properly if you've set the terminal to "unbuffered". Otherwise the terminal will wait for the return key to be struck or the buffer to be filled up before perl6 gets even a single byte of data.
If your handle's encoding allows combining characters to be read, perl6 will wait for more data to be available before it provides a character. This means that inputting an "e" followed by a combining acute will give you an e with an acute rather than giving an "e" and letting the next reading function give you a dangling combiner. However, it also means that when the user inputs just an "e" and has no intention to also input a combining acute, your program will be waiting for another keypress before the initial "e" is returned.
Defined as:
submethod DESTROY(IO::Handle:D:)
Closes the filehandle, unless its native-descriptor is 2 or lower. This ensures the standard filehandles do not get inadvertently closed.
Note that garbage collection is not guaranteed to happen, so you must NOT rely on DESTROY for closing the handles you write to and instead close them yourself. Programs that open a lot of files should close the handles explicitly as well, regardless of whether they were open for writing, since too many files might get opened before garbage collection happens and the no longer used handles get closed.
Defined as:
method gist(IO::Handle:D: --> Str:D)
Returns a string containing information which .path, if any, the handle is created for and whether it is .opened.
say IO::Handle.new; # IO::Handle<(Any)>(closed) say "foo".IO.open; # IO::Handle<"foo".IO>(opened)
Defined as:
method eof(IO::Handle:D: --> Bool:D)
Non-blocking. Returns True if the read operations have exhausted the contents of the handle. For seekable handles, this means current position is at or beyond the end of file and seeking an exhausted handle back into the file's contents will result in eof returning False again.
On non-seekable handles and handles opened to zero-size files (including special files in /proc/), EOF won't be set until a read operation fails to read any bytes. For example, in this code, the first read consumes all of the data, but it's only until the second read that reads nothing would the EOF on a TTY handle be set:
$ echo "x" | perl6 -e 'with $*IN { .read: 10000; .eof.say; .read: 10; .eof.say }' False True
Defined as:
multi method encoding(IO::Handle:D: --> Str:D) multi method encoding(IO::Handle:D: $enc --> Str:D)
Returns a Str representing the encoding currently used by the handle, defaulting to "utf8". Nil indicates the filehandle is currently in binary mode. Specifying an optional positional $enc argument switches the encoding used by the handle; specify Nil as encoding to put the handle into binary mode.
The accepted values for encoding are case-insensitive. The available encodings vary by implementation and backend. On Rakudo MoarVM the following are supported:
utf8 utf16 utf16le utf16be utf8-c8 iso-8859-1 windows-1251 windows-1252 windows-932 ascii
The default encoding is utf8, which undergoes normalization into Unicode NFC (normalization form canonical). In some cases you may want to ensure no normalization is done; for this you can use utf8-c8. Before using utf8-c8 please read Unicode: Filehandles and I/O for more information on utf8-c8 and NFC.
As of Rakudo 2018.04 windows-932 is also supported which is a variant of ShiftJIS.
Implementation may choose to also provide support for aliases, e.g. Rakudo allows aliases latin-1 for iso-8859-1 encoding and dashed utf versions: utf-8 and utf-16.
Unlike utf8, utf16 has an endianness — either big endian or little endian. This relates to the ordering of bytes. Computer CPUs also have an endianness. Perl 6's utf16 format specifier will use the endianness of host system when encoding. When decoding it will look for a byte order mark and if it is there use that to set the endianness. If there is no byte order mark it will assume the file uses the same endianness as the host system. A byte order mark is the codepoint U+FEFF which is ZERO WIDTH NO-BREAK SPACE. On utf16 encoded files the standard states if it exists at the start of a file it shall be interpreted as a byte order mark, not a U+FEFF codepoint.
While writing will cause a different file to be written on different endian systems, at the release of 2018.10 the byte order mark will be written out when writing a file and files created with the utf16 encoding will be able to be read on either big or little endian systems.
When using utf16be or utf16le encodings a byte order mark is not used. The endianness used is not affected by the host cpu type and is either big endian for utf16be or little endian for utf16le.
In keeping with the standard, a 0xFEFF byte at the start of a file is interpreted as a ZERO WIDTH NO-BREAK SPACE and not as a byte order mark. No byte order mark is written to files that use the utf16be or utf16le encodings.
As of Rakudo 2018.09 on MoarVM, utf16, utf16le and utf16be are supported. In 2018.10, writing to a file with utf16 will properly add a byte order mark (BOM).
with 'foo'.IO { .spurt: "First line is text, then:\nBinary"; my $fh will leave {.close} = .open; $fh.get.say; # OUTPUT: «First line is text, then:» $fh.encoding: Nil; $fh.slurp.say; # OUTPUT: «Buf[uint8]:0x<42 69 6e 61 72 79>» }
Defined as:
sub lines(IO::Handle:D $fh = $*ARGFILES, $limit = Inf, :$close --> Seq:D) method lines(IO::Handle:D: $limit = Inf, :$close --> Seq:D)
Return a Seq each element of which is a line from the handle (that is chunks delineated by .nl-in). If the handle's .chomp attribute is set to True, then characters specified by .nl-in will be stripped from each line.
Reads up to $limit lines, where $limit can be a non-negative Int, Inf, or Whatever (which is interpreted to mean Inf). If :$close is set to True, will close the handle when the file ends or $limit is reached. Subroutine form defaults to $*ARGFILES, if no handle is provided.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
NOTE: the lines are read lazily, so ensure the returned Seq is either fully reified or is no longer needed when you close the handle or attempt to use any other method that changes the file position.
say "The file contains ", '50GB-file'.IO.open.lines.grep(*.contains: 'Perl').elems, " lines that mention Perl"; # OUTPUT: «The file contains 72 lines that mention Perl»
Defined as:
method lock(IO::Handle:D: Bool:D :$non-blocking = False, Bool:D :$shared = False --> True)
Places an advisory lock on the filehandle. If :$non-blocking is True will fail with X::IO::Lock if lock could not be obtained, otherwise will block until the lock can be placed. If :$shared is True will place a shared (read) lock, otherwise will place an exclusive (write) lock. On success, returns True; fails with X::IO::Lock if lock cannot be placed (e.g. when trying to place a shared lock on a filehandle opened in write mode or trying to place an exclusive lock on a filehandle opened in read mode).
You can use lock again to replace an existing lock with another one. To remove a lock, close the filehandle or use unlock.
# One program writes, the other reads, and thanks to locks either # will wait for the other to finish before proceeding to read/write # Writer given "foo".IO.open(:w) { .lock; .spurt: "I ♥ Perl 6!"; .close; # closing the handle unlocks it; we could also use `unlock` method for that } # Reader given "foo".IO.open { .lock: :shared; .slurp.say; # OUTPUT: «I ♥ Perl 6!» .close; }
Defined as:
method unlock(IO::Handle:D: --> True)
Removes a lock from the filehandle.
Defined as:
multi sub words(IO::Handle:D $fh = $*ARGFILES, $limit = Inf, :$close --> Seq:D) multi method words(IO::Handle:D: $limit = Inf, :$close --> Seq:D)
Similar to Str.words, separates the handle's stream on contiguous chunks of whitespace (as defined by Unicode) and returns a Seq of the resultant "words." Takes an optional $limit argument that can be a non-negative Int, Inf, or Whatever (which is interpreted to mean Inf), to indicate only up-to $limit words must be returned. If Bool :$close named argument is set to True, will automatically close the handle when the returned Seq is exhausted. Subroutine form defaults to $*ARGFILES, if no handle is provided.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
my %dict := bag $*IN.words; say "Most common words: ", %dict.sort(-*.value).head: 5;
NOTE: implementations may read more data than necessary when a call to .words is made. That is, $handle.words(2) may read more data than two "words" worth of data and subsequent calls to read methods might not read from the place right after the two fetched words. After a call to .words, the file position should be treated as undefined.
Defined as:
method split(IO::Handle:D: :$close, |c)
Slurps the handle's content and calls Str.split on it, forwarding any of the given arguments. If :$close named parameter is set to True, will close the invocant after slurping.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
my $fh = 'path/to/file'.IO.open; $fh.split: '♥', :close; # Returns file content split on ♥
Defined as:
multi method spurt(IO::Handle:D: Blob $data, :$close = False) multi method spurt(IO::Handle:D: Cool $data, :$close = False)
Writes all of the $data into the filehandle, closing it when finished, if $close is True. For Cool $data, will use the encoding the handle is set to use (IO::Handle.open or IO::Handle.encoding).
Behavior for spurting a Cool when the handle is in binary mode or spurting a Blob when the handle is NOT in binary mode is undefined.
Defined as:
multi method print(**@text --> True) multi method print(Junction:D --> True)
Writes the given @text to the handle, coercing any non-Str objects to Str by calling .Str method on them. Junction arguments autothread and the order of printed strings is not guaranteed. See write to write bytes.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
my $fh = 'path/to/file'.IO.open: :w; $fh.print: 'some text'; $fh.close;
Defined as:
method print-nl(IO::Handle:D: --> True)
Writes the value of $.nl-out attribute into the handle. This attribute, by default, is , but see the page on newline for the rules it follows in different platforms and environments.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
my $fh = 'path/to/file'.IO.open: :w, :nl-out("\r\n"); $fh.print: "some text"; $fh.print-nl; # prints \r\n $fh.close;
Defined as:
multi method printf(IO::Handle:D: Cool $format, *@args)
Formats a string based on the given format and arguments and .prints the result into the filehandle. See sub sprintf for details on acceptable format directives.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
my $fh = open 'path/to/file', :w; $fh.printf: "The value is %d\n", 32; $fh.close;
Defined as:
method out-buffer(--> Int:D) is rw
Controls output buffering and can be set via an argument to open. Takes an int as the size of the buffer to use (zero is acceptable). Can take a Bool: True means to use default, implementation-defined buffer size; False means to disable buffering (equivalent to using 0 as buffer size).
Lastly, can take a Nil to enable TTY-based buffering control: if the handle is a TTY, the buffering is disabled, otherwise, default, implementation-defined buffer size is used.
See flush to write out data currently in the buffer. Changing buffer size flushes the filehandle.
given 'foo'.IO.open: :w, :1000out-buffer { .say: 'Hello world!'; # buffered .out-buffer = 42; # buffer resized; previous print flushed .say: 'And goodbye'; .close; # closing the handle flushes the buffer }
Defined as:
multi method put(**@text --> True) multi method put(Junction:D --> True)
Writes the given @text to the handle, coercing any non-Str objects to Str by calling .Str method on them, and appending the value of .nl-out at the end. Junction arguments autothread and the order of printed strings is not guaranteed.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
my $fh = 'path/to/file'.IO.open: :w; $fh.put: 'some text'; $fh.close;
Defined as:
multi method say(IO::Handle:D: **@text --> True)
This method is identical to put except that it stringifies its arguments by calling .gist instead of .Str.
Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
my $fh = open 'path/to/file', :w; $fh.say(Complex.new(3, 4)); # RESULT: «3+4i\n» $fh.close;
Defined as:
method read(IO::Handle:D: Int(Cool:D) $bytes = 65536 --> Buf:D)
Binary reading; reads and returns up to $bytes bytes from the filehandle. $bytes defaults to an implementation-specific value (in Rakudo, the value of $*DEFAULT-READ-ELEMS, which by default is set to 65536). This method can be called even when the handle is not in binary mode.
(my $file = 'foo'.IO).spurt: 'I ♥ Perl'; given $file.open { say .read: 6; # OUTPUT: «Buf[uint8]:0x<49 20 e2 99 a5 20>» .close; }
Defined as:
method readchars(IO::Handle:D: Int(Cool:D) $chars = 65536 --> Str:D)
Reading chars; reads and returns up to $chars chars (graphemes) from the filehandle. $chars defaults to an implementation-specific value (in Rakudo, the value of $*DEFAULT-READ-ELEMS, which by default is set to 65536). Attempting to call this method when the handle is in binary mode will result in X::IO::BinaryMode exception being thrown.
(my $file = 'foo'.IO).spurt: 'I ♥ Perl'; given $file.open { say .readchars: 5; # OUTPUT: «I ♥ P» .close; }
Defined as:
method write(IO::Handle:D: Blob:D $buf --> True)
Writes $buf to the filehandle. This method can be called even when the handle is not in binary mode.
Defined as:
method seek(IO::Handle:D: Int:D $offset, SeekType:D $whence --> True)
Move the file pointer (that is, the position at which any subsequent read or write operations will begin) to the byte position specified by $offset relative to the location specified by $whence which may be one of:
SeekFromBeginning: The beginning of the file.
SeekFromCurrent: The current position in the file.
SeekFromEnd: The end of the file. Please note that you need to specify a negative offset if you want to position before the end of the file.
Defined as:
method tell(IO::Handle:D: --> Int:D)
Return the current position of the file pointer in bytes.
Defined as:
multi method slurp-rest(IO::Handle:D: :$bin! --> Buf) multi method slurp-rest(IO::Handle:D: :$enc --> Str)
DEPRECATION NOTICE: this method is deprecated in the 6.d version. Do not use it for new code, use .slurp method instead.
Returns the remaining content of the file from the current file position (which may have been set by previous reads or by seek.) If the adverb :bin is provided a Buf will be returned; otherwise the return will be a Str with the optional encoding :enc.
Defined as:
method slurp(IO::Handle:D: :$close, :$bin)
Returns all the content from the current file pointer to the end. If the invocant is in binary mode or if $bin is set to True, will return a Buf, otherwise will decode the content using invocant's current .encoding and return a Str.
If :$close is set to True, will close the handle when finished reading.
Note: On Rakudo this method was introduced with release 2017.04; $bin arg was added in 2017.10.
Defined as:
multi method Supply(IO::Handle:D: :$size = 65536)
Returns a Supply that will emit the contents of the handle in chunks. The chunks will be Buf if the handle is in binary mode or, if it isn't, Str decoded using same encoding as IO::Handle.encoding.
The size of the chunks is determined by the optional :size named parameter and 65536 bytes in binary mode or 65536 characters in non-binary mode.
"foo".IO.open(:bin).Supply(:size<10>).tap: *.perl.say; # OUTPUT: # Buf[uint8].new(73,32,226,153,165,32,80,101,114,108) # Buf[uint8].new(32,54,33,10) "foo".IO.open.Supply(:size<10>).tap: *.perl.say; # OUTPUT: # "I ♥ Perl" # " 6!\n"
Defined as:
method path(IO::Handle:D:)
For a handle opened on a file this returns the IO::Path that represents the file. For the standard I/O handles $*IN, $*OUT, and $*ERR it returns an IO::Special object.
Defined as:
method IO(IO::Handle:D:)
Alias for .path
Returns the value of .path, coerced to Str.
say "foo".IO.open.path; # OUTPUT: «"foo".IO»
Defined as:
method close(IO::Handle:D: --> Bool:D) multi sub close(IO::Handle $fh)
Closes an open filehandle. It's not an error to call close on an already-closed filehandle. Returns True on success. If you close one of the standard filehandles (by default: $*IN, $*OUT, or $*ERR), that is any handle with native-descriptor 2 or lower, you won't be able to re-open such a handle.
It's a common idiom to use LEAVE phaser for closing the handles, which ensures the handle is closed regardless of how the block is left.
if $do-stuff-with-the-file { my $fh = open "path-to-file"; LEAVE close $fh; # ... do stuff with the file } sub do-stuff-with-the-file (IO $path-to-file) my $fh = $path-to-file.open; # stick a `try` on it, since this will get run even when the sub is # called with wrong arguments, in which case the `$fh` will be an `Any` LEAVE try close $fh; # ... do stuff with the file } given "foo/bar".IO.open(:w) { .spurt: "I ♥ Perl 6!"; .close; }
Note: unlike some other languages, Perl 6 does not use reference counting, and so the filehandles are NOT closed when they go out of scope. While they will get closed when garbage collected, garbage collection isn't guaranteed to get run. This means you must use an explicit close on handles opened for writing, to avoid data loss, and an explicit close is recommended on handles opened for reading as well, so that your program does not open too many files at the same time, triggering exceptions on further open calls.
Note several methods allow for providing :close argument, to close the handle after the operation invoked by the method completes. As a simpler alternative, the IO::Path type provides many reading and writing methods that let you work with files without dealing with filehandles directly.
Defined as:
method flush(IO::Handle:D: --> True)
Will flush the handle, writing any of the buffered data. Returns True on success; otherwise, fails with X::IO::Flush.
given "foo".IO.open: :w { LEAVE .close; .print: 'something'; 'foo'.IO.slurp.say; # (if the data got buffered) OUTPUT: «» .flush; # flush the handle 'foo'.IO.slurp.say; # OUTPUT: «something» }
Defined as:
method native-descriptor()
This returns a value that the operating system would understand as a "file descriptor" and is suitable for passing to a native function that requires a file descriptor as an argument such as fcntl or ioctl.
Defined as:
method nl-in(--> Str:D) is rw
One of the attributes that can be set via .new or open. Defaults to ["\x0A", "\r\n"]. Takes either a Str or Array of Str specifying input line ending(s) for this handle. If .chomp attribute is set to True, will strip these endings in routines that chomp, such as get and lines.
with 'test'.IO { .spurt: '1foo2bar3foo'; # write some data into our test file my $fh will leave {.close} = .open; # can also set .nl-in via .open arg $fh.nl-in = [<foo bar>]; # set two possible line endings to use; $fh.lines.say; # OUTPUT: ("1", "2", "3").Seq }
Defined as:
has Str:D $.nl-out is rw = "\n";
One of the attributes that can be set via .new or open. Defaults to "\n". Takes a Str specifying output line ending for this handle, to be used by methods .put and .say.
with 'test'.IO { given .open: :w { .put: 42; .nl-out = 'foo'; .put: 42; .close; } .slurp.perl.say; # OUTPUT: «"42\n42foo"» }
Defined as:
method opened(IO::Handle:D: --> Bool:D)
Returns True if the handle is open, False otherwise.
Defined as:
method t(IO::Handle:D: --> Bool:D)
Returns True if the handle is opened to a TTY, False otherwise.
As of 6.d language (early implementation available in Rakudo compiler version 2018.08), a few helper methods are available to simplify creation of custom IO::Handle objects. In your subclass you simply need to implement those methods to affect all of the related features. If your handle wants to work with textual read/write methods and doesn't use the standard .open method, be sure to call .encoding method in your custom handle to get decoder/encoder properly set up:
class IO::URL is IO::Handle { has $.URL is required; has Buf $!content; submethod TWEAK { use WWW; # ecosystem module that will let us `get` a web page use DOM::Tiny; # ecosystem module that will parse out all text from HTML $!content := Buf.new: DOM::Tiny.parse(get $!URL).all-text(:trim).encode; self.encoding: 'utf8'; # set up encoder/decoder } method open(|) { self } # block out some IO::Handle methods method close(|) { self } # that work with normal low-level file method opened { ! self.EOF } # handles, since we don't. This isn't method lock(| --> True) { } # necessary, but will make our handle method unlock( --> True) { } # be more well-behaved if someone # actually calls one of these methods. There are more of these you # can handle, such as .tell, .seek, .flush, .native-descriptor, etc. method WRITE(|) { # For this handle we'll just die on write. If yours can handle writes. # The data to write will be given as a Blob positional argument. die "Cannot write into IO::URL"; } method READ(\bytes) { # We splice off the requested number of bytes from the head of # our content Buf. The handle's decoder will handle decoding them # automatically, if textual read methods were called on the handle. $!content.splice: 0, bytes } method EOF { # For "end of file", we'll simply report whether we still have # any bytes of the website we fetched on creation. not $!content } } my $fh := IO::URL.new: :URL<www.perl6.org>; # .slurp and print all the content from the website. We can use all other # read methods, such as .lines, or .get, or .readchars. All of them work # correctly, even though we only defined .READ and .EOF $fh.slurp.say;
Defined as:
method WRITE(IO::Handle:D: Blob:D \data --> Bool:D)
Called whenever a write operation is performed on the handle. Always receives the data as a Blob, even if a textual writing method has been called.
class IO::Store is IO::Handle { has @.lines = []; submethod TWEAK { self.encoding: 'utf8'; # set up encoder/decoder } method WRITE(IO::Handle:D: Blob:D \data --> Bool:D) { @!lines.push: data.decode(); True; } method gist() { return @!lines.join("\n" ); } } my $store = IO::Store.new(); my $output = $PROCESS::OUT; $PROCESS::OUT = $store; .say for <one two three>; $PROCESS::OUT = $output; say $store.lines(); # OUTPUT «[one two three]»
In this example we are creating a simple WRITE redirection which stores anything written to the filehandle to an array. Se need to save the standard output first, which we do in $output, and then everything that is printed or said (through say) gets stored in the defined IO::Store class. Two things should be taken into account in this class. By default, IO::Handles are in binary mode, so we need to TWEAK the objects if we want them to work with text. Second, a WRITE operation should return True if successful. It will fail if it does not.
Defined as:
method READ(IO::Handle:D: Int:D \bytes --> Buf:D)
Called whenever a read operation is performed on the handle. Receives the number of bytes requested to read. Returns a Buf with those bytes which can be used to either fill the decoder buffer or returned from reading methods directly. The result is allowed to have fewer than the requested number of bytes, including no bytes at all.
If you provide your own .READ, you very likely need to provide your own .EOF as well, for all the features to behave correctly.
The compiler may call .EOF method any number of times during a read operation to ascertain whether a call to .READ should be made. More bytes than necessary to satisfy a read operation may be requested from .READ, in which case the extra data may be buffered by the IO::Handle or the decoder it's using, to fulfill any subsequent reading operations, without necessarily having to make another .READ call.
class IO::Store is IO::Handle { has @.lines = []; submethod TWEAK { self.encoding: 'utf8'; # set up encoder/decoder } method WRITE(IO::Handle:D: Blob:D \data --> Bool:D) { @!lines.push: data; True; } method whole() { my Buf $everything = Buf.new(); for @!lines -> $b { $everything ~= $b; } return $everything; } method READ(IO::Handle:D: Int:D \bytes --> Buf:D) { my Buf $everything := self.whole(); return $everything; } method EOF { my $everything = self.whole(); !$everything; } } my $store := IO::Store.new(); $store.print( $_ ) for <one two three>; say $store.read(3).decode; # OUTPUT «one» say $store.read(3).decode; # OUTPUT «two»
In this case, we have programmed the two READ and EOF methods, as well as WRITE, which stores every line in an element in an array. The read method actually calls READ, returning 3 bytes, which correspond to the three characters in the first two elements. Please note that it's the IO::Handle base class the one that is taking care of cursor, since READ just provides a handle into the whole content of the object; the base class will READ 1024 * 1024 bytes at a time. If your object is planned to hold an amount of bytes bigger than that, you will have to handle an internal cursor yourself. That is why in this example we don't actually use the bytes argument.
Defined as:
method EOF(IO::Handle:D: --> Bool:D)
Indicates whether "end of file" has been reached for the data source of the handle; i.e. no more data can be obtained by calling .READ method. Note that this is not the same as eof method, which will return True only if .EOF returns True and all the decoder buffers, if any were used by the handle, are also empty. See .READ for an example implementation.
See also the related role IO and the related class IO::Path.
Asynchronous notification for file and directory changes
enum FileChangeEvent (:FileChanged(1), :FileRenamed(2));
class IO::Notification { class Change { has $.path; has $.event; } ... }
IO::Notification.watch-path($path) produces a Supply of IO::Notification::Change events for a file or directory.
Here is a small example that prints the first ten FileChanged-notifications for the current working directory:
my $finish = Promise.new; my $count = 0; IO::Notification.watch-path($*CWD).act( -> $change { $count++ if $change.event ~~ FileChanged; say "($count) $change.path(): $change.event()"; $finish.keep if $count >= 10; }); await $finish;
The type of the change is very much dependent both on the platform and on specific system calls that were used initiate the change. At this point in time you should not rely on the type of change in general, and test your particular situation.
method watch-path(IO::Notification: Str() $path, :$scheduler = $*SCHEDULER)
Returns a Supply that emits IO::Notification::Change objects.
If $path is a file, only modifications of that file are reported. If $path is a directory, both modifications to the directory itself (for example permission changes) and to files in the directory (including new files in the directory) are reported.
:$scheduler allows you to specify which thread scheduler is responsible for the notification stream.
File or directory path
class IO::Path is Cool does IO { }
IO::Path is the workhorse of IO operations.
Conceptually, an IO::Path object consists of a volume, a directory, and a basename. It supports both purely textual operations, and operations that access the filesystem, e.g. to resolve a path, or to read all content of a file.
At creation, each IO::Path object is given information about the current working directory the path might be relative to using the $.CWD attribute (defaults to $*CWD), as well as what operating system semantics should be used for path manipulation using the special IO::Spec type given in the $.SPEC attribute.
The $.SPEC defaults to the value of $*SPEC, which uses the object suitable for the operating system the code is currently running on. This is the default most code will be comfortable with.
In certain situations, e.g. testing, you may wish to force $*SPEC to use one of the specific SPEC modules: IO::Spec::Unix, IO::Spec::Win32, IO::Spec::Cygwin, and IO::Spec::QNX, or to create IO::Path objects via shortcut subclasses IO::Path::Unix, IO::Path::Win32, IO::Path::Cygwin, and IO::Path::QNX that pre-set the $.SPEC attribute for you.
The rest of this document silently assumes Unix semantics in its examples, unless stated otherwise.
Defined as:
multi method new(Str:D $path, IO::Spec :$SPEC = $*SPEC, Str() :$CWD = $*CWD) multi method new( :$basename!, :$dirname = '.', :$volume = '' IO::Spec :$SPEC = $*SPEC, Str() :$CWD = $*CWD )
Creates a new IO::Path object from a path string (which is being parsed for volume, directory name and basename), or from volume, directory name and basename passed as named arguments.
The path's operation will be performed using :$SPEC semantics (defaults to current $*SPEC) and will use :$CWD as the directory the path is relative to (defaults to $*CWD).
IO::Path.new("foo", :CWD</home/camelia>) .IO.CWD.say; # OUTPUT: «/home/camelia»
Read-only. Contains implicit or explicit value of :$CWD argument to .new.
IO::Path.new("foo", :SPEC(IO::Spec::Unix.new))\ .IO.SPEC.^name.say; # OUTPUT: «IO::Spec::Unix»
Read-only. Contains implicit or explicit value of :$SPEC argument to .new.
IO::Path.new("foo").path.say; # OUTPUT: «foo»
Read-only. Returns the string the object was constructed from or the value of $SPEC.join($volume, $dirname, $basename) if multi-part version of .new was used. NOTE: this does not include the $.CWD; see IO::Path.absolute and IO::Path.relative for stringification options that include $.CWD.
NOTE: Implementations may cache operations done with this attribute, so modifying its value (via cloning or Proxy) is NOT recommended and may result in broken IO::Path objects. Create a new IO::Path object instead.
Defined as:
multi method ACCEPTS(IO::Path:D: Cool:D $other --> Bool:D)
Coerces the argument to IO::Path, if necessary. Returns True if .absolute method on both paths returns the same string. NOTE: it's possible for two paths that superficially point to the same resource to NOT smartmatch as True, if they were constructed differently and were never fully resolved:
say "foo/../bar".IO ~~ "bar".IO # False
The reason is the two paths above may point to different resources when fully resolved (e.g. if foo is a symlink). Resolve the paths before smartmatching to check they point to same resource:
say "foo/../bar".IO.resolve(:completely) ~~ "bar".IO.resolve(:completely) # True
Defined as:
method basename(IO::Path:D:)
Returns the basename part of the path object, which is the name of the filesystem object itself that is referenced by the path.
"docs/README.pod".IO.basename.say; # OUTPUT: «README.pod» "/tmp/".IO.basename.say; # OUTPUT: «tmp»
Note that in IO::Spec::Win32 semantics, the basename of a Windows share is \, not the name of the share itself:
IO::Path::Win32.new('//server/share').basename.say; # OUTPUT: «\»
Defined as:
method add(IO::Path:D: Str() $what --> IO::Path:D)
Concatenates a path fragment to the invocant and returns the resultant IO::Path. If adding ../ to paths that end with a file, you may need to call resolve for the resultant path to be accessible by other IO::Path methods like dir or open. See also sibling and parent.
"foo/bar".IO.mkdir; "foo/bar".IO.add("meow") .resolve.relative.say; # OUTPUT: «foo/bar/meow» "foo/bar".IO.add("/meow") .resolve.relative.say; # OUTPUT: «foo/bar/meow» "foo/bar".IO.add("meow.txt").resolve.relative.say; # OUTPUT: «foo/bar/meow.txt» "foo/bar".IO.add("../meow") .resolve.relative.say; # OUTPUT: «foo/meow» "foo/bar".IO.add("../../") .resolve.relative.say; # OUTPUT: «.»
Defined as:
method child(IO::Path:D: Str() $childname --> IO::Path:D)
Alias for .add. NOTE: This method has been deprecated as of the 6.d version, and will be removed in the future. For any new code, please use .add
Defined as:
method cleanup(IO::Path:D: --> IO::Path:D)
Returns a new path that is a canonical representation of the invocant path, cleaning up any extraneous path parts:
"foo/./././..////bar".IO.cleanup.say; # OUTPUT: «"foo/../bar".IO» IO::Path::Win32.new("foo/./././..////bar") .cleanup.say; "foo\..\bar".IO; # OUTPUT: «"foo\..\bar".IO»
Note that no filesystem access is made. See also resolve.
Defined as:
method comb(IO::Path:D: |args --> Seq:D)
Opens the file and processes its contents the same way Str.comb does, taking the same arguments. Implementations may slurp the file in its entirety when this method is called.
Defined as:
method split(IO::Path:D: |args --> Seq:D)
Opens the file and processes its contents the same way Str.split does, taking the same arguments. Implementations may slurp the file in its entirety when this method is called.
Defined as:
multi method extension(IO::Path:D: --> Str:D) multi method extension(IO::Path:D: Int :$parts --> Str:D) multi method extension(IO::Path:D: Range :$parts --> Str:D) multi method extension(IO::Path:D: Str $subst, Int :$parts, Str :$joiner --> IO::Path:D) multi method extension(IO::Path:D: Str $subst, Range :$parts, Str :$joiner --> IO::Path:D)
Returns the extension consisting of $parts parts (defaults to 1), where a "part" is defined as a dot followed by possibly-empty string up to the end of the string, or previous part. That is "foo.tar.gz" has an extension of two parts: first part is "gz" and second part is "tar" and calling "foo.tar.gz".IO.extension: :2parts gives "tar.gz". If an extension with the specified number of $parts is not found, returns an empty string.
$parts can be a Range, specifying the minimum number of parts and maximum number of parts the extension should have. The routine will attempt to much the most parts it can. If $parts range's endpoints that are smaller than 0 they'll be treated as 0; implementations may treat endpoints larger than 2⁶³-1 as 2⁶³-1. Ranges with NaN or Str endpoints will cause an exception to be thrown.
If $subst is provided, the extension will be instead replaced with $subst and a new IO::Path object will be returned. It will be joined to the file's name with $joiner, which defaults to an empty string when $subst is an empty string and to "." when $subst is not empty. Note: if as the result of replacement the basename of the path ends up being empty, it will be assumed to be . (a single dot).
# Getting an extension: say "foo.tar.gz".IO.extension; # OUTPUT: «gz» say "foo.tar.gz".IO.extension: :2parts; # OUTPUT: «tar.gz» say "foo.tar.gz".IO.extension: :parts(^5); # OUTPUT: «tar.gz» say "foo.tar.gz".IO.extension: :parts(0..1); # OUTPUT: «gz» # Replacing an extension say "foo.tar.gz".IO.extension: ''; # OUTPUT: «"foo.tar".IO» say "foo.tar.gz".IO.extension: 'ZIP'; # OUTPUT: «"foo.tar.ZIP".IO» say "foo.tar.gz".IO.extension: 'ZIP', :0parts; # OUTPUT: «"foo.tar.gz.ZIP".IO» say "foo.tar.gz".IO.extension: 'ZIP', :2parts; # OUTPUT: «"foo.ZIP".IO» say "foo.tar.gz".IO.extension: 'ZIP', :parts(^5); # OUTPUT: «"foo.ZIP".IO» # Replacing an extension using non-standard joiner: say "foo.tar.gz".IO.extension: '', :joiner<_>; # OUTPUT: «"foo.tar_".IO» say "foo.tar.gz".IO.extension: 'ZIP', :joiner<_>; # OUTPUT: «"foo.tar_ZIP".IO» say "foo.tar.gz".IO.extension: 'ZIP', :joiner<_>, :2parts; # OUTPUT: «"foo_ZIP".IO» say "foo.tar.gz".IO.extension: 'ZIP', :joiner<_>, :parts(^5); # OUTPUT: «"foo_ZIP".IO» # EDGE CASES: # There is no 5-part extension, so returned value is an empty string say "foo.tar.gz".IO.extension: :5parts; # OUTPUT: «» # There is no 5-part extension, so we replaced nothing: say "foo.tar.gz".IO.extension: 'ZIP', :5parts; # OUTPUT: «"foo.tar.gz".IO» # Replacing a 0-part extension is just appending: say "foo.tar.gz".IO.extension: 'ZIP', :0parts; # OUTPUT: «"foo.tar.gz.ZIP".IO» # Replace 1-part of the extension, using '.' joiner say "...".IO.extension: 'tar'; # OUTPUT: «"...tar".IO» # Replace 1-part of the extension, using empty string joiner say "...".IO.extension: 'tar', :joiner(''); # OUTPUT: «"..tar".IO» # Remove 1-part extension; results in empty basename, so result is ".".IO say ".".IO.extension: ''; # OUTPUT: «".".IO»
Defined as:
method dirname(IO::Path:D:)
Returns the directory name portion of the path object. That is, it returns the path excluding the volume and the base name. Unless the dirname consist of only the directory separator (i.e. it's the top directory), the trailing directory separator will not be included in the return value.
say IO::Path.new("/home/camelia/myfile.p6").dirname; # OUTPUT: «/home/camelia» say IO::Path::Win32.new("C:/home/camelia").dirname; # OUTPUT: «/home» say IO::Path.new("/home").dirname; # OUTPUT: «/»
Defined as:
method volume(IO::Path:D:)
Returns the volume portion of the path object. On Unix system, this is always the empty string.
say IO::Path::Win32.new("C:\\Windows\\registry.ini").volume; # OUTPUT: «C:»
Defined as:
method parts(IO::Path:D: --> Map:D)
Returns a Map with the keys volume, dirname, basename whose values are the same as available via methods .volume, .dirname, and .basename respectively.
say IO::Path::Win32.new("C:/rakudo/perl6.bat").parts.perl; # OUTPUT: «Map.new((:basename("perl6.bat"),:dirname("/rakudo"),:volume("C:")))»
Defined as:
method perl(IO::Path:D: --> Str:D)
Returns a string that, when given passed through EVAL gives the original invocant back.
"foo/bar".IO.perl.say; # OUTPUT: IO::Path.new("foo/bar", :SPEC(IO::Spec::Unix), :CWD("/home/camelia"))
Note that this string includes the value of the .CWD attribute that is set to $*CWD when the path object was created, by default.
Defined as:
method gist(IO::Path:D: --> Str:D)
Returns a string, part of which contains either the value of .absolute (if path is absolute) or .path. Note that no escaping of special characters is made, so e.g. "\b" means a path contains a backslash and letter "b", not a backspace.
say "foo/bar".IO; # OUTPUT: «"foo/bar".IO» say IO::Path::Win32.new: 「C:\foo/bar\」; # OUTPUT: «"C:\foo/bar\".IO»
Defined as:
method Str(IO::Path:D: --> Str)
Alias for IO::Path.path. In particular, note that default stringification of an IO::Path does NOT use the value of $.CWD attribute. To stringify while retaining full path information use .absolute or .relative methods.
Defined as:
method succ(IO::Path:D: --> IO::Path:D)
Returns a new IO::Path constructed from the invocant, with .basename changed by calling Str.succ on it.
"foo/file02.txt".IO.succ.say; # OUTPUT: «"foo/file03.txt".IO»
Defined as:
method open(IO::Path:D: *%opts)
Opens the path as a file; the named options control the mode, and are the same as the open function accepts.
Defined as:
method pred(IO::Path:D: --> IO::Path:D)
Returns a new IO::Path constructed from the invocant, with .basename changed by calling Str.pred on it.
"foo/file02.txt".IO.pred.say; # OUTPUT: «"foo/file01.txt".IO»
Defined as:
method watch(IO::Path:D: --> Supply:D)
Equivalent to calling IO::Notification.watch-path with the invocant as the argument.
Defined as:
method is-absolute(IO::Path:D: --> Bool)
Returns True if the path is an absolute path, and False otherwise.
"/foo".IO.is-absolute.say; # OUTPUT: «True» "bars".IO.is-absolute.say; # OUTPUT: «False»
Note that on Windows a path that starts with a slash or backslash is still considered absolute even if no volume was given, as it is absolute for that particular volume:
IO::Path::Win32.new("/foo" ).is-absolute.say; # OUTPUT: «True» IO::Path::Win32.new("C:/foo").is-absolute.say; # OUTPUT: «True» IO::Path::Win32.new("C:foo" ).is-absolute.say; # OUTPUT: «False»
Defined as:
method is-relative(IO::Path:D: --> Bool)
Returns True if the path is a relative path, and False otherwise. Windows caveats for .is-absolute apply.
Defined as:
multi method absolute(IO::Path:D: --> Str) multi method absolute(IO::Path:D: $base --> Str)
Returns a new Str object that is an absolute path. If the invocant is not already an absolute path, it is first made absolute using $base as base, if it is provided, or the .CWD attribute the object was created with if it is not.
Defined as:
method relative(IO::Path:D: $base = $*CWD --> Str)
Returns a new Str object with the path relative to the $base. If $base is not provided, $*CWD is used in its place. If the invocant is not an absolute path, it's first made to be absolute using the .CWD attribute the object was created with, and then is made relative to $base.
Defined as:
multi method parent(IO::Path:D:) multi method parent(IO::Path:D: UInt:D $level)
Returns the parent path of the invocant. Note that no actual filesystem access is made, so the returned parent is physical and not the logical parent of symlinked directories.
'/etc/foo'.IO.parent.say; # OUTPUT: «"/etc".IO» '/etc/..' .IO.parent.say; # OUTPUT: «"/etc".IO» '/etc/../'.IO.parent.say; # OUTPUT: «"/etc".IO» './' .IO.parent.say; # OUTPUT: «"..".IO» 'foo' .IO.parent.say; # OUTPUT: «".".IO» '/' .IO.parent.say; # OUTPUT: «"/".IO» IO::Path::Win32.new('C:/').parent.say; # OUTPUT: «"C:/".IO»
If $level is specified, the call is equivalent to calling .parent() $level times:
say "/etc/foo".IO.parent(2) eqv "/etc/foo".IO.parent.parent; # OUTPUT: «True»
Defined as:
method resolve(IO::Path:D: :$completely --> IO::Path)
Returns a new IO::Path object with all symbolic links and references to the parent directory (..) resolved. This means that the filesystem is examined for each directory in the path, and any symlinks found are followed.
# bar is a symlink pointing to "/baz" my $io = "foo/./bar/..".IO.resolve; # now "/" (the parent of "/baz")
If :$completely, which defaults to False, is set to a true value, the method will fail with X::IO::Resolve if it cannot completely resolve the path, otherwise, it will resolve as much as possible, and will merely perform cleanup of the rest of the path. The last part of the path does NOT have to exist to :$completely resolve the path.
NOTE: Currently (April 2017) this method doesn't work correctly on all platforms, e.g. Windows, since it assumes POSIX semantics.
Defined as:
sub dir(Cool $path = '.', Mu :$test = none('.', '..')) method dir(IO::Path:D: Mu :$test = none('.', '..'))
Returns the contents of a directory as a lazy list of IO::Path objects representing relative paths, filtered by smartmatching their names (as strings) against the :test parameter.
Since the tests are performed against Str arguments, not IO, the tests are executed in the $*CWD, instead of the target directory. When testing against file test operators, this won't work:
dir('mydir', test => { .IO.d })
while this will:
dir('mydir', test => { "mydir/$_".IO.d })
NOTE: a dir call opens a directory for reading, which counts towards maximum per-process open files for your program. Be sure to exhaust returned Seq before doing something like recursively performing more dir calls. You can exhaust it by assigning to a @-sigiled variable or simply looping over it. Note how examples below push further dirs to look through into an Array, rather than immediately calling dir on them. See also IO::Dir module that gives you finer control over closing dir handles.
Examples:
# To iterate over the contents of the current directory: for dir() -> $file { say $file; } # As before, but include even '.' and '..' which are filtered out by # the default :test matcher: for dir(test => *) -> $file { say $file; } # To get the names of all .jpg and .jpeg files in ~/Downloads: my @jpegs = $*HOME.dir: test => /:i '.' jpe?g $/;
An example program that lists all files and directories recursively:
sub MAIN($dir = '.') { my @todo = $dir.IO; while @todo { for @todo.pop.dir -> $path { say $path.Str; @todo.push: $path if $path.d; } } }
A lazy way to find the first three files ending in ".p6" recursively starting from the current directory:
my @stack = '.'.IO; my $perl-files = gather while @stack { with @stack.pop { when :d { @stack.append: .dir } .take when .extension.lc eq 'p6' } } .put for $perl-files[^3];
For most file tests, you can do a smartmatch ~~ or you can call a method. You don't need to actually open a filehandle in the traditional way (although you can) to do a filetest. You can simply append .IO to the filename. For instance, here is how to check whether a file is readable using smartmatch:
'/path/to/file'.IO ~~ :r;
File tests include:
:d (Directory)
:e (Exists)
:f (File)
:l (Symbolic link)
:r (Readable)
:rw (Readable and writable)
:s (Size)
:w (Writable)
:x (Executable)
:z (Zero size)
Smartmatching on Pairs can be used to perform multiple tests at once:
say :d & :x; # OUTPUT: «all(d => True, x => True)» say '/tmp'.IO ~~ :d & :x; # OUTPUT: «True» say '/'.IO ~~ :d & :rw; # OUTPUT: «False»
All of the above tests can be used as methods (without the colon), though method tests may throw X::IO::DoesNotExist as documented below. Three tests only exist as methods: accessed, changed and modified.
You can also perform file tests on an already opened filehandle by testing against its .path method. For example, given filehandle $fh:
$fh.path ~~ :r; $fh.path.r; # method form
Defined as:
method e(--> Bool:D)
Returns True if the invocant is a path that exists.
Defined as:
method d(--> Bool:D)
Returns True if the invocant is a path that exists and is a directory. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method f(--> Bool:D)
Returns True if the invocant is a path that exists and is a file. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method s(--> Int:D)
Returns the file size in bytes. May be called on paths that are directories, in which case the reported size is dependent on the operating system. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
say $*EXECUTABLE.IO.s; # OUTPUT : «467»
Defined as:
method l(--> Bool:D)
Returns True if the invocant is a path that exists and is a symlink. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method r(--> Bool:D)
Returns True if the invocant is a path that exists and is accessible. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method w(--> Bool:D)
Returns True if the invocant is a path that exists and is writable. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method rw(--> Bool:D)
Returns True if the invocant is a path that exists and is readable and writable. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method x(--> Bool:D)
Returns True if the invocant is a path that exists and is executable. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method rwx(--> Bool:D)
Returns True if the invocant is a path that exists and is executable, readable, and writable. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method z(--> Bool:D)
Returns True if the invocant is a path that exists and has size of 0. May be called on paths that are directories, in which case the reported file size (and thus the result of this method) is dependent on the operating system. The method will fail with X::IO::DoesNotExist if the path points to a non-existent filesystem entity.
Defined as:
method sibling(IO::Path:D: Str() $sibling --> IO::Path:D)
Allows to reference a sibling file or directory. Returns a new IO::Path based on the invocant, with the .basename changed to $sibling. The $sibling is allowed to be a multi-part path fragment; see also .add.
say '.bashrc'.IO.sibling: '.bash_aliases'; # OUTPUT: «.bash_aliases".IO» say '/home/camelia/.bashrc'.IO.sibling: '.bash_aliases'; # OUTPUT: «/home/camelia/.bash_aliases".IO» say '/foo/' .IO.sibling: 'bar'; # OUTPUT: «/bar".IO» say '/foo/.'.IO.sibling: 'bar'; # OUTPUT: «/foo/bar".IO»
Defined as:
method words(IO::Path:D: :$chomp = True, :$enc = 'utf8', :$nl-in = ["\x0A", "\r\n"], |c --> Seq:D)
Opens the invocant and returns its words.
The behavior is equivalent to opening the file specified by the invocant, forwarding the :$chomp, :$enc, and :$nl-in arguments to IO::Handle.open, then calling IO::Handle.words on that handle, forwarding any of the remaining arguments to that method, and returning the resultant Seq.
NOTE: words are lazily read. The handle used under the hood is not closed until the returned Seq is fully reified, and this could lead to leaking open filehandles. It is possible to avoid leaking open filehandles using the $limit argument to cut down the Seq of words to be generated.
my %dict := bag 'my-file.txt'.IO.words; say "Most common words: ", %dict.sort(-*.value).head: 5;
Defined as:
method lines(IO::Path:D: :$chomp = True, :$enc = 'utf8', :$nl-in = ["\x0A", "\r\n"], |c --> Seq:D)
Opens the invocant and returns its lines.
The behavior is equivalent to opening the file specified by the invocant, forwarding the :$chomp, :$enc, and :$nl-in arguments to IO::Handle.open, then calling IO::Handle.lines on that handle, forwarding any of the remaining arguments to that method, and returning the resultant Seq.
NOTE: the lines are ready lazily and the handle used under the hood won't get closed until the returned Seq is fully reified, so ensure it is, or you'll be leaking open filehandles. (TIP: use the $limit argument)
say "The file contains ", '50GB-file'.IO.lines.grep(*.contains: 'Perl').elems, " lines that mention Perl"; # OUTPUT: «The file contains 72 lines that mention Perl»
Defined as:
multi method slurp(IO::Path:D: :$bin, :$enc)
Read all of the file's content and return it as either Buf, if :$bin is True, or if not, as Str decoded with :$enc encoding, which defaults to utf8. File will be closed afterwards. See &open for valid values for :$enc.
Defined as:
method spurt(IO::Path:D: $data, :$enc, :$append, :$createonly)
Opens the file path for writing, and writes all of the $data into it. File will be closed, afterwards. Will fail if it cannot succeed for any reason. The $data can be any Cool type or any Blob type. Arguments are as follows:
:$enc — character encoding of the data. Takes same values as :$enc in IO::Handle.open. Defaults to utf8. Ignored if $data is a Blob.
:$append — open the file in append mode, preserving existing contents, and appending data to the end of the file.
:$createonly — fail if the file already exists.
Defined as:
multi method chdir(IO::Path:D: Str() $path, :$d = True, :$r, :$w, :$x)
DEPRECATION NOTICE: this method will be deprecated in 6.d language and removed in 6.e. Do not use it for new code. Instead, create a new path or use add method. For altering current working directory see &chdir and &*chdir subroutines.
Contrary to the name, the .chdir method does not change any directories, but merely concatenates the given $path to the invocant and returns the resultant IO::Path. Optional file tests can be performed by providing :d, :r, :w, or :x Bool named arguments; when set to True, they'll perform .d, .r, .w, and .x tests respectively. By default, only :d is set to True.
Defined as:
method mkdir(IO::Path:D: Int() $mode = 0o777 --> IO::Path:D)
Creates a new directory, including its parent directories, as needed (similar to *nix utility mkdir with -p option). That is, mkdir "foo/bar/ber/meow" will create foo, foo/bar, and foo/bar/ber directories as well if they do not exist.
Returns the IO::Path object pointing to the newly created directory on success; fails with X::IO::Mkdir if directory cannot be created.
See also mode for explanation and valid values for $mode.
Defined as:
sub rmdir(*@dirs --> List:D) method rmdir(IO::Path:D: --> True)
Remove the invocant, or in sub form, all of the provided directories in the given list, which can contain any Cool object. Only works on empty directories.
Method form returns True on success and throws an exception of type X::IO::Rmdir if the directory cannot be removed (e.g. the directory is not empty, or the path is not a directory). Subroutine form returns a list of directories that were successfully deleted.
To delete non-empty directory, see rmtree in File::Directory::Tree module.
Defined as:
method chmod(IO::Path:D: Int() $mode --> Bool)
Changes the POSIX permissions of a file or directory to $mode. Returns True on success; on failure, fails with X::IO::Chmod.
The mode is expected as an integer following the standard numeric notation, and is best written as an octal number:
'myfile'.IO.chmod(0o444); # make a file read-only 'somedir'.IO.chmod(0o777); # set 0777 permissions on a directory
Make sure you don't accidentally pass the intended octal digits as a decimal number (or string containing a decimal number):
'myfile'.IO.chmod: '0444'; # BAD!!! (interpreted as mode 0o674) 'myfile'.IO.chmod: '0o444'; # OK (an octal in a string) 'myfile'.IO.chmod: 0o444; # Also OK (an octal literal)
Defined as:
method rename(IO::Path:D: IO() $to, :$createonly = False --> Bool:D) sub rename(IO() $from, IO() $to, :$createonly = False --> Bool:D)
Renames a file or directory. Returns True on success; fails with X::IO::Rename if :$createonly is True and the $to path already exists or if the operation failed for some other reason.
Note: some renames will always fail, such as when the new name is on a different storage device. See also: move.
Defined as:
method copy(IO::Path:D: IO() $to, :$createonly --> Bool:D) sub copy(IO() $from, IO() $to, :$createonly --> Bool:D)
Copies a file. Returns True on success; fails with X::IO::Copy if :$createonly is True and the $to path already exists or if the operation failed for some other reason, such as when $to and $from are the same file.
Defined as:
method move(IO::Path:D: IO() $to, :$createonly --> Bool:D) sub move(IO() $from, IO() $to, :$createonly --> Bool:D)
Copies a file and then removes the original. If removal fails, it's possible to end up with two copies of the file. Returns True on success; fails with X::IO::Move if :$createonly is True and the $to path already exists or if the operation failed for some other reason, such as when $to and $from are the same file.
To avoid copying, you can use rename, if the files are on the same storage device. It also works with directories, while move does not.
Defined as:
method Numeric(IO::Path:D: --> Numeric:D)
Coerces .basename to Numeric. Fails with X::Str::Numeric if base name is not numerical.
Defined as:
method Int(IO::Path:D: --> Int:D)
Coerces .basename to Int. Fails with X::Str::Numeric if base name is not numerical.
Defined as:
method symlink(IO::Path:D $target: IO() $link --> Bool:D) sub symlink( IO() $target, IO() $link --> Bool:D)
Create a new symbolic link $link to existing $target. Returns True on success; fails with X::IO::Symlink if the symbolic link could not be created. If $target does not exist, creates a dangling symbolic link. To create a hard link, see link.
Note: on Windows, creation of symbolic links may require escalated privileges.
Defined as:
method link(IO::Path:D $target: IO() $link --> Bool:D) sub link( IO() $target, IO() $link --> Bool:D)
Create a new hard link $link to existing $target. Returns True on success; fails with X::IO::Link if the hard link could not be created. To create a symbolic link, see symlink.
Defined as:
method unlink(IO::Path:D: --> True) sub unlink(*@filenames --> List:D)
Delete all specified ordinary files, links, or symbolic links for which there are privileges to do so. See rmdir to delete directories.
The subroutine form returns the names of all the files in the list, excluding those for which the filesystem raised some error; since trying to delete a file that does not exist does not raise any error at that level, this list will include the names of the files in the list that do not exist.
The method form returns True on success, or fails with X::IO::Unlink if the operation could not be completed. If the file to be deleted does not exist, the routine treats it as success.
'foo.txt'.IO.open(:w).close; 'bar'.IO.mkdir; say unlink <foo.txt bar not-there.txt>; # OUTPUT: «[foo.txt not-there.txt]» # `bar` is not in output because it failed to delete (it's a directory) # `not-there.txt` is present. It never existed, so that's deemed a success. # Method form `fail`s: say .exception.message without 'bar'.IO.unlink; # OUTPUT: «Failed to remove the file […] illegal operation on a directory»
Defined as:
method IO(IO::Path:D: --> IO::Path)
Returns the invocant.
Defined as:
method SPEC(IO::Path:D: --> IO::Spec)
Returns the IO::Spec object that was (implicitly) specified at object creation time.
my $io = IO::Path.new("/bin/bash"); say $io.SPEC; # OUTPUT: «(Unix)» say $io.SPEC.dir-sep; # OUTPUT: «/»
There are also 3 methods for fetching the 3 timestamps of a file (inode), on Operating Systems where these are available:
Returns an Instant object indicating when the content of the file was last modified. Compare with changed.
say "path/to/file".IO.modified; # Instant:1424089165 say "path/to/file".IO.modified.DateTime; # 2015-02-16T12:18:50Z
Return an Instant object representing the timestamp when the file was last accessed. Note: depending on how the filesystem was mounted, the last accessed time may not update on each access to the file, but only on the first access after modifications.
say "path/to/file".IO.accessed; # Instant:1424353577 say "path/to/file".IO.accessed.DateTime; # 2015-02-19T13:45:42Z
Returns an Instant object indicating the metadata of the file or directory was last changed (e.g. permissions, or files created/deleted in directory). Compare with modified.
say "path/to/file".IO.changed; # Instant:1424089165 say "path/to/file".IO.changed.DateTime; # 2015-02-16T12:18:50Z
Return an IntStr object representing the POSIX permissions of a file. The Str part of the result is the octal representation of the file permission, like the form accepted by the chmod(1) utility.
say ~"path/to/file".IO.mode; # e.g. '0644' say +"path/to/file".IO.mode; # e.g. 420, where sprintf('%04o', 420) eq '0644'
The result of this can be used in the other methods that take a mode as an argument.
"path/to/file1".IO.chmod("path/to/file2".IO.mode); # will change the # permissions of file1 # to be the same as file2
IO::Path pre-loaded with IO::Spec::Cygwin
class IO::Path::Cygwin is IO::Path { }
This sub-class of IO::Path, pre-loaded with IO::Spec::Cygwin in the $.SPEC attribute.
Same as IO::Path.new, except :$SPEC cannot be set and defaults to IO::Spec::Cygwin, regardless of the operating system the code is being run on.
Defined as:
method perl(IO::Path::Cygwin:D: --> Str:D)
Returns a string that, when given passed through EVAL gives the original invocant back.
IO::Path::Cygwin.new("foo/bar").perl.say; # OUTPUT: IO::Path::Cygwin.new("foo/bar", :CWD("/home/camelia"))
Note that this string includes the value of the .CWD attribute that is set to $*CWD when the path object was created, by default.
IO::Path pre-loaded with IO::Spec::QNX
class IO::Path::QNX is IO::Path { }
This sub-class of IO::Path, pre-loaded with IO::Spec::QNX in the $.SPEC attribute.
Same as IO::Path.new, except :$SPEC cannot be set and defaults to IO::Spec::QNX, regardless of the operating system the code is being run on.
Defined as:
method perl(IO::Path::QNX:D: --> Str:D)
Returns a string that, when given passed through EVAL gives the original invocant back.
IO::Path::QNX.new("foo/bar").perl.say; # OUTPUT: IO::Path::QNX.new("foo/bar", :CWD("/home/camelia"))
Note that this string includes the value of the .CWD attribute that is set to $*CWD when the path object was created, by default.
IO::Path pre-loaded with IO::Spec::Unix
class IO::Path::Unix is IO::Path { }
This sub-class of IO::Path, pre-loaded with IO::Spec::Unix in the $.SPEC attribute.
Same as IO::Path.new, except :$SPEC cannot be set and defaults to IO::Spec::Unix, regardless of the operating system the code is being run on.
Defined as:
method perl(IO::Path::Unix:D: --> Str:D)
Returns a string that, when given passed through EVAL gives the original invocant back.
IO::Path::Unix.new("foo/bar").perl.say; # OUTPUT: IO::Path::Unix.new("foo/bar", :CWD("/home/camelia"))
Note that this string includes the value of the .CWD attribute that is set to $*CWD when the path object was created, by default.
IO::Path pre-loaded with IO::Spec::Win32
class IO::Path::Win32 is IO::Path { }
This sub-class of IO::Path, pre-loaded with IO::Spec::Win32 in the $.SPEC attribute.
Same as IO::Path.new, except :$SPEC cannot be set and defaults to IO::Spec::Win32, regardless of the operating system the code is being run on.
Defined as:
method perl(IO::Path::Win32:D: --> Str:D)
Returns a string that, when given passed through EVAL gives the original invocant back.
IO::Path::Win32.new("foo/bar").perl.say; # OUTPUT: IO::Path::Win32.new("foo/bar", :CWD("C:\\Users\\camelia"))
Note that this string includes the value of the .CWD attribute that is set to $*CWD when the path object was created, by default.
Buffered inter-process string or binary stream
class IO::Pipe is IO::Handle {}
An IO::Pipe object closely corresponds to a UNIX pipe. It has one end where it consumes string or binary data, and another where it reproduces the same data. It is buffered, so that a write without a read doesn't immediately block.
Pipes can be easily constructed with sub run and Proc::Async.new.
Defined as:
method close(IO::Pipe: --> Proc:D)
Closes the pipe and returns Proc object from which the pipe originates.
Defined as:
method IO(IO::Pipe: --> IO::Path:U)
Returns an IO::Path type object.
Defined as:
method path(IO::Pipe: --> IO::Path:U)
Returns an IO::Path type object.
Defined as:
method proc(IO::Pipe: --> Proc:D)
Returns the Proc object from which the pipe originates.
Network socket
role IO::Socket { ... }
IO::Socket contains read and write methods for sockets. It is usually used through IO::Socket::INET.
method recv(IO::Socket:D: Cool $elems = Inf, :$bin)
Receive a packet and return it, either as a Blob if :bin was passed, or a Str if not. Receives up to $elems or 65535 (whichever is smaller) bytes or characters.
Fails if the socket is not connected.
method read(IO::Socket:D: Int(Cool) $bytes)
Reads $bytes bytes from the socket and returns them in a Blob.
Fails if the socket is not connected.
Defined as:
method get(IO::Socket:D: --> Str:D)
Reads a single line of input from the socket, removing the trailing newline characters (as set by .nl-in). Returns Nil, if no more input is available.
Fails if the socket is not connected.
method print(IO::Socket:D: Str(Cool) $string)
Writes the supplied string to the socket, thus sending it to other end of the connection. The binary version is #method write.
Fails if the socket is not connected.
method write(IO::Socket:D: Blob:D $buf)
Writes the supplied buffer to the socket, thus sending it to other end of the connection. The string version is #method print.
Fails if the socket is not connected.
method put(IO::Socket:D: Str(Cool) $string)
Writes the supplied string, with a \n appended to it, to the socket, thus sending it to other end of the connection.
Fails if the socket is not connected.
method close(IO::Socket:D)
Closes the socket.
Fails if the socket is not connected.
method native-descriptor()
This returns a value that the operating system would understand as a "socket descriptor" and is suitable for passing to a native function that requires a socket descriptor as an argument such as setsockopt.
Asynchronous socket in TCP or UDP
class IO::Socket::Async {}
IO::Socket::Async|/type/IO::Socket::Async provides asynchronous sockets, for both the server and the client side.
Here is a simple example of a simple "hello world" HTTP server that listens on port 3333:
react { whenever IO::Socket::Async.listen('0.0.0.0', 3333) -> $conn { whenever $conn.Supply.lines -> $line { $conn.print: qq:heredoc/END/; HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Content-Encoding: UTF-8 <html> <body> <h1>Hello World!</h1> <p>{ $line }</p> </body> </html> END $conn.close; } } CATCH { default { say .^name, ': ', .Str; say "handled in $?LINE"; } } }
And a client that connects to it, and prints out what the server answers:
await IO::Socket::Async.connect('127.0.0.1', 3333).then( -> $promise { given $promise.result { .print("Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"); react { whenever .Supply() -> $v { $v.print; done; } } .close; } });
IO::Socket::Async can also send and receive UDP messages An example server that outputs all the data it receives would be:
my $socket = IO::Socket::Async.bind-udp('localhost', 3333); react { whenever $socket.Supply -> $v { if $v.chars > 0 { say $v; } } }
And an associated client might be:
my $socket = IO::Socket::Async.udp(); await $socket.print-to('localhost', 3333, "Hello, Perl 6!");
The CATCH phaser can be included to deal specifically with problems that might occur in this kind of sockets, such as a port being already taken:
react { whenever IO::Socket::Async.listen('0.0.0.0', 3000) -> $conn { whenever $conn.Supply.lines -> $line { $conn.print: qq:heredoc/END/; HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Content-Encoding: UTF-8 <html> <body> <h1>Hello World!</h1> <p>{ $line }</p> </body> </html> END $conn.close; } QUIT { default { say .^name, '→ ', .Str; say "handled in line $?LINE"; } } } } # Will print this, if address 3000 is already in use: # X::AdHoc→ address already in use # handled in 23
Main difference with using other phasers such as CATCH is that this kind of exception will be caught within the whenever block and will put exiting the program, or not, under your control.
The IO::Socket::Async cannot be constructed directly, either connect or listen (for TCP connections) or udp or bind-udp (for UDP data) should be used to create a client or a server respectively.
method connect(Str $host, Int $port --> Promise)
Attempts to connect to the TCP server specified by $host and $port, returning a Promise that will either be kept with a connected IO::Socket::Async or broken if the connection cannot be made.
method listen(Str $host, Int $port --> Supply)
Creates a listening socket on the specified $host and $port, returning a Supply to which the accepted client IO::Socket::Asyncs will be emitted. This Supply should be tapped start listening for client connections. You can use $port = 0 if you want the operating system to find one for you.
To close the underlying listening socket, the Tap returned by tapping the listener should be closed.
For example, when using tap:
my $listener = IO::Socket::Async.listen('127.0.0.1', 8080); my $tap = $listener.tap({ ... }); # When you want to close the listener $tap.close;
Or when using whenever:
my $listener = IO::Socket::Async.listen('127.0.0.1', 5000); my $tap; react { $tap = do whenever $listener -> $conn { ... } } # When you want to close the listener, you can still use: $tap.close;
method udp(IO::Socket::Async:U: :$broadcast --> IO::Socket::Async)
Returns an initialized IO::Socket::Async client object that is configured to send UDP messages using print-to or write-to. The :broadcast adverb will set the SO_BROADCAST option which will allow the socket to send packets to a broadcast address.
method bind-udp(IO::Socket::Async:U: Str() $host, Int() $port, :$broadcast --> IO::Socket::Async)
This returns an initialized IO::Socket::Async server object that is configured to receive UDP messages sent to the specified $host and $port and is equivalent to listen for a TCP socket. The :broadcast adverb can be specified to allow the receipt of messages sent to the broadcast address.
method print(Str $str --> Promise)
Attempt to send $str on the IO::Socket::Async that will have been obtained indirectly via connect or listen, returning a Promise that will be kept with the number of bytes sent or broken if there was an error sending.
method print-to(IO::Socket::Async:D: Str() $host, Int() $port, Str() $str --> Promise)
This is the equivalent of print for UDP sockets that have been created with the udp method, it will try send a UDP message of $str to the specified $host and $port returning a Promise that will be kept when the data is successfully sent or broken if it was unable to send the data. In order to send to a broadcast address the :broadcast flag must have been specified when the socket was created.
method write(Blob $b --> Promise)
This method will attempt to send the bytes in $b on the IO::Socket::Async that will have been obtained indirectly via connect or listen, returning a Promise that will be kept with the number of bytes sent or broken if there was an error sending.
method write-to(IO::Socket::Async:D: Str() $host, Int() $port, Blob $b --> Promise)
This is the equivalent of write for UDP sockets that have been created with the udp method. It will try send a UDP message comprised of the bytes in the Blob $b to the specified $host and $port returning a Promise that will be kept when the data is successfully sent or broken if it was unable to send the data. In order to send to a broadcast address the :broadcast flag must have been specified when the socket was created.
method Supply(:$bin, :$buf = buf8.new --> Supply)
Returns a Supply which can be tapped to obtain the data read from the connected IO::Socket::Async as it arrives. By default the data will be emitted as characters, but if the :bin adverb is provided a Buf of bytes will be emitted instead, optionally in this case you can provide your own Buf with the :buf named parameter.
A UDP socket in character mode will treat each packet as a complete message and decode it. In the event of a decoding error, the Supply will quit.
On the other hand, a TCP socket treats the incoming packets as part of a stream, and feeds the incoming bytes into a streaming decoder. It then emits whatever characters the decoder considers ready. Since strings work at grapheme level in Perl 6, this means that only known complete graphemes will be emitted. For example, if the UTF-8 encoding were being used and the last byte in the packet decoded to a, this would not be emitted since the next packet may include a combining character that should form a single grapheme together with the a. Control characters (such as \n) always serve as grapheme boundaries, so any text-based protocols that use newlines or null bytes as terminators will not need special consideration. A TCP socket will also quit upon a decoding error.
method close()
Close the connected client IO::Socket::Async which will have been obtained from the listen Supply or the connect Promise.
In order to close the underlying listening socket created by listen you can close the Tap. See listen for examples.
method socket-host(--> Str)
Returns the IP address of the local end of this socket.
method peer-host(--> Str)
Returns the IP address of the remote end of this socket.
method socket-port(--> Int)
Returns the port of the local end of this socket.
method peer-port(--> Int)
Returns the port of the remote end of this socket.
method native-descriptor(--> Int)
Returns the file descriptor of this socket.
TCP Socket
class IO::Socket::INET does IO::Socket {}
IO::Socket::INET provides TCP sockets, both the server and the client side.
For UDP support, please see IO::Socket::Async.
Here is an example of a very simplistic "echo" server that listens on localhost, port 3333:
my $listen = IO::Socket::INET.new( :listen, :localhost<localhost>, :localport(3333) ); loop { my $conn = $listen.accept; try { while my $buf = $conn.recv(:bin) { $conn.write: $buf; } } $conn.close; CATCH { default { .payload.say; } } }
And a client that connects to it, and prints out what the server answers:
my $conn = IO::Socket::INET.new( :host<localhost>, :port(3333) ); $conn.print: 'Hello, Perl 6'; say $conn.recv; $conn.close;
Please bear in mind that this is a synchronous connection; an attempt by any of the nodes to write without the other reading will produce an Could not receive data from socket: Connection reset by peer error.
multi method new( :$host, :$port, :$family = PF_INET, :$encoding = 'utf-8', :$nl-in = "\r\n", --> IO::Socket::INET:D) multi method new( :$localhost, :$localport, :$family = PF_INET, :$listen, :$encoding = 'utf-8', :$nl-in = "\r\n", --> IO::Socket::INET:D)
Creates a new socket.
If :$listen is True, creates a new socket that listen on :$localhost (which can be an IP address or a domain name) on port :$localport; in other words the :$listen flag determines the server mode of the socket. Otherwise (i.e., :$listen is False), the new socket opens immediately a connection to :$host on port :$port.
:$family defaults to PF_INET constant for IPv4, and can be set to PF_INET6 constant for IPv6.
For text operations (such as #method lines and #method get), :$encoding specifies the encoding, and :$nl-in determines the character(s) that separate lines.
method get()
Reads a line from the socket and returns it as of type Str. Return Nil on end-of-file (EOF).
method lines()
Returns a lazy list of lines read from the socket.
method accept()
In listen/server mode, waits for a new incoming connection. Once a new connection is established, an IO::Socket::INET instance (or a subclass instance) for consuming the connection is returned.
Platform specific operations on file and directory paths
class IO::Spec { }
Objects of this class are not used directly but as a sub-class specific to the platform perl is running on via the $*SPEC variable which will contain an object of the appropriate type.
The sub-classes are documented separately, with the platform-specific differences documented in IO::Spec::Cygwin, IO::Spec::QNX, IO::Spec::Unix and IO::Spec::Win32.
NOTE: the IO::Spec::* classes provide low-level path operations. Unless you're creating your own high-level path manipulation routines, you don't need to use IO::Spec::*. Use IO::Path instead.
NOTE2: no special validation is done by these classes (e.g. check whether path contains a null character). It is the job of higher-level classes, like IO::Path, to do that.
Platform specific operations on file and directory paths for Cygwin
class IO::Spec::QNX is IO::Spec { }
This sub-class of IO::Spec will be available from the $*SPEC variable for a perl running on Cygwin .
NOTE: the IO::Spec::* classes provide low-level path operations. Unless you're creating your own high-level path manipulation routines, you don't need to use IO::Spec::*. Use IO::Path instead.
NOTE2: no special validation is done by these classes (e.g. check whether path contains a null character). It is the job of higher-level classes, like IO::Path, to do that.
Defined as:
method abs2rel(IO::Path:D $path, IO::Path:D $base = $*CWD --> Str:D)
Returns a string that represents $path, but relative to $base path. Both $path and $base may be relative paths. $base defaults to $*CWD. Uses IO::Spec::Win32's semantics.
Defined as:
method canonpath(Str() $path, :$parent --> Str:D)
Returns a string that is a canonical representation of $path. If :$parent is set to true, will also clean up references to parent directories. NOTE: the routine does not access the filesystem.
IO::Spec::Cygwin.canonpath(「C:\foo\\..\bar\..\ber」).say; # OUTPUT: «C:/foo/../bar/../ber» IO::Spec::Cygwin.canonpath("foo///./../bar/../ber").say; # OUTPUT: «foo/../bar/../ber» IO::Spec::Cygwin.canonpath("foo///./../bar/../ber", :parent).say; # OUTPUT: «ber»
Defined as:
method catdir (*@parts --> Str:D)
Concatenates multiple path fragments and returns the canonical representation of the resultant path as a string. The @parts are Str objects and are allowed to contain path separators.
IO::Spec::Cygwin.catdir(<foo/bar ber perl>).say; # OUTPUT: «foo/bar/ber/perl»
Defined as:
method catpath (Str:D $volume, Str:D $dir, Str:D $file --> Str:D)
Same as IO::Spec::Win32.catpath, except will also change all backslashes to slashes at the end:
IO::Spec::Cygwin.catpath('C:', '/some/dir', 'foo.txt').say; # OUTPUT: «C:/some/dir/foo.txt» IO::Spec::Cygwin.catpath('C:', '/some/dir', '').say; # OUTPUT: «C:/some/dir» IO::Spec::Cygwin.catpath('', '/some/dir', 'foo.txt').say; # OUTPUT: «/some/dir/foo.txt» IO::Spec::Cygwin.catpath('E:', '', 'foo.txt').say; # OUTPUT: «E:foo.txt»
Defined as:
method is-absolute(Str:D $path --> Bool:D)
Returns True if the $path starts with a slash ("/") or backslash ("\"), even if they have combining character on them, optionally preceded by a volume:
say IO::Spec::Cygwin.is-absolute: "/foo"; # OUTPUT: «True» say IO::Spec::Cygwin.is-absolute: "/\x[308]foo"; # OUTPUT: «True» say IO::Spec::Cygwin.is-absolute: 「C:\foo」; # OUTPUT: «True» say IO::Spec::Cygwin.is-absolute: "bar"; # OUTPUT: «False»
Defined as:
method join(|c)
Same as IO::Spec::Win32.join, except replaces backslashes with slashes in the final result.
Defined as:
method rel2abs(|c --> List:D)
Same as IO::Spec::Win32.rel2abs, except replaces backslashes with slashes in the final result.
Defined as:
method split(|c --> List:D)
Same as IO::Spec::Win32.split, except replaces backslashes with slashes in all the values of the final result.
Defined as:
method splitpath(|c --> List:D)
Same as IO::Spec::Win32.splitpath, except replaces backslashes with slashes in all the values of the final result.
Defined as:
method tmpdir(--> IO::Path:D)
Attempts to locate a system's temporary directory by checking several typical directories and environmental variables. Uses current directory if no suitable directories are found.
Platform specific operations on file and directory paths QNX
class IO::Spec::QNX is IO::Spec { }
This sub-class of IO::Spec specific to QNX will be available via $*SPEC if the perl is running on QNX.
NOTE: the IO::Spec::* classes provide low-level path operations. Unless you're creating your own high-level path manipulation routines, you don't need to use IO::Spec::*. Use IO::Path instead.
NOTE2: no special validation is done by these classes (e.g. check whether path contains a null character). It is the job of higher-level classes, like IO::Path, to do that.
Defined as:
method canonpath(Str() $path, :$parent --> Str:D)
Returns a string that is a canonical representation of $path. If :$parent is set to true, will also clean up references to parent directories. NOTE: the routine does not access the filesystem, so no symlinks are followed.
IO::Spec::QNX.canonpath("foo//../bar/../ber").say; # OUTPUT: «foo/../bar/../ber» IO::Spec::QNX.canonpath("foo///./../bar/../ber").say; # OUTPUT: «foo/../bar/../ber» IO::Spec::QNX.canonpath("foo///./../bar/../ber", :parent).say; # OUTPUT: «ber»
Platform specific operations on file and directory paths for POSIX
class IO::Spec::Unix is IO::Spec { }
On object of this type is available via the variable $*SPEC if the Perl 6 interpreter is running on a Unix-like platform.
The IO::Spec::* classes provide low-level path operations. Unless you're creating your own high-level path manipulation routines, you don't need to use IO::Spec::*. Use IO::Path instead.
Beware that no special validation is done by these classes (e.g. check whether path contains a null character). It is the job of higher-level classes, like IO::Path, to do that.
Defined as:
method abs2rel(IO::Path:D $path, IO::Path:D $base = $*CWD --> Str:D)
Returns a string that represents $path, but relative to $base path. Both $path and $base may be relative paths. $base defaults to $*CWD.
Defined as:
method basename(Str:D $path --> Str:D)
Takes a path as a string and returns a possibly-empty portion after the last slash:
IO::Spec::Unix.basename("foo/bar/") .perl.say; # OUTPUT: «""» IO::Spec::Unix.basename("foo/bar/.").perl.say; # OUTPUT: «"."» IO::Spec::Unix.basename("foo/bar") .perl.say; # OUTPUT: «"bar"»
Defined as:
method canonpath(Str() $path, :$parent --> Str:D)
Returns a string that is a canonical representation of $path. If :$parent is set to true, will also clean up references to parent directories. NOTE: the routine does not access the filesystem, so no symlinks are followed.
IO::Spec::Unix.canonpath("foo//../bar/../ber").say; # OUTPUT: «foo/../bar/../ber» IO::Spec::Unix.canonpath("foo///./../bar/../ber").say; # OUTPUT: «foo/../bar/../ber» IO::Spec::Unix.canonpath("foo///./../bar/../ber", :parent).say; # OUTPUT: «ber»
Defined as:
method catdir (*@parts --> Str:D)
Concatenates multiple path fragments and returns the canonical representation of the resultant path as a string. The @parts are Str objects and are allowed to contain path separators.
IO::Spec::Unix.catdir(<foo/bar ber perl>).say; # OUTPUT: «foo/bar/ber/perl»
Alias for catdir.
Defined as:
method catpath ($, Str:D $part1, Str:D $part2 --> Str:D)
Takes two path fragments and concatenates them, adding or removing a path separator, if necessary. The first argument is ignored (it exists to maintain consistent interface with other IO::Spec|/type/IO::Spec types for systems that have volumes).
IO::Spec::Unix.catpath($, 'some/dir', 'and/more').say; # OUTPUT: «some/dir/and/more»
Defined as:
method curdir()
Returns a string representing the current directory:
say '.' eq $*SPEC.curdir; # OUTPUT: «True»
Defined as:
method curupdir()
Returns a none Junction of strings representing the current directory and the "one directory up":
say $*SPEC.curupdir; # OUTPUT: «none(., ..)» my @dirs = <. foo .. bar>; say @dirs.grep(* eq $*SPEC.curupdir); # OUTPUT: «(foo bar)»
Neither foo nor bar are equal to the representation of the current or parent directory, that is why they are returned by grep.
Defined as:
method devnull(--> Str:D)
Returns the string "/dev/null" representing the "Null device":
$*SPEC.devnull.IO.spurt: "foo bar baz";
Defined as:
method dir-sep(--> Str:D)
Returns the string "/" representing canonical directory separator character.
IO::Spec::Unix.dir-sep.say; # OUTPUT: «/»
NOTE: Most users would want to use the higher-level routine IO::Path.extension instead of this lower-level version.
Defined as:
method extension(Str:D $path --> Str:D)
Takes a string representing a base name and returns the characters after the last dot ("."), or empty string if no dots are present. The routine makes no attempt to detect path separators and will return everything after the last dot.
$*SPEC.extension('foo.' ).perl.say; # OUTPUT: «""» $*SPEC.extension('foo.txt' ).perl.say; # OUTPUT: «"txt"» $*SPEC.extension('foo.tar.gz').perl.say; # OUTPUT: «"gz"» $*SPEC.extension('foo' ).perl.say; # OUTPUT: «""» $*SPEC.extension('bar.foo/foo').perl.say; # OUTPUT: «"foo/foo"»
Defined as:
method is-absolute(Str:D $path --> Bool:D)
Returns True if the $path starts with a slash ("/"), even if it has combining character on it:
say IO::Spec::Unix.is-absolute: "/foo"; # OUTPUT: «True» say IO::Spec::Unix.is-absolute: "/\x[308]foo"; # OUTPUT: «True» say IO::Spec::Unix.is-absolute: "bar"; # OUTPUT: «False»
Defined as:
method join ($, Str:D $dir, Str:D $file --> Str:D)
Similar to catpath, takes two path fragments and concatenates them, adding or removing a path separator, if necessary, except it will return just $file if both $dir and $file are string '/' or if $dir is the string '.'. The first argument is ignored (it exists to maintain consistent interface with other IO::Spec types for systems that have volumes).
IO::Spec::Unix.join($, 'foo', 'bar').say; # OUTPUT: «foo/bar» IO::Spec::Unix.join($, '/', '/').say; # OUTPUT: «/» IO::Spec::Unix.join($, '.', 'foo').say; # OUTPUT: «foo» say $*SPEC.join(True,".","/foo"); # OUTPUT: «/foo»
Defined as:
method path(--> Seq:D)
Splits the value of %*ENV<PATH> on colons (":"), replaces empty parts with ".", and returns a Seq with each of the resultant parts. Returns an empty Seq if %*ENV<PATH> is not set or is an empty string.
%*ENV<PATH> = 'foo:bar/ber::foo:'; IO::Spec::Unix.path.perl.say; # OUTPUT: «("foo", "bar/ber", ".", "foo", ".").Seq»
Defined as:
method rel2abs(Str() $path, $base = $*CWD --> Str:D)
Returns a string representing $path converted to absolute path, based at $base, which defaults to $*CWD. If $base is not an absolute path, it will be made absolute relative to $*CWD, unless $*CWD and $base are the same.
say $*CWD; # OUTPUT: «"/home/camelia".IO» say IO::Spec::Unix.rel2abs: 'foo'; # OUTPUT: «/home/camelia/foo» say IO::Spec::Unix.rel2abs: './'; # OUTPUT: «/home/camelia» say IO::Spec::Unix.rel2abs: 'foo/../../'; # OUTPUT: «/home/camelia/foo/../..» say IO::Spec::Unix.rel2abs: '/foo/'; # OUTPUT: «/foo» say IO::Spec::Unix.rel2abs: 'foo', 'bar'; # OUTPUT: «/home/camelia/bar/foo» say IO::Spec::Unix.rel2abs: './', '/bar'; # OUTPUT: «/bar» say IO::Spec::Unix.rel2abs: '/foo/', 'bar'; # OUTPUT: «/foo» say IO::Spec::Unix.rel2abs: 'foo/../../', 'bar'; # OUTPUT: «/home/camelia/bar/foo/../..»
Defined as:
method rootdir(--> Str:D)
Returns string '/', representing root directory.
Defined as:
method split(Cool:D $path --> List:D)
Splits the given $path into "volume", "dirname", and "basename" and returns the result as a List of three Pairs, in that order. The "volume" is always an empty string and exists for consistency with other IO::Spec classes.
IO::Spec::Unix.split('C:/foo/bar.txt').perl.say; # OUTPUT: «(:volume(""), :dirname("C:/foo"), :basename("bar.txt"))» IO::Spec::Unix.split('/foo/').perl.say; # OUTPUT: «(:volume(""), :dirname("/"), :basename("foo"))» IO::Spec::Unix.split('///').perl.say; # OUTPUT: «(:volume(""), :dirname("/"), :basename("/"))» IO::Spec::Unix.split('./').perl.say; # OUTPUT: «(:volume(""), :dirname("."), :basename("."))» IO::Spec::Unix.split('.').perl.say; # OUTPUT: «(:volume(""), :dirname("."), :basename("."))» IO::Spec::Unix.split('').perl.say; # OUTPUT: «(:volume(""), :dirname(""), :basename(""))»
Defined as:
method splitdir(Cool:D $path --> List:D)
Splits the given $path on slashes.
IO::Spec::Unix.splitdir('C:\foo/bar.txt').perl.say; # OUTPUT: «("C:\\foo", "bar.txt")» IO::Spec::Unix.splitdir('/foo/').perl.say; # OUTPUT: «("", "foo", "")» IO::Spec::Unix.splitdir('///').perl.say; # OUTPUT: «("", "", "", "")» IO::Spec::Unix.splitdir('./').perl.say; # OUTPUT: «(".", "")» IO::Spec::Unix.splitdir('.').perl.say; # OUTPUT: «(".",)» IO::Spec::Unix.splitdir('').perl.say; # OUTPUT: «("",)»
Defined as:
method splitpath(Cool:D $path, :$nofile --> List:D)
Splits the given $path into a list of 3 strings: volume, dirname, and file. The volume is always an empty string, returned for API compatibility with other IO::Spec types. If :$nofile named argument is set to True, the content of the file string is undefined and should be ignored; this is a means to get a performance boost, as implementations may use faster code path when file is not needed.
IO::Spec::Unix.splitpath('C:\foo/bar.txt').perl.say; # OUTPUT: «("", "C:\\foo/", "bar.txt")» IO::Spec::Unix.splitpath('C:\foo/bar.txt', :nofile).perl.say; # OUTPUT: «("", "C:\\foo/bar.txt", "")» IO::Spec::Unix.splitpath('/foo/').perl.say; # OUTPUT: «("", "/foo/", "")» IO::Spec::Unix.splitpath('/foo/', :nofile).perl.say; # OUTPUT: «("", "/foo/", "")» IO::Spec::Unix.splitpath('///').perl.say; # OUTPUT: «("", "///", "")» IO::Spec::Unix.splitpath('./').perl.say; # OUTPUT: «("", "./", "")» IO::Spec::Unix.splitpath('.').perl.say; # OUTPUT: «("", "", ".")» IO::Spec::Unix.splitpath('').perl.say; # OUTPUT: «("", "", "")»
Defined as:
method tmpdir(--> IO::Path:D)
Attempts to locate a system's temporary directory by checking several typical directories and environmental variables. Uses current directory if no suitable directories are found.
Defined as:
method updir()
Returns a string representing the directory one up from current:
say '..' eq $*SPEC.updir; # OUTPUT: «True»
Platform specific operations on file and directory paths for Windows
class IO::Spec::Win32 is IO::Spec { }
Objects of this class are used not directly but as a sub-class specific to the platform Perl 6 is running on via the $*SPEC variable, which will contain an object of the appropriate type.
NOTE: the IO::Spec::* classes provide low-level path operations. Unless you're creating your own high-level path manipulation routines, you don't need to use IO::Spec::*. Use IO::Path instead.
NOTE2: no special validation is done by these classes (e.g. check whether path contains a null character). It is the job of higher-level classes, like IO::Path, to do that.
Defined as:
method basename(Str:D $path --> Str:D)
Takes a path as a string and returns a possibly-empty portion after the last slash or backslash:
IO::Spec::Win32.basename("foo/bar/") .perl.say; # OUTPUT: «""» IO::Spec::Win32.basename("foo/bar\\").perl.say; # OUTPUT: «""» IO::Spec::Win32.basename("foo/bar/.").perl.say; # OUTPUT: «"."» IO::Spec::Win32.basename("foo/bar") .perl.say; # OUTPUT: «"bar"»
Defined as:
method canonpath(Str() $path, :$parent --> Str:D)
Returns a string that is a canonical representation of $path. If :$parent is set to true, will also clean up references to parent directories. NOTE: the routine does not access the filesystem.
IO::Spec::Win32.canonpath("C:/foo//../bar/../ber").say; # OUTPUT: «C:\foo\..\bar\..\ber» IO::Spec::Win32.canonpath("C:/foo///./../bar/../ber").say; # OUTPUT: «C:\foo\..\bar\..\ber» IO::Spec::Win32.canonpath("C:/foo///./../bar/../ber", :parent).say; # OUTPUT: «C:\ber»
Defined as:
method catdir (*@parts --> Str:D)
Concatenates multiple path fragments and returns the canonical representation of the resultant path as a string. The @parts are Str objects and are allowed to contain path separators.
IO::Spec::Win32.catdir(<foo/bar ber perl>).say; # OUTPUT: «foo\bar\ber\perl»
Alias for catdir.
Defined as:
method catpath (Str:D $volume, Str:D $dir, Str:D $file --> Str:D)
Concatenates a path from given volume, a chain of directories, and file. An empty string can be given for any of the three arguments. No attempt to make the path canonical is made. Use canonpath for that purpose.
IO::Spec::Win32.catpath('C:', '/some/dir', 'foo.txt').say; # OUTPUT: «C:/some/dir\foo.txt» IO::Spec::Win32.catpath('C:', '/some/dir', '').say; # OUTPUT: «C:/some/dir» IO::Spec::Win32.catpath('', '/some/dir', 'foo.txt').say; # OUTPUT: «/some/dir\foo.txt» IO::Spec::Win32.catpath('E:', '', 'foo.txt').say; # OUTPUT: «E:foo.txt»
Defined as:
method devnull(--> Str:D)
Returns the string "nul" representing the "Null device":
$*SPEC.devnull.IO.spurt: "foo bar baz";
Defined as:
method dir-sep(--> Str:D)
Returns the string 「\」 representing canonical directory separator character.
IO::Spec::Win32.dir-sep.say; # OUTPUT: «\»
Defined as:
method is-absolute(Str:D $path --> Bool:D)
Returns True if the $path starts with a slash ("/") or backslash ("\"), even if they have combining character on them, optionally preceded by a volume:
say IO::Spec::Win32.is-absolute: "/foo"; # OUTPUT: «True» say IO::Spec::Win32.is-absolute: "/\x[308]foo"; # OUTPUT: «True» say IO::Spec::Win32.is-absolute: 「C:\foo」; # OUTPUT: «True» say IO::Spec::Win32.is-absolute: "bar"; # OUTPUT: «False»
Defined as:
method join (Str:D $volume, Str:D $dir, Str:D $file --> Str:D)
Similar to catpath, takes two path fragments and concatenates them, adding or removing a path separator, if necessary, except it will return just $file if both $dir and $file are string '/' or if $dir is the string '.'. The first argument is ignored (it exists to maintain consistent interface with other IO::Spec types for systems that have volumes).
IO::Spec::Win32.join('C:', '/some/dir', 'foo.txt').say; # OUTPUT: «C:/some/dir\and/more» IO::Spec::Win32.join('C:', '.', 'foo.txt').say; # OUTPUT: «C:foo.txt» IO::Spec::Win32.join('C:', 「\」, '/').say; # OUTPUT: «C:\» IO::Spec::Win32.join('//server/share', 「\」, '/').say; # OUTPUT: «//server/share» IO::Spec::Win32.join('E:', '', 'foo.txt').say; # OUTPUT: «E:foo.txt»
Defined as:
method path(--> Seq:D)
Splits the value of %*ENV<PATH> (or %*ENV<Path> if the former is not set) on semicolons (";") and returns a Seq with each of the resultant parts, always adding element "." to the head. Removes all double quotes (") it finds.
%*ENV<PATH> = 'foo;"bar"/"ber"'; IO::Spec::Win32.path.perl.say; # OUTPUT: «(".", "foo", "bar/ber").Seq»
Defined as:
method rel2abs(Str() $path, $base = $*CWD --> Str:D)
Returns a string representing $path converted to absolute path, based at $base, which defaults to $*CWD. If $base is not an absolute path, it will be made absolute relative to $*CWD, unless $*CWD and $base are the same.
say $*CWD; # OUTPUT: «"C:\Users\camelia".IO» say IO::Spec::Win32.rel2abs: 'foo'; # OUTPUT: «C:\Users\camelia\foo» say IO::Spec::Win32.rel2abs: './'; # OUTPUT: «C:\Users\camelia» say IO::Spec::Win32.rel2abs: 'foo/../../'; # OUTPUT: «C:\Users\camelia\foo\..\..» say IO::Spec::Win32.rel2abs: '/foo/'; # OUTPUT: «C:\foo» say IO::Spec::Win32.rel2abs: 'foo', 'bar'; # OUTPUT: «C:\Users\camelia\bar\foo» say IO::Spec::Win32.rel2abs: './', '/bar'; # OUTPUT: «\bar» say IO::Spec::Win32.rel2abs: '/foo/', 'bar'; # OUTPUT: «C:\foo» say IO::Spec::Win32.rel2abs: 'foo/../../', 'bar'; # OUTPUT: «C:\Users\camelia\bar\foo\..\..»
Defined as:
method rootdir(--> Str:D)
Returns string 「\」, representing root directory.
Defined as:
method split(Cool:D $path --> List:D)
Splits the given $path into "volume", "dirname", and "basename" and returns the result as a List of three Pairs, in that order. The "volume" is always an empty string and exists for consistency with other IO::Spec classes.
IO::Spec::Win32.split('C:/foo/bar.txt').perl.say; # OUTPUT: «(:volume("C:"), :dirname("/foo"), :basename("bar.txt"))» IO::Spec::Win32.split('/foo/').perl.say; # OUTPUT: «(:volume(""), :dirname("/"), :basename("foo"))» IO::Spec::Win32.split('///').perl.say; # OUTPUT: «(:volume(""), :dirname("/"), :basename("\\"))» IO::Spec::Win32.split('./').perl.say; # OUTPUT: «(:volume(""), :dirname("."), :basename("."))» IO::Spec::Win32.split('.').perl.say; # OUTPUT: «(:volume(""), :dirname("."), :basename("."))» IO::Spec::Win32.split('').perl.say; # OUTPUT: «(:volume(""), :dirname(""), :basename(""))»
Defined as:
method splitdir(Cool:D $path --> List:D)
Splits the given $path on slashes and backslashes.
IO::Spec::Win32.splitdir('C:\foo/bar.txt').perl.say; # OUTPUT: «("C:", "foo", "bar.txt")» IO::Spec::Win32.splitdir('/foo/').perl.say; # OUTPUT: «("", "foo", "")» IO::Spec::Win32.splitdir('///').perl.say; # OUTPUT: «("", "", "", "")» IO::Spec::Win32.splitdir('./').perl.say; # OUTPUT: «(".", "")» IO::Spec::Win32.splitdir('.').perl.say; # OUTPUT: «(".",)» IO::Spec::Win32.splitdir('').perl.say; # OUTPUT: «("",)»
Defined as:
method splitpath(Cool:D $path, :$nofile --> List:D)
Splits the given $path into a list of 3 strings: volume, dirname, and file. The volume is always an empty string, returned for API compatibility with other IO::Spec types. If :$nofile named argument is set to True, the content of the file string is undefined and should be ignored; this is a means to get a performance boost, as implementations may use faster code path when file is not needed.
IO::Spec::Win32.splitpath('C:\foo/bar.txt').perl.say; # OUTPUT: «("C:", "\\foo/", "bar.txt")» IO::Spec::Win32.splitpath('C:\foo/bar.txt', :nofile).perl.say; # OUTPUT: «("C:", "\\foo/bar.txt", "")» IO::Spec::Win32.splitpath('/foo/').perl.say; # OUTPUT: «("", "/foo/", "")» IO::Spec::Win32.splitpath('/foo/', :nofile).perl.say; # OUTPUT: «("", "/foo/", "")» IO::Spec::Win32.splitpath('///').perl.say; # OUTPUT: «("", "///", "")» IO::Spec::Win32.splitpath('./').perl.say; # OUTPUT: «("", "./", "")» IO::Spec::Win32.splitpath('.').perl.say; # OUTPUT: «("", "", ".")» IO::Spec::Win32.splitpath('').perl.say; # OUTPUT: «("", "", "")»
Defined as:
method tmpdir(--> IO::Path:D)
Attempts to locate a system's temporary directory by checking several typical directories and environmental variables. Uses current directory if no suitable directories are found.
Path to special I/O device
class IO::Special does IO { }
Used as a $.path attribute in filehandles for special standard input $*IN and output $*OUT and $*ERR. Provides a bridged interface of IO::Handle, mostly file tests and stringification.
method new(:$!what!)
Takes a single required attribute what. It is unlikely that you will ever need to construct one of these objects yourself.
say $*IN.path.what; # OUTPUT: «<STDIN>» say $*OUT.path.what; # OUTPUT: «<STDOUT>» say $*ERR.path.what; # OUTPUT: «<STDERR>»
Returns one of the strings '<STDIN>', '<STDOUT>', or '<STDERR>', specifying the type of the special IO device.
method WHICH(IO::Special:D: --> Str)
This returns a string that identifies the object. The string is composed by the type of the instance (IO::Special) and the what attribute:
$*IN.path.what; # OUTPUT: «<STDIN>» $*IN.path.WHICH; # OUTPUT: «IO::Special<STDIN>»
method Str(IO::Special:D:)
This returns '<STDIN>', '<STDOUT>', or '<STDERR>' as appropriate.
method IO(IO::Special:D: --> IO::Special)
Returns the invocant.
say $*IN.path.IO.what; # OUTPUT: «<STDIN>» say $*IN.path.what; # OUTPUT: «<STDIN>»
method e(IO::Special:D: --> True)
The 'exists' file test operator, always returns True.
method d(IO::Special:D: --> False)
The 'directory' file test operator, always returns False.
method f(IO::Special:D: --> False)
The 'file' file test operator, always returns False.
method s(IO::Special:D: --> 0)
The 'size' file test operator, always returns 0.
method l(IO::Special:D: --> False)
The 'symbolic links' file test operator, always returns False.
method r(IO::Special:D: --> Bool)
The 'read access' file test operator, returns True if and only if this instance represents the standard input handle(<STDIN>).
method w(IO::Special:D: --> Bool)
The 'write access' file test operator, returns True only if this instance represents either the standard output (<STOUT>) or the standard error (<STDERR>) handle.
method x(IO::Special:D: --> False)
The 'execute access' file test operator, always returns False.
method modified(IO::Special:D: --> Instant)
The last modified time for the filehandle. It always returns an Instant type object.
method accessed(IO::Special:D: --> Instant)
The last accessed time for the filehandle. It always returns an Instant type object.
method changed(IO::Special:D: --> Instant)
The last changed time for the filehandle. It always returns an Instant type object.
method mode(IO::Special:D: --> Nil)
The mode for the filehandle, it always returns Nil
Specific moment in time
class Instant is Cool does Real { }
An Instant is a particular moment in time measured in atomic seconds, with fractions. It is not tied to or aware of any epoch.
An Instant can be used to create a DateTime object set to that Instant. The pseudo-constant now returns the current time as an Instant.
Basic math is defined for Instants (as well as Durations). Adding an Instant to a Duration returns another Instant. Subtracting two Instants will yield a Duration. Adding two Instants is explicitly disallowed. All other operations with Instants are undefined.
The methods that involve knowledge of leap seconds always assume that there will be no further leaps after the last leap second that the implementation knows about, which may not be the last leap second that has actually been scheduled. This means you can get different results, depending on the compiler version you're using. For example, the December 31, 2016 leap second was announced in July and shipped with Rakudo 2016.07, so 2016.06 and earlier releases won't know about it:
$ perl6-2016.06 -e 'say Instant.from-posix: 1485726595' Instant:1485726631 $ perl6-2016.07 -e 'say Instant.from-posix: 1485726595' Instant:1485726632
Since a Rakudo compiler always returns 0 for future leap seconds it doesn't know about, you can patch your old code when new leap seconds are announced, so it will give correct results, regardless of what version of the compiler it runs on:
$ perl6-2016.06 -e 'say ($*VM.version before v2016.07 ?? 1 !! 0) + Instant.from-posix: 1485726595' Instant:1485726632 $ perl6-2016.07 -e 'say ($*VM.version before v2016.07 ?? 1 !! 0) + Instant.from-posix: 1485726595' Instant:1485726632
method from-posix($posix, Bool $prefer-leap-second = False)
Converts the POSIX timestamp $posix to an Instant. If $prefer-leap-second is True, the return value will be the first of the two possible seconds in the case of a leap second.
say DateTime.new(Instant.from-posix(915148800, True)); # OUTPUT: «1998-12-31T23:59:60Z» say DateTime.new(Instant.from-posix(915148800)); # OUTPUT: «1999-01-01T00:00:00Z»
method to-posix()
Converts the invocant to a POSIX timestamp and returns a two element list containing the POSIX timestamp and a Bool. It is the inverse of #method from-posix, except that the second return value is True if *and only if* this Instant is in a leap second.
say DateTime.new("1999-01-01T00:00:00Z").Instant.to-posix; # OUTPUT: «(915148800 False)» say DateTime.new('1998-12-31T23:59:60Z').Instant.to-posix; # OUTPUT: «(915148800 True)»
Defined as:
method Date(Instant:D: --> Date:D)
Coerces the invocant to Date.
my $i = "/etc/passwd".IO.modified; say $i; # OUTPUT: «Instant:1451489025.878018» say $i.Date; # OUTPUT: «2015-12-30»
Defined as:
method DateTime(Instant:D: --> DateTime:D)
Coerces the invocant to DateTime.
say now.DateTime; # OUTPUT: «2017-05-09T14:02:58.147165Z»
Integer (arbitrary-precision)
class Int is Cool does Real { }
Int objects store integral numbers of arbitrary size. Ints are immutable.
There are two main syntax forms for Int literals
123; # Int in decimal notation :16<BEEF>; # Int in radix notations
For your convenience common radix forms come with a prefix shortcut.
say so :2<11111111> == 0b11111111 == :8<377> == 0o377 == 255 == 0d255 == :16<ff> == 0xff; # OUTPUT: «True»
All forms allow underscores between any two digits which can serve as visual separators, but don't carry any meaning:
5_00000; # five Lakhs 500_000; # five hundred thousand 0xBEEF_CAFE; # a strange place :2<1010_1010>; # 0d170
Radix notation also supports round and angle brackets which allow you to parse a string for a given base, and putting together digits into a whole number respectively:
:16("9F"); # 159 :100[99, 2, 3]; # 990203
These notations allow you to use variables, too:
my $two = "2"; my $ninety-nine = "99"; :16($ninety-nine); # 153 :100[99, $two, 3]; # 990203
Defined as:
method Capture()
Throws X::Cannot::Capture.
Defined as:
multi sub chr(Int:D --> Str:D) multi method chr(Int:D: --> Str:D)
Returns a one-character string, by interpreting the integer as a Unicode codepoint number and converting it to the corresponding character.
Example:
65.chr; # returns "A" 196.chr; # returns "Ä"
Defined as:
multi sub expmod( $x, $y, $mod --> Int:D) multi sub expmod(Int:D $x, Int $y, Int $mod --> Int:D) multi method expmod(Int:D: Int $y, Int $mod --> Int:D)
Returns the given Int raised to the $y power within modulus $mod, that is gives the result of ($x ** $y) mod $mod. The subroutine form can accept non-Int arguments, which will be coerced to Int.
say expmod(4, 2, 5); # OUTPUT: «1» say 7.expmod(2, 5); # OUTPUT: «4»
$y argument can also be negative, in which case, the result is equivalent to ($x ** $y) mod $mod.
say 7.expmod(-2, 5); # OUTPUT: «4»
Defined as:
method polymod(Int:D: +@mods)
Returns a sequence of mod results corresponding to the divisors in @mods in the same order as they appear there. For the best effect, the divisors should be given from the smallest "unit" to the largest (e.g. 60 seconds per minute, 60 minutes per hour) and the results are returned in the same way: from smallest to the largest (5 seconds, 4 minutes). The last non-zero value will be the last remainder.
say 120.polymod(10); # OUTPUT: «(0 12)» say 120.polymod(10,10); # OUTPUT: «(0 2 1)»
In the first case, 120 is divided by 10 giving as a remainder 12, which is the last element. In the second, 120 is divided by 10, giving 12, whose remainder once divided by 10 is 2; the result of the integer division of 12 div 10 is the last remainder. The number of remainders will be always one more item than the number of given divisors. If the divisors are given as a lazy list, runs until the remainder is 0 or the list of divisors is exhausted. All divisors must be Ints, unless the method is called on a non-Int number.
my $seconds = 1 * 60*60*24 # days + 3 * 60*60 # hours + 4 * 60 # minutes + 5; # seconds say $seconds.polymod(60, 60); # OUTPUT: «(5 4 27)» say $seconds.polymod(60, 60, 24); # OUTPUT: «(5 4 3 1)» say 120.polymod: 1, 10, 10², 10³, 10⁴; # OUTPUT: «(0 0 12 0 0 0)» say 120.polymod: lazy 1, 10, 10², 10³, 10⁴; # OUTPUT: «(0 0 12)» say 120.polymod: 1, 10, 10² … ∞; # OUTPUT: «(0 0 12)» say ⅔.polymod(⅓); # OUTPUT: «(0 2)» say 5.Rat.polymod(.3, .2); # OUTPUT: «(0.2 0 80)» my @digits-in-base37 = 9123607.polymod(37 xx *); # Base conversion say @digits-in-base37.reverse # OUTPUT: «[4 32 4 15 36]»
To illustrate how the Int, non-lazy version of polymod works, consider this code that implements it:
my $seconds = 2 * 60*60*24 # days + 3 * 60*60 # hours + 4 * 60 # minutes + 5; # seconds my @pieces; for 60, 60, 24 -> $divisor { @pieces.push: $seconds mod $divisor; $seconds div= $divisor } @pieces.push: $seconds; say @pieces; # OUTPUT: «[5 4 3 2]»
For a more detailed discussion, see this blog post
Defined as:
multi sub is-prime (Int:D $number --> Bool:D) multi method is-prime (Int:D: --> Bool:D)
Returns True if this Int is known to be a prime, or is likely to be a prime based on a probabilistic Miller-Rabin test.
Returns False if this Int is known not to be a prime.
say 2.is-prime; # OUTPUT: «True» say is-prime(9); # OUTPUT: «False»
Defined as:
multi method lsb(Int:D:) multi sub lsb(Int:D)
Short for "Least Significant Bit". Returns Nil if the number is 0. Otherwise returns the zero-based index from the right of the least significant (rightmost) 1 in the binary representation of the number.
say 0b01011.lsb; # OUTPUT: «0» say 0b01010.lsb; # OUTPUT: «1» say 0b10100.lsb; # OUTPUT: «2» say 0b01000.lsb; # OUTPUT: «3» say 0b10000.lsb; # OUTPUT: «4»
Defined as:
multi method msb(Int:D:) multi sub msb(Int:D)
Short for "Most Significant Bit". Returns Nil if the number is 0. Otherwise returns the zero-based index from the right of the most significant (leftmost) 1 in the binary representation of the number.
say 0b00001.msb; # OUTPUT: «0» say 0b00011.msb; # OUTPUT: «1» say 0b00101.msb; # OUTPUT: «2» say 0b01010.msb; # OUTPUT: «3» say 0b10011.msb; # OUTPUT: «4»
Defined as:
multi sub unival(Int:D --> Numeric) multi method unival(Int:D: --> Numeric)
Returns the number represented by the Unicode codepoint with the given integer number, or NaN if it does not represent a number.
say ord("¾").unival; # OUTPUT: «0.75» say 190.unival; # OUTPUT: «0.75» say unival(65); # OUTPUT: «NaN»
Returns a Range object that represents the range of values supported.
multi sub infix:<div>(Int:D, Int:D --> Int:D)
Does an integer division, rounded down.
Dual value integer and string
class IntStr is Int is Str { }
The dual value types (often referred to as allomorphs) allow for the representation of a value as both a string and a numeric type. Typically they will be created for you when the context is "stringy" but they can be determined to be numbers, such as in some quoting constructs:
my $f = <42>; say $f.^name; # OUTPUT: «IntStr»
As a subclass of both Int and Str, an IntStr will be accepted where either is expected. However, IntStr does not share object identity with Int- or Str-only variants:
my $int-str = <42>; my Int $int = $int-str; # OK! my Str $str = $int-str; # OK! say 42 ∈ <42 55 1>; # False; ∈ operator cares about object identity
method new(Int $i, Str $s)
The constructor requires both the Int and the Str value, when constructing one directly the values can be whatever is required:
my $f = IntStr.new(42, "forty two"); say +$f; # OUTPUT: «42» say ~$f; # OUTPUT: «"forty two"»
Defined as:
multi method Bool(IntStr:D: --> Bool:D)
This method may be provided by the parent classes and not implemented in IntStr directly.
Returns False if the invocant is numerically 0, otherwise returns True. String portion is not considered.
method Int
Returns the integer value of the IntStr.
Defined as:
multi method Numeric(IntStr:D: --> Int:D) multi method Numeric(IntStr:U: --> Int:D)
The :D variant returns the numeric portion of the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value 0.
Defined as:
multi method Real(IntStr:D: --> Int:D) multi method Real(IntStr:U: --> Int:D)
The :D variant returns the numeric portion of the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value 0.
Returns the string value of the IntStr.
Defined as:
multi method ACCEPTS(IntStr:D: Any:D $value)
If $value is Numeric (including another allomorph), checks if invocant's Numeric part ACCEPTS the $value. If $value is Str, checks if invocant's Str part ACCEPTS the $value. If value is anything else, checks if both Numeric and Str parts ACCEPTS the $value.
say <5> ~~ "5.0"; # OUTPUT: «False» say <5> ~~ 5.0 ; # OUTPUT: «True» say <5> ~~ <5.0>; # OUTPUT: «True»
multi sub infix:<cmp>(IntStr:D $a, IntStr:D $b)
Compare two IntStr objects. The comparison is done on the Int value first and then on the Str value. If you want to compare in a different order then you would coerce to an Int or Str value first:
my $f = IntStr.new(42, "smaller"); my $g = IntStr.new(43, "larger"); say $f cmp $g; # OUTPUT: «Less» say $f.Str cmp $g.Str; # OUTPUT: «More»
Interface for container objects that can be iterated over
role Iterable { }
Iterable serves as an API for objects that can be iterated with for and related iteration constructs, like assignment to a Positional variable.
Iterable objects nested in other Iterable objects (but not within scalar containers) flatten in certain contexts, for example when passed to a slurpy parameter (*@a), or on explicit calls to flat.
Its most important aspect is a method stub for iterator.
class DNA does Iterable { has $.chain; method new ($chain where { $chain ~~ /^^ <[ACGT]>+ $$ / } ) { self.bless( :$chain ); } method iterator(DNA:D:) { $!chain.comb.rotor(3).iterator; } } my $a := DNA.new('GAATCC'); .say for $a; # OUTPUT: «(G A A)(T C C)»
This example mixes in the Iterable role to offer a new way of iterating over what is essentially a string (constrained by where to just the four DNA letters). In the last statement, for actually hooks to the iterator role printing the letters in groups of 3.
Defined as:
method iterator(--> Iterator:D)
Method stub that ensures all classes doing the Iterable role have a method iterator.
It is supposed to return an Iterator.
say (1..10).iterator;
Defined as:
method flat(--> Iterable)
Returns another Iterable that flattens out all iterables that the first one returns.
For example
say (<a b>, 'c').elems; # OUTPUT: «2» say (<a b>, 'c').flat.elems; # OUTPUT: «3»
because <a b> is a List and thus iterable, so (<a b>, 'c').flat returns ('a', 'b', 'c'), which has three elems.
Note that the flattening is recursive, so ((("a", "b"), "c"), "d").flat returns ("a", "b", "c", "d"), but it does not flatten itemized sublists:
say ($('a', 'b'), 'c').perl; # OUTPUT: «($("a", "b"), "c")»
Defined as:
method lazy(--> Iterable)
Returns a lazy iterable wrapping the invocant.
say (1 ... 1000).is-lazy; # OUTPUT: «False» say (1 ... 1000).lazy.is-lazy; # OUTPUT: «True»
Defined as:
method hyper(Int(Cool) :$batch = 64, Int(Cool) :$degree = 4)
Returns another Iterable that is potentially iterated in parallel, with a given batch size and degree of parallelism.
The order of elements is preserved.
say ([1..100].hyper.map({ $_ +1 }).list);
Use hyper in situations where it is OK to do the processing of items in parallel, and the output order should be kept relative to the input order. See race for situations where items are processed in parallel and the output order does not matter.
The degree option (short for "degree of parallelism") configures how many parallel workers should be started. To start 4 workers (e.g. to use at most 4 cores), pass :4degree to the hyper or race method. Note that in some cases, choosing a degree higher than the available CPU cores can make sense, for example I/O bound work or latency-heavy tasks like web crawling. For CPU-bound work, however, it makes no sense to pick a number higher than the CPU core count.
The batch size option configures the number of items sent to a given parallel worker at once. It allows for making a throughput/latency trade-off. If, for example, an operation is long-running per item, and you need the first results as soon as possible, set it to 1. That means every parallel worker gets 1 item to process at a time, and reports the result as soon as possible. In consequence, the overhead for inter-thread communication is maximized. In the other extreme, if you have 1000 items to process and 10 workers, and you give every worker a batch of 100 items, you will incur minimal overhead for dispatching the items, but you will only get the first results when 100 items are processed by the fastest worker (or, for hyper, when the worker getting the first batch returns.) Also, if not all items take the same amount of time to process, you might run into the situation where some workers are already done and sit around without being able to help with the remaining work. In situations where not all items take the same time to process, and you don't want too much inter-thread communication overhead, picking a number somewhere in the middle makes sense. Your aim might be to keep all workers about evenly busy to make best use of the resources available.
You can also check out this blog post on the semantics of hyper and race
Defined as:
method race(Int(Cool) :$batch = 64, Int(Cool) :$degree = 4 --> Iterable)
Returns another Iterable that is potentially iterated in parallel, with a given batch size and degree of parallelism (number of parallel workers).
Unlike hyper, race does not preserve the order of elements.
say ([1..100].race.map({ $_ +1 }).list);
Use race in situations where it is OK to do the processing of items in parallel, and the output order does not matter. See hyper for situations where you want items processed in parallel and the output order should be kept relative to the input order.
Blog post on the semantics of hyper and race
See hyper for an explanation of :$batch and :$degree.
Generic API for producing a sequence of values
constant IterationEnd role Iterator { }
A Iterator is an object that can generate or provide elements of a sequence. Users usually don't have to care about iterators, their usage is hidden behind iteration APIs such as for @list { }, map, grep, head, tail, skip and list indexing with .[$idx].
The main API is the pull-one method, which either returns the next value, or the sentinel value IterationEnd if no more elements are available. Each class implementing Iterator must provide a pull-one method. All other non-optional Iterator API methods are implemented in terms of pull-one, but can also be overridden by consuming classes for performance or other reasons. There are also optional Iterator API methods that will only be called if they are implemented by the consuming class: these are not implemented by the Iterator role.
Iterators only allow one iteration over the entire sequence. It's forbidden to make attempts to fetch more data, once IterationEnd has been generated, and behavior for doing so is undefined. For example, the following Seq will not cause the die to be called under normal use, because pull-one will never be called after it returns IterationEnd:
class SkippingArray is Array { # skip all undefined values while iterating method iterator { class :: does Iterator { has $.index is rw = 0; has $.array is required; method pull-one { $.index++ while !$.array.AT-POS($.index).defined && $.array.elems > $.index; $.array.elems > $.index ?? $.array.AT-POS($.index++) !! IterationEnd } }.new(array => self) } } my @a := SkippingArray.new; @a.append: 1, Any, 3, Int, 5, Mu, 7; for @a -> $a, $b { say [$a, $b]; } # OUTPUT: «[1 3][5 7]»
The only valid use of the sentinel value IterationEnd in a program is identity comparison (using =:=) with the result of a method in the iterator API. Any other behavior is undefined and implementation dependent.
Please bear in mind that IterationEnd is a constant, so if you are going to compare it against the value of a variable, this variable will have to be bound, not assigned. Comparing directly to the output of pull-one will work.
my $it = (1,2).iterator; $it.pull-one for ^2; say $it.pull-one =:= IterationEnd; # OUTPUT: «True»
However, if we use a variable we and we assign it, the result will be incorrect:
my $it = (1,2).iterator; $it.pull-one for ^2; my $is-it-the-end = $it.pull-one; say $is-it-the-end =:= IterationEnd; # OUTPUT: «False»
So we'll have to bind the variable to make it work:
my $is-it-the-end := $it.pull-one; say $is-it-the-end =:= IterationEnd; # OUTPUT: «True»
Defined as:
method pull-one(Iterator:D: --> Mu)
This method stub ensures that classes implementing the Iterator role provide a method named pull-one.
The pull-one method is supposed to produce and return the next value if possible, or return the sentinel value IterationEnd if no more values could be produced.
my $i = (1 .. 3).iterator; say $i.pull-one; # OUTPUT: «1» say $i.pull-one; # OUTPUT: «2» say $i.pull-one; # OUTPUT: «3» say $i.pull-one.perl; # OUTPUT: «IterationEnd»
As a more illustrative example of its use, here is a count down iterator along with a simplistic subroutine re-implementation of the for loop.
# works the same as (10 ... 1, 'lift off') class CountDown does Iterator { has Int:D $!current = 10; method pull-one ( --> Mu ) { my $result = $!current--; if $result == 0 { return 'lift off' } if $result == -1 { return IterationEnd } # calling .pull-one again after it returns IterationEnd is undefined if $result <= -2 { # so for fun we will give them nonsense data return (1..10).pick; } return $result; } } sub for( Iterable:D $sequence, &do --> Nil ) { my Iterator:D $iterator = $sequence.iterator; loop { # must bind the result so that =:= works my Mu $pulled := $iterator.pull-one; # always check the result and make sure that .pull-one # is not called again after it returns IterationEnd if $pulled =:= IterationEnd { last } do( $pulled ); } } for( Seq.new(CountDown.new), &say ); # OUTPUT: «10987654321lift off»
It would be more idiomatic to use while or until, and a sigilless variable.
until IterationEnd =:= (my \pulled = $iterator.pull-one) { do( pulled ); }
Defined as:
method push-exactly(Iterator:D: $target, int $count --> Mu)
Should produce $count elements, and for each of them, call $target.push($value).
If fewer than $count elements are available from the iterator, it should return the sentinel value IterationEnd. Otherwise it should return $count.
my @array; say (1 .. ∞).iterator.push-exactly(@array, 3); # OUTPUT: «3» say @array; # OUTPUT: «[1 2 3]»
The Iterator role implements this method in terms of pull-one. In general, this is a method that is not intended to be called directly from the end user who, instead, should implement it in classes that mix the iterator role. For instance, this class implements that role:
class DNA does Iterable does Iterator { has $.chain; has Int $!index = 0; method new ($chain where { $chain ~~ /^^ <[ACGT]>+ $$ / and $chain.chars %% 3 } ) { self.bless( :$chain ); } method iterator( ){ self } method pull-one( --> Mu){ if $!index < $.chain.chars { my $codon = $.chain.comb.rotor(3)[$!index div 3]; $!index += 3; return $codon; } else { return IterationEnd; } } method push-exactly(Iterator:D: $target, int $count --> Mu) { return IterationEnd if $.chain.elems / 3 < $count; for ^($count) { $target.push: $.chain.comb.rotor(3)[ $_ ]; } } }; my $b := DNA.new("AAGCCT"); for $b -> $a, $b, $c { say "Never mind" }; # Does not enter the loop my $þor := DNA.new("CAGCGGAAGCCT"); for $þor -> $first, $second { say "Coupled codons: $first, $second"; # OUTPUT: «Coupled codons: C A G, C G GCoupled codons: A A G, C C T» }
This code, which groups DNA chains in triplets (usually called codons) returns those codons when requested in a loop; if too many are requested, like in the first case for $b -> $a, $b, $c, it simply does not enter the loop since push-exactly will return IterationEnd since it is not able to serve the request for exactly 3 codons. In the second case, however, it requests exactly two codons in each iteration of the loop; push-exactly is being called with the number of loop variables as the $count variable.
Defined as:
method push-at-least(Iterator:D: $target, int $count --> Mu)
Should produce at least $count elements, and for each of them, call $target.push($value).
If fewer than $count elements are available from the iterator, it should return the sentinel value IterationEnd. Otherwise it should return $count.
Iterators with side effects should produce exactly $count elements; iterators without side effects (such as Range iterators) can produce more elements to achieve better performance.
my @array; say (1 .. ∞).iterator.push-at-least(@array, 10); # OUTPUT: «10» say @array; # OUTPUT: «[1 2 3 4 5 6 7 8 9 10]»
The Iterator role implements this method in terms of pull-one. In general, it is also not intended to be called directly as in the example above. It can be implemented, if unhappy with this default implementation, by those using this role. See the documentation for push-exactly for an example implementation.
Defined as:
method push-all(Iterator:D: $target)
Should produce all elements from the iterator and push them to $target.
my @array; say (1 .. 1000).iterator.push-all(@array); # All 1000 values are pushed
The Iterator role implements this method in terms of push-at-least. As in the case of the other push-* methods, it is mainly intended for developers implementing this role. push-all is called when assigning an object with this role to an array, for instance, like in this example:
class DNA does Iterable does Iterator { has $.chain; has Int $!index = 0; method new ($chain where { $chain ~~ /^^ <[ACGT]>+ $$ / and $chain.chars %% 3 } ) { self.bless( :$chain ); } method iterator( ){ self } method pull-one( --> Mu){ if $!index < $.chain.chars { my $codon = $.chain.comb.rotor(3)[$!index div 3]; $!index += 3; return $codon; } else { return IterationEnd; } } method push-all(Iterator:D: $target) { for $.chain.comb.rotor(3) -> $codon { $target.push: $codon; } } }; my $b := DNA.new("AAGCCT"); my @dna-array = $b; say @dna-array; # OUTPUT: «[(A A G) (C C T)]»
The push-all method implemented pushes to the target iterator in lists of three aminoacid representations; this is called under the covers when we assign $b to @dna-array.
Defined as:
method push-until-lazy(Iterator:D: $target --> Mu)
Should produce values until it considers itself to be lazy, and push them onto $target.
The Iterator role implements this method as a no-op if is-lazy returns a True value, or as a synonym of push-all if not.
This matters mostly for iterators that have other iterators embedded, some of which might be lazy, while others aren't.
Defined as:
method is-lazy(Iterator:D: --> Bool:D)
Should return True for iterators that consider themselves lazy, and False otherwise.
Built-in operations that know that they can produce infinitely many values return True here, for example (1..6).roll(*).
say (1 .. 100).is-lazy; # OUTPUT: «False» say (1 .. ∞).is-lazy; # OUTPUT: «True»
The Iterator role implements this method returning False, indicating a non-lazy iterator.
Defined as:
method sink-all(Iterator:D: --> IterationEnd)
Should exhaust the iterator purely for the side-effects of producing the values, without actually saving them in any way. Should always return IterationEnd. If there are no side-effects associated with producing a value, then it can be implemented by a consuming class to be a virtual no-op.
say (1 .. 1000).iterator.sink-all; # OUTPUT: «IterationEnd»
The Iterator role implements this method as a loop that calls pull-one until it is exhausted.
Defined as:
method skip-one(Iterator:D: $target --> Mu)
Should skip producing one value. The return value should be truthy if the skip was successful and falsy if there were no values to be skipped:
my $i = <a b>.iterator; say $i.skip-one; say $i.pull-one; say $i.skip-one # OUTPUT: «1b0»
The Iterator role implements this method as a call pull-one and returning whether the value obtained was not IterationEnd.
Defined as:
method skip-at-least(Iterator:D: $target, int $to-skip --> Mu)
Should skip producing $to-skip values. The return value should be truthy if the skip was successful and falsy if there were not enough values to be skipped:
my $i = <a b c>.iterator; say $i.skip-at-least(2); say $i.pull-one; say $i.skip-at-least(20); # OUTPUT: «1c0»
The Iterator role implements this method as a loop calling skip-one and returning whether it returned a truthy value sufficient number of times.
Defined as:
method skip-at-least-pull-one(Iterator:D: $target, int $to-skip --> Mu)
Should skip producing $to-skip values and if the iterator is still not exhausted, produce and return the next value. Should return IterationEnd if the iterator got exhausted at any point:
my $i = <a b c>.iterator; say $i.skip-at-least-pull-one(2); say $i.skip-at-least-pull-one(20) =:= IterationEnd; # OUTPUT: «cTrue»
The Iterator role implements this method as calling skip-at-least and then calling pull-one if it was not exhausted yet.
Please see the PredictiveIterator role if your Iterator can know how many values it can still produce without actually producing them.
Logical superposition of values
class Junction is Mu { }
A junction is an unordered composite value of zero or more values. Junctions autothread over many operations, which means that the operation is carried out for each junction element (also known as eigenstate), and the result is junction of the return values of all those operators.
Junctions collapse into a single value in boolean context, so when used in a conditional, a negation or an explicit coercion to Bool through the so or ? prefix operators. The semantics of this collapse depend on the junction type, which can be all, any, one or none.
type | constructor | operator | True if ... |
---|---|---|---|
all | all | & | no value evaluates to False |
any | any | | | at least one value evaluates to True |
one | one | ^ | exactly one value evaluates to True |
none | none | no value evaluates to True |
As the table shows, in order to create junctions, you use the string that represents the type followed by any object, or else call .all, .none or .one on the object.
say so 3 == (1..30).one; # OUTPUT: «True» say so ("a" ^ "b" ^ "c") eq "a"; # OUTPUT: «True»
Junctions are very special objects. They fall outside the Any hierarchy, being only, as any other object, subclasses of Mu. That enables a feature for most methods: autothreading. Autothreading happens when a junction is bound to a parameter of a code object that doesn't accept values of type Junction. Instead of producing an error, the signature binding is repeated for each value of the junction.
Example:
my $j = 1|2; if 3 == $j + 1 { say 'yes'; }
First autothreads over the infix:<+> operator, producing the Junction 2|3. The next autothreading step is over infix:<==> , which produces False|True. The if conditional evaluates the junction in boolean context, which collapses it to True. So the code prints yes\n.
The type of a Junction does not affect the number of items in the resultant Junction after autothreading. For example, using a one Junction during Hash key lookup, still results in a Junction with several items. It is only in boolean context would the type of the Junction come into play:
my %h = :42foo, :70bar; say %h{one <foo meow>}:exists; # OUTPUT: «one(True, False)» say so %h{one <foo meow>}:exists; # OUTPUT: «True» say %h{one <foo bar>}:exists; # OUTPUT: «one(True, True)» say so %h{one <foo bar>}:exists; # OUTPUT: «False»
Note that the compiler is allowed, but not required, to parallelize autothreading (and Junction behavior in general), so it is usually an error to autothread junctions over code with side effects.
Autothreading implies that the function that's autothreaded will also return a Junction of the values that it would usually return.
(1..3).head( 2|3 ).say; # OUTPUT: «any((1 2), (1 2 3))»
Since .head returns a list, the autothreaded version returns a Junction of lists.
(1..3).contains( 2&3 ).say; # OUTPUT: «all(True, True)»
Likewise, .contains returns a Boolean; thus, the autothreaded version returns a Junction of Booleans. In general, all methods and routines that take an argument of type T and return type TT, will also accept junctions of T, returning junctions of TT.
Implementations are allowed to short-circuit Junctions. For example one or more routine calls (a(), b(), or c()) in the code below might not get executed at all, if the result of the conditional has been fully determined from routine calls already performed (only one truthy return value is enough to know the entire Junction is true):
if a() | b() | c() { say "At least one of the routines was called and returned a truthy value" }
Junctions are meant to be used as matchers in boolean context; introspection of junctions is not supported. If you feel the urge to introspect a junction, use a Set or a related type instead.
Usage examples:
my @list = <1 2 "Great">; @list.append(True).append(False); my @bool_or_int = grep Bool|Int, @list; sub is_prime(Int $x) returns Bool { # 'so' is for boolean context so $x %% none(2..$x.sqrt); } my @primes_ending_in_1 = grep &is_prime & / 1$ /, 2..100; say @primes_ending_in_1; # OUTPUT: «[11 31 41 61 71]» my @exclude = <~ .git>; for dir(".") { say .Str if .Str.ends-with(none @exclude) }
Special care should be taken when using all with arguments that may produce an empty list:
my @a = (); say so all(@a) # True, because there are 0 False's
To express "all, but at least one", you can use @a && all(@a)
my @a = (); say so @a && all(@a); # OUTPUT: «False»
Negated operators are special-cased when it comes to autothreading. $a !op $b is rewritten internally as !($a op $b). The outer negation collapses any junctions, so the return value always a plain Bool.
my $word = 'yes'; my @negations = <no none never>; if $word !eq any @negations { say '"yes" is not a negation'; }
Note that without this special-casing, an expression like $word ne any @words would always evaluate to True for non-trivial lists on one side.
For this purpose, infix:<ne> counts as a negation of infix:<eq> .
In general it is more readable to use a positive comparison operator and a negated junction:
my $word = 'yes'; my @negations = <no none never>; if $word eq none @negations { say '"yes" is not a negation'; }
Failures are just values like any other, as far as Junctions are concerned:
my $j = +any "not a number", "42", "2.1"; (gather $j».take).grep(Numeric).say; # OUTPUT: «(42 2.1)»
Above, we've used prefix + operator on a Junction to coerce the strings inside of it to Numeric. Since the operator returns a Failure when Str that doesn't contain a number gets coerced to Numeric, one of the elements in the Junction is a Failure, but same Failure rules as normal apply and the Failure doesn't explode just because it's in a Junction, and we can .grep it out. The exception will be thrown, if you try to use the Failure as a value—just like were this Failure on its own and not part of the Junction:
my $j = +any "not a number", "42", "2.1"; try say $j == 42; $! and say "Got exception: $!.^name()"; # OUTPUT: «Got exception: X::Str::Numeric»
Note that if an exception gets thrown when any of the values in a Junction get computed, it will be thrown just as if the problematic value were computed on its own and not with a Junction; you can't just compute the values that work while ignoring exceptions:
sub calc ($_) { die when 13 } my $j = any 1..42; say try calc $j; # OUTPUT: «Nil»
Only one value above causes an exception, but the result of the try block is still a Nil. A possible way around it is to cheat and evaluate the values of the Junction individually and then re-create the Junction from the result:
sub calc ($_) { die when 13 } my $j = any 1..42; $j = any (gather $j».take).grep: {Nil !=== try calc $_}; say so $j == 42; # OUTPUT: «True»
Note that using Junctions on the right-hand side of ~~ works slightly differently than using Junctions with other operators.
Consider this example:
say 25 == (25 | 42); # OUTPUT: «any(True, False)» – Junction say 25 ~~ (25 | 42); # OUTPUT: «True» – Bool
The reason is that == (and most other operators) are subject to auto-threading, and therefore you will get a Junction as a result. On the other hand, ~~ will call .ACCEPTS on the right-hand-side (in this case on a Junction) and the result will be a Bool.
Defined as:
multi method new(Junction: \values, Str :$type!) multi method new(Junction: Str:D \type, \values)
Constructor to define a new Junction from the type that defines de Junction and a set of values.
my $j = Junction.new(<Þor Oðinn Loki>, type => "all"); my $n = Junction.new( "one", 1..6 )
Defined as:
multi method defined(Junction:D:)
Checks for definedness instead of Boolean values.
say ( 3 | Str).defined ; # OUTPUT: «True» say (one 3, Str).defined; # OUTPUT: «True» say (none 3, Str).defined; # OUTPUT: «False»
Failures are also considered non-defined:
my $foo=Failure.new; say (one 3, $foo).defined; # OUTPUT: «True»
Since 6.d, this method will autothread.
Defined as:
multi method Bool(Junction:D:)
Collapses the Junction and returns a single Boolean value according to the type and the values it holds. Every element is transformed to Bool.
my $n = Junction.new( "one", 1..6 ); say $n.Bool; # OUTPUT: «False»
All elements in this case are converted to True, so it's false to assert that only one of them is.
my $n = Junction.new( "one", <0 1> ); say $n.Bool; # OUTPUT: «True»
Just one of them is truish in this case, 1, so the coercion to Bool returns True.
Defined as:
multi method Str(Junction:D:)
Autothreads the .Str method over its elements and returns results as a Junction. Output methods that use .Str method (print and put) are special-cased to autothread junctions, despite being able to accept a Mu type.
Defined as:
multi method gist(Junction:D:)
Collapses the Junction and returns a Str composed of the type of the junction and the gists of its components:
<a 42 c>.all.say; # OUTPUT: «all(a, 42, c)»
Defined as:
multi method perl(Junction:D:)
Collapses the Junction and returns a Str composed of perls of its components that evaluates to the equivalent Junction with equivalent components:
<a 42 c>.all.perl.put; # OUTPUT: «all("a", IntStr.new(42, "42"), "c")»
Defined as:
multi sub infix:<~>(Str:D $a, Junction:D $b) multi sub infix:<~>(Junction:D $a, Str:D $b) multi sub infix:<~>(Junction:D \a, Junction:D \b)
The infix ~ concatenation can be used to merge junctions into a single one or merge Junctions with strings. The resulting junction will have all elements merged as if they were joined into a nested loop:
my $odd = 1|3|5; my $even = 2|4|6; my $merged = $odd ~ $even; say $merged; #OUTPUT: «any(12, 14, 16, 32, 34, 36, 52, 54, 56)» say "Found 34!" if 34 == $merged; #OUTPUT: «Found 34!» my $prefixed = "0" ~ $odd; say "Found 03" if "03" == $prefixed; #OUTPUT: «Found 03!» my $postfixed = $odd ~ "1"; say "Found 11" if 11 == $postfixed; #OUTPUT: «Found 11!»
On the other hand, the versions of ~ that use a string as one argument will just concatenate the string to every member of the Junction, creating another Junction with the same number of elements.
Kernel related information
class Kernel does Systemic { }
Built-in class for providing kernel related information. Usually accessed through the $*KERNEL dynamic variable.
method arch
Instance method returning the "arch" (as in "architecture") information of the Kernel object. Dies if the "arch" could not be established.
method archname
Instance method returning the concatenation of hardware and name.
method bits
Instance method returning the number of bits used in the architecture of the processor. Usually 32 or 64.
method cpu-cores(--> Int)
Instance / Class method returning the number of CPU cores that are available.
say $*KERNEL.cpu-cores; # OUTPUT: «8»
method cpu-usage(--> Int)
Instance / Class method returning the amount of CPU uses since the start of the program (in microseconds).
method free-memory(--> Int)
Instance / Class method returning the available memory on the system. When using the JVM, this returns the available memory to the JVM instead. This method is only available in release v2019.06 and later.
method total-memory(--> Int)
Instance / Class method returning the total memory available to the system. When using the JVM, this returns the total memory available to the JVM instead. This method is only available in release v2019.06 and later.
method endian(--> Endian:D)
Class method that returns the Endian object associated with the kernel architecture (either LittleEndian or BigEndian).
Defined as
method hardware
Instance method returning the hardware information of the Kernel object. Dies if the hardware information could not be established.
say $*KERNEL.hardware; # OUTPUT: «x86_64»
method hostname
Instance method returning the hostname of the Kernel object.
method release
Instance method returning the release information of the Kernel object. Dies if the release information could not be established.
Defined as:
multi method signal(Kernel:D: Str:D $signal --> Int:D) multi method signal(Kernel:D: Signal:D \signal --> Int:D) multi method signal(Kernel:D: Int:D \signal --> Int:D)
Instance method returning the Signal numeric code for a given name for the Kernel object.
say $*KERNEL.signal("INT"); # OUTPUT: «2»
Instance method returning a list of Signals that are supported by the kernel represented by the Kernel object.
Tagged location in the source code
class Label {}
Labels are used in Perl 6 to tag loops so that you can specify the one you want to jump to with statements such as last. You can use it to jump out of loops and get to outer ones, instead of just exiting the current loop or going to the statement before.
USERS: # the label for @users -> $u { for $u.pets -> $pet { # usage of a label next USERS if $pet.barks; } say "None of {$u}'s pets barks"; } say USERS.^name; # OUTPUT: «Label»
Those label are objects of type Label, as shown in the last statement. Labels can be used in any loop construct, as long as they appear right before the loop statement.
my $x = 0; my $y = 0; my $t = ''; A: while $x++ < 2 { $t ~= "A$x"; B: while $y++ < 2 { $t ~= "B$y"; redo A if $y++ == 1; last A } } say $t; # OUTPUT: «A1B1A1A2»
Putting them on the line before the loop or the same line is optional. Labels must follow the syntax of ordinary identifiers, although traditionally we will use the latin alphabet in uppercase so that they stand out in the source. You can use, however, other alphabets like here:
駱駝道: while True { say 駱駝道.name; last 駱駝道; }
Defined as:
method name()
Not terribly useful, returns the name of the defined label:
A: while True { say A.name; # OUTPUT: «A» last A; }
Defined as:
method next(Label:)
Begin the next iteration of the loop associated with the label.
MY-LABEL: for 1..10 { next MY-LABEL if $_ < 5; print "$_ "; } # OUTPUT: «5 6 7 8 9 10 »
Defined as:
method redo(Label:)
Repeat the same iteration of the loop associated with the label.
my $has-repeated = False; MY-LABEL: for 1..10 { print "$_ "; if $_ == 5 { LEAVE $has-repeated = True; redo MY-LABEL unless $has-repeated; } } # OUTPUT: «1 2 3 4 5 5 6 7 8 9 10 »
Defined as:
method last(Label:)
Terminate the execution of the loop associated with the label.
MY-LABEL: for 1..10 { last MY-LABEL if $_ > 5; print "$_ "; } # OUTPUT: «1 2 3 4 5 »
Sequence of values
my class List does Iterable does Positional { }
List stores items sequentially and potentially lazily.
Indexes into lists and arrays start at 0 by default.
You can assign to list elements if they are containers. Use Arrays to have every value of the list stored in a container.
List implements Positional and as such provides support for subscripts.
In Perl 6, assigning a List to a scalar variable does not lose information. The difference is that iteration generally treats a list (or any other list-like object, like a Seq or an Array) inside a scalar as a single element.
my $s = (1, 2, 3); for $s { } # one iteration for $s.list { } # three iterations my $t = [1, 2, 3]; for $t { } # one iteration for $t.list { } # three iterations my @a = 1, 2, 3; for @a { } # three iterations for @a.item { } # one iteration
This operation is called itemization or putting in an item context. .item does the job for objects, as well as $( ... ) and, on array variables, $@a.
Lists generally don't interpolate (flatten) into other lists, except when they are in list context and the single argument to an operation such as append:
my $a = (1, 2, 3); my $nested = ($a, $a); # two elements my $flat = $nested.map({ .Slip }); # six elements, with explicit Slip my @b = <a b>; @b.append: $a.list; # The array variable @b has 5 elements, because # the list $a is the sole argument to append say @b.elems; # OUTPUT: «5» my @c = <a b>; @c.append: $a.list, 7; # The array variable @c has 4 elements, because # the list $a wasn't the only argument and thus # wasn't flatten by the append operation say @c.elems; # OUTPUT: «4» my @d = <a b>; @d.append: $a; # The array variable @d has 3 elements, because # $a is in and as far as append is # concerned a single element say @d.elems; # OUTPUT: «3»
The same flattening behavior applies all objects that do the Iterable role, notable hashes:
my %h = a => 1, b => 2; my @b = %h; say @b.elems; # OUTPUT: «2» my @c = %h, ; say @c.elems; # OUTPUT: «1» my @d = $%h; say @d.elems; # OUTPUT: «1»
Slurpy parameters (*@a) flatten non-itemized sublists:
sub fe(*@flat) { @flat.elems } say fe(<a b>, <d e>); # OUTPUT: «4» say fe(<a b>, <d e>.item); # OUTPUT: «3»
The empty list is created with (). Smartmatching against the empty list will check for the absence of elements.
my @a; for @a, @a.list, @a.Seq -> \listoid { say listoid ~~ () } # OUTPUT: «TrueTrueTrue»
Coercion to Bool also indicates if the List got any elements.
my @a; say [@a.elems, @a.Bool, ?@a]; # OUTPUT: «[0 False False]» @a.push: 42; say [@a.elems, @a.Bool, ?@a]; # OUTPUT: «[1 True True]» say 'empty' unless @a; # no output
Defined as:
multi method ACCEPTS(List:D: $topic)
If $topic is an Iterable, returns True or False based on whether the contents of the two Iterables match. A Whatever element in the invocant matches anything in the corresponding position of the $topic Iterable. A HyperWhatever matches any number of any elements, including no elements:
say (1, 2, 3) ~~ (1, *, 3); # OUTPUT: «True» say (1, 2, 3) ~~ (9, *, 5); # OUTPUT: «False» say (1, 2, 3) ~~ ( **, 3); # OUTPUT: «True» say (1, 2, 3) ~~ ( **, 5); # OUTPUT: «False» say (1, 3) ~~ (1, **, 3); # OUTPUT: «True» say (1, 2, 4, 5, 3) ~~ (1, **, 3); # OUTPUT: «True» say (1, 2, 4, 5, 6) ~~ (1, **, 5); # OUTPUT: «False» say (1, 2, 4, 5, 6) ~~ ( ** ); # OUTPUT: «True» say () ~~ ( ** ); # OUTPUT: «True»
In addition, returns False if either the invocant or $topic is a lazy Iterable, unless $topic is the same object as the invocant, in which case True is returned.
If $topic is not an Iterable, returns the invocant if the invocant has no elements or its first element is a Match object (this behavior powers m:g// smartmatch), or False otherwise.
Defined as:
sub elems($list --> Int:D) method elems(List:D: --> Int:D)
Returns the number of elements in the list.
say (1,2,3,4).elems; # OUTPUT: «4»
Defined as:
sub end($list --> Int:D) method end(List:D: --> Int:D)
Returns the index of the last element.
say (1,2,3,4).end; # OUTPUT: «3»
Defined as:
sub keys($list --> Seq:D) method keys(List:D: --> Seq:D)
Returns a sequence of indexes into the list (e.g., 0..(@list.elems-1)).
say (1,2,3,4).keys; # OUTPUT: «0..3»
Defined as:
sub values($list --> Seq:D) method values(List:D: --> Seq:D)
Returns a sequence of the list elements, in order.
say (1,2,3,4).^name; # OUTPUT: «List» say (1,2,3,4).values.^name; # OUTPUT: «Seq»
Defined as:
sub kv($list --> Seq:D) method kv(List:D: --> Seq:D)
Returns an interleaved sequence of indexes and values. For example
<a b c>.kv; # (0 a 1 b 2 c)
Defined as:
sub pairs($list --> Seq:D) method pairs(List:D: --> Seq:D)
Returns a sequence of pairs, with the indexes as keys and the list values as values.
<a b c>.pairs # (0 => a 1 => b 2 => c)
Defined as:
method antipairs(List:D: --> Seq:D)
Returns a Seq of pairs, with the values as keys and the indexes as values, i.e. the direct opposite to pairs.
say <a b c>.antipairs; # OUTPUT: «(a => 0 b => 1 c => 2)»
Defined as:
method invert(List:D: --> Seq:D)
Assumes every element of the List is a Pair. Returns all elements as a Seq of Pairs where the keys and values have been exchanged. If the value of a Pair is an Iterable, then it will expand the values of that Iterable into separate pairs.
my $l = List.new('a' => (2, 3), 'b' => 17); say $l.invert; # OUTPUT: «(2 => a 3 => a 17 => b)»
Defined as:
sub join($separator, *@list) method join(List:D: $separator = "")
Treats the elements of the list as strings by calling .Str on each of them, interleaves them with $separator and concatenates everything into a single string. Note that you can omit the $separator if you use the method syntax.
Example:
join ', ', <a b c>; # RESULT: «a, b, c»
Note that the method form does not flatten sublists:
say (1, <a b c>).join('|'); # OUTPUT: «1|a b c»
The method form also allows you to omit the separator:
say <a b c>.join; # OUTPUT: «abc»
But it behaves slurpily, flattening all arguments after the first into a single list:
say join('|', 3, 'þ', 1+4i); # OUTPUT: «3|þ|1+4i» say join ', ', <a b c>, 'd', 'e' , 'f'; # OUTPUT: «a, b, c, d, e, f»
In this case, the first list <a b c is slurped and flattened, unlike what happens when join is invoked as a method.
If one of the elements of the list happens to be a Junction, then join will also return a Junction with concatenation done as much as possible:
say ("a"|"b","c","d").join; # OUTPUT: «any(acd,bcd)»
Defined as:
multi method map(Hash:D \hash) multi method map(Iterable:D \iterable) multi method map(|c) multi method map(\SELF: █; :$label, :$item) multi sub map(&code, +values)
Examples applied to lists are included here for the purpose of illustration.
For a list, it invokes &code for each element and gathers the return values in a sequence and returns it. This happens lazily, i.e. &code is only invoked when the return values are accessed.Examples:
say ('hello', 1, 22/7, 42, 'world').map: { .^name } # OUTPUT: «(Str Int Rat Int Str)» say map *.Str.chars, 'hello', 1, 22/7, 42, 'world'; # OUTPUT: «(5 1 8 2 5)»
map inspects the arity of the code object, and tries to pass as many arguments to it as expected:
sub b($a, $b) { "$a before $b" }; say <a b x y>.map(&b).join(', '); # OUTPUT: «a before b, x before y»
iterates the list two items at a time.
Note that map does not flatten embedded lists and arrays, so
((1, 2), <a b>).map({ .join(',')})
passes (1, 2) and <a b> in turn to the block, leading to a total of two iterations and the result sequence "1,2", "a,b". See method flatmap for an alternative that flattens.
If &code is a Block loop phasers will be executed and loop control statements will be treated as in loop control flow. Please note that return is executed in the context of its definition. It is not the return statement of the block but the surrounding Routine. Using a Routine will also handle loop control statements and loop phasers. Any Routine specific control statement or phaser will be handled in the context of that Routine.
sub s { my &loop-block = { return # return from sub s }; say 'hi'; (1..3).map: &loop-block; say 'oi‽' # dead code }; s # RESULT: «hi»
Defined as:
method flatmap(List:D: &code --> Seq:D)
Like map iterates over the elements of the invocant list, feeding each element in turn to the code reference, and assembling the return values from these invocations in a result list.
The use of flatmap is strongly discouraged. Instead of .flatmap( ), please use .map( ).flat as it is clear when the .flat is called and is not confusing like .flatmap.
Unlike map it flattens non-itemized lists and arrays, so
## flatmap my @list = ('first1', ('second2', ('third3', 'third4'), 'second5'), 'first6'); say @list.flatmap({.reverse}).perl; # OUTPUT «("first1", "second5", "third3", "third4", "second2", "first6").Seq» ## map say @list.map({"$_ was a {.^name}"}).perl; # OUTPUT «("first1 was a Str", "second2 third3 third4 second5 was a List", "first6 was a Str").Seq» ## .map .flat has the same output as .flatmap say @list.map({.reverse}).flat.perl # OUTPUT «("first1", "second5", "third3", "third4", "second2", "first6").Seq»
Defined as:
multi method gist(List:D: --> Str:D)
Returns the string containing the parenthesized "gist" of the List, listing up to the first 100 elements, separated by space, appending an ellipsis if the List has more than 100 elements. If List is-lazy, returns string '(...)'
put (1, 2, 3).gist; # OUTPUT «(1 2 3)» put (1..∞).List.gist; # OUTPUT «(...)» put (1..200).List.gist; # OUTPUT: # (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 # 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 # 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 # 96 97 98 99 100 ...)
Defined as:
sub grep(Mu $matcher, *@elems, :$k, :$kv, :$p, :$v --> Seq:D) method grep(List:D: Mu $matcher, :$k, :$kv, :$p, :$v --> Seq:D)
Returns a sequence of elements against which $matcher smartmatches. The elements are returned in the order in which they appear in the original list.
Examples:
say ('hello', 1, 22/7, 42, 'world').grep: Int; # OUTPUT: «(1 42)» say grep { .Str.chars > 3 }, 'hello', 1, 22/7, 42, 'world'; # OUTPUT: «(hello 3.142857 world)»
Note that if you want to grep for elements that do not match, you can use a none-Junction:
say <a b 6 d 8 0>.grep(none Int); # OUTPUT: «(a b d)» say <a b c d e f>.grep(none /<[aeiou]>/); # OUTPUT: «(b c d f)»
Another option to grep for elements that do not match a regex is to use a block:
say <a b c d e f>.grep({! /<[aeiou]>/}) # OUTPUT: «(b c d f)»
The reason the example above works is because a regex in boolean context applies itself to $_. In this case, ! boolifies the /<[aeiou]>/ regex and negates the result. Smartmatching against a Callable (in this case a Block) returns the value returned from that callable, so the boolified result of a regex is then used to decide whether the current value should be kept in the result of a grep.
The optional named parameters :k, :kv, :p, :v provide the same functionality as on slices:
k
Only return the index values of the matching elements in order.
kv
Return both the index and matched elements in order.
p
Return the index and the matched element as a Pair, in order.
v
Only return the matched elements (same as not specifying any named parameter at all).
Examples:
say ('hello', 1, 22/7, 42, 'world').grep: Int, :k; # OUTPUT: «(1 3)» say grep { .Str.chars > 3 }, :kv, 'hello', 1, 22/7, 42, 'world'; # OUTPUT: «(0 hello 2 3.142857 4 world)» say grep { .Str.chars > 3 }, :p, 'hello', 1, 22/7, 42, 'world'; # OUTPUT: «(0 => hello 2 => 3.142857 4 => world)»
Defined as:
sub first(Mu $matcher, *@elems, :$k, :$kv, :$p, :$end) method first(List:D: Mu $matcher?, :$k, :$kv, :$p, :$end)
Returns the first item of the list which smartmatches against $matcher, returns Nil when no values match. The optional named parameter :end indicates that the search should be from the end of the list, rather than from the start.
Examples:
say (1, 22/7, 42, 300).first: * > 5; # OUTPUT: «42» say (1, 22/7, 42, 300).first: * > 5, :end; # OUTPUT: «300» say ('hello', 1, 22/7, 42, 'world').first: Complex; # OUTPUT: «Nil»
The optional named parameters :k, :kv, :p provide the same functionality as on slices:
k
Return the index value of the matching element. Index is always counted from the beginning of the list, regardless of whether the :end named parameter is specified or not.
kv
Return both the index and matched element.
p
Return the index and the matched element as a Pair.
Examples:
say (1, 22/7, 42, 300).first: * > 5, :k; # OUTPUT: «2» say (1, 22/7, 42, 300).first: * > 5, :p; # OUTPUT: «2 => 42» say (1, 22/7, 42, 300).first: * > 5, :kv, :end; # OUTPUT: «(3 300)»
In method form, the $matcher can be omitted, in which case the first available item (or last if :end is set) will be returned. See also head and tail methods.
Defined as:
multi method head(Any:D:) is raw multi method head(Any:D: Callable:D $w) multi method head(Any:D: $n)
This method is directly inherited from Any, and it returns the first $n items of the list, an empty list if $n <= 0, or the first element with no argument. The version that takes a Callable uses a WhateverCode to specify all elements, starting from the first, but the last ones.
Examples:
say <a b c d e>.head ; # OUTPUT: «a» say <a b c d e>.head(2); # OUTPUT: «(a b)» say <a b c d e>.head(*-3); # OUTPUT: «(a b)»
Defined as:
multi method tail(List:D:) multi method tail(List:D: $n --> Seq:D)
Returns a Seq containing the last $n items of the list. Returns an empty Seq if $n <= 0. Defaults to the last element if no argument is specified. Throws an exception if the list is lazy.
Examples:
say <a b c d e>.tail(*-3);# OUTPUT: «(d e)» say <a b c d e>.tail(2); # OUTPUT: «(d e)» say <a b c d e>.tail; # OUTPUT: «e»
In the first case, $n is taking the shape of a WhateverCode to indicate the number of elements from the beginning that will be excluded. $n can be either a Callable, in which case it will be called with the value 0, or anything else that can be converted to a number, in which case it will use that as the number of elements in the output Seq.
say <a b c d e>.tail( { $_ - 2 } ); # OUTPUT: «(c d e)»
Defined as:
multi method categorize() multi method categorize(Whatever) multi method categorize($test, :$into!, :&as) multi method categorize($test, :&as) multi sub categorize($test, +items, :$into!, *%named ) multi sub categorize($test, +items, *%named )
These methods are directly inherited from Any; see Any.list for more examples.
This routine transforms a list of values into a hash representing the categorizations of those values according to $test, which is called once for every element in the list; each hash key represents one possible categorization for one or more of the incoming list values, and the corresponding hash value contains an array of those list values categorized by the $test, acting like a mapper, into the category of the associated key.
Note that, unlike classify, which assumes that the return value of the mapper is a single value, categorize always assumes that the return value of the mapper is a list of categories that are appropriate to the current value.
Example:
sub mapper(Int $i) returns List { $i %% 2 ?? 'even' !! 'odd', $i.is-prime ?? 'prime' !! 'not prime' } say categorize &mapper, (1, 7, 6, 3, 2); # OUTPUT: «{even => [6 2], not prime => [1 6], # odd => [1 7 3], prime => [7 3 2]}»
Defined as:
multi method classify($test, :$into!, :&as) multi method classify($test, :&as) multi sub classify($test, +items, :$into!, *%named ) multi sub classify($test, +items, *%named )
Transforms a list of values into a hash representing the classification of those values; each hash key represents the classification for one or more of the incoming list values, and the corresponding hash value contains an array of those list values classified into the category of the associated key. $test will be an expression that will produce the hash keys according to which the elements are going to be classified.
Example:
say classify { $_ %% 2 ?? 'even' !! 'odd' }, (1, 7, 6, 3, 2); # OUTPUT: «{even => [6 2], odd => [1 7 3]}» say ('hello', 1, 22/7, 42, 'world').classify: { .Str.chars }; # OUTPUT: «{1 => [1], 2 => [42], 5 => [hello world], 8 => [3.142857]}»
It can also take :as as a named parameter, transforming the value before classifying it:
say <Innie Minnie Moe>.classify( { $_.chars }, :as{ lc $_ }); # OUTPUT: «{3 => [moe], 5 => [innie], 6 => [minnie]}»
This code is classifying by number of characters, which is the expression that has been passed as $test parameter, but the :as block lowercases it before doing the transformation. The named parameter :into can also be used to classify into a newly defined variable:
<Innie Minnie Moe>.classify( { $_.chars }, :as{ lc $_ }, :into( my %words{Int} ) ); say %words; # OUTPUT: «{3 => [moe], 5 => [innie], 6 => [minnie]}»
We are declaring the scope of %words{Int} on the fly, with keys that are actually integers; it gets created with the result of the classification.
Defined as:
method Bool(List:D: --> Bool:D)
Returns True if the list has at least one element, and False for the empty list.
say ().Bool; # OUTPUT: «False» say (1).Bool; # OUTPUT: «True»
Defined as:
method Str(List:D: --> Str:D)
Stringifies the elements of the list and joins them with spaces (same as .join(' ')).
say (1,2,3,4,5).Str; # OUTPUT: «1 2 3 4 5»
Defined as:
method Int(List:D: --> Int:D)
Returns the number of elements in the list (same as .elems).
say (1,2,3,4,5).Int; # OUTPUT: «5»
Defined as:
method Numeric(List:D: --> Int:D)
Returns the number of elements in the list (same as .elems).
say (1,2,3,4,5).Numeric; # OUTPUT: «5»
Defined as:
method Capture(--> Capture:D)
Returns a Capture where each Pair, if any, in the List has been converted to a named argument (with the key of the Pair stringified). All other elements in the List are converted to positional arguments in the order they are found, i.e. the first non pair item in the list becomes the first positional argument, which gets index 0, the second non pair item becomes the second positional argument, getting index 1 etc.
my $list = (7, 5, a => 2, b => 17); my $capture = $list.Capture; say $capture.keys; # OUTPUT: «(0 1 a b)» my-sub(|$capture); # RESULT: «7, 5, 2, 17» sub my-sub($first, $second, :$a, :$b) { say "$first, $second, $a, $b" }
A more advanced example demonstrating the returned Capture being matched against a Signature.
my $list = (7, 5, a => 2, b => 17); say so $list.Capture ~~ :($ where * == 7,$,:$a,:$b); # OUTPUT: «True» $list = (8, 5, a => 2, b => 17); say so $list.Capture ~~ :($ where * == 7,$,:$a,:$b); # OUTPUT: «False»
Defined as:
multi sub pick($count, *@list --> Seq:D) multi method pick(List:D: $count --> Seq:D) multi method pick(List:D: --> Mu)
If $count is supplied: Returns $count elements chosen at random and without repetition from the invocant. If * is passed as $count, or $count is greater than or equal to the size of the list, then all elements from the invocant list are returned in a random sequence; i.e. they are returned shuffled.
In method form, if $count is omitted: Returns a single random item from the list, or Nil if the list is empty
Examples:
say <a b c d e>.pick; # OUTPUT: «b» say <a b c d e>.pick: 3; # OUTPUT: «(c a e)» say <a b c d e>.pick: *; # OUTPUT: «(e d a b c)»
Defined as:
multi sub roll($count, *@list --> Seq:D) multi method roll(List:D: $count --> Seq:D) multi method roll(List:D: --> Mu)
If $count is supplied: Returns a sequence of $count elements, each randomly selected from the list. Each random choice is made independently, like a separate die roll where each die face is a list element. If * is passed as $count returns a lazy, infinite sequence of randomly chosen elements from the original list.
If $count is omitted: Returns a single random item from the list, or Nil if the list is empty
Examples:
say <a b c d e>.roll; # 1 random letter say <a b c d e>.roll: 3; # 3 random letters say roll 8, <a b c d e>; # 8 random letters my $random-digits := (^10).roll(*); say $random-digits[^15]; # 15 random digits
Defined as:
multi method eager(List:D: --> List:D) multi sub eager(*@elems --> List:D)
Evaluates all elements in the List eagerly, and returns them as a List.
my \ll = (lazy 1..5).cache; say ll[]; # OUTPUT: «(...)» say ll.eager # OUTPUT: «(1 2 3 4 5)»
Defined as:
multi sub reverse(*@list --> Seq:D) multi method reverse(List:D: --> Seq:D)
Returns a Seq with the same elements in reverse order.
Note that reverse always refers to reversing elements of a list; to reverse the characters in a string, use flip.
Examples:
say <hello world!>.reverse; # OUTPUT: «(world! hello)» say reverse ^10; # OUTPUT: «(9 8 7 6 5 4 3 2 1 0)»
Defined as:
multi sub rotate(@list, Int:D $n = 1 --> List:D) multi method rotate(List:D: Int:D $n = 1 --> List:D)
Returns the list rotated by $n elements.
Examples:
<a b c d e>.rotate(2); # <c d e a b> <a b c d e>.rotate(-1); # <e a b c d>
Defined as:
multi sub sort(*@elems --> Seq:D) multi sub sort(&custom-routine-to-use, *@elems --> Seq:D) multi method sort(List:D: --> Seq:D) multi method sort(List:D: &custom-routine-to-use --> Seq:D)
Sorts the list, smallest element first. By default infix:<cmp> is used for comparing list elements.
If &custom-routine-to-use is provided, and it accepts two arguments, it is invoked for pairs of list elements, and should return Order::Less, Order::Same or Order::More.
If &custom-routine-to-use accepts only one argument, the list elements are sorted according to custom-routine-to-use($a) cmp custom-routine-to-use($b) . The return values of &custom-routine-to-use are cached, so that &custom-routine-to-use is only called once per list element.
Examples:
say (3, -4, 7, -1, 2, 0).sort; # OUTPUT: «(-4 -1 0 2 3 7)» say (3, -4, 7, -1, 2, 0).sort: *.abs; # OUTPUT: «(0 -1 2 3 -4 7)» say (3, -4, 7, -1, 2, 0).sort: { $^b leg $^a }; # OUTPUT: «(7 3 2 0 -4 -1)»
Additionally, if &custom-routine-to-use returns a List, elements will be sorted based upon multiple values with subsequent values in the List being used to break the tie if the comparison between the prior elements evaluate to Order::Same.
my @resistance = ( %( first-name => 'Kyle', last-name => 'Reese' ), %( first-name => 'Sarah', last-name => 'Connor' ), %( first-name => 'John', last-name => 'Connor' ), ); .say for @resistance.sort: { .<last-name>, .<first-name> }; #`( OUTPUT: {first-name => John, last-name => Connor} {first-name => Sarah, last-name => Connor} {first-name => Kyle, last-name => Reese} )
This sorting can be based on characteristics of a single element:
say <ddd aaa bbb bb ccc c>.sort( {.chars, .Str} ); # OUTPUT: «(c bb aaa bbb ccc ddd)»
In this case, elements of the array are sorted in ascending order according first to the string length (.chars) and second to the actual alphabetical order .Str) if the length is exactly the same.
Any number of criteria can be used in this:
say <01 11 111 2 20 02>.sort( { .Int, .comb.sum, .Str } ); # OUTPUT: «(01 02 2 11 20 111)»
Defined as:
multi method reduce(Any:U: & --> Nil) multi method reduce(Any:D: &with) multi sub reduce (&with, +list)
The first form is obviously a no-op. The second form generates a single "combined" value from a list of arbitrarily many values, by iteratively applying a function which knows how to combine two values.
If @values contains just a single element, the operator is applied to that single element if possible; if not, it returns the element itself.
say [-] <10 5 3>; #OUTPUT: 2 say [-] 10; #OUTPUT: 10
If it contains no elements, an exception is thrown, unless &with is an operator with a known identity value. For this reason, you may want to prefix the input list with an explicit identity value:
my @strings = ("One good string!", "And one another good string!"); say reduce { $^a ~ $^b }, '', |@strings; # like @strings.join my @numbers = (1,2,3,4,5); say reduce { $^a > $^b ?? $^a !! $^b }, 0, |@numbers; # like @numbers.max
If &with is the function object of an operator, its inherent identity value and associativity is respected - in other words, (VAL1, VAL2, VAL3).reduce(&[OP]) is the same as VAL1 OP VAL2 OP VAL3 even for operators which aren't left-associative:
# Raise 2 to the 81st power, because 3 to the 4th power is 81 [2,3,4].reduce(&[**]).lsb.say; # OUTPUT: «81» (2**(3**4)).lsb.say; # OUTPUT: «81» (2**3**4).lsb.say; # OUTPUT: «81» # Subtract 4 from -1, because 2 minus 3 is -1 [2,3,4].reduce(&[-]).say; # OUTPUT: «-5» ((2-3)-4).say; # OUTPUT: «-5» (2-3-4).say; # OUTPUT: «-5»
Since reducing with an infix operator is a common thing to do, the [ ] metaoperator provides a syntactic shortcut:
# The following all do the same thing... my @numbers = (1,2,3,4,5); say reduce { $^a + $^b }, 0, |@numbers; say reduce * + *, 0, |@numbers; say reduce &[+], @numbers; # operator does not need explicit identity say [+] @numbers; # most people write it this way
Please note also the use of reduce in sub form. Since reduce is an implicit loop, it responds to next, last and redo statements inside &with:
say (2,3,4,5).reduce: { last if $^a > 7; $^a + $^b }; # says 9
Practical example:
# Generate a random-ish math formula like "(4 + ((3 * x) + 11) / 6))" my @ops = [Z] (<+ - * />, 1..20)».roll(4); say ('x', |@ops).reduce: -> $formula, [$op, $number] { Bool.pick ?? "($formula $op $number)" !! "($number $op $formula)" }
Note: In the functional programming world, this operation is generally called a fold. With a right-associative operator it is a right fold, otherwise (and usually) it is a left fold:
sub infix:<foo>($a, $b) is assoc<right> { "($a, $b)" } say [foo] 1, 2, 3, 4; # OUTPUT: «(1, (2, (3, 4)))» sub infix:<bar>($a, $b) is assoc<left> { "($a, $b)" } say [bar] 1, 2, 3, 4; # OUTPUT: «(((1, 2), 3), 4)»
Defined as:
multi sub produce(&with, *@values) multi method produce(List:D: &with)
Generates a list of all intermediate "combined" values along with the final result by iteratively applying a function which knows how to combine two values.
If @values contains just a single element, a list containing that element is returned immediately. If it contains no elements, an exception is thrown, unless &with is an operator with a known identity value.
If &with is the function object of an operator, its inherent identity value and associativity is respected - in other words, (VAL1, VAL2, VAL3).produce(&[OP]) is the same as VAL1 OP VAL2 OP VAL3 even for operators which aren't left-associative:
# Raise 2 to the 81st power, because 3 to the 4th power is 81 [2,3,4].produce(&[**]).say; # OUTPUT: «(4 81 2417851639229258349412352)» say produce &[**], (2,3,4); # OUTPUT: «(4 81 2417851639229258349412352)» say [\**] (2,3,4); # OUTPUT: «(4 81 2417851639229258349412352)» # Subtract 4 from -1, because 2 minus 3 is -1 [2,3,4].produce(&[-]).say; # OUTPUT: «(2 -1 -5)» say produce &[-], (2,3,4); # OUTPUT: «(2 -1 -5)» say [\-] (2,3,4); # OUTPUT: «(2 -1 -5)»
A triangle metaoperator [\ ] provides a syntactic shortcut for producing with an infix operator:
# The following all do the same thing... my @numbers = (1,2,3,4,5); say produce { $^a + $^b }, @numbers; say produce * + *, @numbers; say produce &[+], @numbers; # operator does not need explicit identity say [\+] @numbers; # most people write it this way
The visual picture of a triangle [\ is not accidental. To produce a triangular list of lists, you can use a "triangular comma":
[\,] 1..5; # ( # (1) # (1 2) # (1 2 3) # (1 2 3 4) # (1 2 3 4 5) # )
Since produce is an implicit loop, it responds to next, last and redo statements inside &with:
say (2,3,4,5).produce: { last if $^a > 7; $^a + $^b }; # OUTPUT: «(2 5 9)»
Defined as:
multi sub combinations($from, $of = 0..* --> Seq:D) multi method combinations(List:D: Int() $of --> Seq:D) multi method combinations(List:D: Iterable:D $of = 0..* --> Seq:D)
Returns a Seq with all $of-combinations of the invocant list. $of can be a numeric Range, in which case combinations of the range of item numbers it represents will be returned (i.e. 2.6 .. 4 will return 2-, 3-, and 4-item combinations>). Otherwise, $of is coerced to an Int.
.say for <a b c>.combinations: 2; # OUTPUT: # (a b) # (a c) # (b c)
Above, there are three possible ways to combine the 2-items lists from the original list, which is what we receive in the output. See permutations if you want permutations instead of combinations.
With Range argument, we get both three 2-item combinations and one 3-item combination:
.say for <a b c>.combinations: 2..3; # OUTPUT: # (a b) # (a c) # (b c) # (a b c)
If $of is negative or is larger than there are items in the given list, an empty list will be returned. If $of is zero, a 1-item list containing an empty list will be returned (there's exactly 1 way to pick no items).
The subroutine form is equivalent to the method form called on the first argument ($from), with the exception that if $from is not an Iterable, it gets coerced to an Int and combinations are made from a Range constructed with 0..^$from instead:
.say for combinations 3, 2 # OUTPUT: # (0 1) # (0 2) # (1 2)
Note: some implementations may limit the maximum value of non-Iterable $from. On Rakudo, 64-bit systems have a limit of 2³¹-1 and 32-bit systems have a limit of 2²⁸-1.
Defined as:
multi sub permutations(Int() $from --> Seq:D) multi sub permutations(Iterable $from --> Seq:D) multi method permutations(List:D: --> Seq:D)
Returns all possible permutations of a list as a Seq of lists:
.say for <a b c>.permutations; # OUTPUT: # (a b c) # (a c b) # (b a c) # (b c a) # (c a b) # (c b a)
permutations treats all elements as unique, thus (1, 1, 2).permutations returns a list of 6 elements, even though there are only three distinct permutations, due to first two elements being the same.
The subroutine form behaves the same as the method form, computing permutations from its first argument $from. If $from is not an Iterable, coerces $from to an Int and picks from a Range constructed with 0..^$from:
.say for permutations 3; # OUTPUT: # (0 1 2) # (0 2 1) # (1 0 2) # (1 2 0) # (2 0 1) # (2 1 0)
Defined as:
method rotor(*@cycle, Bool() :$partial --> Seq:D)
Returns a sequence of lists, where each sublist is made up of elements of the invocant.
In the simplest case, @cycle contains just one integer, in which case the invocant list is split into sublists with as many elements as the integer specifies. If :$partial is True, the final chunk is included even if it doesn't satisfy the length requirement:
say ('a'..'h').rotor(3).join('|'); # OUTPUT: «a b c|d e f» say ('a'..'h').rotor(3, :partial).join('|'); # OUTPUT: «a b c|d e f|g h»
If the element of @cycle is a Pair instead, the key of the pair specifies the length of the return sublist, and the value the gap between sublists; negative gaps produce overlap:
say ('a'..'h').rotor(2 => 1).join('|'); # OUTPUT: «a b|d e|g h» say ('a'..'h').rotor(3 => -1).join('|'); # OUTPUT: «a b c|c d e|e f g»
If @cycle contains more than element, rotor cycles through it to find the number of elements for each sublist:
say ('a'..'h').rotor(2, 3).join('|'); # OUTPUT: «a b|c d e|f g» say ('a'..'h').rotor(1 => 1, 3).join('|'); # OUTPUT: «a|c d e|f»
Combining multiple cycles and :partial also works:
say ('a'..'h').rotor(1 => 1, 3 => -1, :partial).join('|'); # OUTPUT: «a|c d e|e|g h»
See this blog post for more elaboration on rotor.
Defined As:
multi method batch(Int:D $batch --> Seq) multi method batch(Int:D :$elems --> Seq)
Returns a Seq of the elements in batches of :$elems or $batch, respectively. If the number of elements is not a multiple of $batch, the last batch may have less than $batch elements, similar to .rotor($batch, :partial).
sub cross(+@e, :&with --> Seq:D)
Computes the cross-product of two or more lists or iterables. This returns a sequence of lists where the first item in each list is an item from the first iterable, the second is from the second given iterable, etc. Every item will be paired with every other item in all the other lists.
say cross(<a b c>, <d e f>).map(*.join).join(",") # OUTPUT: «ad,ae,af,bd,be,bf,cd,ce,cf»
The cross routine has an infix synonym as well, named X.
say (<a b c> X <d e f>).map(*.join).join(",") # output is the same as the previous example
If the optional with parameter is passed, it is used as a reduction operation to apply to each of the cross product items.
say cross([1, 2, 3], [4, 5, 6], :with(&infix:<*>)).join(","); # OUTPUT: «4,5,6,8,10,12,12,15,18»
The X operator can be combined with another operator as a metaoperator to perform a reduction as well:
say ([1, 2, 3] X* [4, 5, 6]).join(",") # same output as the previous example
Defined as:
sub zip(+@e, :&with --> Seq:D)
Builds a 'list of lists', returned as a sequence, from multiple input lists or other iterables.
zip iterates through each of the input lists synchronously, 'Zipping' them together, so that elements are grouped according to their input list index, in the order that the lists are provided.
say zip(<a b c>, <d e f>, <g h i>); # OUTPUT: «((a d g) (b e h) (c f i))»
zip has an infix synonym, the Z operator.
say <a b c> Z <d e f> Z <g h i>; # same output
zip can provide input to a for loop :
for <a b c> Z <d e f> Z <g h i> -> [$x,$y,$z] {say ($x,$y,$z).join(",")} # OUTPUT: «a,d,g # b,e,h # c,f,i»
, or more succinctly:
say .join(",") for zip <a b c>, <d e f>, <g h i>; # same output
Note, that if the input lists have an unequal number of elements, then zip terminates once the shortest input list is exhausted, and trailing elements from longer input lists are discarded.
say <a b c> Z <d e f m n o p> Z <g h i>; # ((a d g) (b e h) (c f i))
In cases where data clipping is possible, but undesired, then consider using roundrobin instead of zip.
The optional with parameter will additionally reduce the zipped lists. For example, the following multiplies corresponding elements together to return a single list of products.
.say for zip <1 2 3>, [1, 2, 3], (1, 2, 3), :with(&infix:<*>); # OUTPUT: «1 # 8 # 27»
The Z form can also be used to perform reduction by implicitly setting the with parameter with a metaoperator :
.say for <1 2 3> Z* [1, 2, 3] Z* (1, 2, 3); # same output
Defined as:
sub roundrobin(+list-of-lists --> Seq)
Builds a 'list of lists', returned as a sequence, from multiple input lists or other iterables. roundrobin returns an identical result to that of zip, except when the input lists are allowed to have an unequal number of elements.
say roundrobin <a b c>, <d e f>, <g h i>; # OUTPUT: «((a d g) (b e h) (c f i))» say .join(",") for roundrobin([1, 2], [2, 3], [3, 4]); # OUTPUT: «1,2,3 # 2,3,4»
roundrobin does not terminate once one or more of the input lists become exhausted, but proceeds until all elements from all lists have been processed.
say roundrobin <a b c>, <d e f m n o p>, <g h i j>; # OUTPUT: «((a d g) (b e h) (c f i) (m j) (n) (o) (p))» say .join(",") for roundrobin([1, 2], [2, 3, 57, 77], [3, 4, 102]); # OUTPUT: «1,2,3 # 2,3,4 # 57,102 # 77»
Therefore no data values are lost due in the 'zipping' operation. A record of which input list provided which element cannot be gleaned from the resulting sequence, however.
roundrobin can be useful in combining messy data to the point where a manual post-processing step can then be undertaken.
Defined as:
sub sum($list --> Numeric:D) method sum(List:D: --> Numeric:D)
Returns the sum of all elements in the list or 0 if the list is empty. Throws an exception if an element can not be coerced into Numeric.
say (1, 3, pi).sum; # OUTPUT: «7.14159265358979» say (1, "0xff").sum; # OUTPUT: «256» say sum(0b1111, 5); # OUTPUT: «20»
When being called on native integer arrays, it is also possible to specify a :wrap named parameter. This will add the values as native integers, wrapping around if they exceed the size of a native integer. If you are sure you will not exceed that value, or if you don't mind, using :wrap will make the calculation about 20x as fast.
my int @values = ^1_000_000; say @a.sum(:wrap); # OUTPUT: «499999500000»
Defined as:
method fmt($format = '%s', $separator = ' ' --> Str:D)
Returns a string where each element in the list has been formatted according to $format and where each element is separated by $separator.
For more information about formats strings, see sprintf.
my @a = 8..11; say @a.fmt('%03d', ','); # OUTPUT: «008,009,010,011»
Assumes the list contains Match objects and returns the value of .from called on the first element of the list.
'abcdefg' ~~ /(c)(d)/; say $/.list.from; # OUTPUT: «2» "abc123def" ~~ m:g/\d/; say $/.list.from; # OUTPUT: «3»
"abc123def" ~~ m:g/\d/; say $/.to; # OUTPUT: «6»
Assumes the List contains Match objects, such as the $/ variable being a List, when using :g modifier in regexes. Returns the value of .to called on the last element of the list.
Defined as:
method sink(--> Nil) { }
It does nothing, and returns Nil, as the definition clearly shows.
sink [1,2,Failure.new("boo!"),"still here"]; # OUTPUT: «»
In general, creates a set which has as members elements of the list.
say <æ ß þ €>.Set; # OUTPUT: «set(ß æ þ €)»
However, there might be some unexpected changes in case the list includes non-scalar data structures. For instance, with Pairs:
my @a = (:42a, :33b); say @a; # OUTPUT: «[a => 42 b => 33]» say @a.Set; # OUTPUT: «set(a b)»
The set will be composed of the keys of the Pair whose corresponding value is not 0, eliminating all the values. Please check the Set documentation for more examples and a more thorough explanation.
multi sub infix:<cmp>(List @a, List @b)
Evaluates Lists by comparing element @a[$i] with @b[$i] (for some Int $i, beginning at 0) and returning Order::Less, Order::Same, or Order::More depending on if and how the values differ. If the operation evaluates to Order::Same, @a[$i + 1] is compared with @b[$i + 1]. This is repeated until one is greater than the other or all elements are exhausted.
If the Lists are of different lengths, at most only $n comparisons will be made (where $n = @a.elems min @b.elems). If all of those comparisons evaluate to Order::Same, the final value is selected based upon which List is longer.
say (1, 2, 3) cmp (1, 2, 3); # OUTPUT: «Same» say (4, 5, 6) cmp (4, 5, 7); # OUTPUT: «Less» say (7, 8, 9) cmp (7, 8, 8); # OUTPUT: «More» say (1, 2) cmp (1, 2, 3); # OUTPUT: «Less» say (1, 2, 3) cmp (1, 2); # OUTPUT: «More» say (9).List cmp (^10).List; # OUTPUT: «More»
A low-level, re-entrant, mutual exclusion lock
class Lock {}
A Lock is a low-level concurrency control construct. It provides mutual exclusion, meaning that only one thread may hold the lock at a time. Once the lock is unlocked, another thread may then lock it.
A Lock is typically used to protect access to one or more pieces of state. For example, in this program:
my $x = 0; my $l = Lock.new; await (^10).map: { start { $l.protect({ $x++ }); } } say $x; # OUTPUT: «10»
The Lock is used to protect operations on $x. An increment is not an atomic operation; without the lock, it would be possible for two threads to both read the number 5 and then both store back the number 6, thus losing an update. With the use of the Lock, only one thread may be running the increment at a time.
A Lock is re-entrant, meaning that a thread that holds the lock can lock it again without blocking. That thread must unlock the same number of times before the lock can be obtained by another thread (it works by keeping a recursion count).
It's important to understand that there is no direct connection between a Lock and any particular piece of data; it is up to the programmer to ensure that the Lock is held during all operations that involve the data in question. The OO::Monitors module, while not a complete solution to this problem, does provide a way to avoid dealing with the lock explicitly and encourage a more structured approach.
The Lock class is backed by operating-system provided constructs, and so a thread that is waiting to acquire a lock is, from the point of view of the operating system, blocked.
Code using high-level Perl 6 concurrency constructs should avoid using Lock. Waiting to acquire a Lock blocks a real Thread, meaning that the thread pool (used by numerous higher-level Perl 6 concurrency mechanisms) cannot use that thread in the meantime for anything else.
Any await performed while a Lock is held will behave in a blocking manner; the standard non-blocking behavior of await relies on the code following the `await` resuming on a different Thread from the pool, which is incompatible with the requirement that a Lock be unlocked by the same thread that locked it. See Lock::Async for an alternative mechanism that does not have this shortcoming.
By their nature, Locks are not composable, and it is possible to end up with hangs should circular dependencies on locks occur. Prefer to structure concurrent programs such that they communicate results rather than modify shared data structures, using mechanisms like Promise, Channel and Supply.
Defined as:
method protect(Lock:D: &code)
Obtains the lock, runs &code, and releases the lock afterwards. Care is taken to make sure the lock is released even if the code is left through an exception.
Note that the Lock itself needs to be created outside the portion of the code that gets threaded and it needs to protect. In the first example below, Lock is first created and assigned to $lock, which is then used inside the Promises to protect the sensitive code. In the second example, a mistake is made: the Lock is created right inside the Promise, so the code ends up with a bunch of separate locks, created in a bunch of threads, and thus they don't actually protect the code we want to protect.
# Right: $lock is instantiated outside the portion of the # code that will get threaded and be in need of protection my $lock = Lock.new; await ^20 .map: { start { $lock.protect: { print "Foo"; sleep rand; say "Bar"; } } } # !!! WRONG !!! Lock is created inside threaded area! await ^20 .map: { start { Lock.new.protect: { print "Foo"; sleep rand; say "Bar"; } } }
Defined as:
method lock(Lock:D:)
Acquires the lock. If it is currently not available, waits for it.
my $l = Lock.new; $l.lock;
Since a Lock is implemented using OS-provided facilities, a thread waiting for the lock will not be scheduled until the lock is available for it. Since Lock is re-entrant, if the current thread already holds the lock, calling lock will simply bump a recursion count.
While it's easy enough to use the lock method, it's more difficult to correctly use unlock. Instead, prefer to use the protect method instead, which takes care of making sure the lock/unlock calls always both occur.
Defined as:
method unlock(Lock:D:)
Releases the lock.
my $l = Lock.new; $l.lock; $l.unlock;
It is important to make sure the Lock is always released, even if an exception is thrown. The safest way to ensure this is to use the protect method, instead of explicitly calling lock and unlock. Failing that, use a LEAVE phaser.
my $l = Lock.new; { $l.lock; LEAVE $l.unlock; }
Defined as:
my class ConditionVariable { method wait(); method signal(); method signal_all(); } method condition(Lock:D: --> ConditionVariable:D)
Returns a condition variable. Compare https://web.stanford.edu/~ouster/cgi-bin/cs140-spring14/lecture.php?topic=locks or https://en.wikipedia.org/wiki/Monitor_%28synchronization%29 for background.
my $l = Lock.new; $l.condition;
A non-blocking, non-re-entrant, mutual exclusion lock
class Lock::Async {}
A Lock::Async instance provides a mutual exclusion mechanism: when the lock is held, any other code wishing to lock must wait until the holder calls unlock.
Unlike Lock, which provides a traditional OS-backed mutual exclusion mechanism, Lock::Async works with the high-level concurrency features of Perl 6. The lock method returns a Promise, which will be kept when the lock is available. This Promise can be used with non-blocking await. This means that a thread from the thread pool need not be consumed while waiting for the Lock::Async to be available, and the code trying to obtain the lock will be resumed once it is available.
The result is that it's quite possible to have many thousands of outstanding Lock::Async lock requests, but just a small number of threads in the pool. Attempting that with a traditional Lock would not go so well!
There is no requirement that a Lock::Async is locked and unlocked by the same physical thread, meaning it is possible to do a non-blocking await while holding the lock. The flip side of this is Lock::Async is not re-entrant.
While Lock::Async works in terms of higher-level Perl 6 concurrency mechanisms, it should be considered a building block. Indeed, it lies at the heart of the Supply concurrency model. Prefer to structure programs so that they communicate results rather than mutate shared data structures, using mechanisms like Promise, Channel and Supply.
Defined as:
method lock(Lock::Async:D: --> Promise:D)
Returns a Promise that will be kept when the lock is available. In the case that the lock is already available, an already kept Promise will be returned. Use await to wait for the lock to be available in a non-blocking manner.
my $l = Lock::Async.new; await $l.lock;
Prefer to use protect instead of explicit calls to lock and unlock.
Defined as:
method unlock(Lock::Async:D: --> Nil)
Releases the lock. If there are any outstanding lock Promises, the one at the head of the queue will then be kept, and potentially code scheduled on the thread pool (so the cost of calling unlock is limited to the work needed to schedule another piece of code that wants to obtain the lock, but not to execute that code).
my $l = Lock::Async.new; await $l.lock; $l.unlock;
Prefer to use protect instead of explicit calls to lock and unlock. However, if wishing to use the methods separately, it is wise to use a LEAVE block to ensure that unlock is reliably called. Failing to unlock will mean that nobody can ever lock this particular Lock::Async instance again.
my $l = Lock::Async.new; { await $l.lock; LEAVE $l.unlock; }
Defined as:
method protect(Lock::Async:D: &code)
Calls lock, does an await to wait for the lock to be available, and reliably calls unlock afterwards, even if the code throws an exception.
Note that the Lock::Async itself needs to be created outside the portion of the code that gets threaded and it needs to protect. In the first example below, Lock::Async is first created and assigned to $lock, which is then used inside the Promises to protect the sensitive code. In the second example, a mistake is made, the Lock::Async is created right inside the Promise, so the code ends up with a bunch of separate locks, created in a bunch of threads, and thus they don't actually protect the code we want to protect.
# Right: $lock is instantiated outside the portion of the # code that will get threaded and be in need of protection my $lock = Lock::Async.new; await ^20 .map: { start { $lock.protect: { print "Foo"; sleep rand; say "Bar"; } } } # !!! WRONG !!! Lock::Async is instantiated inside threaded area! await ^20 .map: { start { my $lock = Lock::Async.new; $lock.protect: { print "Foo"; sleep rand; say "Bar"; } } }
Defined as:
method protect-or-queue-on-recursion(Lock::Async:D: &code)
When calling protect on a Lock::Async instance that is already locked, the method is forced to block until the lock gets unlocked. protect-or-queue-on-recursion avoids this issue by either behaving the same as protect if the lock is unlocked or the lock was locked by something outside the caller chain, returning Nil, or queueing the call to &code and returning a Promise if the lock had already been locked at another point in the caller chain.
my Lock::Async $lock .= new; my Int $count = 0; # The lock is unlocked, so the code runs instantly. $lock.protect-or-queue-on-recursion({ $count++ }); # Here, we have caller recursion. The outer call only returns a Promise # because the inner one does. If we try to await the inner call's Promise # from the outer call, the two calls will block forever since the inner # caller's Promise return value is just the outer's with a then block. $lock.protect-or-queue-on-recursion({ $lock.protect-or-queue-on-recursion({ $count++ }).then({ $count++ }) }); # Here, the lock is locked, but not by anything else on the caller chain. # This behaves just like calling protect would in this scenario. for 0..^2 { $lock.protect-or-queue-on-recursion({ $count++; }); } say $count; # OUTPUT: 5
Defined as:
method with-lock-hidden-from-recursion-check(&code)
Temporarily resets the Lock::Async recursion list so that it no longer includes the lock this method is called on and runs the given &code immediately if the call to the method occurred in a caller chain where protect-or-queue-on-recursion has already been called and the lock has been placed on the recursion list.
my Lock::Async $lock .= new; my Int $count = 0; $lock.protect-or-queue-on-recursion({ my Int $count = 0; # Runs instantly. $lock.with-lock-hidden-from-recursion-check({ $count++; }); # Runs after the outer caller's protect-or-queue-on-recursion call has # finished running. $lock.protect-or-queue-on-recursion({ $count++; }).then({ say $count; # OUTPUT: 2 }); say $count; # OUTPUT: 1 });
Compile-time routine
class Macro is Routine { }
A macro is a Routine whose invocation typically happens during parsing. By returning an AST, a macro can inject code into the calling location.
Immutable mapping from strings to values
class Map does Associative does Iterable { }
A Map is an immutable mapping from string keys to values of arbitrary types. It serves as a base class for Hash, which is mutable.
In list context a Map behaves as a list of Pair objects.
Note that the order in which keys, values and pairs are retrieved is generally arbitrary, but the keys, values and pairs methods return them always in the same order when called on the same object.
my %e := Map.new('a', 1, 'b', 2); say %e.keys; # can print "a b\n" or "b a\n"; say %e.values; # prints "1 2\n" if the previous line # printed "a b\n", "b a\n" otherwise
To retrieve a value from the Map by key, use the { } postcircumfix operator:
my $map = Map.new('a', 1, 'b', 2); say $map{'a'}; # OUTPUT: «1» say $map{ 'a', 'b' }; # OUTPUT: «(1 2)»
To check whether a given key is stored in a Map, modify the access with the :exists adverb:
my $map = Map.new('a', 1, 'b', 2); my $key = 'a'; if $map{$key}:exists { say "$map{} has key $key"; }
Being an immutable instance, it is not possible to add keys after a Map has been initialized:
my $m = Map.new( 'a', 1, 'b', 2 ); $m{ 'c' } = 'foo'; # WRONG! # Cannot modify an immutable Str
Defined as:
method new(*@args)
Creates a new Map from a list of alternating keys and values, with the same semantics as described for hash assigning in the Hash documentation, except, for literal pair handling. To ensure pairs correctly get passed, add extra parentheses around all the arguments.
my %h = Map.new('a', 1, 'b', 2); # WRONG: :b(2) interpreted as named argument say Map.new('a', 1, :b(2) ).keys; # OUTPUT: «(a)» # RIGHT: :b(2) interpreted as part of Map's contents say Map.new( ('a', 1, :b(2)) ).keys; # OUTPUT: «(a b)»
Defined as:
method elems(Map:D: --> Int:D)
Returns the number of pairs stored in the Map.
my %map = Map.new('a', 1, 'b', 2); say %map.elems; # OUTPUT: «2»
Defined as:
multi method ACCEPTS(Map:D: Positional $topic) multi method ACCEPTS(Map:D: Cool:D $topic) multi method ACCEPTS(Map:D: Regex $topic) multi method ACCEPTS(Map:D: Any $topic)
Used in smartmatching if the right-hand side is an Map.
If the topic is list-like (Positional), returns True if any of the list elements exist as a key in the Map.
If the topic is of type Cool (strings, integers etc.), returns True if the topic exists as a key.
If the topic is a regex, returns True if any of the keys match the regex.
As a fallback, the topic is coerced to a list, and the Positional behavior is applied.
Defined as:
method gist(Map:D: --> Str:D)
Returns the string containing the "gist" of the Map, sorts the pairs and lists up to the first 100, appending an ellipsis if the Map has more than 100 pairs.
Defined as:
method keys(Map:D: --> Seq:D)
Returns a Seq of all keys in the Map.
my $m = Map.new('a' => (2, 3), 'b' => 17); say $m.keys; # OUTPUT: «(a b)»
Defined as:
method values(Map:D: --> Seq:D)
Returns a Seq of all values in the Map.
my $m = Map.new('a' => (2, 3), 'b' => 17); say $m.values; # OUTPUT: «((2 3) 17)»
Defined as:
method pairs(Map:D: --> Seq:D)
Returns a Seq of all pairs in the Map.
my $m = Map.new('a' => (2, 3), 'b' => 17); say $m.pairs; # OUTPUT: «(a => (2 3) b => 17)»
Defined as:
method antipairs(Map:D: --> Seq:D)
Returns all keys and their respective values as a Seq of Pairs where the keys and values have been exchanged, i.e. the opposite of method pairs. Unlike the invert method, there is no attempt to expand list values into multiple pairs.
my $m = Map.new('a' => (2, 3), 'b' => 17); say $m.antipairs; # OUTPUT: «((2 3) => a 17 => b)»
Defined as:
method invert(Map:D: --> Seq:D)
Returns all keys and their respective values as a Seq of Pairs where the keys and values have been exchanged. The difference between invert and antipairs is that invert expands list values into multiple pairs.
my $m = Map.new('a' => (2, 3), 'b' => 17); say $m.invert; # OUTPUT: «(2 => a 3 => a 17 => b)»
Defined as:
method kv(Map:D: --> Seq:D)
Returns a Seq of keys and values interleaved.
Map.new('a', 1, 'b', 2).kv # (a 1 b 2)
Defined as:
method list(Map:D: --> List:D)
Returns a List of all keys and values in the Map.
my $m = Map.new('a' => (2, 3), 'b' => 17); say $m.list; # OUTPUT: «(b => 17 a => (2 3))»
Defined as:
multi method sort(Map:D: --> Seq:D)
Returns a Seq of Pair objects, which are the pairs of the hash, sorted by key. Equivalent to %hash.sort: *.key
# These are equivalent: say Map.new(<c 3 a 1 b 2>).sort; # OUTPUT: «(a => 1 b => 2 c => 3)» say Map.new(<c 3 a 1 b 2>).sort: *.key; # OUTPUT: «(a => 1 b => 2 c => 3)»
See Any.sort for additional available candidates.
Defined as:
method Int(Map:D: --> Int:D)
Returns the number of pairs stored in the Map (same as .elems).
my $m = Map.new('a' => 2, 'b' => 17); say $m.Int; # OUTPUT: «2»
Defined as:
method Numeric(Map:D: --> Int:D)
Returns the number of pairs stored in the Map (same as .elems).
my $m = Map.new('a' => 2, 'b' => 17); say $m.Numeric; # OUTPUT: «2»
Defined as:
method Bool(Map:D: --> Bool:D)
Returns True if the invocant contains at least one key/value pair.
my $m = Map.new('a' => 2, 'b' => 17); say $m.Bool; # OUTPUT: «True»
Defined as:
method Capture(Map:D:)
Returns a Capture where each key, if any, has been converted to a named argument with the same value as it had in the original Map. The returned Capture will not contain any positional arguments.
my $map = Map.new('a' => 2, 'b' => 17); my $capture = $map.Capture; my-sub(|$capture); # RESULT: «2, 17» sub my-sub(:$a, :$b) { say "$a, $b" }
Result of a successful regex match
class Match is Capture is Cool does NQPMatchRole {}
Match objects are the result of a successful regex match, this does include any zero-width match. They store a reference to the original string (.orig), positional and named captures, the positions of the start and end of the match in the original string, and a payload referred to as AST (abstract syntax tree), which can be used to build data structures from complex regexes and grammars.
The last match is also stored in the $¢ Match object, which is lexically scoped to the regex, that is, only available from within the regular expression, as shown here:
my $c; 'abc' ~~ /.$${ $c = $¢ }/; say $c; # OUTPUT: «「c」»
In this case, we are running the code among curly braces when the match occurs, in this case the last letter in the string (actually, the last, indicated by the double $, character); $c gets the value of the cursor $¢, which contains the Match; when used with say, the Match is stringified by calling .Str on it. This $¢ offers a way of capturing the Match inside a regular expression; outside, you need to use $/
my $c; 'camelia' ~~ /<[ l m ]> {$c = $¢}/; say $c; # OUTPUT: «「m」» say $/; # OUTPUT: «「m」»
Note: This feature works only from Perl 6 version 2018.02. It would have returned Nil with any previous version. Alternatively and prior to that version, you could use $/ which, inside the regex, has the same value:
'123' ~~ / (\d) { say $0; say $/; } \d+ /; # OUTPUT: «「1」「1」 0 => 「1」»
The main difference between $/ and $¢ is scope: the latter only has a value inside the regex:
'123' ~~ / (\d) { say $/; say $¢; } \d+ /; # OUTPUT: «「1」 0 => 「1」「1」 0 => 「1」» say "¢ → ", $¢, "/ is $/"; ; # OUTPUT: «¢ → Nil/ is 123»
Submatches are also Match objects (or lists of Match objects, if the corresponding regex was quantified), so each match object can be seen as the root of a tree of match objects.
A Match object can also hold the result of a match in progress (while the grammar engine is running), in which case the pos method returns the current position. This view on Match objects is only visible if you call code from within a regex.
method pos()
Returns the current position as a string index into Match.target for a regex match in progress:
my $a = 'abcdef'; $a ~~ /b. {say $/.pos }../; say $/.pos; # OUTPUT: «3»
You should not use this method on finished Match, as the output can be implementation specific.
method target()
Returns a string representation of the object against which the regex matches. This is the value that the regex engine works with internally.
my $a = "þor" ~~ /o/; say $a.target # OUTPUT: «þor»
Returns the numbers of characters in the matched string.
Returns the same as .Str.chars.
Defined as:
method clone()
Clones the Match object.
Returns the original input to the regex engine, which is usually a string, but doesn't need to be (could be anything that can be coerced to a string):
42 ~~ /.+/; say $/.orig; # OUTPUT: «42» say $/.orig.^name; # OUTPUT: «Int»
See #method target for a close equivalent that always returns a string.
Returns the index of the starting position of the match.
Returns the index of the end position of the match.
Returns the payload that was set with make.
Defined as
method make(Match:D: Mu $payload) sub make(Mu $payload)
Sets the .ast attribute, which will be retrieved using .made.
$/.make("your payload here");
That is, it stores an arbitrary payload into the Match object that can later be retrieved via .made method.
This is typically used in a grammar's actions class methods, where a piece of data is stored by one method and then later retrieved by another. It's up to you what data you store. It could be a tree node, result of a calculation, or a list of values.
The sub form operates on the current Match $/, which can be a convenient shortcut:
method my-action ($/) { make "foo: $/"; }
method actions(Match:D: --> Mu)
Returns the actions object (if any was set; else Mu) that the grammar used from which this Match object was created.
Alias for #method made.
Defined as:
method Bool(Capture:D: --> Bool:D)
Returns True on successful and False on unsuccessful matches. Please note that any zero-width match can also be successful.
say 'abc' ~~ /^/; # OUTPUT: «「」» say $/.from, ' ', $/.to, ' ', ?$/; # OUTPUT: «0 0 True»
Defined as:
method Str(Match:D: --> Str:D)
Returns the matched text.
"abc123def" ~~ /\d+/; say $/.Str; # OUTPUT: «123»
Defined as:
method Int(Match:D: --> Int:D)
Tries to convert stringified result of the matched text into Int.
say ('12345' ~~ /234/).Int; # OUTPUT: «234» say ('12345' ~~ /234/).Int.^name; # OUTPUT: «Int» # the next line produces a warning about using Nil (result of a no match) in numeric context say ('one-two' ~~ /234/).Int; # OUTPUT: «0» # because Nil.Int returns 0
Returns a list of pairs, with the index or submatch name as key and the submatches as values. The list is ordered by starting position of the submatches.
Returns a list of pairs, with the index or submatch name as key and the submatches as values. The list is ordered by starting position of the submatches.
Those parts of the string that were not matched by submatches are interleaved with the other pairs, with the string ~ as key.
Returns a list of positional submatches.
Returns a hash of named submatches.
Defined as:
method prematch(Match:D: --> Str:D)
Returns the part of the original string leading up to the match.
'abcdefg' ~~ /cd/; say $/.prematch; # OUTPUT: «ab» # will return a list of three match objects "abc123def" ~~ m:g/\d/; say $/.[1].prematch; # OUTPUT: «abc1»
Defined as:
method postmatch(Match:D: --> Str:D)
Returns the part of the original string following the match.
'abcdefg' ~~ /cd/; say $/.postmatch; # OUTPUT: «efg» # will return a list of three match objects "abc123def" ~~ m:g/\d/; say $/.[1].postmatch; # OUTPUT: «3def»
Defined as:
multi sub infix:<eqv>(Match:D \a, Match:D \b)
Returns True if the attributes pos, from and orig are equal, and if made, Capture::list and Capture::hash are either the same or both undefined.
Metaobject that can hold attributes
role Metamodel::AttributeContainer {}
Classes, roles and grammars can have attributes. Storage and introspection of attributes is implemented by this role.
method add_attribute(Metamodel::AttributeContainer: $obj, $attribute)
Adds an attribute. $attribute must be an object that supports the methods name, type and package, which are called without arguments. It can for example be of type Attribute.
method attributes(Metamodel::AttributeContainer: $obj)
Returns a list of attributes. For most Perl 6 types, these will be objects of type Attribute.
method set_rw(Metamodel::AttributeContainer: $obj)
Marks a type whose attributes default to having a write accessor. For example in
class Point is rw { has $.x; has $.y; }
The is rw trait on the class calls the set_rw method on the meta class, making all the attributes implicitly writable, so that you can write;
my $p = Point.new(x => 1, y => 2); $p.x = 42;
method rw(Metamodel::AttributeContainer: $obj)
Returns a true value if method set_rw has been called on this object, that is, if new public attributes are writable by default.
TODO: compose_attributes, get_attribute_for_usage Also TODO: describe :local, :excl, :all options of method attributesMetaobject that supports the C3 method resolution order
role Metamodel::C3MRO { }
Meta model role for the C3 method resolution order (MRO). Note: this method, along with almost the whole metamodel, is part of the Rakudo implementation.
The method resolution order for a type is a flat list of types including the type itself, and (recursively) all super classes. It determines in which order the types will be visited for determining which method to call with a given name, or for finding the next method in a chain with nextsame, callsame, nextwith or callwith.
class CommonAncestor { }; # implicitly inherits from Any class Child1 is CommonAncestor { } class Child2 is CommonAncestor { } class GrandChild2 is Child2 { } class Weird is Child1 is GrandChild2 { }; say Weird.^mro; # OUTPUT: «(Weird) (Child1) (GrandChild2) (Child2) (CommonAncestor) (Any) (Mu)»
C3 is the default resolution order for classes and grammars in Perl 6. Note that roles generally do not appear in the method resolution order (unless they are punned into a class, from which another type inherits), because methods are copied into classes at role application time.
method compute_mro($type)
Computes the method resolution order.
method mro($type)
Returns a list of types in the method resolution order, even those that are marked is hidden.
say Int.^mro; # OUTPUT: «((Int) (Cool) (Any) (Mu))»
method mro_unhidden($type)
Returns a list of types in method resolution order, excluding those that are marked with is hidden.
Metaobject representing a Perl 6 class.
class Metamodel::ClassHOW does Metamodel::Naming does Metamodel::Documenting does Metamodel::Versioning does Metamodel::Stashing does Metamodel::AttributeContainer does Metamodel::MethodContainer does Metamodel::PrivateMethodContainer does Metamodel::MultiMethodContainer does Metamodel::RoleContainer does Metamodel::MultipleInheritance does Metamodel::DefaultParent does Metamodel::C3MRO does Metamodel::MROBasedMethodDispatch does Metamodel::MROBasedTypeChecking does Metamodel::Trusting does Metamodel::BUILDPLAN does Metamodel::Mixins does Metamodel::ArrayType does Metamodel::BoolificationProtocol does Metamodel::REPRComposeProtocol does Metamodel::InvocationProtocol does Metamodel::Finalization { }
Metamodel::ClassHOW is the meta class behind the class keyword.
say so Int.HOW ~~ Metamodel::ClassHOW; # OUTPUT: «True» say Int.^methods(:all).pick.name; # OUTPUT: «random Int method name»
Warning: This class is part of the Rakudo implementation, not a part of the language itself.
method add_fallback(Metamodel::ClassHOW:D: $obj, $condition, $calculator)
Installs a method fallback, that is, add a way to call methods that weren't statically added.
Both $condition and $calculator must be callables that receive the invocant and the method name once a method is called that can't be found in the method cache.
If $condition returns a true value, $calculator is called with the same arguments, and must return the code object to be invoked as the method, and is added to the method cache.
If $condition returns a false value, the next fallback (if any) is tried, and if none matches, an exception of type X::Method::NotFound is thrown.
User-facing code (that is, code not dabbling with meta classes) should use method FALLBACK instead.
method can(Metamodel::ClassHOW:D: $obj, $method-name)
Given a method name, it returns a List of methods that are available with this name.
class A { method x($a) {} }; class B is A { method x() {} }; say B.^can('x').elems; # OUTPUT: «2» for B.^can('x') { say .arity; # OUTPUT: «1, 2» }
In this example, class B has two possible methods available with name x (though a normal method call would only invoke the one installed in B directly). The one in B has arity 1 (i.e. it expects one argument, the invocant (self)), and the one in A expects 2 arguments (self and $a).
method lookup(Metamodel::ClassHOW:D: $obj, $method-name --> Method:D)
Returns the first matching Method with the provided name. If no method was found, returns a VM-specific sentinel value (typically a low-level NULL value) that can be tested for with a test for definedness. It is potentially faster than .^can but does not provide a full list of all candidates.
say Str.^lookup('Int').perl; # OUTPUT: «method Int (Str:D $: *%_) { #`(Method|39910024) ... }» for <upper-case uc> { Str.^lookup: $^meth andthen .("foo").say orelse "method `$meth` not found".say } # OUTPUT: # method `upper-case` not found # FOO
method compose(Metamodel::ClassHOW:D: $obj)
A call to compose brings the meta object and thus the class it represents into a fully functional state, so if you construct or modify a class, you must call the compose method before working with the class.
It updates the method cache, checks that all methods that are required by roles are implemented, does the actual role composition work, and sets up the class to work well with language interoperability.
method (:$name, :$repr = 'P6opaque', :$ver, :$auth)
Creates a new type from the metamodel, which we can proceed to build
my $type = Metamodel::ClassHOW.new_type(name => "NewType", ver => v0.0.1, auth => 'github:perl6' ); $type.HOW.add_method($type,"hey", method { say "Hey" }); $type.hey; # OUTPUT: «Hey» $type.HOW.compose($type); my $instance = $type.new; $instance.hey; # OUTPUT: «Hey»
We add a single method by using Higher Order Workings methods, and then we can use that method directly as class method; we can then compose the type, following which we can create already an instance, which will behave in the exact same way.
Provides an implementation of a concrete instance of a role
class Metamodel::ConcreteRoleHOW does Metamodel::Naming does Metamodel::Versioning does Metamodel::PrivateMethodContainer does Metamodel::MethodContainer does Metamodel::MultiMethodContainer does Metamodel::AttributeContainer does Metamodel::RoleContainer does Metamodel::MultipleInheritance does Metamodel::ArrayType does Metamodel::Concretization {}
You can use this to build roles, in the same way that ClassHOW can be used to build classes:
my $a = Metamodel::ConcreteRoleHOW.new_type(name => "Bar"); $a.^compose; say $a.^roles; # OUTPUT: «(Mu)»
The main difference with ClassHOW.new_type is that you can mix-in roles in this newly created one.
This class is Rakudo specific, and provided only for completeness. Not really intended to be used by the final user.
Support for parameterized roles that have not been instantiated
class Metamodel::CurriedRoleHOW does Metamodel::Naming does Metamodel::TypePretense does Metamodel::RolePunning {}
Sometimes, we see references to roles that provide parameters but do not fully resolve them. For example, in:
class C does R[Type] { }
We need to represent R[T], but we cannot yet fully specialize the role because we don't have the first parameter at hand. We may also run into the issue where we have things like:
sub foo(R[T] $x) { ... } if $x ~~ R[T] { ... }
Where we clearly want to talk about a partial parameterization of a role and actually want to do so in a way distinct from a particular instantiation of it. This meta-object represents those "partial types" as both a way to curry on your way to a full specialization, but also as a way to do type-checking or punning.
This class will show up in parameterized roles. For instance:
role Zipi[::T] { method zape { "Uses " ~ T.^name }; } role Zipi[::T, ::Y] { method zape { "Uses " ~ T.^name ~ " and " ~ Y.^name }; } for Zipi[Int], Zipi[Int,Str] -> $role { say $role.HOW; say $role.new().zape; } # OUTPUT: # Perl6::Metamodel::CurriedRoleHOW.new # Uses Int # Perl6::Metamodel::CurriedRoleHOW.new # Uses Int and Str
Since there are several variants of Zipi, providing a parameter curries it, but it's still up to the compiler to find out the actual realization taking into account the ParametricRoleGroup, so these (partially instantiated) roles show up as Metamodel::CurriedRoleHOW as shown in the example; even if there's a single parameter an instantiated role will also be of the same type:
role Zape[::T] {}; say Zape[Int].HOW; #: «Perl6::Metamodel::CurriedRoleHOW.new»
Note: As most of the Metamodel classes, this class is here mainly for illustration purposes and it's not intended for the final user to instantiate.
Metaobject representing a Perl 6 enum.
class Metamodel::EnumHOW does Metamodel::Naming does Metamodel::Documenting does Metamodel::Stashing does Metamodel::AttributeContainer does Metamodel::MethodContainer does Metamodel::MultiMethodContainer does Metamodel::RoleContainer does Metamodel::BaseType does Metamodel::MROBasedMethodDispatch does Metamodel::MROBasedTypeChecking does Metamodel::BUILDPLAN does Metamodel::BoolificationProtocol does Metamodel::REPRComposeProtocol does Metamodel::InvocationProtocol does Metamodel::Mixins { }
Metamodel::EnumHOW is the meta-class behind the enum keyword.
enum Numbers <1 2>; say Numbers.HOW ~~ Metamodel::EnumHOW; # OUTPUT: «True»
The following enum declaration:
our Int enum Error <Warning Failure Exception Sorrow Panic>;
Is roughly equivalent to this code using Metamodel::EnumHOW's methods:
BEGIN { my constant Error = Metamodel::EnumHOW.new_type: :name<Error>, :base_type(Int); Error.^add_role: Enumeration; Error.^add_role: NumericEnumeration; Error.^compose; for <Warning Failure Exception Sorrow Panic>.kv -> Int $v, Str $k { # Note: Enumeration.pred and .succ will not work when adding enum # values as pairs. They should be instances of the enum itself, but # this isn't possible to do without nqp. Error.^add_enum_value: $k => $v; OUR::{$k} := Error.^enum_from_value: $v; } Error.^compose_values; OUR::<Error> := Error; }
Warning: This class is part of the Rakudo implementation, and is not a part of the language specification.
method new_type(:$name!, :$base_type?, :$repr = 'P6opaque', :$is_mixin)
Creates a new type object for an enum. $name is the enum name, $base_type is the type given when the enum is declared using a scoped declaration (if any), and $repr is the type representation passed to the enum using the repr trait. $is_mixin is unused.
method add_parent($obj, $parent)
Sets the base type of an enum. This can only be used if no base type was passed to .new_type.
method set_export_callback($obj, $callback)
Sets the enum's export callback, which is invoked when calling .compose_values. This is called when applying the export trait to an enum. $callback should be a routine of some sort, taking no arguments, that handles exporting the enum's values.
method export_callback($obj)
Returns the export callback set by .set_export_callback.
method compose($obj, :$compiler_services)
Completes a type object for an enum. This is when any roles done by the enum are mixed in. This needs to be called before any enum values can be added using .add_enum_value.
method is_composed($obj)
Returns 1 if the enum is composed, otherwise returns 0.
method compose_values($obj)
Calls the export callback set by .set_export_callback and removes it from state. This should be called after adding the enum's values using .add_enum_value.
method set_composalizer($c)
Sets the composalizer for an enum, which produces a type that can be mixed in with another. $c should be a routine of some that has the following signature:
:($type, $name, @enum_values)
method composalizer($obj)
Returns the composalizer set by .set_composalizer.
method add_enum_value($obj, $value)
Adds a value to this enum. $value should be an instance of the enum itself, as type Enumeration.
method enum_values($obj)
Returns the values for the enum.
enum Numbers <10 20>; say Numbers.^enum_values; # OUTPUT: {10 => 0, 20 => 1}
method elems($obj)
Returns the number of values.
enum Numbers <10 20>; say Numbers.^elems; # OUTPUT: 2
method enum_from_value($obj, $value)
Given a value of the enum's base type, return the corresponding enum.
enum Numbers <10 20>; say Numbers.^enum_from_value(0); # OUTPUT: 10
method enum_value_list($obj)
Returns a list of the enum values.
enum Numbers <10 20>; say Numbers.^enum_value_list; # OUTPUT: (10 20)
Metaobject supporting object finalization
role Metamodel::Finalization { ... }
This role takes care that DESTROY submethods are called (if they exist) when an object is garbage-collected.
method setup_finalization(Metamodel::Finalization:D: $obj)
Collects the DESTROY submethods from this class and all its superclasses, and marks the class as needing action on garbage collection.
A metamodel for a kind that implements finalization semantics must call this method at type composition time.
method destroyers(Metamodel::Finalization:D: $obj --> List:D)
Returns a list of all finalization methods.
Metaobject that supports resolving inherited methods
role Metamodel::MROBasedMethodDispatch { }
This role implements locating methods based on the method resolution order of related (usually "super"/"parent") types.
method find_method($obj, $name, $no_fallback, *%adverbs)
Given a method name, it returns the method object of that name which is closest in the method resolution order (MRO). If no method can be found, it returns a VM-specific sentinel value (typically a low-level NULL value) that can be tested for with a test for definedness:
for <upper-case uc> { Str.^find_method: $^meth andthen .("foo").say orelse "method `$meth` not found".say } # OUTPUT: # method `upper-case` not found # FOO
If :no_fallback is supplied, fallback methods are not considered.
method find_method_qualified($obj, $type, $name)
Given a method name and a type, returns the method from that type. This is used in calls like
self.SomeParentClass::the_method();
method can($obj, $name)
Returns the list of methods of that name the object can do.
Defined as:
method publish_method_cache($obj)
Walk MRO and add methods to cache, unless another method lower in the class hierarchy "shadowed" it.
Metaobject that supports storing and introspecting methods
role Metamodel::MethodContainer {}
roles, classes, grammars and enums can contain methods. This role implements the API around storing and introspecting them.
say .name for Int.^methods(:all); # don't do that, because it changes type Int globally. # just for demonstration purposes. Int.^add_method('double', method ($x:) { 2 * $x }); say 21.double; # OUTPUT: «42»
method add_method(Metamodel::MethodContainer: $obj, $name, $code)
Adds a method to the meta class, to be called with name $name. This should only be done before a type is composed.
method methods(Metamodel::MethodContainer: $obj, :$all, :$local)
Returns a list of public methods available on the class (which includes methods from superclasses and roles). By default this stops at the classes Cool, Any or Mu; to really get all methods, use the :all adverb. If :local is set, only methods declared directly in the class are returned.
class A { method x() { }; } say A.^methods(); # x say A.^methods(:all); # x infinite defined ...
The returned list contains objects of type Method, which you can use to introspect their signatures and call them.
Some introspection method-look-alikes like WHAT will not show up, although they are present in any Perl 6 object. They are handled at the grammar level and will likely remain so for bootstrap reasons.
method method_table(Metamodel::MethodContainer:D: $obj --> Hash:D)
Returns a hash where the keys are method names, and the values are methods. Note that the keys are the names by which the methods can be called, not necessarily the names by which the methods know themselves.
method lookup(Metamodel::MethodContainer: $obj, $name --> Method)
Returns the first matching method object of the provided $name or (Mu) if no method object was found. The search for a matching method object is done by following the mro of $obj. Note that lookup is supposed to be used for introspection, if you're after something which can be invoked you probably want to use find_method instead.
say 2.5.^lookup("sqrt").perl: # OUTPUT: «method sqrt (Rat $: *%_) ...» say Str.^lookup("BUILD").perl; # OUTPUT: «submethod BUILD (Str $: :$value = "", *%_ --> Nil) ...» say Int.^lookup("does-not-exist"); # OUTPUT: «(Mu)»
The difference between find_method and lookup are that find_method will use a default candidate for parametric roles, whereas lookup throws an exception in this case, and that find_method honors FALLBACK methods, which lookup does not.
TODO: submethod_table, declares_method, cache, cache_get, cache_addMetaobject that supports multiple inheritance
role Metamodel::MultipleInheritance {}
Classes, roles and grammars can have parent classes, that is, classes to which method lookups fall back to, and to whose type the child class conforms to.
This role implements the capability of having zero, one or more parent (or super) classes.
In addition, it supports the notion of hidden classes, whose methods are excluded from the normal dispatching chain, so that for example nextsame ignores it.
This can come in two flavors: methods from a class marked as is hidden are generally excluded from dispatching chains, and class A hides B adds B as a parent class to A, but hides it from the method resolution order, so that mro_unhidden skips it.
method add_parent(Metamodel::MultipleInheritance:D: $Obj, $parent, :$hides)
Adds $parent as a parent type. If $hides is set to a true value, the parent type is added as a hidden parent.
$parent must be a fully composed typed. Otherwise an exception of type X::Inheritance::NotComposed is thrown.
method parents(Metamodel::MultipleInheritance:D: $obj, :$all, :$tree)
Returns the list of parent classes. By default it stops at Cool, Any or Mu, which you can suppress by supplying the :all adverb. With :tree, a nested list is returned.
class D { }; class C1 is D { }; class C2 is D { }; class B is C1 is C2 { }; class A is B { }; say A.^parents(:all).perl; # OUTPUT: «(B, C1, C2, D, Any, Mu)» say A.^parents(:all, :tree).perl; # OUTPUT: «[B, ([C1, [D, [Any, [Mu]]]], [C2, [D, [Any, [Mu]]]])]»
method hides(Metamodel::MultipleInheritance:D: $obj)
Returns a list of all hidden parent classes.
method hidden(Metamodel::MultipleInheritance:D: $obj)
Returns a true value if (and only if) the class is marked is hidden.
method set_hidden(Metamodel::MultipleInheritance:D: $obj)
Marks the type as hidden.
Metaobject that supports named types
role Metamodel::Naming { }
Meta model role for (optionally) named things, like classes, roles and enums.
method name($type)
Returns the name of the meta object, if any.
say 42.^name; # OUTPUT: «Int»
method set_name($type, $new_name)
Sets the new name of the meta object.
Metaobject representing a Perl 6 package.
class Metamodel::PackageHOW does Metamodel::Naming does Metamodel::Documenting does Metamodel::Stashing does Metamodel::TypePretense does Metamodel::MethodDelegation { }
Metamodel::ClassHOW is the meta class behind the package keyword.
package P {}; say P.HOW; # OUTPUT: «Perl6::Metamodel::PackageHOW.new»
Warning: This class is part of the Rakudo implementation, not a part of the language itself.
Defined as:
method archetypes()
Returns the archetypes for this model, that is, the properties a meta-type can implement.
Defined as:
method new(*%named)
Creates a new PackageHOW.
Defined as:
method new_type(:$name = '<anon>', :$repr, :$ver, :$auth)
Creates a new package, with optional representation, version and auth field.
Defined as:
method compose($obj, :$compiler_services)
Sets the meta-package as composed.
Defined as:
method is_composed($obj)
Returns the composed status of the meta-package.
Represents a group of roles with different parameterizations
class Metamodel::ParametricRoleGroupHOW does Metamodel::Naming does Metamodel::Documenting does Metamodel::Stashing does Metamodel::TypePretense does Metamodel::RolePunning does Metamodel::BoolificationProtocol {}
A ParametricRoleGroupHOW groups a set of ParametricRoleHOW, every one of them representing a single role declaration with their own parameter sets.
(role Zape[::T] {}).HOW.say; # OUTPUT: «Perl6::Metamodel::ParametricRoleHOW.new» Zape.HOW.say ; # OUTPUT: «Perl6::Metamodel::ParametricRoleGroupHOW.new»
ParametricRoleHOWs need to be added to this kind of group:
my \zape := Metamodel::ParametricRoleGroupHOW.new_type( name => "zape"); my \zipi := Metamodel::ParametricRoleHOW.new_type( name => "zipi", group => zape); say zipi.HOW; # OUTPUT: «Perl6::Metamodel::ParametricRoleHOW.new»
Note: As most of the Metamodel classes, this class is here mainly for illustration purposes and it's not intended for the final user to instantiate.
Represents a non-instantiated, parameterized, role.
class Metamodel::ParametricRoleHOW does Metamodel::Naming does Metamodel::Documenting does Metamodel::Versioning does Metamodel::MethodContainer does Metamodel::PrivateMethodContainer does Metamodel::MultiMethodContainer does Metamodel::AttributeContainer does Metamodel::RoleContainer does Metamodel::MultipleInheritance does Metamodel::Stashing does Metamodel::TypePretense does Metamodel::RolePunning does Metamodel::ArrayType {}
A Metamodel::ParametricRoleHOW represents a non-instantiated, possibly parameterized, role:
(role Zape[::T] {}).HOW.say;# OUTPUT: «Perl6::Metamodel::ParametricRoleHOW.new» (role Zape {}).HOW.say; # OUTPUT: «Perl6::Metamodel::ParametricRoleHOW.new»
As usual, .new_type will create a new object of this class.
my \zipi := Metamodel::ParametricRoleHOW.new_type( name => "zape", group => "Zape"); say zipi.HOW; # OUTPUT: «Perl6::Metamodel::ParametricRoleHOW.new»
The extra group argument will need to be used to integrate it in a parametric role group, which will need to be defined in advance.
Note: As most of the Metamodel classes, this one is here mainly for illustration purposes and it's not intended for the final user to instantiate, unless their intention is really to create a parametric role group.
Metaobject that supports low-level type operations
class Metamodel::Primitives {}
Metamodel::Primitives provides low-level operations for working with types, which are otherwise only available as implementation-dependent directives. These primitives are available as class methods.
Here is an example that steals the meta model instance from the Int class to create a custom type (usually you would create your own meta class if you mess with something as low-level), which allows calling of just one method called why:
my Mu $type := Metamodel::Primitives.create_type(Int.HOW, 'P6opaque'); $type.^set_name('why oh why?'); my %methods = why => sub ($) { say 42 }; Metamodel::Primitives.install_method_cache($type, %methods, :authoritative); $type.why; # 42 $type.list; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Method::NotFound: Method 'list' not found for invocant of class 'why oh why?'»
method create_type(Mu $how, $repr = 'P6opaque')
Creates and returns a new type from a meta object $how and a representation name.
method set_package(Mu $type, $package)
Sets the package associated with the type.
method install_method_cache( Mu $type, %cache, :$authoritative = True)
Installs a method cache, that is, a mapping from method names to code objects. If :authoritative is missing, or set to True, then calls of methods that do not exist in the cache will throw an exception of type X::Method::NotFound. If :authoritative is set to False, the usual fallback mechanism are tried.
method configure_type_checking( Mu $type, @cache, :$authoritative = True, :$call_accepts = False )
Configures the type checking for $type. @cache is a list of known types against which $type checks positively (so in a classical class-based system, the type itself and all recursive superclasses). If :authoritative is missing or True, this type will fail checks against all types not in @cache. If :call_accepts is True, the method ACCEPTS will be called for type checks against this type.
method configure_destroy(Mu $type, $destroy)
Configures whether DESTROY methods are called (if present) when the garbage collector collects an object of this type (if $destroy is set to a true value). This comes with a performance overhead, so should only be set to a true value if necessary.
method compose_type(Mu $type, $configuration)
Composes $type (that is, finalizes it to be ready for instantiation). See https://github.com/perl6/nqp/blob/master/docs/6model/repr-compose-protocol.markdown for what $configuration can contain (until we have better docs, sorry).
method rebless(Mu $object, Mu $type)
Changes $obj to be of type $type. This only works if $type type-checks against the current type of $obj, and if the storage of $object is a subset of that of $type.
method is_type(Mu \obj, Mu \type --> Bool:D)
Type-checks obj against type
Metaobject that supports private methods
role Metamodel::PrivateMethodContainer { ... }
In Perl 6, classes, roles and grammars can have private methods, that is, methods that are only callable from within the class, and are not inherited by types derived by inheritance.
class A { # the ! declares a private method method !double($x) { say 2 * $x; } method call-double($y) { # call with ! instead of . self!double($y); } }
For the purposes of dispatching and scoping, private methods are closer to subroutines than to methods. However they share access to self and attributes with methods.
method add_private_method(Metamodel::PrivateMethodContainer: $obj, $name, $code)
Adds a private method $code with name $name.
method private_method_table(Metamodel::PrivateMethodContainer: $obj)
Returns a hash of name => &method_object
TODO: document find_private_method, once we've figured out how to represent or catch nqp::null in Perl 6 landMetaobject that supports holding/containing roles
role Metamodel::RoleContainer {}
Implements the ability to hold roles to be held for composition.
class A does SomeRole {}
roughly corresponds to
class A { BEGIN A.^add_role(SomeRole); }
method add_role(Metamodel::RoleContainer:D: $obj, Mu $role)
Adds the $role to the list of roles to be composed.
method roles_to_compose(Metamodel::RoleContainer:D: $obj --> List:D)
returns a list of roles added with add_role, which are to be composed at type composition time.
Metaobject that supports
role Perl6::Metamodel::RolePunning {}
Implements the ability to create objects from Roles without the intermediate need to use a class. Not intended to be used directly (will in fact error if it's used), but via punning of roles, as below. This is also Rakudo specific and not part of the spec.
role A { method b { return "punned" } }; my $a = A.new; say $a.b; # OUTPUT: «punned»
Metaobject that supports trust relations between types
role Metamodel::Trusting is SuperClass { ... }
Normally, code in a class or role can only access its own private methods. If another type declares that it trusts that first class, then access to private methods of that second type is possible. Metamodel::Trusting implements that aspect of the Perl 6 object system.
class A { my class B { trusts A; # that's where Metamodel::Trusting comes in method !private_method() { say "Private method in B"; } } method build-and-poke { # call a private method from B # disallowed if A doesn't trust B B.new()!B::private_method(); } }; A.build-and-poke; # Private method in A
method add_trustee(Metamodel::Trusting:D: $type, Mu $trustee)
Trust $trustee.
class A { BEGIN A.^add_trustee(B); # same as 'trusts B'; }
method trusts(Metamodel::Trusting:D: $type --> List)
Returns a list of types that the invocant trusts.
class A { trusts Int; }; say .^name for A.^trusts; # Int
method is_trusted(Metamodel::Trusting:D: $type, $claimant)
Returns 1 if $type trusts $claimant, and 0 otherwise. Types always trust themselves.
Metaobjects that support versioning
role Metamodel::Versioning { ... }
Metamodel role for (optionally) versioning metaobjects.
When you declare a type, you can pass it a version, author, and/or API and get them, like so:
class Versioned:ver<0.0.1>:auth<github:Kaiepi>:api<1> { } say Versioned.^ver; # OUTPUT: «v0.0.1» say Versioned.^auth; # OUTPUT: «github:Kaiepi» say Versioned.^api; # OUTPUT: «1»
This is roughly equivalent to the following, which also sets them explicitly:
BEGIN { class Versioned { } Versioned.^set_ver: v0.0.1; Versioned.^set_auth: 'github:Kaiepi'; Versioned.^set_api: <1>; } say Versioned.^ver; # OUTPUT: «v0.0.1» say Versioned.^auth; # OUTPUT: «github:Kaiepi» say Versioned.^api; # OUTPUT: «1»
method ver($obj)
Returns the version of the metaobject, if any, otherwise returns Mu.
method auth($obj)
Returns the author of the metaobject, if any, otherwise returns an empty string.
method api($obj)
Returns the API of the metaobject, if any, otherwise returns an empty string.
method set_ver($obj, $ver)
Sets the version of the metaobject.
method set_auth($obj, $auth)
Sets the author of the metaobject.
method set_api($obj, $api)
Sets the API of the metaobject.
Member function
class Method is Routine { }
A type for methods that behave the same way then Routine with some exceptions listed in the following. For details of a method's parameter list see Signature.
To create a method outside a class definition, use the declarators my and method. If an identifier is provided the methods name will be injected into the scope specified by the declarator.
my $m = method ($invocant: $param) { say "$invocant: '$param'"; } "greeting".$m("hello"); # OUTPUT: «greeting: 'hello'» <a b c>.&(my method (List:D:) { say self.perl; self }).say; # OUTPUT: «("a", "b", "c")(a b c)»
The invocant of a method defaults to self. A type constraint including a type-smiley can be used and is honored both for methods defined in a class and for free floating methods. Call the latter with .& on an object.
my method m(Int:D: $b){ say self.^name } my $i = 1; $i.&m(<a>); # OUTPUT: «Int»
Methods will ignore extra named arguments where other types of Routine will throw at runtime. Extra arguments will be forwarded by nextsame and friends.
class A { multi method m(:$a, :$b) { say "2 named" } } class B is A { method m(:$a) { say "1 named"; nextsame } } B.m( :1a, :2b ); # OUTPUT: «1 named2 named»
sub lastcall(--> True)
Truncates the current dispatch chain, which means any calls to nextsame, callsame, nextwith, and callwith will not find any of the next candidates. Note that since samewith restarts the dispatch from the start, it's not affected by the truncation of current chain with lastcall.
Consider example below. foo(6) uses nextsame when lastcall hasn't been called, and so it reaches the Any candidate. foo(2) calls nextsame as well, but since lastcall was called first, the dispatch chain was truncated and the Any candidate was not reached. The last call, foo(1), calls lastcall too, however, it then uses samewith, which isn't affected by it, and so the dispatch re-starts from scratch, hits the Int candidate with the new argument 6, and then proceeds to the Any candidate via nextsame (which isn't affected by the lastcall that was used before the samewith was called):
multi foo (Int $_) { say "Int: $_"; lastcall when *.is-prime; nextsame when * %% 2; samewith 6 when * !%% 2; } multi foo (Any $x) { say "Any $x" } foo 6; say '----'; foo 2; say '----'; foo 1; # OUTPUT: # Int: 6 # Any 6 # ---- # Int: 2 # ---- # Int: 1 # Int: 6 # Any 6
Immutable collection of distinct objects with Real weights
class Mix does Mixy { }
A Mix is an immutable collection of distinct elements in no particular order that each have a real-number weight assigned to them. (For mutable mixes, see MixHash instead.)
Mixes are often used for performing weighted random selections - see .roll.
Objects/values of any type are allowed as mix elements. Within a Mix, items that would compare positively with the === operator are considered the same element, with a combined weight.
my $recipe = (butter => 0.22, sugar => 0.1, flour => 0.275, sugar => 0.02).Mix; say $recipe.elems; # OUTPUT: «3» say $recipe.keys.sort; # OUTPUT: «butter flour sugar» say $recipe.pairs.sort; # OUTPUT: «"butter" => 0.22 "flour" => 0.275 "sugar" => 0.12» say $recipe.total; # OUTPUT: «0.615»
Mixes can be treated as object hashes using the { } postcircumfix operator, which returns the corresponding numeric weight for keys that are elements of the mix, and 0 for keys that aren't:
my $recipe = (butter => 0.22, sugar => 0.1, flour => 0.275, sugar => 0.02).Mix; say $recipe<butter>; # OUTPUT: «0.22» say $recipe<sugar>; # OUTPUT: «0.12» say $recipe<chocolate>; # OUTPUT: «0»
Mixes can be composed using the mix subroutine (or Mix.new, for which it is a shorthand). Any positional parameters, regardless of their type, become elements of the mix - with a weight of 1 for each time the parameter occurred:
my $n = mix "a", "a", "b" => 0, 3.14, π, π; # The Pair is a single element say $n.keys.map: *.^name; # OUTPUT: «(Rat Pair Num Str)» say $n.pairs; # OUTPUT: «(3.14 => 1 (b => 0) => 1 3.141592653589793 => 2 a => 2)»
Alternatively, the .Mix coercer (or its functional form, Mix()) can be called on an existing object to coerce it to a Mix. Its semantics depend on the type and contents of the object. In general it evaluates the object in list context and creates a mix with the resulting items as elements, although for Hash-like objects or Pair items, only the keys become elements of the mix, and the (cumulative) values become the associated numeric weights:
my $n = ("a", "a", "b" => 0, "c" => 3.14).Mix; say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Str))» say $n.pairs; # OUTPUT: «(a => 2 c => 3.14)»
Elements with a 0 value, as b above, are simply eliminated from the Mix.
Alternatively, since Mixes are Associative, we can use the % sigil to declare them; in that case, we can employ is to declare their type:
my %n is Mix = ("a", "a", "b" => 0, "c" => 3.14); say %n.^name; # OUTPUT: «Mix» say %n; # OUTPUT: «Mix(a(2), c(3.14))»
Since 6.d (2019.03 and later) it is also possible to specify the type of values you would like to allow in a Mix. This can either be done when calling .new:
# only allow strings my $n = Mix[Str].new: <a b b c c c>;
or using the masquerading syntax:
# only allow strings my %m is Mix[Str] = <a b b c c c>; say %m<b>; # 2 say %m<d>; # 0 # only allow whole numbers my %m is Mix[Int] = <a b b c c c>; # Type check failed in binding; expected Int but got Str ("a")
Mixes can use all kind of set operators returning either Bool or other Mixes:
my $this-mix = (sugar => ⅓, spice => ¼, all-things-nice => ¾); my $that-mix = ( sugar => 1, spice => 2); say $that-mix (<) $this-mix; # OUTPUT: «True» say $that-mix (^) $this-mix; # OUTPUT: «set(all-things-nice)» say $that-mix (+) $this-mix; # OUTPUT: «Bag(spice(2), sugar)»
With their equivalent Unicode operators:
say $that-mix ⊂ $this-mix; # OUTPUT: «True» say $that-mix ⊖ $this-mix; # OUTPUT: «set(all-things-nice)» say $that-mix ⊎ $this-mix; # OUTPUT: «Bag(spice(2), sugar)»
See Set/Bag Operators for a complete list of set and bag operators with detailed explanations.
sub mix(*@args --> Mix)
Creates a new Mix from @args.
Defined as:
method Bag (--> Bag:D)
Coerces the Mix to a Bag. The weights are convert to Int, which means the number of keys in the resulting Bag can be fewer than in the original Mix, if any of the weights are negative or truncate to zero.
Defined as:
method BagHash (--> BagHash:D)
Coerces the Mix to a BagHash. The weights are convert to Int, which means the number of keys in the resulting BagHash can be fewer than in the original Mix, if any of the weights are negative or truncate to zero.
Note: This method is inherited from Any, however, Mixes do not have an inherent order and you should not trust it returning a consistent output.
Same as the other elements in the Bag/Mix suite, order is not guaranteed or consistent and you shouldn't rely on methods like reverse above returning always the same result.
Mutable collection of distinct objects with Real weights
class MixHash does Mixy { }
A MixHash is a mutable mix, meaning a collection of distinct elements in no particular order that each have a real-number weight assigned to them. (For immutable mixes, see Mix instead.)
Objects/values of any type are allowed as mix elements. Within a MixHash, items that would compare positively with the === operator are considered the same element, with a combined weight.
my $recipe = (butter => 0.22, sugar => 0.1, flour => 0.275, sugar => 0.02).MixHash; say $recipe.elems; # OUTPUT: «3» say $recipe.keys.sort; # OUTPUT: «butter flour sugar» say $recipe.pairs.sort; # OUTPUT: «"butter" => 0.22 "flour" => 0.275 "sugar" => 0.12» say $recipe.total; # OUTPUT: «0.615»
MixHashes can be treated as object hashes using the { } postcircumfix operator, which returns the corresponding numeric weight for keys that are elements of the mix, and 0 for keys that aren't. It can also be used to modify weights; Setting a weight to 0 automatically removes that element from the mix, and setting a weight to a non-zero number adds that element if it didn't already exist:
my $recipe = (butter => 0.22, sugar => 0.1, flour => 0.275, sugar => 0.02).MixHash; say $recipe<butter>; # OUTPUT: «0.22» say $recipe<sugar>; # OUTPUT: «0.12» say $recipe<chocolate>; # OUTPUT: «0» $recipe<butter> = 0; $recipe<chocolate> = 0.30; say $recipe.pairs; # OUTPUT: «"sugar" => 0.12 "flour" => 0.275 "chocolate" => 0.3»
MixHashes can be composed using MixHash.new. Any positional parameters, regardless of their type, become elements of the mix - with a weight of 1 for each time the parameter occurred:
my $n = MixHash.new: "a", "a", "b" => 0, "c" => 3.14; say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Pair) (Pair))» say $n.pairs; # OUTPUT: «(a => 2 (c => 3.14) => 1 (b => 0) => 1)»
Alternatively, the .MixHash coercer (or its functional form, MixHash()) can be called on an existing object to coerce it to a MixHash. Its semantics depend on the type and contents of the object. In general it evaluates the object in list context and creates a mix with the resulting items as elements, although for Hash-like objects or Pair items, only the keys become elements of the mix, and the (cumulative) values become the associated numeric weights:
my $n = ("a", "a", "b" => 0, "c" => 3.14).MixHash; say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Str))» say $n.pairs; # OUTPUT: «(a => 2 c => 3.14)»
Since 6.d (2019.03 and later) it is also possible to specify the type of values you would like to allow in a MixHash. This can either be done when calling .new:
# only allow strings my $n = MixHash[Str].new: <a b b c c c>;
or using the masquerading syntax:
# only allow strings my %mh is MixHash[Str] = <a b b c c c>; say %mh<b>; # 2 say %mh<d>; # 0 # only allow whole numbers my %mh is MixHash[Int] = <a b b c c c>; # Type check failed in binding; expected Int but got Str ("a")
my ($a, $b) = MixHash(2 => 2, 4), MixHash(2 => 1.5, 3 => 2, 4); say $a (<) $b; # OUTPUT: «False» say $a (<+) $b; # OUTPUT: «False» say $a (^) $b; # OUTPUT: «Mix(2(0.5), 3(2))» say $a (+) $b; # OUTPUT: «Mix(2(3.5), 4(2), 3(2))» # Unicode versions: say $a ⊂ $b; # OUTPUT: «False» say $a ≼ $b; # OUTPUT: «False» say $a ⊖ $b; # OUTPUT: «Mix(2(0.5), 3(2))» say $a ⊎ $b; # OUTPUT: «Mix(2(3.5), 4(2), 3(2))»
See Set/Bag Operators for a complete list of set and bag operators with detailed explanations.
MixHash inherits reverse from Any, however, Mixes do not have an inherent order and you should not trust it returning a consistent output.
If you sort a MixHash, the result is a list of pairs, at which point reverse makes perfect sense:
my $a = MixHash.new(2, 2, 18, 3, 4); say $a; # OUTPUT: «MixHash(18, 2(2), 3, 4)» say $a.sort; # OUTPUT: «(2 => 2 3 => 1 4 => 1 18 => 1)» say $a.sort.reverse; # OUTPUT: «(18 => 1 4 => 1 3 => 1 2 => 2)»
Defined as:
method Bag (--> Bag:D)
Coerces the MixHash to a Bag. The weights are converted to Int, which means the number of keys in the resulting Bag can be fewer than in the original MixHash, if any of the weights are negative or truncate to zero.
Defined as:
method BagHash (--> BagHash:D)
Coerces the MixHash to a BagHash. The weights are converted to Int, which means the number of keys in the resulting BagHash can be fewer than in the original MixHash, if any of the weights are negative or truncate to zero.
This method is inherited from Any, however, Mixes do not have an inherent order and you should not trust it returning a consistent output.
Collection of distinct objects with Real weights
role Mixy does Baggy { }
A role for collections of weighted values. See Mix and MixHash. Mixy objects differ from Baggy objects in that the weights of Mixy are Reals rather than Ints.
method total(--> Real)
Returns the sum of all the weights
say mix('a', 'b', 'c', 'a', 'a', 'd').total == 6; # OUTPUT: «True» say %(a => 5.6, b => 2.4).Mix.total == 8; # OUTPUT: «True»
method roll($count = 1)
Similar to a Bag.roll, but with Real weights rather than integral ones.
The root of the Perl 6 type hierarchy.
class Mu { }
The root of the Perl 6 type hierarchy. For the origin of the name, see https://en.wikipedia.org/wiki/Mu_%28negative%29. One can also say that there are many undefined values in Perl 6, and Mu is the most undefined value.
Note that most classes do not derive from Mu directly, but rather from Any.
Defined as:
method iterator(--> Iterator)
Coerces the invocant to a list by applying its .list method and uses iterator on it.
my $it = Mu.iterator; say $it.pull-one; # OUTPUT: «(Mu)» say $it.pull-one; # OUTPUT: «IterationEnd»
Declared as
multi method defined( --> Bool:D)
Returns False on a type object, and True otherwise.
say Int.defined; # OUTPUT: «False» say 42.defined; # OUTPUT: «True»
A few types (like Failure) override defined to return False even for instances:
sub fails() { fail 'oh noe' }; say fails().defined; # OUTPUT: «False»
Declared as
multi sub defined(Mu --> Bool:D)
invokes the .defined method on the object and returns its result.
multi method isa(Mu $type --> Bool:D) multi method isa(Str:D $type --> Bool:D)
Returns True if the invocant is an instance of class $type, a subset type or a derived class (through inheritance) of $type. does is similar, but includes roles.
my $i = 17; say $i.isa("Int"); # OUTPUT: «True» say $i.isa(Any); # OUTPUT: «True» role Truish {}; my $but-true = 0 but Truish; say $but-true.^name; # OUTPUT: «Int+{Truish}» say $but-true.does(Truish); # OUTPUT: «True» say $but-true.isa(Truish); # OUTPUT: «False»
method does(Mu $type --> Bool:D)
Returns True if and only if the invocant conforms to type $type.
my $d = Date.new('2016-06-03'); say $d.does(Dateish); # True (Date does role Dateish) say $d.does(Any); # True (Date is a subclass of Any) say $d.does(DateTime); # False (Date is not a subclass of DateTime)
Unlike isa, which returns True only for superclasses, does includes both superclasses and roles.
say $d.isa(Dateish); # OUTPUT: «False»
Using the smartmatch operator ~~ is a more idiomatic alternative.
my $d = Date.new('2016-06-03'); say $d ~~ Dateish; # OUTPUT: «True» say $d ~~ Any; # OUTPUT: «True» say $d ~~ DateTime; # OUTPUT: «False»
multi sub Bool(Mu --> Bool:D) multi method Bool( --> Bool:D)
Returns False on the type object, and True otherwise.
Many built-in types override this to be False for empty collections, the empty string or numerical zeros
say Mu.Bool; # OUTPUT: «False» say Mu.new.Bool; # OUTPUT: «True» say [1, 2, 3].Bool; # OUTPUT: «True» say [].Bool; # OUTPUT: «False» say %( hash => 'full' ).Bool; # OUTPUT: «True» say {}.Bool; # OUTPUT: «False» say "".Bool; # OUTPUT: «False» say 0.Bool; # OUTPUT: «False» say 1.Bool; # OUTPUT: «True» say "0".Bool; # OUTPUT: «True»
Declared as:
method Capture(Mu:D: --> Capture:D)
Returns a Capture with named arguments corresponding to invocant's public attributes:
class Foo { has $.foo = 42; has $.bar = 70; method bar { 'something else' } }.new.Capture.say; # OUTPUT: «\(:bar("something else"), :foo(42))»
multi method Str(--> Str)
Returns a string representation of the invocant, intended to be machine readable. Method Str warns on type objects, and produces the empty string.
say Mu.Str; # Use of uninitialized value of type Mu in string context. my @foo = [2,3,1]; say @foo.Str # OUTPUT: «2 3 1»
multi sub gist(+args --> Str) multi method gist( --> Str)
Returns a string representation of the invocant, optimized for fast recognition by humans. As such lists will be truncated at 100 elements. Use .perl to get all elements.
The default gist method in Mu re-dispatches to the perl method for defined invocants, and returns the type name in parenthesis for type object invocants. Many built-in classes override the case of instances to something more specific that may truncate output.
gist is the method that say calls implicitly, so say $something and say $something.gist generally produce the same output.
say Mu.gist; # OUTPUT: «(Mu)» say Mu.new.gist; # OUTPUT: «Mu.new»
multi method perl(--> Str)
Returns a Perlish representation of the object (i.e., can usually be re-evaluated with EVAL to regenerate the object). The exact output of perl is implementation specific, since there are generally many ways to write a Perl expression that produces a particular value.
method item(Mu \item:) is raw
Forces the invocant to be evaluated in item context and returns the value of it.
say [1,2,3].item.perl; # OUTPUT: «$[1, 2, 3]» say %( apple => 10 ).item.perl; # OUTPUT: «${:apple(10)}» say "abc".item.perl; # OUTPUT: «"abc"»
method self(--> Mu)
Returns the object it is called on.
multi method clone(Mu:U: *%twiddles) multi method clone(Mu:D: *%twiddles)
This method will clone type objects, or die if it's invoked with any argument.
say Num.clone( :yes ) # OUTPUT: «(exit code 1) Cannot set attribute values when cloning a type object in block <unit>»
If invoked with value objects, it creates a shallow clone of the invocant, including shallow cloning of private attributes. Alternative values for public attributes can be provided via named arguments with names matching the attributes' names.
class Point2D { has ($.x, $.y); multi method gist(Point2D:D:) { "Point($.x, $.y)"; } } my $p = Point2D.new(x => 2, y => 3); say $p; # OUTPUT: «Point(2, 3)» say $p.clone(y => -5); # OUTPUT: «Point(2, -5)»
Note that .clone does not go the extra mile to shallow-copy @. and %. sigiled attributes and, if modified, the modifications will still be available in the original object:
class Foo { has $.foo is rw = 42; has &.boo is rw = { say "Hi" }; has @.bar = <a b>; has %.baz = <a b c d>; } my $o1 = Foo.new; with my $o2 = $o1.clone { .foo = 70; .bar = <Z Y>; .baz = <Z Y X W>; .boo = { say "Bye" }; } # Hash and Array attribute modifications in clone appear in original as well: say $o1; # OUTPUT: «Foo.new(foo => 42, bar => ["Z", "Y"], baz => {:X("W"), :Z("Y")}, …» say $o2; # OUTPUT: «Foo.new(foo => 70, bar => ["Z", "Y"], baz => {:X("W"), :Z("Y")}, …» $o1.boo.(); # OUTPUT: «Hi» $o2.boo.(); # OUTPUT: «Bye»
To clone those, you could implement your own .clone that clones the appropriate attributes and passes the new values to Mu.clone, for example, via nextwith.
class Bar { has $.quux; has @.foo = <a b>; has %.bar = <a b c d>; method clone { nextwith :foo(@!foo.clone), :bar(%!bar.clone), |%_ } } my $o1 = Bar.new( :42quux ); with my $o2 = $o1.clone { .foo = <Z Y>; .bar = <Z Y X W>; } # Hash and Array attribute modifications in clone do not affect original: say $o1; # OUTPUT: «Bar.new(quux => 42, foo => ["a", "b"], bar => {:a("b"), :c("d")})» say $o2; # OUTPUT: «Bar.new(quux => 42, foo => ["Z", "Y"], bar => {:X("W"), :Z("Y")})»
The |%_ is needed to slurp the rest of the attributes that would have been copied via shallow copy.
multi method new(*%attrinit) multi method new($, *@)
Default method for constructing (create + initialize) new objects of a class. This method expects only named arguments which are then used to initialize attributes with accessors of the same name.
Classes may provide their own new method to override this default.
new triggers an object construction mechanism that calls submethods named BUILD in each class of an inheritance hierarchy, if they exist. See the documentation on object construction for more information.
method bless(*%attrinit --> Mu:D)
Low-level object construction method, usually called from within new, implicitly from the default constructor, or explicitly if you create your own constructor. bless creates a new object of the same type as the invocant, using the named arguments to initialize attributes and returns the created object.
It is usually invoked within custom new method implementations:
class Point { has $.x; has $.y; multi method new($x, $y) { self.bless(:$x, :$y); } } my $p = Point.new(-1, 1);
In this case we are declaring new as a multi method so that we can still use the default constructor like this: Point.new( x => 3, y => 8 ). In this case we are declaring this new method simply to avoid the extra syntax of using pairs when creating the object. self.bless returns the object, which is in turn returned by new.
However, in general, implementing a customized new method might not be the best way of initializing a class, even more so if the default constructor is disabled, since it can make it harder to correctly initialize the class from a subclass. For instance, in the above example, the new implementation takes two positional arguments that must be passed from the subclass to the superclass in the exact order. That is not a real problem if it's documented, but take into account bless will eventually be calling BUILD in the class that is being instantiated. This might result in some unwanted problems, like having to create a BUILD submethod to serve it correctly:
class Point { has Int $.x; has Int $.y; multi method new($x, $y) { self.bless(:$x, :$y); } } class Point-with-ID is Point { has Int $.ID is rw = 0; submethod BUILD( *%args ) { say %args; # OUTPUT: «{x => 1, y => 2}» for self.^attributes -> $attr { if $attr.Str ~~ /ID/ { $attr.set_value( self, "*" ~ %args<x> ~ "-" ~ %args<y> ) ; } } } } my $p = Point-with-ID.new(1,2); say $p.perl; # OUTPUT: «Point-with-ID.new(ID => "*1-2", x => 1, y => 2)»
In this code, bless, called within Point.new, is eventually calling BUILD with the same parameters. We have to create a convoluted way of using the $.ID attribute using the meta-object protocol so that we can instantiate it and thus serve that new constructor, which can be called on Point-with-ID since it is a subclass.
We might have to use something similar if we want to instantiate superclasses. bless will help us with that, since it is calling across all the hierarchy:
class Str-with-ID is Str { my $.counter = 0; has Int $.ID is rw = 0; multi method new( $str ) { self.bless( value => $str, ID => $.counter++ ); } submethod BUILD( *%args ) { for self.^attributes -> $attr { if $attr.Str ~~ /ID/ { $attr.set_value( self, %args<ID> ) ; } } } } say Str-with-ID.new("1.1,2e2").ID; # OUTPUT: «0» my $enriched-str = Str-with-ID.new("3,4"); say "$enriched-str, {$enriched-str.^name}, {$enriched-str.ID}"; # OUTPUT: «3,4, Str-with-ID, 1»
We are enriching Str with an auto-incrementing ID. We create a new since we want to initialize it with a string and, besides, we need to instantiate the superclass. We do so using bless from within new. bless is going to call Str.BUILD. It will *capture* the value it's looking for, the pair value = $str> and initialize itself. But we have to initialize also the properties of the subclass, which is why within BUILD we use the previously explained method to initialize $.ID with the value that is in the %args variable. As shown in the output, the objects will be correctly initialized with its ID, and will correctly behave as Str, converting themselves in just the string in the say statement, and including the ID property as required.
For more details see the documentation on object construction.
method CREATE(--> Mu:D)
Allocates a new object of the same type as the invocant, without initializing any attributes.
say Mu.CREATE.defined; # OUTPUT: «True»
multi method print(--> Bool:D)
Prints value to $*OUT after stringification using .Str method without adding a newline at end.
"abc\n".print; # RESULT: «abc»
multi method put(--> Bool:D)
Prints value to $*OUT, adding a newline at end, and if necessary, stringifying non-Str object using the .Str method.
"abc".put; # RESULT: «abc»
multi method say()
Will say to standard output.
say 42; # OUTPUT: «42»
What say actually does is, thus, deferred to the actual subclass. In most cases it calls .gist on the object, returning a compact string representation.
In non-sink context, say will always return True.
say (1,[1,2],"foo",Mu).map: so *.say ; # OUTPUT: «1[1 2]foo(Mu)(True True True True)»
However, this behavior is just conventional and you shouldn't trust it for your code. It's useful, however, to explain certain behaviors.
say is first printing out in *.say, but the outermost say is printing the True values returned by the so operation.
multi method ACCEPTS(Mu:U: $other)
ACCEPTS is the method that smartmatching with the infix ~~ operator and given/when invokes on the right-hand side (the matcher).
The Mu:U multi performs a type check. Returns True if $other conforms to the invocant (which is always a type object or failure).
say 42 ~~ Mu; # OUTPUT: «True» say 42 ~~ Int; # OUTPUT: «True» say 42 ~~ Str; # OUTPUT: «False»
Note that there is no multi for defined invocants; this is to allow autothreading of junctions, which happens as a fallback mechanism when no direct candidate is available to dispatch to.
multi method WHICH(--> ObjAt:D)
Returns an object of type ObjAt which uniquely identifies the object. Value types override this method which makes sure that two equivalent objects return the same return value from WHICH.
say 42.WHICH eq 42.WHICH; # OUTPUT: «True»
method WHERE(--> Int)
Returns an Int representing the memory address of the object.
multi method WHY(--> Pod::Block::Declarator)
Returns the attached Pod::Block::Declarator.
For instance:
#| Initiate a specified spell normally sub cast(Spell $s) { do-raw-magic($s); } #= (do not use for class 7 spells) say &cast.WHY; # OUTPUT: «Initiate a specified spell normally(do not use for class 7 spells)»
See Pod declarator blocks for details about attaching Pod to variables, classes, functions, methods, etc.
multi sub trait_mod:<is>(Mu:U \type, :$export!)
Marks a type as being exported, that is, available to external users.
my class SomeClass is export { }
A user of a module or class automatically gets all the symbols imported that are marked as is export.
See Exporting and Selective Importing Modules for more details.
method return()
The method return will stop execution of a subroutine or method, run all relevant phasers and provide invocant as a return value to the caller. If a return type constraint is provided it will be checked unless the return value is Nil. A control exception is raised and can be caught with CONTROL.
sub f { (1|2|3).return }; say f(); # OUTPUT: «any(1, 2, 3)»
Same as method return except that return-rw returns a writable container to the invocant (see more details here: return-rw).
method emit()
Emits the invocant into the enclosing supply or react block.
react { whenever supply { .emit for "foo", 42, .5 } { say "received {.^name} ($_)"; }} # OUTPUT: # received Str (foo) # received Int (42) # received Rat (0.5)
method take()
Returns the invocant in the enclosing gather block.
sub insert($sep, +@list) { gather for @list { FIRST .take, next; take slip $sep, .item } } say insert ':', <a b c>; # OUTPUT: «(a : b : c)»
sub take(\item)
Takes the given item and passes it to the enclosing gather block.
#| randomly select numbers for lotto my $num-selected-numbers = 6; my $max-lotto-numbers = 49; gather for ^$num-selected-numbers { take (1 .. $max-lotto-numbers).pick(1); }.say; # six random values
sub take-rw(\item)
Returns the given item to the enclosing gather block, without introducing a new container.
my @a = 1...3; sub f(@list){ gather for @list { take-rw $_ } }; for f(@a) { $_++ }; say @a; # OUTPUT: «[2 3 4]»
method so()
Evaluates the item in boolean context (and thus, for instance, collapses Junctions), and returns the result. It is the opposite of not, and equivalent to the ? operator.
One can use this method similarly to the English sentence: "If that is so, then do this thing". For instance,
my @args = <-a -e -b -v>; my $verbose-selected = any(@args) eq '-v' | '-V'; if $verbose-selected.so { say "Verbose option detected in arguments"; } # OUTPUT: «Verbose option detected in arguments»
The $verbose-selected variable in this case contains a Junction, whose value is any(any(False, False), any(False, False), any(False, False), any(True, False)). That is actually a truish value; thus, negating it will yield False. The negation of that result will be True. so is performing all those operations under the hood.
method not()
Evaluates the item in boolean context (leading to final evaluation of Junctions, for instance), and negates the result. It is the opposite of so and its behavior is equivalent to the ! operator.
my @args = <-a -e -b>; my $verbose-selected = any(@args) eq '-v' | '-V'; if $verbose-selected.not { say "Verbose option not present in arguments"; } # OUTPUT: «Verbose option not present in arguments»
Since there is also a prefix version of not, this example reads better as:
my @args = <-a -e -b>; my $verbose-selected = any(@args) eq '-v' | '-V'; if not $verbose-selected { say "Verbose option not present in arguments"; } # OUTPUT: «Verbose option not present in arguments»
Codepoint string in Normal Form C (composed)
class NFC is Uni {}
A Codepoint string in Unicode Normalization Form C. It is created by Canonical Decomposition, followed by Canonical Composition. For more information on what this means, see Unicode TR15.
Codepoint string in Normal Form D (decomposed)
class NFD is Uni {}
A Codepoint string in the "D" Unicode Normalization Form
Codepoint string in Normal Form KC (compatibility composed)
class NFKC is Uni {}
A Codepoint string in Unicode Normalization Form KC. It is created by Compatibility Decomposition, followed by Canonical Composition. For more information on what this means, see Unicode TR15.
Codepoint string in Normal Form KD (compatibility decomposed)
class NFKD is Uni {}
A Codepoint string in Unicode Normalization Form KD. It is created by Compatibility Decomposition. For more information on what this means, see Unicode TR15.
Absence of a value or a benign failure
class Nil is Cool { }
The value Nil may be used to fill a spot where a value would normally go, and in so doing, explicitly indicate that no value is present. It may also be used as a cheaper and less explosive alternative to a Failure. (In fact, class Failure is derived from Nil, so smartmatching Nil will also match Failure.)
The class Nil is the same exact thing as its only possible value, Nil.
say Nil === Nil.new; # OUTPUT: «True»
Along with Failure, Nil and its sub classes may always be returned from a routine even when the routine specifies a particular return type. It may also be returned regardless of the definedness of the return type, however, Nil is considered undefined for all other purposes.
sub a( --> Int:D ) { return Nil } a().say; # OUTPUT: «Nil»
Nil is what is returned from empty routines or closure, or routines that use a bare return statement.
sub a { }; a().say; # OUTPUT: «Nil» sub b { return }; b().say; # OUTPUT: «Nil» say (if 1 { }); # OUTPUT: «Nil» { ; }().say; # OUTPUT: «Nil» say EVAL ""; # OUTPUT: «Nil»
In a list, Nil takes the space of one value. Iterating a Nil behaves like iteration of any non-iterable value, producing a sequence of one Nil. (When you need the other meaning, the special value Empty is available to take no spaces when inserted into list, and to return no values when iterated.)
(1, Nil, 3).elems.say; # OUTPUT: «3» (for Nil { $_ }).perl.say; # OUTPUT: «(Nil,)»
Any method call on Nil of a method that does not exist, and consequently, any subscripting operation, will succeed and return Nil.
say Nil.ITotallyJustMadeThisUp; # OUTPUT: «Nil» say (Nil)[100]; # OUTPUT: «Nil» say (Nil){100}; # OUTPUT: «Nil»
When assigned to a container, the Nil value (but not any subclass of Nil) will attempt to revert the container to its default value; if no such default is declared, Perl 6 assumes Any.
Since a hash assignment expects two elements, use Empty not Nil, e.g.
my %h = 'a'..'b' Z=> 1..*; # stuff happens %h = Empty; # %h = Nil will generate an error
However, if the container type is constrained with :D, assigning Nil to it will immediately throw an exception. (In contrast, an instantiated Failure matches :D because it's a definite value, but will fail to match the actual nominal type unless it happens to be a parent class of Failure.) Native types can not have default values nor hold a type object. Assigning Nil to a native type container will fail with a runtime error.
my Int $x = 42; $x = Nil; $x.say; # OUTPUT: «(Int)» sub f( --> Int:D ){ Nil }; # this definedness constraint is ignored my Int:D $i = f; # this definedness constraint is not ignored, so throws CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $y; expected Int but got Any (Any)» sub g( --> Int:D ){ fail "oops" }; # this definedness constraint is ignored my Any:D $h = g; # failure object matches Any:D, so is assigned
but
my Int:D $j = g; # It will throw both exceptions: # Earlier failure: # oops # in sub g at <unknown file> line 1 # in block <unit> at <unknown file> line 1 # # Final error: # Type check failed in assignment to $j; expected Int:D but got Failure (Failure.new(exception...) # in block <unit> at <unknown file> line 1
Because an untyped variable is type Any, assigning a Nil to one will result in an (Any) type object.
my $x = Nil; $x.say; # OUTPUT: «(Any)» my Int $y = $x; # will throw an exception CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $y; expected Int but got Any (Any)»
If you are looking for a variable which transforms objects into type objects when said variable appears on the right-hand side, you can type the container as Nil.
my Nil $x; my Str $s = $x; $s.say; # OUTPUT: «(Str)»
There is an important exception to this transforms-into-type-object rule: assigning Nil to a variable which has a default will restore that default.
my Int $x is default(42) = -1; my $y = 1; for $x, $y -> $val is rw { $val = Nil unless $val > 0 } $x.say; # OUTPUT: «42»
method append(*@)
Warns the user that they tried to append onto a Nil.
method gist(--> Str:D)
Returns "Nil".
method Str()
Warns the user that they tried to stringify a Nil.
method new(*@)
Returns Nil
method prepend(*@)
Warns the user that they tried to prepend onto a Nil.
method push(*@)
Warns the user that they tried to push onto a Nil.
method unshift(*@)
Warns the user that they tried to unshift onto a Nil.
method FALLBACK(| --> Nil) {}
The fallback method takes any arguments and always returns a Nil.
method Numeric()
Warns the user that they tried to numify a Nil.
Floating-point number
class Num is Cool does Real { }
A Num object stores a floating-point number. It is immutable. On most platforms, it's an IEEE 754 64-bit floating point numbers, aka "double precision".
The value Inf is an instance of Num and represents value that's too large to represent in 64-bit double-precision floating point number (roughly, above 1.7976931348623158e308 for positive Inf and below -1.7976931348623157e308 for negative Inf) as well as returned from certain operations as defined by the IEEE 754-2008 standard.
say 2e300 ** 2e300; # OUTPUT: «Inf» say (-1/0).Num; # OUTPUT: «-Inf»
The ∞ U+221E Unicode character can be used instead of the word Inf and can be handy when Inf would otherwise require an unspace, such as when writing Complex numbers:
say Inf+Inf\i; # Backslash (unspace) before `i` required say ∞+∞i; # No backslash is needed
Note that there are just two infinities (positive and negative), so even if an operation that would instinctively give a "larger" infinity is performed, the result in still an infinity of the original magnitude. The infinities can be compared, operated and used as an argument as if they were simply a number that's too big to represent or to signify "without bounds" or limits:
say ∞²; # OUTPUT: «Inf» say 42 + Inf === ∞; # OUTPUT: «True» say atan ∞; # OUTPUT: «1.5707963267949» say -∞ < 42 < ∞; # OUTPUT: «True» my $l := 1, 2, 4, 8 ... Inf; # Infinite sequence (no limits)
In some cases, it's used as an implicit value to represent "all of them"
say "House of M".comb(3,Inf).join("←X→"); # OUTPUT: «Hou←X→se ←X→of ←X→M»
In the example above, Inf can be eliminated, since it's the default value for the second argument of .comb, used to indicate how many parts should be returned.
Division of an infinity by another infinity results in a NaN:
say ∞/∞; # OUTPUT: «NaN»
The value NaN is an instance of Num and represents a floating point not-a-number value, which is returned from some routines where a concrete number as the answer is not defined, but a Numeric value is still acceptable. NaN is defined and boolifies to True, but is not numerically equal to any value (including itself).
say cos ∞; # OUTPUT: «NaN» say (0/0).Num; # OUTPUT: «NaN»
To test for NaN, use isNaN method or === operator:
say (0/0).isNaN; # OUTPUT: «True» say (0/0).Num === NaN; # OUTPUT: «True»
method rand(Num:D: --> Num)
Returns a pseudo random number between 0 and the invocant.
sub srand(Int $seed --> Int:D)
Seeds the pseudo random number generator used by Num.rand with the provided value. Note that srand is called with a platform dependent value when a Perl 6 program is started.
Defined as:
method Capture()
Throws X::Cannot::Capture.
method Int(Num:D:)
Converts the number to an Int. Fails with X::Numeric::CannotConvert if the invocant is a NaN or Inf/-Inf. No rounding is performed.
method Rat(Num:D: Real $epsilon = 1e-6)
Converts the number to a Rat with $epsilon precision. If the invocant is a Inf, -Inf, or a NaN, converts them to a Rat with 0 denominator and 1, -1, or 0 numerator, respectively.
method FatRat(Num:D: Real $epsilon = 1e-6)
Converts the number to a FatRat with the precision $epsilon. If invocant is a Inf, -Inf, or a NaN, converts them to a FatRat with 0 denominator and 1, -1, or 0 numerator, respectively.
Dual value floating-point number and string
class NumStr is Num is Str { }
The dual value types (often referred to as allomorphs) allow for the representation of a value as both a string and a numeric type. Typically they will be created for you when the context is "stringy" but they can be determined to be numbers, such as in some quoting constructs:
my $f = <42.1e0>; say $f.^name; # OUTPUT: «NumStr»
As a subclass of both Num and Str, a NumStr will be accepted where either is expected. However, NumStr does not share object identity with Num- or Str-only variants:
my $num-str = <42e10>; my Num $num = $num-str; # OK! my Str $str = $num-str; # OK! say 42e10 ∈ <42e10 55 1>; # False; ∈ operator cares about object identity
method new(Num $i, Str $s)
The constructor requires both the Num and the Str value, when constructing one directly the values can be whatever is required:
my $f = NumStr.new(42.1e0, "forty two and a bit"); say +$f; # OUTPUT: «42.1» say ~$f; # OUTPUT: «"forty two and a bit"»
Defined as:
multi method Bool(NumStr:D: --> Bool:D)
This method may be provided by the parent classes and not implemented in NumStr directly.
Returns False if the invocant is numerically ±0e0, otherwise returns True. String portion is not considered.
method Num
Returns the Num value of the NumStr.
Defined as:
multi method Numeric(NumStr:D: --> Num:D) multi method Numeric(NumStr:U: --> Num:D)
The :D variant returns the numeric portion of the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value 0e0.
Defined as:
multi method Real(NumStr:D: --> Num:D) multi method Real(NumStr:U: --> Num:D)
The :D variant returns the numeric portion of the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value 0e0.
Returns the string value of the NumStr.
Defined as:
multi method ACCEPTS(NumStr:D: Any:D $value)
If $value is Numeric (including another allomorph), checks if invocant's Numeric part ACCEPTS the $value. If $value is Str, checks if invocant's Str part ACCEPTS the $value. If value is anything else, checks if both Numeric and Str parts ACCEPTS the $value.
say <5e0> ~~ "5.0"; # OUTPUT: «False» say <5e0> ~~ 5.0 ; # OUTPUT: «True» say <5e0> ~~ <5.0>; # OUTPUT: «True»
multi sub infix:<cmp>(NumStr:D $a, NumStr:D $b)
Compare two NumStr objects. The comparison is done on the Num value first and then on the Str value. If you want to compare in a different order then you would coerce to a Num or Str value first:
my $f = NumStr.new(42.1e0, "smaller"); my $g = NumStr.new(43.1e0, "larger"); say $f cmp $g; # OUTPUT: «Less» say $f.Str cmp $g.Str; # OUTPUT: «More»
Number or object that can act as a number
role Numeric { ... }
Common role for numbers and types that can act as numbers.
Binary numeric operations return an object of the "wider" type:
Int narrowest Rat FatRat Num Complex widest
So for example the product of a Rat and an Int is a Rat.
Unary operations that in pure math usually return an irrational number generally return Num in Perl 6.
Defined as:
multi method Numeric(Numeric:D: --> Numeric:D) multi method Numeric(Numeric:U: --> Numeric:D)
The :D variant simply returns the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns self.new.
method Int(Numeric:D: --> Int:D)
If this Numeric is equivalent to a Real, return the equivalent of calling truncate on that Real to get an Int. Fail with X::Numeric::Real otherwise.
method Rat(Numeric:D: Real $epsilon = 1.0e-6 --> Rat:D)
If this Numeric is equivalent to a Real, return a Rat which is within $epsilon of that Real's value. Fail with X::Numeric::Real otherwise.
method Num(Numeric:D: --> Num:D)
If this Numeric is equivalent to a Real, return that Real as a Num as accurately as is possible. Fail with X::Numeric::Real otherwise.
method narrow(Numeric:D --> Numeric:D)
Returns the number converted to the narrowest type that can hold it without loss of precision.
say (4.0 + 0i).narrow.perl; # OUTPUT: «4» say (4.0 + 0i).narrow.^name; # OUTPUT: «Int»
multi method ACCEPTS(Numeric:D: $other)
Returns True if $other can be coerced to Numeric and is numerically equal to the invocant (or both evaluate to NaN).
multi sub log(Numeric:D, Numeric $base = e --> Numeric:D) multi method log(Numeric:D: Numeric $base = e --> Numeric:D)
Calculates the logarithm to base $base. Defaults to the natural logarithm. Returns NaN if $base is negative. Throws an exception if $base is 1.
multi sub log10(Numeric:D --> Numeric:D) multi method log10(Numeric:D: --> Numeric:D)
Calculates the logarithm to base 10. Returns NaN for negative arguments and -Inf for 0.
multi sub exp(Numeric:D, Numeric:D $base = e --> Numeric:D) multi method exp(Numeric:D: Numeric:D $base = e --> Numeric:D)
Returns $base to the power of the number, or e to the power of the number if called without a second argument.
multi method roots(Numeric:D: Int:D $n --> Positional)
Returns a list of the $n complex roots, which evaluate to the original number when raised to the $nth power.
multi sub abs(Numeric:D --> Real:D) multi method abs(Numeric:D: --> Real:D)
Returns the absolute value of the number.
multi sub sqrt(Numeric:D --> Numeric:D) multi method sqrt(Numeric:D --> Numeric:D)
Returns a square root of the number. For real numbers the positive square root is returned.
On negative real numbers, sqrt returns NaN rather than a complex number, in order to not confuse people who are not familiar with complex arithmetic. If you want to calculate complex square roots, coerce to Complex first, or use the roots method.
multi method conj(Numeric:D --> Numeric:D)
Returns the complex conjugate of the number. Returns the number itself for real numbers.
multi method Bool(Numeric:D:)
Returns False if the number is equivalent to zero, and True otherwise.
method succ(Numeric:D:)
Returns the number incremented by one (successor).
method pred(Numeric:D:)
Returns the number decremented by one (predecessor).
Unique identification for an object
class ObjAt is Any {}
Objects of type ObjAt are the return value of .WHICH calls on other objects, and identify an object uniquely.
If two objects compare equally via ===, their .WHICH methods return the same ObjAt object.
See also ValueObjAt for value types.
Defined as:
multi sub infix:<eqv>(ObjAt:D $a, ObjAt:D $b)
Returns True if the two ObjAt are the same, that is, if the object they identify is the same.
my @foo = [2,3,1]; my @bar := @foo; say @foo.WHICH eqv @bar.WHICH; # OUTPUT: «True»
Human readable form for comparison operators.
enum Order (:Less(-1), :Same(0), :More(1));
multi sub infix:<cmp>(\a, \b --> Order:D)
cmp will first try to compare operands as strings (via coercion to Stringy), and, failing that, will try to compare numerically via the <=> operator or any other type-appropriate comparison operator. See also the documentation for the cmp operator.
multi sub infix:«<=>»(Int:D \a, Int:D \b --> Order:D)
Specialized form for Int.
Key/value pair
class Pair does Associative {}
Consists of two parts, a key and a value. Pairs can be seen as the atomic units in Hashes, and they are also used in conjunction with named arguments and parameters.
There are many syntaxes for creating Pairs:
Pair.new('key', 'value'); # The canonical way 'key' => 'value'; # this... :key<value>; # ...means the same as this :key<value1 value2>; # But this is key => <value1 value2> :foo(127); # short for foo => 127 :127foo; # the same foo => 127
Note that last form supports Non-ASCII numerics as well:
# use MATHEMATICAL DOUBLE-STRUCK DIGIT THREE say (:𝟛math-three); # OUTPUT: «math-three => 3»
You can also use an identifier-like literal as key; this will not need the quotes as long as it follows the syntax of ordinary identifiers:
(foo => 127) # the same foo => 127
Variants of this are
:key; # same as key => True :!key; # same as key => False
And this other variant, to be used in routine invocation
sub colon-pair( :$key-value ) { say $key-value; } my $key-value = 'value'; colon-pair( :$key-value ); # OUTPUT: «value» colon-pair( key-value => $key-value ); # OUTPUT: «value»
Colon pairs can be chained without a comma to create a List of Pairs. Depending on context you may have to be explicit when assigning colon lists.
sub s(*%h){ say %h.perl }; s :a1:b2; # OUTPUT: «{:a1, :b2}» my $manna = :a1:b2:c3; say $manna.^name; # OUTPUT: «Pair» $manna = (:a1:b2:c3); say $manna.^name; # OUTPUT: «List»
Any variable can be turned into a Pair of its name and its value.
my $bar = 10; my $p = :$bar; say $p; # OUTPUT: «bar => 10»
It is worth noting that when assigning a Scalar as value of a Pair the value holds the container of the value itself. This means that it is possible to change the value from outside of the Pair itself:
my $v = 'value A'; my $pair = a => $v; $pair.say; # OUTPUT: «a => value A» $v = 'value B'; $pair.say; # OUTPUT: «a => value B»
Please also note that this behavior is totally unrelated to the way used to build the Pair itself (i.e., explicit usage of new, use of colon, fat arrow), as well as if the Pair is bound to a variable.
It is possible to change the above behavior forcing the Pair to remove the scalar container and to hold the effective value itself via the method freeze:
my $v = 'value B'; my $pair = a => $v; $pair.freeze; $v = 'value C'; $pair.say; # OUTPUT: «a => value B»
As Pair implements Associative role, its value can be accessed using Associative subscription operator, however, due to Pair's singular nature, the pair's value will be only returned for the pair's key. Nil object will be returned for any other key. Subscript adverbs such as :exists can be used on Pair.
my $pair = a => 5; say $pair<a>; # OUTPUT: «5» say $pair<a>:exists; # OUTPUT: «True» say $pair<no-such-key>; # OUTPUT: «Nil»
Defined as:
multi method new(Pair: Mu $key, Mu $value) multi method new(Pair: Mu :$key, Mu :$value)
Constructs a new Pair object.
Defined as:
multi method ACCEPTS(Pair:D $: %topic) multi method ACCEPTS(Pair:D $: Pair:D $topic) multi method ACCEPTS(Pair:D $: Mu $topic)
If %topic is an Associative, looks up the value using invocant's key in it and checks invocant's value .ACCEPTS that value:
say %(:42a) ~~ :42a; # OUTPUT: «True» say %(:42a) ~~ :10a; # OUTPUT: «False»
If $topic is another Pair, checks the invocant's value .ACCEPTS the $topic's value. Note that the keys are not considered and can be different:
say :42a ~~ :42a; # OUTPUT: «True» say :42z ~~ :42a; # OUTPUT: «True» say :10z ~~ :42a; # OUTPUT: «False»
If $topic is any other value, the invocant Pair's key is treated as a method name. This method is called on $topic, the boolean result of which is compared against the invocant Pair's boolean value. For example, primality can be tested using smartmatch:
say 3 ~~ :is-prime; # OUTPUT: «True» say 3 ~~ is-prime => 'truthy'; # OUTPUT: «True» say 4 ~~ :is-prime; # OUTPUT: «False»
This form can also be used to check Bool values of multiple methods on the same object, such as IO::Path, by using Junctions:
say "foo" .IO ~~ :f & :rw; # OUTPUT: «False» say "/tmp".IO ~~ :!f; # OUTPUT: «True» say "." .IO ~~ :f | :d; # OUTPUT: «True»
Defined as:
method antipair(--> Pair:D)
Returns a new Pair object with key and value exchanged.
my $p = (6 => 'Perl').antipair; say $p.key; # OUTPUT: «Perl» say $p.value; # OUTPUT: «6»
Defined as:
multi method key(Pair:D:)
Returns the key part of the Pair.
my $p = (Perl => 6); say $p.key; # OUTPUT: «Perl»
Defined as:
multi method value(Pair:D:) is rw
Returns the value part of the Pair.
my $p = (Perl => 6); say $p.value; # OUTPUT: «6»
Defined as:
multi sub infix:<cmp>(Pair:D, Pair:D)
The type-agnostic comparator; compares two Pairs. Compares first their key parts, and then compares the value parts if the keys are equal.
my $a = (Apple => 1); my $b = (Apple => 2); say $a cmp $b; # OUTPUT: «Less»
Defined as:
multi method fmt(Pair:D: Str:D $format --> Str:D)
Takes a format string, and returns a string the key and value parts of the Pair formatted. Here's an example:
my $pair = :Earth(1); say $pair.fmt("%s is %.3f AU away from the sun") # OUTPUT: «Earth is 1.000 AU away from the sun»
For more about format strings, see sprintf.
Defined as:
multi method kv(Pair:D: --> List:D)
Returns a two-element List with the key and value parts of Pair, in that order. This method is a special case of the same-named method on Hash, which returns all its entries as a list of keys and values.
my $p = (Perl => 6); say $p.kv[0]; # OUTPUT: «Perl» say $p.kv[1]; # OUTPUT: «6»
Defined as:
multi method pairs(Pair:D:)
Returns a list of one Pair, namely this one.
my $p = (Perl => 6); say $p.pairs.^name; # OUTPUT: «List» say $p.pairs[0]; # OUTPUT: «Perl => 6»
Defined as:
multi method antipairs(Pair:D:)
Returns a List containing the antipair of the invocant.
my $p = (6 => 'Perl').antipairs; say $p.^name; # OUTPUT: «List» say $p.first; # OUTPUT: «Perl => 6» say $p.first.^name; # OUTPUT: «Pair»
Defined as:
method invert(Pair:D: --> Seq:D)
Returns a Seq. If the .value of the invocant is NOT an Iterable, the Seq will contain a single Pair whose .key is the .value of the invocant and whose .value is the .key of the invocant:
:foo<bar>.invert.perl.say; # OUTPUT: «(:bar("foo"),).Seq»
If invocant's .value is an Iterable, the returned Seq will contain the same number of Pairs as items in the .value, with each of those items a .key of a pair and the .key of the invocant the .value of that pair:
:foo<Perl is great>.invert.perl.say; # OUTPUT: «(:Perl("foo"), :is("foo"), :great("foo")).Seq» :foo{ :42a, :72b }.invert.perl.say; # OUTPUT: «((:a(42)) => "foo", (:b(72)) => "foo").Seq»
To perform the exact .key and .value swap, use .antipair method.
Defined as:
multi method keys(Pair:D: --> List:D)
Returns a List containing the key of the invocant.
say ('Perl' => 6).keys; # OUTPUT: «(Perl)»
Defined as:
multi method values(Pair:D: --> List:D)
Returns a List containing the value of the invocant.
say ('Perl' => 6).values; # OUTPUT: «(6)»
Defined as:
method freeze(Pair:D:)
Makes the value of the Pair read-only, by removing it from its Scalar container, and returns it.
my $str = "apple"; my $p = Pair.new('key', $str); $p.value = "orange"; # this works as expected $p.say; # OUTPUT: «key => orange» $p.freeze.say; # OUTPUT: «orange» $p.value = "a new apple"; # Fails CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Str (apple)»
NOTE: this method is deprecated as of 6.d language version. Instead, create a new Pair, with a decontainerized key/value.
$p.=Map.=head.say; # OUTPUT: «orange»
Defined as:
multi method Str(Pair:D: --> Str:D)
Returns a string representation of the invocant formatted as key ~ \t ~ value.
my $b = eggs => 3; say $b.Str; # OUTPUT: «eggs 3»
Defined as:
method Pair()
Returns the invocant Pair object.
my $pair = eggs => 3; say $pair.Pair === $pair; # OUTPUT: «True»
Element of a Signature
class Parameter { }
Represents a parameter, for purpose of introspection.
The usual way to obtain a Parameter object is to create a signature, and call .params on it to obtain a list of the Parameters.
my $sig = :(Str $x); my $param = $sig.params[0]; say $param.type; # OUTPUT: «Str()»
See Signature for more information, and also for an explanation on what most of the concepts related to parameters mean.
Returns the variable name, which includes all sigils and twigils. This name is used internally when applied to code, or in a declaration determines the name declared. This name is not necessarily usable by a caller – if it is, it will also appear as an alias. Often, the name will chosen descriptively as a form of self-documentation.
If the parameter is anonymous, Nil will be returned.
Defined as:
method sigil(Parameter:D: --> Str:D)
Returns a string containing the parameter's sigil, for a looser definition of "sigil" than what is considered part of the variable's name|method name. Still returns a sigil even if the parameter is anonymous.
This "sigil" is actually an introspection used to help determine the normal binding style of a parameter, if it has not been altered through a trait.
Sigil | Will bind to | Default behavior |
---|---|---|
$ | Scalar | Generate new Scalar, use instead of Scalar in argument, if any |
@ | Positional | Bind directly to the argument |
@ | PositionalBindFailover | If binding failed, call argument's .cache method, bind to result |
% | Associative | Bind directly to the argument |
& | Callable | Bind directly to the argument |
\ | (anything) | Bind directly to the argument, keep existing Scalar, if any |
Also, | will bind to all remaining arguments and make new Capture if needed.
Returns the nominal type constraint of the parameter.
Returns the coercion type of the parameter.
Returns additional constraints on the parameter (usually as an all-Junction).
Defined as:
method named(Parameter:D: --> Bool:D)
Returns True if it's a named parameter.
my Signature $sig = :(Str $x, Bool :$is-named); say $sig.params[0].named; # OUTPUT: «False» say $sig.params[1].named; # OUTPUT: «True»
Defined as:
method named_names(Parameter:D: --> List:D)
Returns the list of externally usable names/aliases for a named parameter.
Defined as:
method positional(Parameter:D: --> Bool:D)
Returns True if the parameter is positional.
my Signature $sig = :(Str $x, Bool :$is-named); say $sig.params[0].positional; # OUTPUT: «True» say $sig.params[1].positional; # OUTPUT: «False»
Defined as:
method slurpy(Parameter:D: --> Bool:D)
Returns True for slurpy parameters.
Defined as:
method twigil(Parameter:D: --> Str:D)
Returns a string containing the twigil part of the parameter's name.
Defined as:
method optional(Parameter:D: --> Bool:D)
Returns True for optional parameters.
Defined as:
method raw(Parameter:D: --> Bool:D)
Returns True for raw parameters.
sub f($a, $b is raw, \c) { my $sig = &?ROUTINE.signature; for ^$sig.params.elems { say $sig.params[$_].raw; } } f(17, "4711", 42); OUTPUT: «FalseTrueTrue»
Raw parameters bind either a variable or a value passed to it, with no decontainerization taking place. That means that if a variable was passed to it, you can assign to the parameter. This is different from rw-parameter which can only bind to variables, never to values.
This is the normal behavior for parameters declared with a sigil of '\', which is not really a sigil insofar as it is only used on the parameter.
sub f(\x) { x = 5; } f(my $x); # works f(42); # dies CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Int»
Other parameters may become raw through use of the 'is raw' trait. These still use their sigil in code.
sub f($x is raw) { $x = 5; }
Defined as:
method capture(Parameter:D: --> Bool:D)
Returns True for parameters that capture the rest of the argument list into a single Capture object.
sub how_many_extra_positionals($!, |capture) { capture.elems.say } how_many_extra_positionals(0, 1, 2, 3); # RESULT: «3» say &how_many_extra_positionals.signature.params[1].capture; # OUTPUT: «True»
Like raw parameters, Capture parameters do not force any context on the values bound to them, which is why their sigils are only used in declarations.
Defined as:
method rw(Parameter:D: --> Bool:D)
Returns True for is rw parameters.
my Signature $sig = :(Str $x is rw, Bool :$is-named); say $sig.params[0].rw; # OUTPUT: «True» say $sig.params[1].rw; # OUTPUT: «False»
Defined as:
method copy(Parameter:D: --> Bool:D)
Returns True for is copy parameters.
my Signature $sig = :(Str $x, Bool :$is-named is copy); say $sig.params[0].copy; # OUTPUT: «False» say $sig.params[1].copy; # OUTPUT: «True»
Defined as:
method readonly(Parameter:D: --> Bool:D)
Returns True for read-only parameters (the default).
my Signature $sig = :(Str $x is rw, Bool :$is-named); say $sig.params[0].readonly; # OUTPUT: «False» say $sig.params[1].readonly; # OUTPUT: «True»
Defined as:
method invocant(Parameter:D: --> Bool:D)
Returns True if the parameter is the invocant parameter.
Returns a closure that upon invocation returns the default value for this parameter, or Any if no default was provided.
Defined as:
method type_captures(Parameter:D: --> List:D)
Returns a list of variable names of type captures associated with this parameter. Type captures define a type name within the attached code, which is an alias to the type gleaned from the argument during a call.
sub a(::T ::U $x) { T.say } a(8); # OUTPUT: «(Int)» say &a.signature.params[0].type_captures; # OUTPUT: «(T U)» sub b($x) { $x.^name.say } a(8); # OUTPUT: «Int»
The type used may change from call to call. Once they are defined, type captures can be used wherever you would use a type, even later in same the signature:
sub c(::T $x, T $y, $z) { my T $zz = $z }; c(4, 5, 6); # OK c(4, 5, "six"); # Fails when assigning to $zz, wants Int not Str c("four", 5, "six"); # Fails when binding $y, wants Str, not Int
Type captures may be used at the same time as type constraints.
sub d(::T Numeric $x, T $y) {}; d(4, 5); # OK d(4e0, 5e0); # OK d(4e0, 5); # Fails when binding $y d("four", "five"); # Fails when binding $x
If the parameter has a sub-signature, returns a Signature object for it. Otherwise returns Any.
Parameter.new( ... )
In some situations, specifically when working with the MetaObject Protocol, it makes sense to create Parameter objects programmatically. For this purpose, you can call the new method with the following named parameters:
name
Optional. The name of the variable, if any. Can be specified in the same way as in a Signature. So it may contain specific additional information, such as a sigil ($, @, % or &), a : prefix to indicate a named parameter, a twigil (. or !) to indicate public / private attribute binding, a postfix ! or ? to indicate an optional / mandatory parameter, and the various combinations of +, *, ** prefixes to indicate slurpiness types and | to indicate a Capture.
type
Optional. The type of the parameter. Assumes Any if not specified.
default
Optional. The value of the parameter if the parameter is optional and no argument has been given for that parameter. Assumes not initialization if no argument has been given, which would fall back to the (implicit) type of the parameter.
where
Optional. Additional constraints to be applied to any argument to match with this parameter. Does not set any additional constraints by default.
is-copy
Optional. Allows one to set the "is copy" flag on the parameter. Does not set the flag by default.
is-raw
Optional. Allows one to set the "is raw" flag on the parameter. Does not set the flag by default.
is-rw
Optional. Allows one to set the "is rw" flag on the parameter. Does not set the flag by default.
named
Optional. Indicates whether the parameter is a named parameter or not. Should only be specified if the : prefix is not specified in the name and a named parameter is required.
optional
Optional. Indicates whether the parameter is optional or not. Should only be specified if the ? postfix is not specified in the name and an optional parameter is required.
mandatory
Optional. Indicates whether the parameter is mandatory or not. Should only be specified if the ! postfix is not specified in the name and a mandatory parameter is required.
multi-invocant
Optional. Indicates whether the parameter should be considered in multi-dispatch or not. Defaults to True, so one would need to do :!multi-invocant to make the parameter not be considered in multi-dispatch.
sub-signature
Optional. Specifies any Signature that should be applied to the parameter to deconstruct it. By default, no signature is to be applied.
Perl related information
class Perl does Systemic { }
Built-in class for providing perl related information. Usually accessed through the $*PERL dynamic variable.
Instance method returning the compiler object, of type Compiler, associated with the Perl object.
Instance / Class method returning the names of the Distro objects that are supported by this version of Perl.
Instance / Class method returning the names of the Kernel objects that are supported by this version of Perl.
Instance / Class method returning the names of the VM objects that are supported by this version of Perl.
Block in a Pod document
class Pod::Block { }
Class for a Pod block, and base class for most other Pod classes.
A Pod block has contents (more pod blocks or strings) and a config hash.
Useful subclasses:
Class | Used for |
---|---|
Pod::Block::Para | paragraphs |
Pod::Block::Named | named blocks |
Pod::Block::Declarator | declarator blocks |
Pod::Block::Code | code blocks |
Pod::Block::Comment | comments |
Pod::Block::Table | =begin/end table |
tabular data | |
Pod::Heading | =head1 etc. headings |
Pod::Item | list items |
Pod::Defn | definition lists |
Pod::FormattingCode | formatting codes |
method contents(--> Positional:D)
Returns a list of contents of this block.
method config(--> Map:D)
Returns a hash of configs.
Verbatim code block in a Pod document
class Pod::Block::Code is Pod::Block { }
Class for a code (verbatim) Pod block.
method allowed(--> Positional:D)
Returns a list of formatting codes that are allowed inside the code block.
Comment in a Pod document
class Pod::Block::Comment is Pod::Block { }
Class for a Pod comment.
Declarator block in a Pod document
class Pod::Block::Declarator is Pod::Block { }
Class for a declarator Pod block
method leading(--> Str)
Returns the leading Pod comment attached to the declarator
method trailing(--> Str)
Returns the trailing Pod comment attached to the declarator
method WHEREFORE(--> Mu)
Returns the code object or metaobject to which the Pod block is attached to
Named block in a Pod document
class Pod::Block::Named is Pod::Block { }
Class for a named Pod block. For example
=begin MySection ... =end MySection
creates a Pod::Block::Named with name MySection.
method name(--> Str:D)
Returns the name of the block.
Paragraph in a Pod document
class Pod::Block::Para is Pod::Block { }
Class for a Pod paragraph.
Table in a Pod document
class Pod::Block::Table is Pod::Block { }
Class for a table in a Pod document.
method caption(--> Str:D)
Returns the associated caption of the table.
method headers(--> Positional:D)
Returns a list of table headers. If no headers have been defined the list is empty.
Pod definition list
class Pod::Defn is Pod::Block { }
Class for definition lists in a Pod document.
method term(--> Mu)
Pod formatting code
class Pod::FormattingCode is Pod::Block { }
Class for formatting codes in a Pod document.
method type(--> Mu)
method meta(--> Positional)
Heading in a Pod document
class Pod::Heading is Pod::Block { }
Class for headings in a Pod document.
method level(--> Int)
Returns the level of the heading, starting at 1.
Item in a Pod enumeration list
class Pod::Item is Pod::Block { }
Class for items in Pod enumeration lists.
method level(--> Int)
Returns the level of the enumeration list, starting at 1.
Object that supports looking up values by index
role Positional { ... }
Role for objects which support indexing them using postcircumfix:«[ ]» (usually list-like objects). Example types with Positional role include List, Array, Range, and Buf.
method of()
Returns the type constraint for elements of the positional container. Defaults to Mu.
method elems()
Should return the number of available elements in the instantiated object.
method AT-POS(\position)
Should return the value / container at the given position.
method EXISTS-POS(\position)
Should return a Bool indicating whether the given position actually has a value.
method STORE(\values, :$initialize)
This method should only be supplied if you want to support the:
my @a is Foo = 1,2,3;
syntax for binding your implementation of the Positional role.
Should accept the values to (re-)initialize the object with. The optional named parameter will contain a True value when the method is called on the object for the first time. Should return the invocant.
See Methods to implement for positional subscripting for information about additional methods that can be implemented for the Positional role.
Failover for binding to a Positional
role PositionalBindFailover { ... }
This role provides an interface by which an object can be coerced into a Positional when binding to Positional parameters.
For example, Seq type is not Positional, but you can still write the following, because it does PositionalBindFailover role:
sub fifths(@a) { # @a is constraint to Positional @a[4]; } my $seq := gather { # a Seq, which is not Positional take $_ for 1..*; } say fifths($seq); # OUTPUT: «5»
The invocation of fifths in the example above would ordinarily give a type error, because $seq is of type Seq, which doesn't do the Positional interface that the @-sigil implies.
But the signature binder recognizes that Seq does the PositionalBindFailover role, and calls its cache method to coerce it to a List, which does the Positional role.
The same happens with custom classes that do the role; they simply need to provide an iterator method that produces an Iterator:
class Foo does PositionalBindFailover { method iterator { class :: does Iterator { method pull-one { return 42 unless $++; IterationEnd } }.new } } sub first-five (@a) { @a[^5].say } first-five Foo.new; # OUTPUT: # OUTPUT: «(42 Nil Nil Nil Nil)»
method cache(PositionalBindFailover:D: --> List:D)
Returns a List based on the iterator method, and caches it. Subsequent calls to cache always return the same List object.
method list(PositionalBindFailover:D: --> List:D)
Returns a List based on the iterator method without caching it.
method iterator(PositionalBindFailover:D:) { ... }
This method stub ensure that a class implementing role PositionalBindFailover provides an iterator method.
Iterators that can predict number of values
A PredictiveIterator is a special kind of Iterator that can know how many values it will (still) generate without actually needing to generate those values.
The main addition to the API of the Iterator role, is the count-only method, which should return the number of values the Iterator is still able to generate.
The other addition is the bool-only method, that should return a Bool indicating whether the Iterator is still capable of producing values (aka, is not exhausted yet). By default, this is the Booleanification of the result of the call to the count-only method.
Defined as:
method count-only(--> Int:D) { ... }
It is expected to return the number of values the iterator can still produce without actually producing them. The returned number must adjust itself for items already pulled, so that the method can be called on a partially consumed Iterator.
It will be used in situations where only the number of values of an iterator is needed, e.g. when the .elems method is called.
Important: it's expected the Iterators that implement this method can return that number without producing any values. In other words, it's expected the user of the class will be able to still pull-one after calling this method, and eventually receive as many values as the return value of this method indicated.
Defaults to the Booleanification of the result of calling the count-only method. If it is possible to have a faster way of finding out whether the iterator is capable of producing any value, it should be implemented.
Defined as:
method bool-only(--> Bool:D) { self.count-only.Bool }
Running process (filehandle-based interface)
class Proc {}
Proc is a representation of an invocation of an external process. It provides access to the input, output and error stream as well as the exit code. It is typically created through the run subroutine:
my $proc = run 'echo', 'Hallo world', :out; my $captured-output = $proc.out.slurp: :close; say "Output was $captured-output.perl()";# OUTPUT: «Output was "Hallo world\n"»
Piping several commands is easy too. To achieve the equivalent of the pipe echo "Hello, world" | cat -n in Perl 6, and capture the output from the second command, you can do
my $p1 = run 'echo', 'Hello, world', :out; my $p2 = run 'cat', '-n', :in($p1.out), :out; say $p2.out.get;
You can also feed the :in (standard input) pipe directly from your program, by setting it to True, which will make the pipe available via .in method on the Proc:
my $p = run "cat", "-n", :in, :out; $p.in.say: "Hello,\nworld!"; $p.in.close; say $p.out.slurp: :close; # OUTPUT: «1 Hello, # 2 world!»
In order to capture the standard error, :err can be supplied:
my $p = run "ls", "-l", ".", "qqrq", :out, :err; my $captured-output = $p.out.slurp: :close; my $captured-error = $p.err.slurp: :close; my $exit-code = $p.exitcode;
In sink context, a Proc will call its sink method, throwing an exception if the process has exited with an exit code different from zero:
shell 'exit 1' # OUTPUT: «(exit code 1) The spawned command 'exit 1' exited unsuccessfully (exit code: 1)»
Note: Versions of Rakudo older than 2017.04 do not have .slurp available on IO::Pipe objects; use .slurp-rest instead.
Use Proc::Async for non-blocking operations.
method new(Proc:U: :$in = '-', :$out = '-', :$err = '-', Bool :$bin = False, Bool :$chomp = True, Bool :$merge = False, Str:D :$enc = 'UTF-8', Str:D :$nl = "\n", --> Proc:D) sub shell( $cmd, :$in = '-', :$out = '-', :$err = '-', Bool :$bin = False, Bool :$chomp = True, Bool :$merge = False, Str:D :$enc = 'UTF-8', Str:D :$nl = "\n", :$cwd = $*CWD, Hash() :$env = %*ENV --> Proc:D)
new creates a new Proc object, whereas run or shell create one and spawn it with the command and arguments provided in @args or $cmd, respectively.
$in, $out and $err are the three standard streams of the to-be-launched program, and default to "-" meaning they inherit the stream from the parent process. Setting one (or more) of them to True makes the stream available as an IO::Pipe object of the same name, like for example $proc.out. You can set them to False to discard them. Or you can pass an existing IO::Handle object (for example IO::Pipe) in, in which case this handle is used for the stream.
Please bear in mind that the process streams reside in process variables, not in the dynamic variables that make them available to our programs. Thus, modifying the dynamic filehandle variables (such as $*OUT ) inside the host process will have no effect in the spawned process, unlike $*CWD and $*ENV, whose changes will be actually reflected in it.
my $p-name = "/tmp/program.p6"; my $program = Q:to/END/; #!/usr/bin/env perl6 $*OUT.say( qq/\t$*PROGRAM: This goes to standard output/ ); END spurt $p-name, $program; $*OUT.put: "1. standard output before doing anything weird"; { temp $*OUT = open '/tmp/out.txt', :w; $*OUT.put: "2. temp redefine standard output before this message"; shell( "perl6 $p-name" ).so; } $*OUT.put: "3. everything should be back to normal"; # OUTPUT # 1. standard output before doing anything weird # /tmp/program.p6: This goes to standard output # 3. everything should be back to normal # /tmp/out.txt will contain: # 2. temp redefine standard output before this message
This program shows that the program spawned with shell is not using the temporary $*OUT value defined in the host process (redirected to /tmp/out.txt), but the initial STDOUT defined in the process.
$bin controls whether the streams are handled as binary (i.e. Blob object) or text (i.e. Str objects). If $bin is False, $enc holds the character encoding to encode strings sent to the input stream and decode binary data from the output and error streams.
With $chomp set to True, newlines are stripped from the output and err streams when reading with lines or get. $nl controls what your idea of a newline is.
If $merge is set to True, the standard output and error stream end up merged in $proc.out.
Defined as:
method sink(--> Nil)
When sunk, the Proc object will throw X::Proc::Unsuccessful if the process it ran exited unsuccessfully.
shell 'ls /qqq'; # OUTPUT: «(exit code 1) ls: cannot access '/qqq': No such file or directoryThe spawned command 'ls /qqq' exited unsuccessfully (exit code: 2) n block <unit> at /tmp/3169qXElwq line 1»
method spawn(*@args ($, *@), :$cwd = $*CWD, Hash() :$env = %*ENV --> Bool:D)
Runs the Proc object with the given command, argument list, working directory, and environment.
method shell($cmd, :$cwd = $*CWD, :$env --> Bool:D)
Runs the Proc object with the given command and environment which are passed through to the shell for parsing and execution. See shell for an explanation of which shells are used by default in the most common operating systems.
method command(Proc:D: --> List:D)
The command method is an accessor to a list containing the arguments that were passed when the Proc object was executed via spawn or shell or run.
method pid()
Returns the PID value of the process if available, or Nil.
method exitcode(Proc:D: --> Int:D)
Returns the exit code of the external process, or -1 if it has not exited yet.
method signal(Proc:D:)
Returns the signal number with which the external process was killed, or 0 or an undefined value otherwise.
Running process (asynchronous interface)
class Proc::Async {}
Proc::Async allows you to run external commands asynchronously, capturing standard output and error handles, and optionally write to its standard input.
my $file = ‘foo’.IO; spurt $file, “and\nCamelia\n♡\nme\n”; my $proc = Proc::Async.new: :w, ‘tac’, ‘--’, $file, ‘-’; # my $proc = Proc::Async.new: :w, ‘sleep’, 15; # uncomment to try timeouts react { whenever $proc.stdout.lines { # split input on \r\n, \n, and \r say ‘line: ’, $_ } whenever $proc.stderr { # chunks say ‘stderr: ’, $_ } whenever $proc.ready { say ‘PID: ’, $_ # Only in Rakudo 2018.04 and newer, otherwise Nil } whenever $proc.start { say ‘Proc finished: exitcode=’, .exitcode, ‘ signal=’, .signal; done # gracefully jump from the react block } whenever $proc.print: “I\n♥\nCamelia\n” { $proc.close-stdin } whenever signal(SIGTERM).merge: signal(SIGINT) { once { say ‘Signal received, asking the process to stop’; $proc.kill; # sends SIGHUP, change appropriately whenever signal($_).zip: Promise.in(2).Supply { say ‘Kill it!’; $proc.kill: SIGKILL } } } whenever Promise.in(5) { say ‘Timeout. Asking the process to stop’; $proc.kill; # sends SIGHUP, change appropriately whenever Promise.in(2) { say ‘Timeout. Forcing the process to stop’; $proc.kill: SIGKILL } } } say ‘Program finished’;
Example above produces the following output:
line: me line: ♡ line: Camelia line: and line: Camelia line: ♥ line: I Proc finished. Exit code: 0 Program finished
Alternatively, you can use Proc::Async without using a react block:
# command with arguments my $proc = Proc::Async.new('echo', 'foo', 'bar'); # subscribe to new output from out and err handles: $proc.stdout.tap(-> $v { print "Output: $v" }, quit => { say 'caught exception ' ~ .^name }); $proc.stderr.tap(-> $v { print "Error: $v" }); say "Starting..."; my $promise = $proc.start; # wait for the external program to terminate await $promise; say "Done.";
This produces the following output:
Starting... Output: foo bar Done.
An example that opens an external program for writing:
my $prog = Proc::Async.new(:w, 'hexdump', '-C'); my $promise = $prog.start; await $prog.write(Buf.new(12, 42)); $prog.close-stdin; await $promise;
An example of piping several commands like echo "Hello, world" | cat -n:
my $proc-echo = Proc::Async.new: 'echo', 'Hello, world'; my $proc-cat = Proc::Async.new: 'cat', '-n'; $proc-cat.bind-stdin: $proc-echo.stdout; await $proc-echo.start, $proc-cat.start;
multi method new(*@ ($path, *@args), :$w, :$enc, :$translate-nl --> Proc::Async:D) multi method new( :$path, :@args, :$w, :$enc, :$translate-nl --> Proc::Async:D)
Creates a new Proc::Async object with external program name or path $path and the command line arguments @args.
If :w is passed to new, then a pipe to the external program's standard input stream (stdin) is opened, to which you can write with write and say.
The :enc specifies the encoding for streams (can still be overridden in individual methods) and defaults to utf8.
If :translate-nl is set to True (default value), OS-specific newline terminators (e.g. \r\n on Windows) will be automatically translated to \n.
method stdout(Proc::Async:D: :$bin --> Supply:D)
Returns the Supply for the external program's standard output stream. If :bin is passed, the standard output is passed along in binary as Blob, otherwise it is interpreted as UTF-8, decoded, and passed along as Str.
my $proc = Proc::Async.new(:r, 'echo', 'Perl 6'); $proc.stdout.tap( -> $str { say "Got output '$str' from the external program"; }); my $promise = $proc.start; await $promise;
You must call stdout before you call #method start. Otherwise an exception of class X::Proc::Async::TapBeforeSpawn is thrown.
If stdout is not called, the external program's standard output is not captured at all.
Note that you cannot call stdout both with and without :bin on the same object; it will throw an exception of type X::Proc::Async::CharsOrBytes if you try.
Use .Supply for merged STDOUT and STDERR.
method stderr(Proc::Async:D: :$bin --> Supply:D)
Returns the Supply for the external program's standard error stream. If :bin is passed, the standard error is passed along in binary as Blob, otherwise it is interpreted as UTF-8, decoded, and passed along as Str.
my $proc = Proc::Async.new(:r, 'echo', 'Perl 6'); $proc.stderr.tap( -> $str { say "Got error '$str' from the external program"; }); my $promise = $proc.start; await $promise;
You must call stderr before you call #method start. Otherwise an exception of class X::Proc::Async::TapBeforeSpawn is thrown.
If stderr is not called, the external program's standard error stream is not captured at all.
Note that you cannot call stderr both with and without :bin on the same object; it will throw an exception of type X::Proc::Async::CharsOrBytes if you try.
Use .Supply for merged STDOUT and STDERR.
multi method bind-stdin(IO::Handle:D $handle) multi method bind-stdin(Proc::Async::Pipe:D $pipe)
Sets a handle (which must be opened) or a Pipe as a source of STDIN. The STDIN of the target process must be writable or X::Proc::Async::BindOrUse will be thrown.
my $p = Proc::Async.new("cat", :in); my $h = "/etc/profile".IO.open; $p.bind-stdin($h); $p.start;
This is equivalent to
cat < /etc/profile
and will print the content of /etc/profile to standard output.
method bind-stdout(IO::Handle:D $handle)
Redirects STDOUT of the target process to a handle (which must be opened). If STDOUT is closed X::Proc::Async::BindOrUse will be thrown.
my $p = Proc::Async.new("ls", :out); my $h = "ls.out".IO.open(:w); $p.bind-stdout($h); $p.start;
This program will pipe the output of the ls shell command to a file called ls.out, which we are opened for reading.
method bind-stderr(IO::Handle:D $handle)
Redirects STDERR of the target process to a handle (which must be opened). If STDERR is closed X::Proc::Async::BindOrUse will be thrown.
my $p = Proc::Async.new("ls", "--foo", :err); my $h = "ls.err".IO.open(:w); $p.bind-stderr($h); $p.start;
method w(Proc::Async:D:)
Returns a true value if :w was passed to the constructor, that is, if the external program is started with its input stream made available to output to the program through the .print, .say and .write methods.
method start(Proc::Async:D: :$scheduler = $*SCHEDULER, :$ENV, :$cwd = $*CWD)
Initiates spawning of the external program. Returns a Promise that will be kept with a Proc object once the external program exits or broken if the program cannot be started. Optionally, you can use a scheduler instead of the default $*SCHEDULER, or change the environment the process is going to run in via the named argument :$ENV or the directory via the named argument :$cwd.
If start is called on a Proc::Async object on which it has already been called before, an exception of type X::Proc::Async::AlreadyStarted is thrown.
Note: If you wish to await the Promise and discard its result, using
try await $p.start;
will throw if the program exited with non-zero status, as the Proc returned as the result of the Promise throws when sunk and in this case it will get sunk outside the try. To avoid that, sink it yourself inside the try:
try sink await $p.start;
method started(Proc::Async:D: --> Bool:D)
Returns False before .start has been called, and True afterwards.
method ready(Proc::Async:D: --> Promise:D)
Returns a Promise that will be kept once the process has successfully started. Promise will be broken if the program fails to start.
Implementation-specific note: Starting from Rakudo 2018.04, the returned promise will hold the process id (PID).
method pid(Proc::Async:D: --> Promise:D)
Equivalent to ready.
Returns a Promise that will be kept once the process has successfully started. Promise will be broken if the program fails to start. Returned promise will hold the process id (PID).
Implementation-specific note: Available starting from Rakudo 2018.04.
method path(Proc::Async:D:)
Deprecated as of v6.d. Use command instead.
Returns the name and/or path of the external program that was passed to the new method as first argument.
method args(Proc::Async:D: --> Positional:D)
Deprecated as of v6.d. Use command instead.
Returns the command line arguments for the external programs, as passed to the new method.
method command(Proc::Async:D: --> List:D)
Available as of v6.d.
Returns the command and arguments used for this Proc::Async object:
my $p := Proc::Async.new: 'cat', 'some', 'files'; $p.command.say; # OUTPUT: «(cat some files)»
method write(Proc::Async:D: Blob:D $b, :$scheduler = $*SCHEDULER --> Promise:D)
Write the binary data in $b to the standard input stream of the external program.
Returns a Promise that will be kept once the data has fully landed in the input buffer of the external program.
The Proc::Async object must be created for writing (with Proc::Async.new(:w, $path, @args)). Otherwise an X::Proc::Async::OpenForWriting exception will the thrown.
start must have been called before calling method write, otherwise an X::Proc::Async::MustBeStarted exception is thrown.
method print(Proc::Async:D: Str(Any) $str, :$scheduler = $*SCHEDULER)
Write the text data in $str to the standard input stream of the external program, encoding it as UTF-8.
Returns a Promise that will be kept once the data has fully landed in the input buffer of the external program.
The Proc::Async object must be created for writing (with Proc::Async.new(:w, $path, @args)). Otherwise an X::Proc::Async::OpenForWriting exception will the thrown.
start must have been called before calling method print, otherwise an X::Proc::Async::MustBeStarted exception is thrown.
method say(Proc::Async:D: $output, :$scheduler = $*SCHEDULER)
Calls method gist on the $output, adds a newline, encodes it as UTF-8, and sends it to the standard input stream of the external program, encoding it as UTF-8.
Returns a Promise that will be kept once the data has fully landed in the input buffer of the external program.
The Proc::Async object must be created for writing (with Proc::Async.new(:w, $path, @args)). Otherwise an X::Proc::Async::OpenForWriting exception will the thrown.
start must have been called before calling method say, otherwise an X::Proc::Async::MustBeStarted exception is thrown.
multi method Supply(Proc::Async:D: :$bin!) multi method Supply(Proc::Async:D: :$enc, :$translate-nl)
Returns a Supply of merged stdout and stderr streams. If :$bin named argument is provided, the Supply will be binary, producing Buf objects, otherwise, it will be in character mode, producing Str objects and :$enc named argument can specify encoding to use. The :$translate-nl option specifies whether new line endings should be translated for to match those used by the current operating system (e.g. \r\n on Windows).
react { with Proc::Async.new: «"$*EXECUTABLE" -e 'say 42; note 100'» { whenever .Supply { .print } # OUTPUT: «42100» whenever .start {} } }
It is an error to create both binary and non-binary .Supply. It is also an error to use both .Supply and either stderr or stdout supplies.
method close-stdin(Proc::Async:D: --> True)
Closes the standard input stream of the external program. Programs that read from STDIN often only terminate when their input stream is closed. So if waiting for the promise from #method start hangs (for a program opened for writing), it might be a forgotten close-stdin.
The Proc::Async object must be created for writing (with Proc::Async.new(:w, $path, @args)). Otherwise an X::Proc::Async::OpenForWriting exception will the thrown.
start must have been called before calling method close-stdin, otherwise an X::Proc::Async::MustBeStarted exception is thrown.
method kill(Proc::Async:D: $signal = "HUP")
Sends a signal to the running program. The signal can be a signal name ("KILL" or "SIGKILL"), an integer (9) or an element of the Signal enum (Signal::SIGKILL).
Status/result of an asynchronous computation
my enum PromiseStatus (:Planned(0), :Kept(1), :Broken(2)); class Promise {}
A Promise is used to handle the result of a computation that might not have finished. It allows the user to execute code once the computation is done (with the then method), execution after a time delay (with in), combining promises, and waiting for results.
my $p = Promise.start({ sleep 2; 42}); $p.then({ say .result }); # will print 42 once the block finished say $p.status; # OUTPUT: «Planned» $p.result; # waits for the computation to finish say $p.status; # OUTPUT: «Kept»
There are two typical scenarios for using promises. The first is to use a factory method (start, in, at, anyof, allof, kept, broken) on the type object; those will make sure that the promise is automatically kept or broken for you, and you can't call break or keep on these promises yourself.
The second is to create your promises yourself with Promise.new. If you want to ensure that only your code can keep or break the promise, you can use the vow method to get a unique handle, and call keep or break on it:
sub async-get-with-promise($user-agent, $url) { my $p = Promise.new; my $v = $p.vow; # do an asynchronous call on a fictive user agent, # and return the promise: $user-agent.async-get($url, on-error => -> $error { $v.break($error); }, on-success => -> $response { $v.keep($response); } ); return $p; }
Further examples can be found in the concurrency page.
method start(Promise:U: &code, :$scheduler = $*SCHEDULER --> Promise:D)
Creates a new Promise that runs the given code object. The promise will be kept when the code terminates normally, or broken if it throws an exception. The return value or exception can be inspected with the result method.
The scheduler that handles this promise can be passed as a named argument.
There is also a statement prefix start that provides syntactic sugar for this method:
# these two are equivalent: my $p1 = Promise.start({ ;#`( do something here ) }); my $p2 = start { ;#`( do something here ) };
As of the 6.d version of the language, start statement prefix used in sink context will automatically attach an exceptions handler. If an exception occurs in the given code, it will be printed and the program will then exit, like if it were thrown without any start statement prefixes involved.
use v6.c; start { die }; sleep ⅓; say "hello"; # OUTPUT: «hello»
use v6.d; start { die }; sleep ⅓; say "hello"; # OUTPUT: # Unhandled exception in code scheduled on thread 4 # Died # in block at -e line 1
If you wish to avoid this behavior, use start in non-sink context or catch the exception yourself:
# Don't sink it: my $ = start { die }; sleep ⅓; say "hello"; # OUTPUT: «hello» # Catch yourself: start { die; CATCH { default { say "caught" } } }; sleep ⅓; say "hello"; # OUTPUT: «caughthello»
This behavior exists only syntactically, by using an alternate .sink method for Promise objects created by start blocks in sink context, thus simply sinking a Promise object that was created by other means won't trigger this behavior.
method in(Promise:U: $seconds, :$scheduler = $*SCHEDULER --> Promise:D)
Creates a new Promise that will be kept in $seconds seconds, or later.
my $proc = Proc::Async.new('perl6', '-e', 'sleep 10; warn "end"'); my $result = await Promise.anyof( my $promise = $proc.start, # may or may not work in time Promise.in(5).then: { # fires after 5 seconds no matter what unless $promise { # don't do anything if we were successful note 'timeout'; $proc.kill; } } ).then: { $promise.result } # OUTPUT: «timeout»
$seconds can be fractional or negative. Negative values are treated as 0 (i.e. keeping the returned Promise right away).
Please note that situations like these are often more clearly handled with a react and whenever block.
method at(Promise:U: $at, :$scheduler = $*SCHEDULER --> Promise:D)
Creates a new Promise that will be kept $at the given time—which is given as an Instant or equivalent Numeric—or as soon as possible after it.
my $p = Promise.at(now + 2).then({ say "2 seconds later" }); # do other stuff here await $p; # wait here until the 2 seconds are over
If the given time is in the past, it will be treated as now (i.e. keeping the returned Promise right away).
Please note that situations like these are often more clearly handled with a react and whenever block.
multi method kept(Promise:U: \result = True --> Promise:D)
Returns a new promise that is already kept, either with the given value, or with the default value True.
multi method broken(Promise:U: --> Promise:D) multi method broken(Promise:U: \exception --> Promise:D)
Returns a new promise that is already broken, either with the given value, or with the default value X::AdHoc.new(payload => "Died")
method allof(Promise:U: *@promises --> Promise:D)
Returns a new promise that will be kept when all the promises passed as arguments are kept or broken. The result of the individual Promises is not reflected in the result of the returned promise: it simply indicates that all the promises have been completed in some way. If the results of the individual promises are important then they should be inspected after the allof promise is kept.
In the following requesting the result of a broken promise will cause the original Exception to be thrown. (You may need to run it several times to see the exception.)
my @promises; for 1..5 -> $t { push @promises, start { sleep $t; }; } my $all-done = Promise.allof(@promises); await $all-done; @promises>>.result; say "Promises kept so we get to live another day!";
method anyof(Promise:U: *@promises --> Promise:D)
Returns a new promise that will be kept as soon as any of the promises passed as arguments is kept or broken. The result of the completed Promise is not reflected in the result of the returned promise which will always be Kept.
You can use this to wait at most a number of seconds for a promise:
my $timeout = 5; await Promise.anyof( Promise.in($timeout), start { # do a potentially long-running calculation here }, );
method then(Promise:D: &code)
Schedules a piece of code to be run after the invocant has been kept or broken, and returns a new promise for this computation. In other words, creates a chained promise.
my $timer = Promise.in(2); my $after = $timer.then({ say "2 seconds are over!"; 'result' }); say $after.result; # 2 seconds are over # result
multi method keep(Promise:D: \result = True)
Keeps a promise, optionally setting the result. If no result is passed, the result will be True.
Throws an exception of type X::Promise::Vowed if a vow has already been taken. See method vow for more information.
my $p = Promise.new; if Bool.pick { $p.keep; } else { $p.break; }
multi method break(Promise:D: \cause = False)
Breaks a promise, optionally setting the cause. If no cause is passed, the cause will be False.
Throws an exception of type X::Promise::Vowed if a vow has already been taken. See method vow for more information.
my $p = Promise.new; $p.break('sorry'); say $p.status; # OUTPUT: «Broken» say $p.cause; # OUTPUT: «sorry»
method result(Promise:D)
Waits for the promise to be kept or broken. If it is kept, returns the result; otherwise throws the result as an exception.
method cause(Promise:D)
If the promise was broken, returns the result (or exception). Otherwise, throws an exception of type X::Promise::CauseOnlyValidOnBroken.
multi method Bool(Promise:D:)
Returns True for a kept or broken promise, and False for one in state Planned.
method status(Promise:D --> PromiseStatus)
Returns the current state of the promise: Kept, Broken or Planned:
say "promise got Kept" if $promise.status ~~ Kept;
method scheduler(Promise:D:)
Returns the scheduler that manages the promise.
my class Vow { has Promise $.promise; method keep() { ... } method break() { ... } } method vow(Promise:D: --> Vow:D)
Returns an object that holds the sole authority over keeping or breaking a promise. Calling keep or break on a promise that has vow taken throws an exception of type X::Promise::Vowed.
my $p = Promise.new; my $vow = $p.vow; $vow.keep($p); say $p.status; # OUTPUT: «Kept»
method Supply(Promise:D:)
Returns a Supply that will emit the result of the Promise being Kept or quit with the cause if the Promise is Broken.
multi sub await(Promise:D --> Promise) multi sub await(*@ --> Array)
Waits until one or more promises are all fulfilled, and then returns their values. Also works on channels. Any broken promises will rethrow their exceptions. If a list is passed it will return a list containing the results of awaiting each item in turn.
Item container with custom storage and retrieval
class Proxy {}
A Proxy is an object that allows you to set a hook that executes whenever a value is retrieved from a container (FETCH) or when it is set (STORE). Please note that Proxy can introduce mutability at places where it would break behavior, e.g. in Hash keys.
To create a container that returns twice what was stored in it, you do something like this:
sub double() is rw { my $storage = 0; Proxy.new( FETCH => method () { $storage * 2 }, STORE => method ($new) { $storage = $new }, ) } my $doubled := double(); $doubled = 4; say $doubled; # OUTPUT: «8»
method new(:&FETCH!, :&STORE! --> Proxy:D)
Creates a new Proxy object. &FETCH is called with one argument (the proxy object) when the value is accessed, and must return the value that the fetch produces. &STORE is called with two arguments (the proxy object, and the new value) when a new value is stored in the container.
Stash type for pseudo-packages
class PseudoStash is Map { }
PseudoStash is the stash type (hanging off .WHO) that backs various pseudo-packages. So, when you do MY:: or CALLER::, that gives back a PseudoStash. In most cases, Package:: gives back a Stash. Neither of these are objects the user is expected to create by themselves, but in case you have one, you can just use it like a hash.
my $a = 42; my $b = q/$a/; say MY::{$b}; #OUTPUT: «42»
This shows how you can use a PseudoStash to look up variables, by name, at runtime.
Object hashes with limitation on type of value
role QuantHash does Associative { }
The QuantHash role provides the basic functionality shared by the Setty, Baggy and Mixy roles. These provide object hashes of which the values are limited in some way.
QuantHashes are what set operators use internally.
method hash()
Coerces the QuantHash object to a Hash (by stringifying the objects for the keys) with the values of the hash limited to the same limitation as QuantHash, and returns that.
method Hash()
Coerces the QuantHash object to a Hash (by stringifying the objects for the keys) without any limitations on the values, and returns that.
method of()
Returns the type of value a value of this QuantHash may have. This is typically Bool for Setty, UInt for Baggy or Real for Mixy roles.
method keyof()
Returns the type of value a key of this QuantHash may have. This is typically Mu.
method Setty(--> Setty:D)
Coerce the QuantHash object to the equivalent object that uses the Setty role. Note that for Mixy type coercion items with negative values will be skipped.
my %b is Bag = one => 1, two => 2; say %b.Setty; # OUTPUT: «set(one two)» my %m is Mix = one => 1, minus => -1; say %m.Setty; # OUTPUT: «set(one)»
method Baggy(--> Baggy:D)
Coerce the QuantHash object to the equivalent object that uses the Baggy role. Note that for Mixy type coercion items with negative values will be skipped.
my %s is Set = <one two>; say %s.Baggy; # OUTPUT: «Bag(one, two)» my %m is Mix = one => 1, minus => -1; say %m.Baggy; # OUTPUT: «Bag(one)»
method Mixy(--> Mixy:D)
Coerce the QuantHash object to the equivalent object that uses the Mixy role.
my %s is Set = <one two>; say %s.Mixy; # OUTPUT: «Mix(one, two)» my %b is Bag = one => 1, two => 2; say %b.Mixy; # OUTPUT: «Mix(one, two)»
Performs batches of work in parallel without respecting original order.
class RaceSeq does Iterable does Sequence { }
An RaceSeq is the intermediate object used when the operator race is invoked on a Seq. In general, it's not intended for direct consumption by the developer.
method iterator(RaceSeq:D: --> Iterator:D)
Returns the underlying iterator.
method grep(RaceSeq:D: $matcher, *%options)
Applies grep to the RaceSeq similarly to how it would do it on a Seq.
my @raced = (^10000).map(*²).race; @raced.grep( * %% 3 ).say; # OUTPUT: «(0 9 36 81 144 …»
When you use race on a Seq, this is the method that is actually called.
method map(RaceSeq:D: $matcher, *%options)
Uses maps on the RaceSeq, generally created by application of .race to a preexisting Seq.
method invert(RaceSeq:D:)
Inverts the RaceSeq created from a Seq by .race.
method race(RaceSeq:D:)
Returns the object.
method hyper(RaceSeq:D:)
Creates a HyperSeq object out of the current one.
multi method serial(RaceSeq:D:)
Converts the object to a Seq and returns it.
method is-lazy(--> False )
Returns False.
Defined as:
method sink(--> Nil)
Sinks the underlying data structure, producing any side effects.
Interval of ordered values
class Range is Cool does Iterable does Positional {}
Ranges serve two main purposes: to generate lists of consecutive numbers or strings, and to act as a matcher to check if a number or string is within a certain range.
Ranges are constructed using one of the four possible range operators, which consist of two dots, and optionally a caret which indicates that the endpoint marked with it is excluded from the range.
1 .. 5; # 1 <= $x <= 5 1^.. 5; # 1 < $x <= 5 1 ..^5; # 1 <= $x < 5 1^..^5; # 1 < $x < 5
The caret is also a prefix operator for constructing numeric ranges starting from zero:
my $x = 10; say ^$x; # same as 0 ..^ $x.Numeric
Iterating a range (or calling the list method) uses the same semantics as the ++ prefix and postfix operators, i.e., it calls the succ method on the start point, and then the generated elements.
Ranges always go from small to larger elements; if the start point is bigger than the end point, the range is considered empty.
for 1..5 { .say }; # OUTPUT: «12345» ('a' ^..^ 'f').list; # RESULT: «'b', 'c', 'd', 'e'» 5 ~~ ^5; # RESULT: «False» 4.5 ~~ 0..^5; # RESULT: «True» (1.1..5).list; # RESULT: «(1.1, 2.1, 3.1, 4.1)»
Use the ... sequence operator to produce lists of elements that go from larger to smaller values, or to use offsets other than increment-by-1 and other complex cases.
Use ∞ or * (Whatever) to indicate an end point to be open-ended.
for 1..* { .say }; # start from 1, continue until stopped for 1..∞ { .say }; # the same
Beware that a WhateverCode end point, instead of a plain Whatever, will go through the range operator and create another WhateverCode which returns a Range:
# A Whatever produces the 1..Inf range say (1..*).^name; # OUTPUT: «Range» say (1..*); # OUTPUT: «1..Inf» # Upper end point is now a WhateverCode say (1..*+20).^name; # OUTPUT: «{ ... }» say (1..*+20).WHAT; # OUTPUT: «(WhateverCode)» say (1..*+20).(22); # OUTPUT: «1..42»
Ranges implement Positional interface, so its elements can be accessed using an index. In a case when the index given is bigger than the Range object's size, Nil object will be returned. The access works for lazy Range objects as well.
say (1..5)[1]; # OUTPUT: «2» say (1..5)[10]; # OUTPUT: «Nil» say (1..*)[10]; # OUTPUT: «11»
A Range can be used in a subscript to get a range of values. Please note that assigning a Range to a scalar container turns the Range into an item. Use binding, @-sigiled containers or a slip to get what you mean.
my @numbers = <4 8 15 16 23 42>; my $range := 0..2; .say for @numbers[$range]; # OUTPUT: «4815» my @range = 0..2; .say for @numbers[@range]; # OUTPUT: «4815»
It is possible to shift or scale the interval of a range:
say (1..10) + 1; # OUTPUT: «2..11» say (1..10) - 1; # OUTPUT: «0..9» say (1..10) * 2; # OUTPUT: «2..20» say (1..10) / 2; # OUTPUT: «0.5..5.0»
You can use smartmatch to match against Ranges.
say 3 ~~ 1..12; # OUTPUT: «True» say 2..3 ~~ 1..12; # OUTPUT: «True»
In Rakudo only, you can use the in-range method for matching against a range, which in fact is equivalent to smartmatch except it will throw an exception when out of range, instead of returning False:
say ('א'..'ת').in-range('ע'); # OUTPUT: «True»
However, if it is not included in the range:
say ('א'..'ת').in-range('p', "Letter 'p'"); # OUTPUT: «(exit code 1) Letter 'p' out of range. Is: "p", should be in "א".."ת"
The second parameter to in-range is the optional message that will be printed with the exception. It will print Value by default.
Defined as
multi method ACCEPTS(Range:D: Mu \topic) multi method ACCEPTS(Range:D: Range \topic) multi method ACCEPTS(Range:D: Cool:D \got) multi method ACCEPTS(Range:D: Complex:D \got)
Indicates if the Range contains (overlaps with) another Range. As an example:
my $p = Range.new( 3, 5 ); my $r = Range.new( 1, 10 ); say $p.ACCEPTS( $r ); # OUTPUT: «False» say $r.ACCEPTS( $p ); # OUTPUT: «True» say $r ~~ $p; # OUTPUT: «False» (same as $p.ACCEPTS( $r ) say $p ~~ $r; # OUTPUT: «True» (same as $r.ACCEPTS( $p )
Of course, an infinite Range always contains another Range, therefore:
say 1..10 ~~ -∞..∞; # OUTPUT: «True» say 1..10 ~~ -∞^..^∞; # OUTPUT: «True»
Similarly, a Range with open boundaries often includes other ranges:
say 1..2 ~~ *..10; # OUTPUT: «True» say 2..5 ~~ 1..*; # OUTPUT: «True»
It is also possible to use non-numeric ranges, for instance string based ones:
say 'a'..'j' ~~ 'b'..'c'; # OUTPUT: «False» say 'b'..'c' ~~ 'a'..'j'; # OUTPUT: «True» say 'perl' ~~ -∞^..^∞; # OUTPUT: «True» say 'perl' ~~ -∞..∞; # OUTPUT: «True» say 'perl' ~~ 1..*; # OUTPUT: «True»
When smartmatching a Range of integers with a Cool (string) the ACCEPTS methods exploits the before and after operators in order to check that the Cool value is overlapping the range:
say 1.10 ~~ '5'; # OUTPUT: «False» say '5' before 1; # OUTPUT: «False» say '5' after 10; # OUTPUT: «True» say '5' ~~ *..10; # OUTPUT: «False»
In the above example, since the '5' string is after the 10 integer value, the Range does not overlap with the specified value.
When matching with a Mu instance (i.e., a generic instance), the cmp operator is used.
method min(Range:D:)
Returns the start point of the range.
say (1..5).min; # OUTPUT: «1» say (1^..^5).min; # OUTPUT: «1»
method excludes-min(Range:D: --> Bool:D)
Returns True if the start point is excluded from the range, and False otherwise.
say (1..5).excludes-min; # OUTPUT: «False» say (1^..^5).excludes-min; # OUTPUT: «True»
method max(Range:D:)
Returns the end point of the range.
say (1..5).max; # OUTPUT: «5» say (1^..^5).max; # OUTPUT: «5»
method excludes-max(Range:D: --> Bool:D)
Returns True if the end point is excluded from the range, and False otherwise.
say (1..5).excludes-max; # OUTPUT: «False» say (1^..^5).excludes-max; # OUTPUT: «True»
method bounds()
Returns a list consisting of the start and end point.
say (1..5).bounds; # OUTPUT: «(1 5)» say (1^..^5).bounds; # OUTPUT: «(1 5)»
method infinite(Range:D: --> Bool:D)
Returns True if either end point was declared with ∞ or *.
say (1..5).infinite; # OUTPUT: «False» say (1..*).infinite; # OUTPUT: «True»
method is-int(Range:D: --> Bool:D)
Returns True if both end points are Int values.
say ('a'..'d').is-int; # OUTPUT: «False» say (1..^5).is-int; # OUTPUT: «True» say (1.1..5.5).is-int; # OUTPUT: «False»
method int-bounds(Range:D: --> Positional)
If the Range is an integer range (as indicated by is-int), then this method returns a list with the first and last value it will iterate over (taking into account excludes-min and excludes-max). Returns a Failure if it is not an integer range.
say (2..5).int-bounds; # OUTPUT: «(2 5)» say (2..^5).int-bounds; # OUTPUT: «(2 4)»
Defined as:
multi method minmax(Range:D: --> List:D)
If the Range is an integer range (as indicated by is-int), then this method returns a list with the first and last value it will iterate over (taking into account excludes-min and excludes-max). If the range is not an integer range, the method will return a two element list containing the start and end point of the range unless either of excludes-min or excludes-max are True in which case a Failure is returned.
my $r1 = (1..5); my $r2 = (1^..5); say $r1.is-int, ', ', $r2.is-int; # OUTPUT: «True, True» say $r1.excludes-min, ', ', $r2.excludes-min; # OUTPUT: «False, True» say $r1.minmax, ', ', $r2.minmax; # OUTPUT: «(1 5), (2 5)» my $r3 = (1.1..5.2); my $r4 = (1.1..^5.2); say $r3.is-int, ', ', $r4.is-int; # OUTPUT: «False, False» say $r3.excludes-max, ', ', $r4.excludes-max; # OUTPUT: «False, True» say $r3.minmax; # OUTPUT: «(1.1 5.2)» say $r4.minmax; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::AdHoc: Cannot return minmax on Range with excluded ends»
method elems(Range:D: --> Numeric:D)
Returns the number of elements in the range, e.g. when being iterated over, or when used as a List. Returns Inf if either end point was specified as Inf or *.
say (1..5).elems; # OUTPUT: «5» say (1^..^5).elems; # OUTPUT: «3»
method list(Range:D: --> List:D)
Generates the list of elements that the range represents.
say (1..5).list; # OUTPUT: «(1 2 3 4 5)» say (1^..^5).list; # OUTPUT: «(2 3 4)»
method flat(Range:D: --> List:D)
Generates the list of elements that the range represents.
multi method pick(Range:D: --> Any:D) multi method pick(Range:D: $number --> Seq:D)
Performs the same function as Range.list.pick, but attempts to optimize by not actually generating the list if it is not necessary.
multi method roll(Range:D: --> Any:D) multi method roll(Range:D: $number --> Seq:D)
Performs the same function as Range.list.roll, but attempts to optimize by not actually generating the list if it is not necessary.
multi method sum(--> Numeric:D)
Returns the sum of all elements in the Range. Throws X::Str::Numeric if an element can not be coerced into Numeric.
(1..10).sum # 55
method reverse(Range:D: --> Seq:D)
Returns a Seq where all elements that the Range represents have been reversed. Note that reversing an infinite Range won't produce any meaningful results.
say (1^..5).reverse; # OUTPUT: «(5 4 3 2)» say ('a'..'d').reverse; # OUTPUT: «(d c b a)» say (1..∞).reverse; # OUTPUT: «(Inf Inf Inf ...)»
Defined as:
method Capture(Range --> Capture:D)
Returns a Capture with values of .min .max, .excludes-min, .excludes-max, .infinite, and .is-int as named arguments.
Defined as:
method rand(Range:D --> Num:D)
Returns a pseudo-random value belonging to the range.
say (1^..5).rand; # OUTPUT: «1.02405550417031» say (0.1..0.3).rand; # OUTPUT: «0.2130353370062»
Defined as
multi method EXISTS-POS(Range:D: int \pos) multi method EXISTS-POS(Range:D: Int \pos)
Returns True if pos is greater or equal than zero and lower than self.elems. Returns False otherwise.
say (6..10).EXISTS-POS(2); # OUTPUT: «True» say (6..10).EXISTS-POS(7); # OUTPUT: «False»
Defined as
multi method AT-POS(Range:D: int \pos) multi method AT-POS(Range:D: int:D \pos)
Checks if the Int position exists and in that case returns the element in that position.
say (1..4).AT-POS(2) # OUTPUT: «3»
Defined as
multi method perl(Range:D:)
Returns an implementation-specific string that produces an equivalent object when given to EVAL.
say (1..2).perl # OUTPUT: «1..2»
Defined as
method fmt(|c)
Returns a string where min and max in the Range have been formatted according to |c.
For more information about formats strings, see sprintf.
say (1..2).fmt("Element: %d", ",") # OUTPUT: «Element: 1,Element: 2»
Defined as
multi method WHICH (Range:D:)
This returns a string that identifies the object. The string is composed by the type of the instance (Range) and the min and max attributes:
say (1..2).WHICH # OUTPUT: «Range|1..2»
multi sub infix:<+>(Range:D \r, Real:D \v) multi sub infix:<+>(Real:D \v, Range:D \r)
Takes an Real and adds that number to both boundaries of the Range object. Be careful with the use of parenthesis.
say (1..2) + 2; # OUTPUT: «3..4» say 1..2 + 2; # OUTPUT: «1..4»
multi sub infix:<->(Range:D \r, Real:D \v)
Takes an Real and subtract that number to both boundaries of the Range object. Be careful with the use of parenthesis.
say (1..2) - 1; # OUTPUT: «0..1» say 1..2 - 1; # OUTPUT: «1..1»
multi sub infix:<*>(Range:D \r, Real:D \v) multi sub infix:<*>(Real:D \v, Range:D \r)
Takes an Real and multiply both boundaries of the Range object by that number.
say (1..2) * 2; # OUTPUT: «2..4»
multi sub infix:</>(Range:D \r, Real:D \v)
Takes an Real and divide both boundaries of the Range object by that number.
say (2..4) / 2; # OUTPUT: «1..2»
multi sub infix:<cmp>(Range:D \a, Range:D \b --> Order:D) multi sub infix:<cmp>(Num(Real) \a, Range:D \b --> Order:D) multi sub infix:<cmp>(Range:D \a, Num(Real) \b --> Order:D) multi sub infix:<cmp>(Positional \a, Range:D \b --> Order:D) multi sub infix:<cmp>(Range:D \a, Positional \b --> Order:D)
Compares two Range objects. If you use a Real, it will be compared to the Range b..b. If you use a Positional.
say (1..2) cmp (1..2); # OUTPUT: «Same» say (1..2) cmp (1..3); # OUTPUT: «Less» say (1..4) cmp (1..3); # OUTPUT: «More» say (1..2) cmp 3; # OUTPUT: «Less» say (1..2) cmp [1,2]; # OUTPUT: «Same»
Rational number (limited-precision)
class Rat is Cool does Rational[Int, uint64] { }
Rat objects store rational numbers as a pair of a numerator and denominator. Number literals with a dot but without exponent produce Rats.
say 3.1; # OUTPUT: «3.1» (same as: Rat.new(31, 10)) say 3.1.^name; # OUTPUT: «Rat» say 3.1.nude; # OUTPUT: «(31 10)» say <1/2>; # OUTPUT: «0.5» (same as: Rat.new(1, 2)) say <1/2>.^name; # OUTPUT: «Rat» say <1/2>.nude; # OUTPUT: «(1 2)»
Thus arithmetic with short dotted-decimal numbers does not suffer from floating point errors.
To prevent the numerator and denominator from becoming pathologically large, the denominator is limited to 64 bit storage. On overflow of the denominator a Num (floating-point number) is returned instead.
For example this function crudely approximates a square root, and overflows the denominator quickly:
sub approx-sqrt($n, $iterations) { my $x = $n; $x = ($x + $n / $x) / 2 for ^$iterations; return $x; } say approx-sqrt(2, 5).^name; # OUTPUT: «Rat» say approx-sqrt(2, 10).^name; # OUTPUT: «Num»
If you want arbitrary precision arithmetic with rational numbers, use the FatRat type instead.
Rat objects are immutable.
multi method perl(Rat:D: --> Str:D)
Returns an implementation-specific string that produces an equivalent object when given to EVAL.
say (1/3).perl; # OUTPUT: «<1/3>» say (2/4).perl; # OUTPUT: «0.5»
Dual value rational number and string
class RatStr is Rat is Str {}
The dual value types (often referred to as allomorphs) allow for the representation of a value as both a string and a numeric type. Typically they will be created for you when the context is "stringy" but they can be determined to be numbers, such as in some quoting constructs:
my $f = <42.1>; say $f.^name; # OUTPUT: «RatStr»
As a subclass of both Rat and Str, a RatStr will be accepted where either is expected. However, RatStr does not share object identity with Rat- or Str-only variants:
my $rat-str = <42.1>; my Rat $rat = $rat-str; # OK! my Str $str = $rat-str; # OK! say 42.1 ∈ <42.1 55 1>; # False; ∈ operator cares about object identity
method new(Rat $i, Str $s)
The constructor requires both the Rat and the Str value, when constructing one directly the values can be whatever is required:
my $f = RatStr.new(42.1, "forty two and a bit"); say +$f; # OUTPUT: «42.1» say ~$f; # OUTPUT: «"forty two and a bit"»
Defined as:
multi method Bool(RatStr:D: --> Bool:D)
This method may be provided by the parent classes and not implemented in RatStr directly.
Returns False if the numerator of the numeric portion is 0, otherwise returns True. This applies for < 0/0 > zero-denominator RatStr as well, despite ?< 0/0 >.Num being True. String portion is not considered.
Defined as:
method Capture(RatStr:D --> Capture:D)
Equivalent to Mu.Capture.
Defined as:
multi method Numeric(RatStr:D: --> Rat:D) multi method Numeric(RatStr:U: --> Rat:D)
The :D variant returns the numeric portion of the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value 0.0.
method Rat
Returns the Rat value of the RatStr.
Defined as:
multi method Real(Real:D: --> Rat:D) multi method Real(Real:U: --> Rat:D)
The :D variant returns the numeric portion of the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns value 0.0.
Returns the string value of the RatStr.
Defined as:
multi method ACCEPTS(RatStr:D: Any:D $value)
If $value is Numeric (including another allomorph), checks if invocant's Numeric part ACCEPTS the $value. If $value is Str, checks if invocant's Str part ACCEPTS the $value. If value is anything else, checks if both Numeric and Str parts ACCEPTS the $value.
say <5.0> ~~ "5"; # OUTPUT: «False» say <5.0> ~~ 5 ; # OUTPUT: «True» say <5.0> ~~ <5>; # OUTPUT: «True»
multi sub infix:<cmp>(RatStr:D $a, RatStr:D $b)
Compare two RatStr objects. The comparison is done on the Rat value first and then on the Str value. If you want to compare in a different order then you would coerce to the Rat or Str values first:
my $f = RatStr.new(42.1, "smaller"); my $g = RatStr.new(43.1, "larger"); say $f cmp $g; # OUTPUT: «Less» say $f.Str cmp $g.Str; # OUTPUT: «More»
Number stored as numerator and denominator
role Rational[::NuT, ::DeT] does Real { ... }
Rational is the common role for numbers that are stored as pairs of numerator and denominator. It is parameterized by the types of the numerator (NuT) and denominator (DeT). By default, these are Int, but other types of Rational are possible by using a different parameterization. In addition, Rational objects are immutable throughout their life.
class Positive does Rational[UInt] {}; my Positive $one-third = Positive.new(1,3); say $one-third; # OUTPUT: «0.333333» my Positive $fail =Positive.new(-2,3); # OUTPUT: «Type check failed in binding to parameter 'nu'; expected UInt but got Int (-2)»
Please note that, since DeT is by default equal to NuT, in this case both are instantiated to UInt. Built into Perl 6 are Rat and FatRat, which both do the Rational role.
method new(NuT:D $numerator, DeT:D $denominator --> Rational:D)
Creates a new rational object from numerator and denominator, which it normalizes to the lowest terms. The $denominator can be zero, in which case the numerator is normalized to -1, 0, or 1 depending on whether the original is negative, zero, or positive, respectively.
Defined as:
multi method Bool(Rational:D: --> Bool:D)
Returns False if numerator is 0, otherwise returns True. This applies for <0/0> zero-denominator Rational as well, despite ?<0/0>.Num being True.
Defined as:
method Int(Rational:D: --> Int:D)
Coerces the invocant to Int by truncating non-whole portion of the represented number, if any. If the denominator is zero, will fail with X::Numeric::DivideByZero.
Defined as:
method Num(Rational:D: --> Num:D)
Coerces the invocant to Num by dividing numerator by denominator. If denominator is 0, returns Inf, -Inf, or NaN, based on whether numerator is a positive number, negative number, or 0, respectively.
Defined as:
method ceiling(Rational:D: --> Int:D)
Return the smallest integer not less than the invocant. If denominator is zero, fails with X::Numeric::DivideByZero.
Defined as:
method floor(Rational:D: --> Int:D)
Return the largest integer not greater than the invocant. If denominator is zero, fails with X::Numeric::DivideByZero.
method isNaN(Rational:D: --> Bool:D)
Tests whether the invocant's Num value is a NaN, an acronym for Not available Number. That is both its numerator and denominator are zero.
method numerator(Rational:D: --> NuT:D)
Returns the numerator.
method denominator(Rational:D: --> DeT:D)
Returns the denominator.
method nude(Rational:D: --> Positional)
Returns a list of the numerator and denominator.
method norm(Rational:D: --> Rational:D)
DEPRECATED as of 6.d. The method is no longer needed, because as of 6.d language version, it's required for Rational type to be normalized on creation.
Returns a normalized Rational object, i.e. with positive denominator, and numerator and denominator coprime. The denominator can also by zero, but using it in any operation or a conversion to string will result in an exception.
use v6.c; my Rational $by-zero = 3/0; say $by-zero.norm.perl; # OUTPUT: «<1/0>»
say $by-zero; # OUTPUT: «Attempt to divide by zero when coercing Rational to Str
method base-repeating(Rational:D: Int:D() $base = 10)
Returns a list of two strings that, when concatenated, represent the number in base $base. The second element is the one that repeats. For example:
my ($non-rep, $repeating) = (19/3).base-repeating(10); say $non-rep; # OUTPUT: «6.» say $repeating; # OUTPUT: «3» printf '%s(%s)', $non-rep, $repeating; # OUTPUT: «6.(3)»
19/3 is 6.333333... with the 3 repeating indefinitely.
If no repetition occurs, the second string is empty:
say (5/2).base-repeating(10).perl; # OUTPUT: «("2.5", "")»
The precision for determining the repeating group is limited to 1000 characters, above that, the second string is ???.
$base defaults to 10.
Returns a Range object that represents the range of values supported.
Non-complex number
role Real does Numeric { ... }
Common role for non-Complex numbers.
Defined as:
method Bridge(Real:D:)
Default implementation coerces the invocant to Num and that's the behavior of this method in core Real types. This method primarily exist to make it easy to implement custom Real types by users, with the Bridge method returning one of the core Real types (NOT necessarily a Num) that best represent the custom Real type. In turn, this lets all the core operators and methods obtain a usable value they can work with.
As an example, we can implement a custom Temperature type. It has a unit of measure and the value, which are given during instantiation. We can implement custom operators or conversion methods that work with this type. When it comes to regular mathematical operators, however, we can simply use the .Bridge method to convert the Temperature to Kelvin expressed in one of the core numeric types:
class Temperature is Real { has Str:D $.unit is required where any <K F C>; has Real:D $.value is required; method new ($value, :$unit = 'K') { self.bless :$value :$unit } # Note: implementing .new() that handles $value of type Temperature is left as an exercise method Bridge { when $!unit eq 'F' { ($!value + 459.67) × 5/9 } when $!unit eq 'C' { $!value + 273.15 } $!value } method gist { self.Str } method Str { "$!value degrees $!unit" } } sub postfix:<℃> { Temperature.new: $^value, :unit<C> } sub postfix:<℉> { Temperature.new: $^value, :unit<F> } sub postfix:<K> { Temperature.new: $^value, :unit<K> } my $human := 36.6℃; my $book := 451℉; my $sun := 5778K; say $human; # OUTPUT: «36.6 degrees C» say $human + $book + $sun; # OUTPUT: «6593.677777777778» say 123K + 456K; # OUTPUT: «579»
As we can see from the last two lines of the output, the type of the bridged result is not forced to be any particular core type. It is a Rat, when we instantiated Temperature with a Rat or when conversion was involved, and it is an Int when we instantiated Temperature with an Int.
method Complex(Real:D: --> Complex:D)
Converts the number to a Complex with the number converted to a Num as its real part and 0e0 as the imaginary part.
method Rat(Real:D: Real $epsilon = 1e-6)
Converts the number to a Rat with the precision $epsilon.
Defined as:
multi method Real(Real:D: --> Real:D) multi method Real(Real:U: --> Real:D)
The :D variant simply returns the invocant. The :U variant issues a warning about using an uninitialized value in numeric context and then returns self.new.
sub term:<rand> (--> Num:D) method rand(Real:D: --> Real:D)
Returns a pseudo-random number between zero (inclusive) and the number (non-inclusive). The Bridge method is used to coerce the Real to a numeric that supports rand method.
The term form returns a pseudo-random Num between 0e0 (inclusive) and 1e0 (non-inclusive.)
method sign(Real:D:)
Returns -1 if the number is negative, 0 if it is zero and 1 otherwise.
method round(Real:D: $scale = 1)
Rounds the number to scale $scale. If $scale is 1, rounds to an integer. If scale is 0.1, rounds to one digit after the comma etc.
method floor(Real:D --> Int:D)
Return the largest integer not greater than the number.
method ceiling(Real:D --> Int:D)
Returns the smallest integer not less than the number.
method truncate(Real:D --> Int:D)
Rounds the number towards zero.
method polymod(Real:D: +@mods)
Returns the remainders after applying sequentially all divisors in the @mods argument; the last element of the array will be the last remainder.
say (1e8+1).polymod(10 xx 8); # OUTPUT: «(1 0 0 0 0 0 0 0 1)»
10 xx 8 is simply an array with eight number 10s; the first division by 10 will return 1 as a remainder, while the rest, up to the last, will return 0. With 8 divisors, as above, the result will have one more elements, in this case for the last remainder.
method base(Real:D: Int:D $base where 2..36, $digits? --> Str:D)
Converts the number to a string, using $base as base. For $base larger than ten, capital Latin letters are used.
255.base(16); # 'FF'
The optional $digits argument asks for that many digits of fraction (which may not be negative). If omitted, a reasonable default is chosen based on type. For Int this default is 0. For Num, the default is 8. For Rational, the number of places is scaled to the size of the denominator, with a minimum of 6.
A special value of Whatever (*) can be given as $digits, which functions the same as when $digits is not specified for all Real types except the Rationals. For Rationals, the Whatever indicates that you wish all of the possible digits of the fractional part, but use caution: since there's no detection of repeating fractional parts (the algorithm will eventually stop after generating 2**63 digits).
The final digit produced is always rounded.
say pi.base(10, 3); # OUTPUT: «3.142» say (1/128).base(10, *); # OUTPUT: «0.0078125» say (1/100).base(10, *); # OUTPUT: «0.01» say (1/3) .base(10, *); # WRONG: endlessly repeating fractional part
For reverse operation, see parse-base
String pattern
class Regex is Method { }
A regex is a kind of pattern that describes a set of strings. The process of finding out whether a given string is in the set is called matching. The result of such a matching is a Match object, which evaluates to True in boolean context if the string is in the set.
A regex is typically constructed by a regex literal
rx/ ^ab /; # describes all strings starting with 'ab' / ^ ab /; # same rx/ \d ** 2/; # describes all strings containing at least two digits
A named regex can be defined with the regex declarator followed by its definition in curly braces. Since any regex does Callable introspection requires referencing via &-sigil.
my regex R { \N }; say &R.^name; # OUTPUT: «Regex»
To match a string against a regex, you can use the smartmatch operator:
my $match = 'abc' ~~ rx/ ^ab /; say $match.Bool; # OUTPUT: «True» say $match.orig; # OUTPUT: «abc» say $match.Str; # OUTPUT: «ab» say $match.from; # OUTPUT: «0» say $match.to; # OUTPUT: «2»
Or you can evaluate the regex in boolean context, in which case it matches against the $_ variable
$_ = 'abc'; if / ^ab / { say '"abc" begins with "ab"'; } else { say 'This is a weird alternative Universe'; }
multi method ACCEPTS(Regex:D: Mu --> Match:D) multi method ACCEPTS(Regex:D: @) multi method ACCEPTS(Regex:D: %)
Matches the regex against the argument passed in. If the argument is Positional, it returns the first successful match of any list item. If the argument is Associative, it returns the first successful match of any key. Otherwise it interprets the argument as a Str and matches against it.
In the case of Positional and Associative matches, Nil is returned on failure.
multi method Bool(Regex:D: --> Bool:D)
Matches against the caller's $_ variable, and returns True for a match or False for no match.
Code object with its own lexical scope and
class Routine is Block { }
A Routine is a code object meant for larger unities of code than Block. Routine is the common superclass for Sub (and therefore operators) and Method, the two primary code objects for code reuse.
Routines serve as a scope limiter for return (i.e. a return returns from the innermost outer Routine).
The routine level is also the one at which multiness (multi subs and multi methods) are handled. Subroutines can also be declared anon. See the documentation on the anon declarator for more information.
method name(Routine:D: --> Str:D)
Returns the name of the sub or method.
method package(Routine:D:)
Returns the package in which the routine is defined.
method multi(Routine:D: --> Bool:D)
Returns True if the routine is a multi sub or method. Note that the name of a multi sub refers to its proto and this method would return false if called on it. It needs to be called on the candidates themselves:
multi foo ($, $) {}; say &foo.multi; # OUTPUT: «False» say &foo.candidates».multi; # OUTPUT: «(True)»
method candidates(Routine:D: --> Positional:D)
Returns a list of multi candidates, or a one-element list with itself if it's not a multi
method cando(Capture $c)
Returns a possibly-empty list of candidates that can be called with the given Capture, ordered by narrowest candidate first. For methods, the first element of the Capture needs to be the invocant:
.signature.say for "foo".^can("comb")[0].cando: \(Cool, "o"); # OUTPUT: «(Cool $: Str $matcher, $limit = Inf, *%_)»
method wrap(Routine:D: &wrapper)
Wraps (i.e. in-place modifies) the routine. That means a call to this routine first calls &wrapper, which then can (but doesn't have to) call the original routine with the callsame, callwith, nextsame and nextwith dispatchers. The return value from the routine is also the return value from the wrapper.
wrap returns an instance of a private class called Routine::WrapHandle, which you can pass to unwrap to restore the original routine.
method unwrap($wraphandle)
Restores the original routine after it has been wrapped with wrap. While the signature allows any type to be passed, only the Routine::WrapHandle type returned from wrap can usefully be.
method yada(Routine:D: --> Bool:D)
Returns True if the routine is a stub
say (sub f() { ... }).yada; # OUTPUT: «True» say (sub g() { 1; }).yada; # OUTPUT: «False»
multi sub trait_mod:<is>(Routine $r, :$cached!)
Causes the return value of a routine to be stored, so that when subsequent calls with the same list of arguments are made, the stored value can be returned immediately instead of re-running the routine.
Useful when storing and returning the computed value is much faster than re-computing it every time, and when the time saved trumps the cost of the use of more memory.
Even if the arguments passed to the routine are "reference types" (such as objects or arrays), then for the purpose of caching they will only be compared based on their contents. Thus the second invocation will hit the cache in this case:
say foo( [1, 2, 3] ); # runs foo say foo( [1, 2, 3] ); # doesn't run foo, uses cached value
Since it's still at the experimental stage, you will have to insert the use experimental :cached; statement in any module or script that uses it.
use experimental :cached; sub nth-prime(Int:D $x where * > 0) is cached { say "Calculating {$x}th prime"; return (2..*).grep(*.is-prime)[$x - 1]; } say nth-prime(43); say nth-prime(43); say nth-prime(43);
produces this output:
Calculating 43th prime 191 191 191
multi sub trait_mod:<is>(Routine $r, :$pure!)
Marks a subroutine as pure, that is, it asserts that for the same input, it will always produce the same output without any additional side effects.
The is pure trait is a promise by the programmer to the compiler that it can constant-fold calls to such functions when the arguments are known at compile time.
sub syllables() is pure { say "Generating syllables"; my @vowels = <a e i o u>; return @vowels.append: <k m n sh d r t y> X~ @vowels; }
You can mark function as pure even if they throw exceptions in edge cases or if they modify temporary objects; hence the is pure trait can cover cases that the compiler cannot deduce on its own. On the other hand, you might not want to constant-fold functions that produce a large return value (such as the string or list repetition operators, infix x and xx) even if they are pure, to avoid large precompilation files.
To see it an action with a particular compiler you can try this example:
BEGIN { say ‘Begin’ } say ‘Start’; say (^100).map: { syllables().pick(2..5).join("") }; # Example output: # Begin # Generating syllables # Start # (matiroi yeterani shoriyuru...
Essentially this allows the compiler to perform some operations at compile time. The benefits of constant-folding may include better performance, especially in cases when the folded code is precompiled.
In addition, using a pure function or operator in sink context (that is, where the result is discarded) may lead to a warning. The code
sub double($x) is pure { 2 * $x }; double(21); say "anything"; # WARNING: «Useless use of "double(21)" in expression "double(21)" in sink context (line 2)»
If you want to apply this trait to a multi, you need to apply it to the proto; it will not work otherwise, at least in versions 2018.08 and below.
multi sub trait_mod:<is>(Routine $r, :$rw!)
When a routine is modified with this trait, its return value will be writable. This is useful when returning variables or writable elements of hashes or arrays, for example:
sub walk(\thing, *@keys) is rw { my $current := thing; for @keys -> $k { if $k ~~ Int { $current := $current[$k]; } else { $current := $current{$k}; } } $current; } my %hash; walk(%hash, 'some', 'key', 1, 2) = 'autovivified'; say %hash.perl;
produces
("some" => {"key" => [Any, [Any, Any, "autovivified"]]}).hash
Note that return marks return values as read only; if you need an early exit from an is rw routine, you have to use return-rw instead.
multi sub trait_mod:<is>(Routine $r, :$export!)
Marks a routine as exported to the rest of the world
module Foo { sub double($x) is export { 2 * $x } } import Foo; # makes sub double available say double 21; # 42
From inside another file you'd say use Foo; to load a module and import the exported functions.
See Exporting and Selective Importing Modules for more details.
multi sub trait_mod:<is>(Routine:D $r, :$DEPRECATED!)
Marks a routine as deprecated, optionally with a message what to use instead.
This code
sub f() is DEPRECATED('the literal 42') { 42 } say f();
produces this output:
42 Saw 1 occurrence of deprecated code. ================================================================================ Sub f (from GLOBAL) seen at: deprecated.p6, line 2 Please use the literal 42 instead. -------------------------------------------------------------------------------- Please contact the author to have these occurrences of deprecated code adapted, so that this message will disappear!
multi sub trait_mod:<is>(Routine:D, :$hidden-from-backtrace!)
Hides a routine from showing up in a default backtrace. For example
sub inner { die "OH NOEZ" }; sub outer { inner() }; outer();
produces the error message and backtrace
OH NOEZ in sub inner at bt.p6:1 in sub outer at bt.p6:2 in block <unit> at bt.p6:3
but if inner is marked with hidden-from-backtrace
sub inner is hidden-from-backtrace { die "OH NOEZ" }; sub outer { inner() }; outer();
the error backtrace does not show it:
OH NOEZ in sub outer at bt.p6:2 in block <unit> at bt.p6:3TODO: explain export tags
Defined as
multi sub trait_mod:<is>(Routine:D $r, :$default!)
There is a special trait for Routines called is default. This trait is designed as a way to disambiguate multi calls that would normally throw an error because the compiler would not know which one to use. This means that given the following two Routines, the one with the is default trait will be called.
multi sub f() is default { say "Hello there" } multi sub f() { say "Hello friend" } f(); # OUTPUT: «"Hello there"»
The is default trait can become very useful for debugging and other uses but keep in mind that it will only resolve an ambiguous dispatch between two Routines of the same precedence. If one of the Routines is narrower than another, then that one will be called. For example:
multi sub f() is default { say "Hello there" } multi sub f(:$greet) { say "Hello " ~ $greet } f(); # "Use of uninitialized value $greet..."
In this example, the multi without is default was called because it was actually narrower than the Sub with it.
Defined as:
multi sub trait_mod:<is>(Routine:D $r, :$raw!)
Gives total access to the data structure returned by the routine.
my @zipi = <zape zapatilla>; sub þor() is raw { return @zipi }; þor()[1] = 'pantuflo'; say @zipi; # OUTPUT: «[zape pantuflo]»
Holds all information needed to unwrap a wrapped routine.
class WrapHandle { ... }
WrapHandle is a Rakudo private class created and returned by wrap. Its only use is to unwrap wrapped routines. Either call unwrap on a routine object or call the method restore on a Routine::WrapHandle object.
sub f() { say 'f was called' } my $wrap-handle = &f.wrap({ say 'before'; callsame; say 'after' }); f; # OUTPUT: «beforef was calledafter» $wrap-handle.restore; f; # OUTPUT: «f was called»
As such private class, it may suffer any kind of changes without prior notice. It is only mentioned here since it is visible by the user who checks the return type of the Routine.wrap method.
method restore(--> Bool:D)
Unwraps a wrapped routine and returns Bool::True on success.
A mostly transparent container used for indirections
class Scalar {}
A Scalar is an internal indirection which is for most purposes invisible during ordinary use of Perl 6. It is the default container type associated with the $ sigil. A literal Scalar may be placed around a literal value by enclosing the value in $(…). This notation will appear in the output of a .perl method in certain places where it is important to note the presence of Scalars.
When a value is assigned to a $-sigiled variable, the variable will actually bind to a Scalar, which in turn will bind to the value. When a Scalar is assigned to a $-sigiled variable, the value bound to by that Scalar will be bound to the Scalar which that variable was bound to (a new one will be created if necessary.)
In addition, Scalars delegate all method calls to the value which they contain. As such, Scalars are for the most part invisible. There is, however, one important place where Scalars have a visible impact: a Scalar will shield its content from flattening by most Perl 6 core list operations.
A $-sigiled variable may be bound directly to a value with no intermediate Scalar using the binding operator :=. You can tell if this has been done by examining the output of the introspective pseudo-method .VAR:
my $a = 1; $a.^name.say; # OUTPUT: «Int» $a.VAR.^name.say; # OUTPUT: «Scalar» my $b := 1; $b.^name.say; # OUTPUT: «Int» $b.VAR.^name.say; # OUTPUT: «Int»
This same thing happens when values are assigned to an element of an Array, however, Lists directly contain their values:
my @a = 1, 2, 3; @a[0].^name.say; # OUTPUT: «Int» @a[0].VAR.^name.say; # OUTPUT: «Scalar» [1, 2, 3][0].^name.say; # OUTPUT: «Int» [1, 2, 3][0].VAR.^name.say; # OUTPUT: «Scalar» (1, 2, 3)[0].^name.say; # OUTPUT: «Int» (1, 2, 3)[0].VAR.^name.say; # OUTPUT: «Int»
Array elements may be bound directly to values using := as well; however, this is discouraged as it may lead to confusion. Doing so will break exact round-tripping of .perl output – since Arrays are assumed to place Scalars around each element, Scalars are not denoted with $ in the output of Array.perl.
[1, $(2, 3)].perl.say; # OUTPUT: «[1, (2, 3)]» (1, $(2, 3)).perl.say; # OUTPUT: «(1, $(2, 3))»
Binding a Scalar to a $-sigiled variable replaces the existing Scalar in that variable, if any, with the given Scalar. That means more than one variable may refer to the same Scalar. Because the Scalar may be mutated, this makes it possible to alter the value of both variables by altering only one of them:
my $a = 1; my $b := $a; $b = 2; $a.say; # OUTPUT: «2»
SSA-style constants bind directly to their value with no intervening Scalar, even when assignment (=) is used. They may be forced to use a Scalar by assigning a $-sigiled variable to them, at which point, they behave entirely like $-sigiled variables.
my \c = 1; c.^name.say; # OUTPUT: «Int» c.VAR.^name.say; # OUTPUT: «Int» my $a = 1; my \d = $a; # just "my \d = $ = 1" works, too d.^name.say; # OUTPUT: «Int» d.VAR.^name.say; # OUTPUT: «Scalar» d = 2; # ok c = 2; # fails CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Int»
A Scalar can have its value changed using a hardware-supported atomic compare and swap operation. This is useful when implementing lock free data structures and algorithms. It may also be fetched and assigned to in an "atomic" fashion, which ensures appropriate memory barriering and prevents unwanted optimizations of memory accesses.
A Scalar that will be used with an atomic operation should always be explicitly initialized with a value before any atomic operations are performed upon it. This is to avoid races with lazy allocation and auto-vivification. For example:
cas(@a[5], $expected, $value)
Will work in principle since an Array consists of Scalar containers. However, the container is only bound into the array upon initial assignment. Therefore, there would be a race to do that binding. The Scalar atomic operations will never check for or do any such auto-vivification, so as to make such bugs much more evident (rather than only observed under stress).
method of(Scalar:D: --> Mu)
Returns the type constraint of the container.
Example:
my Cool $x = 42; say $x.VAR.of; # OUTPUT: «(Cool)»
method default(Scalar:D: --> Str)
Returns the default value associated with the container.
Example:
my $x is default(666) = 42; say $x.VAR.default; # OUTPUT: «666»
method name(Scalar:D: --> Str)
Returns the name associated with the container.
Example:
my $x = 42; say $x.VAR.name; # OUTPUT: «$x»
method dynamic(Scalar:D: --> Bool)
Returns whether the variable is visible in dynamic variable lookups.
Example:
my $*FOO = 42; say $*FOO.VAR.dynamic; # OUTPUT: «True»
Defined as:
multi sub atomic-assign($target is rw, $value)
Performs an atomic assignment of $value into the Scalar $target. The atomic-assign routine ensures that any required barriers are performed such that the changed value will be "published" to other threads.
multi sub atomic-fetch($target is rw)
Performs an atomic read of the value in the Scalar $target and returns the read value. Using this routine instead of simply using the variable ensures that the latest update to the variable from other threads will be seen, both by doing any required hardware barriers and also preventing the compiler from lifting reads. For example:
my $started = False; start { atomic-assign($started, True) } until atomic-fetch($started) { }
Is certain to terminate, while in:
my $started = False; start { atomic-assign($started, True) } until $started { }
It would be legal for a compiler to observe that $started is not updated in the loop, and so lift the read out of the loop, thus causing the program to never terminate.
Defined as:
multi sub cas($target is rw, $expected, $value) multi sub cas($target is rw, &operation)
Performs an atomic compare and swap of the value in the Scalar $target. The first form has semantics like:
my $seen = $target; if $seen<> =:= $expected<> { $target = $value; } return $seen;
Except it is performed as a single hardware-supported atomic instruction, as if all memory access to $target were blocked while it took place. Therefore it is safe to attempt the operation from multiple threads without any other synchronization. Since it is a reference comparison, this operation is usually not sensible on value types.
For example:
constant NOT_STARTED = Any.new; constant STARTED = Any.new; my $master = NOT_STARTED; await start { if cas($master, NOT_STARTED, STARTED) === NOT_STARTED { say "Master!" } } xx 4
Will reliably only ever print Master! one time, as only one of the threads will be successful in changing the Scalar from NOT_STARTED to STARTED.
The second form, taking a code object, will first do an atomic fetch of the current value and invoke the code object with it. It will then try to do an atomic compare and swap of the target, using the value passed to the code object as $expected and the result of the code object as $value. If this fails, it will read the latest value, and retry, until a CAS operation succeeds.
Therefore, an item could be added to the head of a linked list in a lock free manner as follows:
class Node { has $.value; has Node $.next; } my Node $head = Node; await start { for ^1000 -> $value { cas $head, -> $next { Node.new(:$value, :$next) } } } xx 4;
This will reliably build up a linked list of 4000 items, with 4 nodes with each value ranging from 0 up to 999.
multi sub infix:<⚛=>($target is rw, $value)
Performs an atomic assignment of $value into the Scalar $target. The ⚛= operator ensures that any required barriers are performed such that the changed value will be "published" to other threads.
multi sub prefix:<⚛>($target is rw)
Performs an atomic read of the value in the Scalar $target and returns the read value. Using this operator instead of simply using the variable ensures that the latest update to the variable from other threads will be seen, both by doing any required hardware barriers and also preventing the compiler from lifting reads. For example:
my $started = False; start { $started ⚛= True } until ⚛$started { }
Is certain to terminate, while in:
my $started = False; start { $started ⚛= True } until $started { }
It would be legal for a compiler to observe that $started is not updated in the loop, and so lift the read out of the loop, thus causing the program to never terminate.
Scheme for automatically assigning tasks to threads
role Scheduler { has &.uncaught_handler is rw }
Common role for schedulers. A scheduler is a piece of code that determines which resources to use to run which task, and when.
Some operations for example on Proc::Async, Promise, Supply allow you to specify a scheduler explicitly; they generally expect those schedulers to follow the interface defined by Scheduler
method uncaught_handler() is rw
RW-Accessor for the handler that is caught for uncaught exceptions from the code that is being scheduled and run.
method cue(&code, Instant :$at, :$in, :$every, :$times = 1; :&catch --> Cancellation)
Schedules a callable (&code) for execution and returns an instantiated Cancellation object to cancel the scheduling of the code for execution (which is especially important if you specify the every = time> named parameter. The adverbs control when and how the code is run:
$at can be an Instant before which the code won't be run. Alternatively $in is the number of seconds (possibly fractional) to wait before running the code. If $at is in the past or $in is negative, the delay is treated as zero. Implementations may equate to zero very small values (e.g. lower than 0.001s) of $in or result of $at - now.
If $every is specified, it is interpreted as the number of seconds (possibly fractional) to wait before re-executing the code. Implementations may treat too-small values as lowest resolution they support, possibly warning in such situations; e.g. treating 0.0001 as 0.001.
$times tells the scheduler how many times to run the code.
&catch is called with the Exception as its sole argument if &code dies.
If $at or $in are Inf, &code will never be run; if $every is Inf, &code will only be run once. If any of the three are -Inf, &code will be run immediately. If any of the three are NaN, an X::Scheduler::CueInNaNSeconds exception will be thrown. This only applies to releases 2019.05 and later.
One should call the cancel method on the returned Cancellation object to cancel the (possibly repeated) cueing of the code.
Control access to shared resources by multiple threads
class Semaphore { }
Protect your shared code, data or device access using semaphores. An example is a printer manager managing a pool of printers without the need of storing print jobs when all printers are occupied. The next job is just blocked until a printer becomes available.
class print-manager { has Array $!printers; has Semaphore $!print-control; method BUILD( Int:D :$nbr-printers ) { for ^$nbr-printers -> $pc { $!printers[$pc] = { :name{"printer-$pc"} }; } $!print-control .= new($nbr-printers); } method find-available-printer-and-print-it($job) { say "Is printed!"; } method print( $print-job ) { $!print-control.acquire; self.find-available-printer-and-print-it($print-job); $!print-control.release; } }
Another example is a protection around code updating sensitive data. In such a case the semaphore is typically initialized to 1.
It is important to have a release on every exit of your program! While this is obvious, it is easy to fall in traps such as throwing an exception caused by some event. When the program dies there is no problem. When the exception is caught your program might eventually come back to the acquire method and will hang indefinitely.
method new( int $permits )
Initialize the semaphore with the number of permitted accesses. E.g. when set to 2, program threads can pass the acquire method twice until it blocks on the third time acquire is called.
method acquire()
Acquire access. When other threads have called the method before and the number of permits are used up, the process blocks until threads passed before releases the semaphore.
method try_acquire(--> Bool)
Same as acquire but will not block. Instead it returns True if access is permitted or False otherwise.
method release()
Release the semaphore raising the number of permissions. Any blocked thread will get access after that.
An iterable, lazy sequence of values
class Seq is Cool does Iterable does PositionalBindFailover { }
A Seq represents anything that can lazily produce a sequence of values. A Seq is born in a state where iterating it will consume the values. However, calling .cache on a Seq will return a List that is still lazy, but stores the generated values for later access. However, assigning a Seq to an array consumes the Seq; alternatively, you can use the lazy statement prefix to avoid it from being iterated during the assignment:
# The Seq created by gather ... take is consumed on the spot here. my @a = gather do { say 'consuming...'; take 'one' }; # OUTPUT: «consuming...» # The Seq here is only consumed as we iterate over @a later. my @a = lazy gather do { say 'consuming...'; take 'one' }; # outputs nothing. .say for @a; # OUTPUT: «consuming...one»
A typical use case is method lines in IO::Handle, which could use a lot of memory if it stored all the lines read from the file. So
for open('README.md').lines -> $line { say $line; }
won't keep all lines from the file in memory.
This implies that you cannot iterate the same Seq object twice (otherwise it couldn't throw away old values), so this dies:
my @a = 1, 2, 3; my @b = <a b c>; my \c = @a Z=> @b; .say for c; .say for c; # fails CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Seq::Consumed: This Seq has already been iterated, and its values consumed # (you might solve this by adding .cache on usages of the Seq, or # by assigning the Seq into an array)»
A high-level construct to generate a Seq is gather/take, as well as many built-in methods like map and grep, low-level constructors to create a Seq from an iterator or from looping constructs are available too.
Caution: No program should ever assume a Seq may only be iterated once even if not cached by the program. Caching is a volatile state exposed to the developer as an optimization. The Seq may become cached by many operations, including calling perl on the Seq (if called prior to a non-cached iteration). From version 6.d, you .perl can be called on consumed <Seq>. If a program assumes a Seq can only iterate once, but then is later changed to call one of these operations during the loop, that assumption will fail.
method new(Iterator:D $iter --> Seq:D)
Creates a new Seq object from the iterator passed as the single argument.
method iterator(Seq:D: --> Iterator:D)
Returns the underlying iterator, and marks the invocant as consumed. If called on an already consumed sequence, throws an error of type X::Seq::Consumed.
method is-lazy(Seq:D: --> Bool:D)
Returns True if the sequence is lazy and potentially infinite, and False otherwise. If called on an already consumed sequence, throws an error of type X::Seq::Consumed.
method eager(Seq:D: --> List:D)
Returns an eagerly evaluated List based on the invocant sequence, and marks it as consumed. If called on an already consumed sequence, throws an error of type X::Seq::Consumed.
my $s = lazy 1..5; say $s.is-lazy; # OUTPUT: «True» say $s.eager; # OUTPUT: «(1 2 3 4 5)» say $s.eager; CATCH { when X::Seq::Consumed { say 'Throws exception if already consumed'; } } # OUTPUT: «Throws exception if already consumed»
multi method from-loop(&body --> Seq:D) multi method from-loop(&body, &cond, :$repeat --> Seq:D) multi method from-loop(&body, &cond, &afterward --> Seq:D)
These methods create new Seq-based callbacks.
The first form produces an infinite Seq by calling &body each time a new element is requested, using the return value from &body as the item. This emulates (or implements) a loop { body } construct.
The second form calls &cond before each call to &body, and terminates the sequence if &cond returns a false value. If $repeat is set to a true value, the first call to &cond is omitted, and &body called right away. This emulates (or implements) while cond { body } and repeat { body } while cond loops.
The third form enables C-style looping by calling a third callback, &afterward, after each call to &body.
Defined as:
method sink(--> Nil)
Calls sink-all if it is an Iterator, sink if the Sequence is a list.
say (1 ... 1000).sink; # OUTPUT: «Nil»
This is something you might want to do for the side effects of producing those values.
Defined as:
multi method skip(Int() $n = 1 --> Seq)
Returns a Seq containing whatever is left of the invocant after throwing away $n of the next available values. Negative values of $n count as 0. Also can take a WhateverCode to indicate how many values to skip from the end. Will block on lazy Seqs until the requested number of values have been discarded.
say (1..5).map({$_}).skip; # OUTPUT: «(2,3,4,5)» say (1..5).map({$_}).skip(3); # OUTPUT: «(4,5)» say (1..5).map({$_}).skip(5); # OUTPUT: «()» say (1..5).map({$_}).skip(-1); # OUTPUT: «(1,2,3,4,5)» say (1..5).map({$_}).skip(*-3); # OUTPUT: «(3,4,5)»
Immutable collection of distinct objects
class Set does Setty { }
A Set is an immutable set, meaning a collection of distinct elements in no particular order. (For mutable sets, see SetHash instead.)
Objects/values of any type are allowed as set elements. Within a Set, every element is guaranteed to be unique (in the sense that no two elements would compare positively with the === operator):
my $fruits = set <peach apple orange apple apple>; say $fruits.elems; # OUTPUT: «3» say $fruits.keys.sort; # OUTPUT: «apple orange peach»
Sets can be treated as object hashes using the { } postcircumfix operator, which returns the value True for keys that are elements of the set, and False for keys that aren't:
my $fruits = set <peach apple orange apple apple>; say $fruits<apple>; # OUTPUT: «True» say $fruits<kiwi>; # OUTPUT: «False»
Sets can be composed using the set subroutine (or Set.new, for which it is a shorthand). Any positional parameters, regardless of their type, become elements of the set:
my $n = set "zero" => 0, "one" => 1, "two" => 2; say $n.keys.perl; # OUTPUT: «(:two(2), :zero(0), :one(1)).Seq» say $n.keys.map(&WHAT); # OUTPUT: «((Pair) (Pair) (Pair))»
Alternatively, the .Set coercer (or its functional form, Set()) can be called on an existing object to coerce it to a Set. Its semantics depend on the type and contents of the object. In general it evaluates the object in list context and creates a set with the resulting items as elements, although for Hash-like objects or Pair items, only the keys become elements of the set - and keys mapped to values which boolify to False are skipped:
my $n = ("zero" => 0, "one" => 1, "two" => 2).Set; say $n.keys.perl; # OUTPUT: «("one", "two").Seq» say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Str))»
Furthermore, you can get a Set by using set operators (see next section) on objects of other types such as List, which will act like they internally call .Set on them before performing the operation. Be aware of the tight precedence of those operators though, which may require you to use parentheses around arguments:
say (1..5) (^) 4; # OUTPUT: «set(1, 2, 3, 5)»
Of course, you can also create a Set with the .new method.
my $fruits = Set.new( <peach apple orange apple apple> );
Since 6.d (2019.03 and later) you can also use this syntax for parameterization of the Set, to specify which type of values are acceptable:
# only allow strings (Str) in the Set my $fruits = Set[Str].new( <peach apple orange apple apple> ); # only allow whole numbers (Int) in the Set my $fruits = Set[Int].new( <peach apple orange apple apple> ); # Type check failed in binding; expected Int but got Str ("peach")
Finally, you can create Set masquerading as a hash by using the is trait:
my %s is Set = <a b c>; say %s<a>; # True say %s<d>; # False
Since 6.d (2019.03 and later), this syntax also allows you to specify the type of values you would like to allow:
# limit to strings my %s is Set[Str] = <a b c>; say %s<a>; # True say %s<d>; # False # limit to whole numbers my %s is Set[Int] = <a b c>; # Type check failed in binding; expected Int but got Str ("a")
Perl 6 provides common set operators, which can take Sets (or any other collections) as input, and return result sets as new Set objects. For example:
my ($a, $b) = set(1, 2, 3), set(2, 4); say $a (<) $b; # OUTPUT: «False» say $a (&) $b; # OUTPUT: «set(2)» say $a (^) $b; # OUTPUT: «set(1, 3, 4)» # Unicode versions: say $a ⊂ $b; # OUTPUT: «False» say $a ∩ $b; # OUTPUT: «set(2)» say $a ⊖ $b; # OUTPUT: «set(1, 3, 4)»
See Set/Bag Operators for a complete list of set operators with detailed explanations.
sub set(*@args --> Set)
Creates a Set from the given @args
Mutable collection of distinct objects
class SetHash does Setty { }
A SetHash is a mutable set, meaning a collection of distinct elements in no particular order. (For immutable sets, see Set instead.)
Objects/values of any type are allowed as set elements. Within a Set, every element is guaranteed to be unique (in the sense that no two elements would compare positively with the === operator):
my $fruits = <peach apple orange apple apple>.SetHash; say $fruits.elems; # OUTPUT: «3» say $fruits.keys.sort; # OUTPUT: «apple orange peach»
SetHashes can be treated as object hashes using the { } postcircumfix operator, which returns the value True for keys that are elements of the set, and False for keys that aren't. Assigning a value that boolifies to True or False, respectively, can be used to add or remove a set element:
my $fruits = <peach apple orange apple apple>.SetHash; say $fruits<apple>; # OUTPUT: «True» say $fruits<kiwi>; # OUTPUT: «False» $fruits<apple kiwi> = False, True; say $fruits.keys.sort; # OUTPUT: «kiwi orange peach»
Here is a convenient shorthand idiom for adding and removing SetHash elements:
my SetHash $fruits .= new; say $fruits<cherry>; # OUTPUT: «False» $fruits<cherry>++; say $fruits<cherry>; # OUTPUT: «True» $fruits<apple banana kiwi>»++; # Add multiple elements $fruits<cherry>--; say $fruits<cherry>; # OUTPUT: «False» $fruits<banana kiwi>»--; # Remove multiple elements
SetHashes can be composed using SetHash.new. Any positional parameters, regardless of their type, become elements of the set:
my $n = SetHash.new: "zero" => 0, "one" => 1, "two" => 2; say $n.keys.perl; # OUTPUT: «(:two(2), :zero(0), :one(1)).Seq» say $n.keys.map(&WHAT); # OUTPUT: «((Pair) (Pair) (Pair))»
Alternatively, the .SetHash coercer (or its functional form, SetHash()) can be called on an existing object to coerce it to a SetHash. Its semantics depend on the type and contents of the object. In general it evaluates the object in list context and creates a set with the resulting items as elements, although for Hash-like objects or Pair items, only the keys become elements of the set - and keys mapped to values which boolify to False are skipped:
my $n = ("zero" => 0, "one" => 1, "two" => 2).SetHash; say $n.keys.perl; # OUTPUT: «("one", "two").Seq» say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Str))»
It is also possible to initialize a single key with the use of {}:
my $sh = SetHash.new; $sh{ 'key1' } = True; $sh{ 'key2' } = 'Hello World!'; $sh{ 'key3' } = 0; # does not store the key since 0.Bool is False say $sh; # OUTPUT: «SetHash(key1 key2)» say $sh.keys.perl; # OUTPUT: «("key1", "key2").Seq»
or, in order to initialize more than one key at the same time, use a list assignment:
my $sh = SetHash.new; $sh{ 'a', 'b', 'c' } = True, False, True; say $sh.keys.perl; # OUTPUT: «("a", "c").Seq»
You can also create SetHash masquerading as a hash by using the is trait:
my %sh is SetHash = <a b c>; say %sh<a>; # True say %sh<d>; # False
Since 6.d (2019.03 and later) it is also possible to specify the type of values you would like to allow in a SetHash. This can either be done when calling .new:
# only allow Pairs my $n = SetHash[Pair].new: "zero" => 0, "one" => 1, "two" => 2;
or using the masquerading syntax:
# only allow strings my %sh is SetHash[Str] = <a b c>; say %sh<a>; # True say %sh<d>; # False # only allow whole numbers my %sh is SetHash[Int] = <a b c>; # Type check failed in binding; expected Int but got Str ("a")
Perl 6 provides common set operators, which can take SetHashes (or any other collections) as input, although result sets are returned as immutable Sets. For example:
my ($a, $b) = SetHash.new(1, 2, 3), SetHash.new(2, 4); say $a (<) $b; # OUTPUT: «False» say $a (&) $b; # OUTPUT: «set(2)» say $a (^) $b; # OUTPUT: «set(1, 3, 4)» say $a (|) $b; # OUTPUT: «set(1, 2, 3, 4)» # Unicode versions: say $a ⊂ $b; # OUTPUT: «False» say $a ∩ $b; # OUTPUT: «set(2)» say $a ⊖ $b; # OUTPUT: «set(1, 3, 4)» say $a ∪ $b; # OUTPUT: «set(1, 2, 3, 4)»
See Set/Bag Operators for a complete list of set operators with detailed explanations.
Collection of distinct objects
role Setty does QuantHash { }
A role for collections which make sure that each element can only appear once. See Set and SetHash.
Defined as:
method new-from-pairs(*@pairs --> Setty:D)
Constructs a Setty object from a list of Pair objects given as positional arguments:
say Set.new-from-pairs: 'butter' => 0.22, 'salt' => 0, 'sugar' => 0.02; # OUTPUT: «set(butter, sugar)»
Note: be sure you aren't accidentally passing the Pairs as positional arguments; the quotes around the keys in the above example are significant.
method grab($count = 1)
Removes and returns $count elements chosen at random (without repetition) from the set.
If * is passed as $count, or $count is greater than or equal to the size of the set, then all its elements are removed and returned in random order.
Only works on mutable sets; When used on an immutable set, it results in an exception.
method grabpairs($count = 1)
Removes $count elements chosen at random (without repetition) from the set, and returns a list of Pair objects whose keys are the grabbed elements and whose values are True.
If * is passed as $count, or $count is greater than or equal to the size of the set, then all its elements are removed and returned as Pairs in the aforementioned way in random order.
Only works on mutable sets; When used on an immutable set, it results in an exception.
multi method pick($count = 1)
Returns $count elements chosen at random (without repetition) from the set.
If * is passed as $count, or $count is greater than or equal to the size of the set, then all its elements are returned in random order (shuffled).
Defined as:
multi method pickpairs(Setty:D: --> Pair:D) multi method pickpairs(Setty:D: $count --> Seq:D)
Returns a Pair or a Seq of Pairs depending on the candidate of the method being invoked. Each Pair returned has an element of the invocant as its key and True as its value. In contrast to grabpairs, the elements are 'picked' without replacement.
If * is passed as $count, or $count is greater than or equal to the number of elements of the invocant, then all element/True Pairs from the invocant are returned in a random sequence; i.e. they are returned shuffled;
Note that each pickpairs invocation maintains its own private state and has no effect on subsequent pickpairs invocations.
my $numbers = set (4, 2, 3); say $numbers.pickpairs; # OUTPUT: «4 => True» say $numbers.pickpairs(1); # OUTPUT: «(3 => True)» say $numbers.pickpairs(*); # OUTPUT: «(2 => True 4 => True 3 => True)»
multi method roll($count = 1)
Returns a lazy list of $count elements, each randomly selected from the set. Each random choice is made independently, like a separate die roll where each die face is a set element.
If * is passed as $count, the list is infinite.
Defined as:
multi method antipairs(Setty:D: --> Seq:D)
Returns all elements in the set and True as a Seq of Pairs, where the element itself is the value, i.e. the opposite of method pairs.
my $s = Set.new(1, 2, 3, 1); say $s.antipairs.sort; # OUTPUT: «(True => 1 True => 2 True => 3)»
Defined as:
multi method keys(Setty:D: --> Seq:D)
Returns a Seq of all elements of the set.
my $s = Set.new(1, 2, 3); say $s.keys; # OUTPUT: «(3 1 2)»
Defined as:
multi method values(Setty:D: --> Seq:D)
Returns a Seq containing as many True values as the set has elements.
my $s = Set.new(1, 2, 3); say $s.values; # OUTPUT: «(True True True)»
Defined as:
multi method kv(Setty:D: --> Seq:D)
Returns a Seq of the set's elements and True values interleaved.
my $s = Set.new(1, 2, 3); say $s.kv; # OUTPUT: «(3 True 1 True 2 True)»
method elems(--> Int)
The number of elements of the set.
method total(--> Int)
The total of all the values of the QuantHash object. For a Setty object, this is just the number of elements.
Defined As:
multi method minpairs(Setty:D: --> Seq:D)
Returns the value of self.pairs (as all Pairs have minimum values). See also Any.minpairs
Defined As:
multi method maxpairs(Setty:D: --> Seq:D)
Returns the value of self.pairs (as all Pairs have maximum values). See also Any.maxpairs
Defined as:
method default(--> False)
Returns the default value of the invocant, i.e. the value which is returned when trying to access an element in the Setty object which has not been previously initialized or when accessing an element which has explicitly been set to Nil or False.
my $s1 = SetHash.new(1, 2, 3); say $s1{2}; # OUTPUT: «True» $s1{2} = Nil; say $s1{2}; # OUTPUT: «False» # access non initialized element say $s1{4}; # OUTPUT: «False»
method ACCEPTS($other)
Returns True if $other and self contain all the same elements, and no others.
Defined as:
method Bag(Setty:D: --> Bag:D)
Returns a Bag containing the elements of the invocant.
my Bag $b = Set.new(1, 2, 3).Bag; say $b; # OUTPUT: «bag(3, 1, 2)»
Defined as:
method BagHash(Setty:D: --> BagHash:D)
Returns a BagHash containing the elements of the invocant.
my BagHash $b = Set.new(1, 2, 3).BagHash; say $b; # OUTPUT: «BagHash.new(3, 1, 2)»
Defined as:
multi method Bool(Setty:D: --> Bool:D)
Returns True if the invocant contains at least one element.
my $s1 = Set.new(1, 2, 3); say $s1.Bool; # OUTPUT: «True» my $s2 = $s1 ∩ Set.new(4, 5); # set intersection operator say $s2.Bool; # OUTPUT: «False»
Defined as:
method Mix(Setty:D: --> Mix:D)
Returns a Mix containing the elements of the invocant.
my Mix $b = Set.new(1, 2, 3).Mix; say $b; # OUTPUT: «mix(3, 1, 2)»
Defined as:
method MixHash(Setty:D: --> MixHash:D)
Returns a MixHash containing the elements of the invocant.
my MixHash $b = Set.new(1, 2, 3).MixHash; say $b; # OUTPUT: «MixHash.new(3, 1, 2)»
Parameter list pattern
class Signature { }
A signature is a static description of the parameter list of a code object. That is, it describes what and how many arguments you need to pass to the code or function in order to call it.
Passing arguments to a signature binds the arguments, contained in a Capture, to the signature.
Signatures appear inside parentheses after subroutine and method names, on blocks after a -> or <-> arrow, as the input to variable declarators like my, or as a separate term starting with a colon.
sub f($x) { } # ^^^^ Signature of sub f my method x() { } # ^^ Signature of a method my $s = sub (*@a) { } # ^^^^^ Signature of an anonymous function for <a b c> -> $x { } # ^^ Signature of a Block my ($a, @b) = 5, (6, 7, 8); # ^^^^^^^^ Signature of a variable declarator my $sig = :($a, $b); # ^^^^^^^^ Standalone Signature object
Signature literals can be used to define the signature of a callback or a closure.
sub f(&c:(Int)) { } sub will-work(Int) { } sub won't-work(Str) { } f(&will-work); f(&won't-work); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Binding::Parameter: Constraint type check failed in binding to parameter '&c'» f(-> Int { 'this works too' } );
Smartmatching signatures against a List is supported.
my $sig = :(Int $i, Str $s); say (10, 'answer') ~~ $sig; # OUTPUT: «True» my $sub = sub ( Str $s, Int $i ) { return $s xx $i }; say $sub.signature ~~ :( Str, Int ); # OUTPUT: «True» given $sig { when :(Str, Int) { say 'mismatch' } when :($, $) { say 'match' } default { say 'no match' } } # OUTPUT: «match»
It matches the second when clause since :($, $) represents a Signature with two scalar, anonymous, arguments, which is a more general version of $sig.
When smartmatching against a Hash, the signature is assumed to consist of the keys of the Hash.
my %h = left => 1, right => 2; say %h ~~ :(:$left, :$right); # OUTPUT: «True»
A signature consists of zero or more parameters, separated by commas.
my $sig = :($a, @b, %c); sub add($a, $b) { $a + $b };
As an exception the first parameter may be followed by a colon instead of a comma to mark the invocant of a method. The invocant is the object that was used to call the method, which is usually bound to self. By specifying it in the signature, you can change the variable name it is bound to.
method ($a: @b, %c) {}; # first argument is the invocant class Foo { method whoami($me:) { "Well I'm class $me.^name(), of course!" } } say Foo.whoami; # OUTPUT: «Well I'm class Foo, of course!»
Parameters can optionally have a type constraint (the default is Any). These can be used to restrict the allowed input to a function.
my $sig = :(Int $a, Str $b);
Type constraints can have any compile-time defined value
subset Positive-integer of Int where * > 0; sub divisors(Positive-integer $n) { $_ if $n %% $_ for 1..$n }; divisors 2.5; # ERROR «Type check failed in binding to parameter '$n'; # expected Positive-integer but got Rat (2.5) $n)» divisors -3; # ERROR: «Constraint type check failed in binding to parameter '$n'; # expected Positive-integer but got Int (-3)»
Please note that in the code above type constraints are enforced at two different levels: the first level checks if it belongs to the type in which the subset is based, in this case Int. If it fails, a Type check error is produced. Once that filter is cleared, the constraint that defined the subset is checked, producing a Constraint type check error if it fails.
Anonymous arguments are fine too, if you don't actually need to refer to a parameter by name, for instance to distinguish between different signatures in a multi or to check the signature of a Callable.
my $sig = :($, @, %a); # two anonymous and a "normal" parameter $sig = :(Int, Positional); # just a type is also fine (two parameters) sub baz(Str) { "Got passed a Str" }
Type constraints may also be type captures.
In addition to those nominal types, additional constraints can be placed on parameters in the form of code blocks which must return a true value to pass the type check
sub f(Real $x where { $x > 0 }, Real $y where { $y >= $x }) { }
The code in where clauses has some limitations: anything that produces side-effects (e.g., printing output, pulling from an iterator, or increasing a state variable) is not supported and may produce surprising results if used. Also, the code of the where clause may run more than once for a single typecheck in some implementations.
The where clause doesn't need to be a code block, anything on the right of the where-clause will be used to smartmatch the argument against it. So you can also write:
multi factorial(Int $ where 0) { 1 } multi factorial(Int $x) { $x * factorial($x - 1) }
The first of those can be shortened to
multi factorial(0) { 1 }
i.e., you can use a literal directly as a type and value constraint on an anonymous parameter.
Tip: pay attention to not accidentally leave off a block when you, say, have several conditions:
-> $y where .so && .name {}( sub one {} ); # WRONG!! -> $y where { .so && .name } {}( sub two {} ); # OK! -> $y where .so & .name.so {}( sub three {} ); # Also good
The first version is wrong and will issue a warning about a sub object coerced to string. The reason is the expression is equivalent to ($y ~~ ($y.so && $y.name)); that is "call .so, and if that is True, call .name; if that is also True use its value for smartmatching…". It's the result of (.so && .name) it will be smartmatched against, but we want to check that both .so and .name are truthy values. That is why an explicit Block or a Junction is the right version.
All previous arguments that are not part of a sub-signature in a Signature are accessible in a where-clause that follows an argument. Therefore, the where-clause of the last argument has access to all arguments of a signature that are not part of a sub-signature. For a sub-signature place the where-clause inside the sub-signature.
sub foo($a, $b where * == $a ** 2) { say "$b is a square of $a" } foo 2, 4; # OUTPUT: «4 is a square of 2»» # foo 2, 3; # OUTPUT: «Constraint type check failed in binding to parameter '$b'…»
Optional arguments can have constraints, too. Any where clause on any parameter will be executed, even if it's optional and not provided by the caller. In that case you may have to guard against undefined values within the where clause.
sub f(Int $a, UInt $i? where { !$i.defined or $i > 5 }) { ... }
Slurpy arguments can not have type constraints. A where-clause in conjunction with a Junction can be used to that effect.
sub f(*@a where {$_.all ~~ Int}) { say @a }; f(42); f(<a>); CATCH { default { say .^name, ' ==> ', .Str } } # OUTPUT: «[42]Constraint type check failed in binding to parameter '@a' ...»
Constraints against Named arguments apply to the value part of the colon-pair.
sub f(Int :$i){}; f :i<forty-two>; CATCH { default { say .^name, ' ==> ', .Str } } # OUTPUT: «X::TypeCheck::Binding::Parameter ==> Type check failed in # binding to parameter '$i'; expected Int but got Str ("forty-two")»
Normally, a type constraint only checks whether the value of the parameter is of the correct type. Crucially, both object instances and type objects will satisfy such a constraint as illustrated below:
say 42.^name; # OUTPUT: «Int» say 42 ~~ Int; # OUTPUT: «True» say Int ~~ Int; # OUTPUT: «True»
Note how both 42 and Int satisfy the match.
Sometimes we need to distinguish between these object instances (42) and type objects (Int). Consider the following code:
sub limit-lines(Str $s, Int $limit) { my @lines = $s.lines; @lines[0 .. min @lines.elems, $limit].join("\n") } say (limit-lines "a \n b \n c \n d \n", 3).perl; # "a \n b \n c \n d " say limit-lines Str, 3; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Multi::NoMatch: Cannot resolve caller lines(Str: ); # none of these signatures match: # (Str:D $: :$count!, *%_) # (Str:D $: $limit, *%_) # (Str:D $: *%_)» say limit-lines "a \n b", Int; # Always returns the max number of lines
Here we really only want to deal with string instances, not type objects. To do this, we can use the :D type constraint. This constraint checks that the value passed is an object instance, in a similar fashion to calling its DEFINITE (meta)method.
To warm up, let's apply :D to the right-hand side of our humble Int example:
say 42 ~~ Int:D; # OUTPUT: «True» say Int ~~ Int:D; # OUTPUT: «False»
Note how only 42 matches Int:D in the above.
Returning to limit-lines, we can now amend its signature to catch the error early:
sub limit-lines(Str:D $s, Int $limit) { }; say limit-lines Str, 3; CATCH { default { put .^name ~ '--' ~ .Str } }; # OUTPUT: «Parameter '$s' of routine 'limit-lines' must be an object instance of type 'Str', # not a type object of type 'Str'. Did you forget a '.new'?»
This is much better than the way the program failed before, since here the reason for failure is clearer.
It's also possible that type objects are the only ones that make sense for a routine to accept. This can be done with the :U type constraint, which checks whether the value passed is a type object rather than an object instance. Here's our Int example again, this time with :U applied:
say 42 ~~ Int:U; # OUTPUT: «False» say Int ~~ Int:U; # OUTPUT: «True»
Now 42 fails to match Int:U while Int succeeds.
Here's a more practical example:
sub can-turn-into(Str $string, Any:U $type) { return so $string.$type; } say can-turn-into("3", Int); # OUTPUT: «True» say can-turn-into("6.5", Int); # OUTPUT: «True» say can-turn-into("6.5", Num); # OUTPUT: «True» say can-turn-into("a string", Num); # OUTPUT: «False»
Calling can-turn-into with an object instance as its second parameter will yield a constraint violation as intended:
say can-turn-into("a string", 123); # OUTPUT: «Parameter '$type' of routine 'can-turn-into' must be a type object # of type 'Any', not an object instance of type 'Int'...»
For explicitly indicating the normal behavior, that is, not constraining whether the argument will be an instance or a type object, :_ can be used, but this is unnecessary. :(Num:_ $) is the same as :(Num $).
To recap, here is a quick illustration of these type constraints, also known collectively as type smileys:
# Checking a type object say Int ~~ Any:D; # OUTPUT: «False» say Int ~~ Any:U; # OUTPUT: «True» say Int ~~ Any:_; # OUTPUT: «True» # Checking an object instance say 42 ~~ Any:D; # OUTPUT: «True» say 42 ~~ Any:U; # OUTPUT: «False» say 42 ~~ Any:_; # OUTPUT: «True» # Checking a user-supplied class class Foo {}; say Foo ~~ Any:D; # OUTPUT: «False» say Foo ~~ Any:U; # OUTPUT: «True» say Foo ~~ Any:_; # OUTPUT: «True» # Checking an instance of a class my $f = Foo.new; say $f ~~ Any:D; # OUTPUT: «True» say $f ~~ Any:U; # OUTPUT: «False» say $f ~~ Any:_; # OUTPUT: «True»
The Classes and Objects document further elaborates on the concepts of instances and type objects and discovering them with the .DEFINITE method.
Keep in mind all parameters have values; even optional ones have default values that are the type object of the constrained type for explicit type constraints. If no explicit type constraint exists, the default value is an Any type object for methods, submethods, and subroutines, and a Mu type object for blocks. This means that if you use the :D type smiley, you'd need to provide a default value or make the parameter required. Otherwise, the default value would be a type object, which would fail the definiteness constraint.
sub divide (Int:D :$a = 2, Int:D :$b!) { say $a/$b } divide :1a, :2b; # OUTPUT: «0.5»
The default value will kick in when that particular parameter, either positional or named, gets no value at all.
sub f($a = 42){ my $b is default('answer'); say $a; $b = $a; say $b }; f; # OUTPUT: «4242» f Nil; # OUTPUT: «Nilanswer»
$a has 42 as its default value. With no value, $a will be assigned the default value declared in the Signature. However, in the second case, it does receive a value, which happens to be Nil. Assigning Nil to any variable resets it to its default value, which has been declared as 'answer' by use of the default trait. That explains what happens the second time we call f. Routine parameters and variables deal differently with default value, which is in part clarified by the different way default values are declared in each case (using = for parameters, using the default trait for variables).
Note: in 6.c language, the default value of :U/:D constrained variables was a type object with such a constraint, which is not initializable, thus you cannot use the .= operator, for example.
use v6.c; my Int:D $x .= new: 42; # OUTPUT: You cannot create an instance of this type (Int:D) # in block <unit> at -e line 1
In the 6.d language, the default default is the type object without the smiley constraint:
use v6.d; my Int:D $x .= new: 42; # OUTPUT: «42»
A closing remark on terminology: this section is about the use of the type smileys :D and :U to constrain the definiteness of arguments. Occasionally definedness is used as a synonym for definiteness; this may be confusing, since the terms have subtly different meanings.
As explained above, definiteness is concerned with the distinction between type objects and object instances. A type object is always indefinite, while an object instance is always definite. Whether an object is a type object/indefinite or an object instance/definite can be verified using the DEFINITE (meta)method.
Definiteness should be distinguished from definedness, which is concerned with the difference between defined and undefined objects. Whether an object is defined or undefined can be verified using the defined-method, which is implemented in class Mu. By default a type object is considered undefined, while an object instance is considered defined; that is: .defined returns False on a type object, and True otherwise. But this default behavior may be overridden by subclasses. An example of a subclass that overrides the default .defined behavior is Failure, so that even an instantiated Failure acts as an undefined value:
my $a = Failure; # Initialize with type object my $b = Failure.new("foo"); # Initialize with object instance say $a.DEFINITE; # Output: «False» : indefinite type object say $b.DEFINITE; # Output: «True» : definite object instance say $a.defined; # Output: «False» : default response say $b.defined; # Output: «False» : .defined override
The signature of a Callable parameter can be constrained by specifying a Signature literal right after the parameter (no whitespace allowed):
sub f(&c:(Int, Str)) { say c(10, 'ten') }; sub g(Int $i, Str $s) { $s ~ $i }; f(&g); # OUTPUT: «ten10»
This shorthand syntax is available only for parameters with the & sigil. For others, you need to use the long version:
sub f($c where .signature ~~ :(Int, Str)) { say $c(10, 'ten') } sub g(Num $i, Str $s) { $s ~ $i } sub h(Int $i, Str $s) { $s ~ $i } # f(&g); # Constraint type check failed f(&h); # OUTPUT: «ten10»
There are multiple ways to constrain return types on a Routine. All versions below are currently valid and will force a type check on successful execution of a routine.
Nil and Failure are always allowed as return types, regardless of any type constraint. This allows Failure to be returned and passed on down the call chain.
sub foo(--> Int) { Nil }; say foo.perl; # OUTPUT: «Nil»
Type captures are not supported.
This form of indicating return types (or constants) in the signature is preferred, since it can handle constant values while the others can't. For consistency, it is the only form accepted on this site.
The return type arrow has to be placed at the end of the parameter list, with or without a , before it.
sub greeting1(Str $name --> Str) { say "Hello, $name" } # Valid sub greeting2(Str $name, --> Str) { say "Hello, $name" } # Valid sub favorite-number1(--> 42) { } # OUTPUT: 42 sub favorite-number2(--> 42) { return } # OUTPUT: 42
If the type constraint is a constant expression, it is used as the return value of the routine. Any return statement in that routine has to be argumentless.
sub foo(Str $word --> 123) { say $word; return; } my $value = foo("hello"); # OUTPUT: hello say $value; # OUTPUT: 123
# The code below will not compile sub foo(Str $word --> 123) { say $word; return $word; } my $value = foo("hello"); say $value;
The keyword returns following a signature declaration has the same function as --> with the caveat that this form does not work with constant values. You cannot use it in a block either. That is why the pointy arrow form is always preferred.
sub greeting(Str $name) returns Str { say "Hello, $name" } # Valid
sub favorite-number returns 42 { } # This will fail.
of is just the real name of the returns keyword.
sub foo() of Int { 42 }; # Valid
sub foo() of 42 { }; # This will fail.
This is similar to placing type constraints on variables like my Type $var = 20;, except the $var is a definition for a routine.
my Int sub bar { 1 }; # Valid
my 42 sub bad-answer {}; # This will fail.
To accept one type but coerce it automatically to another, use the accepted type as an argument to the target type. If the accepted type is Any it can be omitted.
sub f(Int(Str) $want-int, Str() $want-str) { say $want-int.^name ~ ' ' ~ $want-str.^name } f '10', 10; # OUTPUT: «Int Str» use MONKEY; augment class Str { method Date() { Date.new(self) } }; sub foo(Date(Str) $d) { say $d.^name; say $d }; foo "2016-12-01"; # OUTPUT: «Date2016-12-01»
The coercion is performed by calling the method with the name of the type to coerce to, if it exists (e.g. Foo(Bar) coercer, would call method Foo). The method is assumed to return the correct type—no additional checks on the result are currently performed.
Coercion can also be performed on return types:
sub square-str (Int $x --> Str(Int)) { $x² } for 2,4, *² … 256 -> $a { say $a, "² is ", square-str( $a ).chars, " figures long"; } # OUTPUT: «2² is 1 figures long # 4² is 2 figures long # 16² is 3 figures long # 256² is 5 figures long»
In this example, coercing the return type to String allows us to directly apply string methods, such as the number of characters.
A function is variadic if it can take a varying number of arguments; that is, its arity is not fixed. Therefore, optional, named, and slurpy parameters are variadic. An array or hash parameter can be marked as slurpy by leading single (*) or double asterisk (**) or a leading plus (+). A slurpy parameter can bind to an arbitrary number of arguments (zero or more), and it will result in a type that is compatible with the sigil.
These are called "slurpy" because they slurp up any remaining arguments to a function, like someone slurping up noodles.
$ = :($a, @b); # exactly two arguments, where the second one must be Positional $ = :($a, *@b); # at least one argument, @b slurps up any beyond that $ = :(*%h); # no positional arguments, but any number of named arguments sub one-arg (@) { } sub slurpy (*@) { } one-arg (5, 6, 7); # ok, same as one-arg((5, 6, 7)) slurpy (5, 6, 7); # ok slurpy 5, 6, 7 ; # ok # one-arg(5, 6, 7) ; # X::TypeCheck::Argument # one-arg 5, 6, 7 ; # X::TypeCheck::Argument sub named-names (*%named-args) { %named-args.keys }; say named-names :foo(42) :bar<baz>; # OUTPUT: «foo bar»
Positional and named slurpies can be combined; named arguments (i.e., Pairs) are collected in the specified hash, positional arguments in the array:
sub combined-slurpy (*@a, *%h) { { array => @a, hash => %h } } # or: sub combined-slurpy (*%h, *@a) { ... } say combined-slurpy(one => 1, two => 2); # OUTPUT: «{array => [], hash => {one => 1, two => 2}}» say combined-slurpy(one => 1, two => 2, 3, 4); # OUTPUT: «{array => [3 4], hash => {one => 1, two => 2}}» say combined-slurpy(one => 1, two => 2, 3, 4, five => 5); # OUTPUT: «{array => [3 4], hash => {five => 5, one => 1, two => 2}}» say combined-slurpy(one => 1, two => 2, 3, 4, five => 5, 6); # OUTPUT: «{array => [3 4 6], hash => {five => 5, one => 1, two => 2}}»
Note that positional parameters aren't allowed after slurpy parameters:
:(*@args, $last); # ===SORRY!=== Error while compiling: # Cannot put required parameter $last after variadic parameters
Normally a slurpy parameter will create an Array (or compatible type), create a new Scalar container for each argument, and assign the value from each argument to those Scalars. If the original argument also had an intermediary Scalar it is bypassed during this process, and is not available inside the called function.
Sigiled parameters will always impose a context on the collected arguments. Sigilless parameters can also be used slurpily, preceded by a + sign, to work with whatever initial type they started with:
sub zipi( +zape ) { zape.^name => zape }; say zipi( "Hey "); # OUTPUT: «List => (Hey )» say zipi( 1...* ); # OUTPUT: «Seq => (...)»
Slurpy parameters have special behaviors when combined with some traits and modifiers, as described in the section on slurpy array parameters.
There are three variations to slurpy array parameters.
The single asterisk form flattens passed arguments.
The double asterisk form does not flatten arguments.
The plus form flattens according to the single argument rule.
Each will be described in detail in the next few sections. As the difference between each is a bit nuanced, examples are provided for each to demonstrate how each slurpy convention varies from the others.
Slurpy parameters declared with one asterisk will flatten arguments by dissolving one or more layers of bare Iterables.
my @array = <a b c>; my $list := <d e f>; sub a(*@a) { @a.perl.say }; a(@array); # OUTPUT: «["a", "b", "c"]» a(1, $list, [2, 3]); # OUTPUT: «[1, "d", "e", "f", 2, 3]» a([1, 2]); # OUTPUT: «[1, 2]» a(1, [1, 2], ([3, 4], 5)); # OUTPUT: «[1, 1, 2, 3, 4, 5]» a(($_ for 1, 2, 3)); # OUTPUT: «[1, 2, 3]»
A single asterisk slurpy flattens all given iterables, effectively hoisting any object created with commas up to the top level.
Slurpy parameters declared with two stars do not flatten any Iterable arguments within the list, but keep the arguments more or less as-is:
my @array = <a b c>; my $list := <d e f>; sub b(**@b) { @b.perl.say }; b(@array); # OUTPUT: «[["a", "b", "c"],]» b(1, $list, [2, 3]); # OUTPUT: «[1, ("d", "e", "f"), [2, 3]]» b([1, 2]); # OUTPUT: «[[1, 2],]» b(1, [1, 2], ([3, 4], 5)); # OUTPUT: «[1, [1, 2], ([3, 4], 5)]» b(($_ for 1, 2, 3)); # OUTPUT: «[(1, 2, 3),]»
The double asterisk slurpy hides the nested comma objects and leaves them as-is in the slurpy array.
A slurpy parameter created using a plus engages the "single argument rule", which decides how to handle the slurpy argument based upon context. Basically, if only a single argument is passed and that argument is Iterable, that argument is used to fill the slurpy parameter array. In any other case, +@ works like **@.
my @array = <a b c>; my $list := <d e f>; sub c(+@b) { @b.perl.say }; c(@array); # OUTPUT: «["a", "b", "c"]» c(1, $list, [2, 3]); # OUTPUT: «[1, ("d", "e", "f"), [2, 3]]» c([1, 2]); # OUTPUT: «[1, 2]» c(1, [1, 2], ([3, 4], 5)); # OUTPUT: «[1, [1, 2], ([3, 4], 5)]» c(($_ for 1, 2, 3)); # OUTPUT: «[1, 2, 3]»
For additional discussion and examples, see Slurpy Conventions for Functions.
Type captures allow deferring the specification of a type constraint to the time the function is called. They allow referring to a type both in the signature and the function body.
sub f(::T $p1, T $p2, ::C){ # $p1 and $p2 are of the same type T, that we don't know yet # C will hold a type we derive from a type object or value my C $division = $p1 / $p2; return sub (T $p1) { $division * $p1; } } # The first parameter is Int and so must be the 2nd. # We derive the 3rd type from calling the operator that is used in &f. my &s = f(10, 2, Int.new / Int.new); say s(2); # 10 / 2 * 2 == 10
An argument can be positional or named. By default, arguments are positional, except slurpy hash and arguments marked with a leading colon :. The latter is called a colon-pair. Check the following signatures and what they denote:
$ = :($a); # a positional argument $ = :(:$a); # a named argument of name 'a' $ = :(*@a); # a slurpy positional argument $ = :(*%h); # a slurpy named argument
On the caller side, positional arguments are passed in the same order as the arguments are declared.
sub pos($x, $y) { "x=$x y=$y" } pos(4, 5); # OUTPUT: «x=4 y=5»
In the case of named arguments and parameters, only the name is used for mapping arguments to parameters. If a fat arrow is used to construct a Pair only those with valid identifiers as keys are recognized as named arguments.
sub named(:$x, :$y) { "x=$x y=$y" } named( y => 5, x => 4); # OUTPUT: «x=4 y=5»
You can invoke the routine using a variable with the same name as the named argument; in that case : will be used for the invocation so that the name of the variable is understood as the key of the argument.
sub named-shortcut( :$shortcut ) { say "Looks like $shortcut" } named-shortcut( shortcut => "to here"); # OUTPUT: «Looks like to here» my $shortcut = "Þor is mighty"; named-shortcut( :$shortcut ); # OUTPUT: «Looks like Þor is mighty»
It is possible to have a different name for a named argument than the variable name:
sub named(:official($private)) { "Official business!" if $private } named :official;
The colon-pair syntax can be used to provide aliases for arguments:
sub alias-named(:color(:$colour), :type(:class($kind))) { say $colour ~ " " ~ $kind } alias-named(color => "red", type => "A"); # both names can be used alias-named(colour => "green", type => "B"); # more than two names are ok alias-named(color => "white", class => "C"); # every alias is independent
The presence of the colon : will decide whether we are creating a new named argument or not. :$colour will not only be the name of the aliased variable, but also a new named argument (used in the second invocation). However, $kind will just be the name of the aliased variable, that does not create a new named argument. More uses of aliases can be found in sub MAIN.
A function with named arguments can be called dynamically, dereferencing a Pair with | to turn it into a named argument.
multi f(:$named) { note &?ROUTINE.signature }; multi f(:$also-named) { note &?ROUTINE.signature }; for 'named', 'also-named' -> $n { f(|($n => rand)) # OUTPUT: «(:$named)(:$also-named)» } my $pair = :named(1); f |$pair; # OUTPUT: «(:$named)»
The same can be used to convert a Hash into named arguments.
sub f(:$also-named) { note &?ROUTINE.signature }; my %pairs = also-named => 4; f |%pairs; # OUTPUT: «(:$also-named)»
A Hash that contains a list may prove problematic when slipped into named arguments. To avoid the extra layer of containers coerce to Map before slipping.
class C { has $.x; has $.y; has @.z }; my %h = <x y z> Z=> (5, 20, [1,2]); say C.new(|%h.Map); # OUTPUT: «C.new(x => 5, y => 20, z => [1, 2])»
You can create as many aliases to a named argument as you want:
sub alias-named(:color(:$colour), :variety(:style(:sort(:type(:class($kind)))))) { return $colour ~ " " ~ $kind } say alias-named(color => "red", style => "A"); say alias-named(colour => "green", variety => "B"); say alias-named(color => "white", class => "C");
Positional parameters are mandatory by default, and can be made optional with a default value or a trailing question mark:
$ = :(Str $id); # required parameter $ = :($base = 10); # optional parameter, default value 10 $ = :(Int $x?); # optional parameter, default is the Int type object
Named parameters are optional by default, and can be made mandatory with a trailing exclamation mark:
$ = :(:%config); # optional parameter $ = :(:$debug = False); # optional parameter, defaults to False $ = :(:$name!); # mandatory 'name' named parameter
Default values can depend on previous parameters, and are (at least notionally) computed anew for each call
$ = :($goal, $accuracy = $goal / 100); $ = :(:$excludes = ['.', '..']); # a new Array for every call
Dynamic variables are allowed in signatures although they don't provide special behavior because argument binding does connect two scopes anyway.
Non-scalar parameters can be followed or substituted by a sub-signature in parentheses, which will destructure the argument given. The destructuring of a list is just its elements:
sub first(@array ($first, *@rest)) { $first }
or
sub first([$f, *@]) { $f }
While the destructuring of a hash is its pairs:
sub all-dimensions(% (:length(:$x), :width(:$y), :depth(:$z))) { $x andthen $y andthen $z andthen True }
Pointy loops can also destructure hashes, allowing assignment to variables:
my %hhgttu = (:40life, :41universe, :42everything); for %hhgttu -> (:$key, :$value) { say "$key → $value"; } # OUTPUT: «universe → 41life → 40everything → 42»
In general, an object is destructured based on its attributes. A common idiom is to unpack a Pair's key and value in a for loop:
for <Peter Paul Merry>.pairs -> (:key($index), :value($guest)) { }
However, this unpacking of objects as their attributes is only the default behavior. To make an object get destructured differently, change its Capture method.
To match against a compound parameter use a sub-signature following the argument name in parentheses.
sub foo(|c(Int, Str)){ put "called with {c.perl}" }; foo(42, "answer"); # OUTPUT: «called with \(42, "answer")»
To exclude certain parameters from being considered in multiple dispatch, separate them with a double semicolon.
multi sub f(Int $i, Str $s;; :$b) { say "$i, $s, {$b.perl}" }; f(10, 'answer'); # OUTPUT: «10, answer, Any»
Prefixing a parameter with a vertical bar | makes the parameter a Capture, using up all the remaining positional and named arguments.
This is often used in proto definitions (like proto foo (|) {*}) to indicate that the routine's multi definitions can have any type constraints. See proto for an example.
If bound to a variable arguments can be forwarded as a whole using the slip operator |.
sub a(Int $i, Str $s) { say $i.^name ~ ' ' ~ $s.^name } sub b(|c) { say c.^name; a(|c) } b(42, "answer"); # OUTPUT: «CaptureInt Str»
By default, parameters are bound to their argument and marked as read-only. One can change that with traits on the parameter.
The is copy trait causes the argument to be copied, and allows it to be modified inside the routine
sub count-up($x is copy) { $x = ∞ if $x ~~ Whatever; .say for 1..$x; }
The is rw trait, which stands for is read-write, makes the parameter bind to a variable (or other writable container). Assigning to the parameter changes the value of the variable at the caller side.
sub swap($x is rw, $y is rw) { ($x, $y) = ($y, $x); }
On slurpy parameters, is rw is reserved for future use by language designers.
The is raw trait is automatically applied to parameters declared with a backslash as a "sigil", and may also be used to make normally sigiled parameters behave like these do. In the special case of slurpies, which normally produce an Array full of Scalars as described above, is raw will instead cause the parameter to produce a List. Each element of that list will be bound directly as raw parameter.
To explicitly ask for a read-only parameter use the is readonly trait. Please note that this applies only to the container. The object inside can very well have mutator methods and Perl 6 will not enforce immutability on the attributes of the object.
Traits can be followed by the where clause:
sub ip-expand-ipv6($ip is copy where m:i/^<[a..f\d\:]>**3..39$/) { }
method params(Signature:D: --> Positional)
Returns the list of Parameter objects that make up the signature.
method arity(Signature:D: --> Int:D)
Returns the minimal number of positional arguments required to satisfy the signature.
method count(Signature:D: --> Real:D)
Returns the maximal number of positional arguments which can be bound to the signature. Returns Inf if there is a slurpy positional parameter.
Whatever the Signature's return constraint is:
:($a, $b --> Int).returns # OUTPUT: «(Int)»
multi method ACCEPTS(Signature:D: Signature $topic) multi method ACCEPTS(Signature:D: Capture $topic) multi method ACCEPTS(Signature:D: Mu \topic)
If $topic is a Signature returns True if anything accepted by $topic would also be accepted by the invocant, otherwise returns False:
:($a, $b) ~~ :($foo, $bar, $baz?); # OUTPUT: «True» :(Int $n) ~~ :(Str); # OUTPUT: «False»
The $topic is a Capture, returns True if it can be bound to the invocant, i.e., if a function with invocant's Signature would be able to be called with the $topic:
\(1, 2, :foo) ~~ :($a, $b, :foo($bar)); # OUTPUT: «True» \(1, :bar) ~~ :($a); # OUTPUT: «False»
Lastly, the candidate with Mu \topic converts topic to Capture and follows the same semantics as Capture $topic:
<a b c d> ~~ :(Int $a); # OUTPUT: «False» 42 ~~ :(Int); # OUTPUT: «False» (Int.Capture throws) set(<a b>) ~~ :(:$a, :$b); # OUTPUT: «True»
Since where clauses are not introspectable, the method cannot determine whether two signatures ACCEPTS the same sort of where-constrained parameters. Such comparisons will return False. This includes signatures with literals, which are just sugar for the where-constraints:
say :(42) ~~ :($ where 42) # OUTPUT: «False»
Defined as:
method Capture()
Throws X::Cannot::Capture.
Signature.new(params => (...), returns => Type, arity => 1, count => 1)
In some situations, specifically when working with the MetaObject Protocol, it makes sense to create Signature objects programmatically. For this purpose, you can call the new method with the following named parameters:
params
A list of Parameter objects for this signature.
returns
Any constraint the return value should match. Defaults to Mu, which effectively implies no return value constraint check.
arity
The minimal number of positional arguments required to satisfy the signature. Defaults to the number of Parameter objects given with the params parameter.
count
The maximal number of positional arguments which can be bound to the signature. Defaults to the arity if not specified. Specify Inf if there is a slurpy positional parameter.
A kind of List that automatically flattens into an outer container
class Slip is List {}
A Slip is a List that automatically flattens into an outer List (or other list-like container or iterable).
For example it allows you to write a map that produces more than one value into the result without nesting:
say <a b c>.map({ ($_, $_.uc).Slip }).join('|'); # OUTPUT: «a|A|b|B|c|C»
In contrast, when returning an ordinary List, the resulting list is nested:
say <a b c>.map({ $_, $_.uc }).join('|'); # OUTPUT: «a A|b B|c C»
To create a Slip, either coerce another list-like type to it by calling the Slip method, or use the slip subroutine:
# This says "1" and then says "2", rather than saying "(1 2)" .say for gather { take slip(1, 2); }
A Slip may also be created by using the prefix:<|> operator. This differs from the slip subroutine in both precedence and treatment of single arguments. In fact, prefix:<|> only takes a single argument, so in that way, it behaves closer to the .Slip method than the slip subroutine.
my $l = (1, 2, 3); say (1, slip 2, 3).perl; # says (1, 2, 3) , slips 2, 3 into (1, …) say (0, slip $l).perl; # says (0, $(1, 2, 3)), $l does not break apart say (0, $l.Slip).perl; # says (0, 1, 2, 3) , slips from $l into (0, …) say (|$l).perl; # says slip(1, 2, 3) , breaks apart $l say (0, (|$l, 4), 5); # says (0 (1 2 3 4) 5), slips from $l into (…, 4) say (0, ($l.Slip, 4), 5); # says (0 (1 2 3 4) 5), slips from $l into (…, 4) say (0, (slip $l, 4), 5); # says (0 (1 2 3) 4 5), slips ($l, 4) into (0, …, 5) say (0, ($l, 4).Slip, 5); # says (0 (1 2 3) 4 5), slips ($l, 4) into (0, …, 5)
Loops that do not want to produce a value for an iteration use Slips, rather than empty Lists to do so, as do if statements that do not run their blocks.
Please note that prefix:<|> will also apply parameters in a slippy manner to a routine call. It does not forward a Slip to the called routine, that includes return and take.
my \l = gather for 1..10 -> $a, $b { take |($a, $b) }; say l.perl; # OUTPUT: «((1, 2), (3, 4), (5, 6), (7, 8), (9, 10)).Seq» my \m= gather for 1..10 -> $a, $b { take ($a, $b).Slip }; say m.perl; # OUTPUT: «(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).Seq»
Defined as:
multi method List(Slip:D: --> List:D)
Turns it into a list.
Defined as:
multi sub slip(--> Empty) multi sub slip(@args --> Slip:D) multi sub slip(+args --> Slip:D)
Creates a Slip from its arguments by calling .Slip on the object formed by them. Returns Empty if called with void arguments.
Empty is a Slip of the empty List.
say "".comb ~~ Empty; # OUTPUT: «True»
Table for "our"-scoped symbols
class Stash is Hash { }
A Stash is a hash that is used for symbol tables at the package scoping level in Perl 6.
To get a Stash, you can call the .WHO pseudo-method on a package (because it answers the question who lives here?), or if you write the package name as a literal, append two colons:
class Boring { class Nested { }; our sub package_sub { } my sub lexical { }; method a_method() { } } say Boring::.^name; # OUTPUT: «Stash» say Boring.WHO === Boring::; # OUTPUT: «True»
Since it inherits from Hash, you can use all the usual hash functionality:
say Boring::.keys.sort; # OUTPUT: «(&package_sub Nested)» say Boring::<Nested>; # OUTPUT: «(Nested)»
As the example above shows only "our"-scoped things appear in the Stash (nested classes are "our" by default, but can be excluded with "my".) Lexicals and methods are not included in a Stash, since they do not live in the package table. Lexicals live in a separate lexical pad, which is only visible from inside the scope. Methods (in the case that the package is also a class) have a separate method table, and are accessible through introspection on the class itself, via .can and .^methods.
String of characters
class Str is Cool does Stringy { }
Built-in class for strings. Objects of type Str are immutable, but read the FAQ to understand precisely what this means.
multi method chop(Str:D:) multi method chop(Str:D: Int() $chopping)
Returns the string with $chopping characters removed from the end.
say "Whateverable".chop(3.6); # OUTPUT: «Whatevera» my $string= "Whateverable"; say $string.chop("3"); # OUTPUT: «Whatevera»
The $chopping positional is converted to Int before being applied to the string.
Defined as:
multi sub chomp(Str:D --> Str:D) multi method chomp(Str:D: --> Str:D)
Returns the string with a logical newline (any codepoint that has the NEWLINE property) removed from the end.
Examples:
say chomp("abc\n"); # OUTPUT: «abc» say "def\r\n".chomp; # OUTPUT: «def» NOTE: \r\n is a single grapheme! say "foo\r".chomp; # OUTPUT: «foo»
Defined as:
multi method contains(Str:D: Cool:D $needle --> Bool:D) multi method contains(Str:D: Str:D $needle --> Bool:D) multi method contains(Str:D: Cool:D $needle, Int(Cool:D) $pos --> Bool:D) multi method contains(Str:D: Str:D $needle, Int:D $pos --> Bool:D)
Coerces the invocant (represented in the signature by Str:D:, that would be the haystack) and first argument (which we are calling $needle) to Str (if it's not already, that is, in the first and third multi forms), and searches for $needle in the invocant (or haystack) starting from $pos characters into the string, if that is included as an argument. Returns True if $needle is found. $pos is an optional parameter, and if it's not present, contains will search from the beginning of the string (using the first two forms of the multi).
say <Hello, World>.contains('Hello', 0); # OUTPUT: «True» say "Hello, World".contains('Hello'); # OUTPUT: «True» say "Hello, World".contains('hello'); # OUTPUT: «False» say "Hello, World".contains('Hello', 1); # OUTPUT: «False» say "Hello, World".contains(','); # OUTPUT: «True» say "Hello, World".contains(',', 3); # OUTPUT: «True» say "Hello, World".contains(',', 10); # OUTPUT: «False»
In the first example, coercion is used to convert a List to a Str. In the 4th case, the 'Hello' string is not found since we have started looking at the second position in it (index 1). Note that because of how a List or Array is coerced into a Str, the results may sometimes be surprising. See traps.
Defined as:
multi sub lc(Str:D --> Str:D) multi method lc(Str:D: --> Str:D)
Returns a lower-case version of the string.
Examples:
lc("A"); # RESULT: «"a"» "A".lc; # RESULT: «"a"»
multi sub uc(Str:D --> Str:D) multi method uc(Str:D: --> Str:D)
Returns an uppercase version of the string.
multi sub fc(Str:D --> Str:D) multi method fc(Str:D: --> Str:D)
Does a Unicode "fold case" operation suitable for doing caseless string comparisons. (In general, the returned string is unlikely to be useful for any purpose other than comparison.)
multi sub tc(Str:D --> Str:D) multi method tc(Str:D: --> Str:D)
Does a Unicode "titlecase" operation, that is changes the first character in the string to title case, or to upper case if the character has no title case mapping
multi sub tclc(Str:D --> Str:D) multi method tclc(Str:D: --> Str:D)
Turns the first character to title case, and all other characters to lower case
multi sub wordcase(Cool $x --> Str) multi sub wordcase(Str:D $x --> Str) multi method wordcase(Str:D: :&filter = &tclc, Mu :$where = True --> Str)
Returns a string in which &filter has been applied to all the words that match $where. By default, this means that the first letter of every word is capitalized, and all the other letters lowercased.
multi method unival(Str:D --> Numeric)
Returns the numeric value that the first codepoint in the invocant represents, or NaN if it's not numeric.
say '4'.unival; # OUTPUT: «4» say '¾'.unival; # OUTPUT: «0.75» say 'a'.unival; # OUTPUT: «NaN»
multi method univals(Str:D --> List)
Returns a list of numeric values represented by each codepoint in the invocant string, and NaN for non-numeric characters.
say "4a¾".univals; # OUTPUT: «(4 NaN 0.75)»
multi sub chars(Cool $x --> Int:D) multi sub chars(Str:D $x --> Int:D) multi sub chars(str $x --> int) multi method chars(Str:D: --> Int:D)
Returns the number of characters in the string in graphemes. On the JVM, this currently erroneously returns the number of codepoints instead.
multi method encode(Str:D $encoding = 'utf8', :$replacement, Bool() :$translate-nl = False, :$strict)
Returns a Blob which represents the original string in the given encoding and normal form. The actual return type is as specific as possible, so $str.encode('UTF-8') returns a utf8 object, $str.encode('ISO-8859-1') a buf8. If :translate-nl is set to True, it will translate newlines from \n to \n\r, but only in Windows. $replacement indicates how characters are going to be replaced in the case they are not available in the current encoding, while $strict indicates whether unmapped codepoints will still decode; for instance, codepoint 129 which does not exist in windows-1252.
my $str = "Þor is mighty"; say $str.encode("ascii", :replacement( 'Th') ).decode("ascii"); # OUTPUT: «Thor is mighty»
In this case, any unknown character is going to be substituted by Th. We know in advance that the character that is not known in the ascii encoding is Þ, so we substitute it by its latin equivalent, Th. In the absence of any replacement set of characters, :replacement is understood as a Bool:
say $str.encode("ascii", :replacement).decode("ascii"); # OUTPUT: «?or is mighty»
If :replacement is not set or assigned a value, the error Error encoding ASCII string: could not encode codepoint 222 will be issued (in this case, since þ is codepoint 222).
Since the Blob returned by encode is the original string in normal form, and every element of a Blob is a byte, you can obtain the length in bytes of a string by calling a method that returns the size of the Blob on it:
say "þor".encode.bytes; # OUTPUT: «4» say "þor".encode.elems; # OUTPUT: «4»
multi method index(Str:D: Cool:D $needle --> Int:D) multi method index(Str:D: Str:D $needle --> Int:D) multi method index(Str:D: Cool:D $needle, Cool:D $pos --> Int:D) multi method index(Str:D: Str:D $needle, Int:D $pos --> Int:D)
Searches for $needle in the string starting from $pos (if present). It returns the offset into the string where $needle was found, and Nil if it was not found.
Examples:
say index "Camelia is a butterfly", "a"; # OUTPUT: «1» say index "Camelia is a butterfly", "a", 2; # OUTPUT: «6» say index "Camelia is a butterfly", "er"; # OUTPUT: «17» say index "Camelia is a butterfly", "Camel"; # OUTPUT: «0» say index "Camelia is a butterfly", "Onion"; # OUTPUT: «Nil» say index("Camelia is a butterfly", "Onion").defined ?? 'OK' !! 'NOT'; # OUTPUT: «NOT»
Other forms of index, including a sub, are inherited from Cool. Check them there.
multi sub rindex(Str:D $haystack, Str:D $needle, Int $startpos = $haystack.chars --> Int) multi method rindex(Str:D $haystack: Str:D $needle, Int $startpos = $haystack.chars --> Int)
Returns the last position of $needle in $haystack not after $startpos. Returns Nil if $needle wasn't found.
Examples:
say rindex "Camelia is a butterfly", "a"; # OUTPUT: «11» say rindex "Camelia is a butterfly", "a", 10; # OUTPUT: «6»
Defined as:
multi method indices(Str:D: Str:D $needle, :$overlap --> List:D) multi method indices(Str:D: Str:D $needle, Int:D $start, :$overlap --> List:D)
Searches for all occurrences of $needle in the string starting from position $start, or zero if it is not specified, and returns a List with all offsets in the string where $needle was found, or an empty list if it was not found.
If the optional parameter :overlap is specified the search continues from the index directly following the previous match, otherwise the search will continue after the previous match.
say "banana".indices("a"); # OUTPUT: «(1 3 5)» say "banana".indices("ana"); # OUTPUT: «(1)» say "banana".indices("ana", :overlap); # OUTPUT: «(1 3)» say "banana".indices("ana", 2); # OUTPUT: «(3)»
method match($pat, :continue(:$c), :pos(:$p), :global(:$g), :overlap(:$ov), :exhaustive(:$ex), :st(:$nd), :rd(:$th), :$nth, :$x --> Match)
Performs a match of the string against $pat and returns a Match object if there is a successful match; it returns (Any) otherwise. Matches are stored in the default match variable $/. If $pat is not a Regex object, match will coerce the argument to a Str and then perform a literal match against $pat.
A number of optional named parameters can be specified, which alter how the match is performed.
:continue
The :continue adverb takes as an argument the position where the regex should start to search. If no position is specified for :c it will default to 0 unless $/ is set, in which case it defaults to $/.to.
:pos
Takes a position as an argument. Fails if regex cannot be matched from that position, unlike :continue.
:global
Instead of searching for just one match and returning a Match object, search for every non-overlapping match and return them in a List.
:overlap
Finds all matches including overlapping matches, but only returns one match from each starting position.
:exhaustive
Finds all possible matches of a regex, including overlapping matches and matches that start at the same position.
:st, :nd, :rd, :nth
Returns the nth match in the string. The argument can be a Numeric or an Iterable producing monotonically increasing numbers (that is, the next produced number must be larger than the previous one). The Iterable will be lazily reified and if non-monotonic sequence is encountered an exception will be thrown.
If Iterable argument is provided the return value and $/ variable will be set to a possibly-empty List of Match objects.
:x
Takes as an argument the number of matches to return, stopping once the specified number of matches has been reached. The value must be a Numeric or a Range; other values will cause .match to return a Failure containing X::Str::Match::x exception.
Examples:
say "properly".match('perl'); # OUTPUT: «「perl」» say "properly".match(/p.../); # OUTPUT: «「prop」» say "1 2 3".match([1,2,3]); # OUTPUT: «「1 2 3」» say "a1xa2".match(/a./, :continue(2)); # OUTPUT: «「a2」» say "abracadabra".match(/ a .* a /, :exhaustive); # OUTPUT: «(「abracadabra」 「abracada」 「abraca」 「abra」 「acadabra」 「acada」 「aca」 「adabra」 「ada」 「abra」)» say 'several words here'.match(/\w+/,:global); # OUTPUT: «(「several」 「words」 「here」)» say 'abcdef'.match(/.*/, :pos(2)); # OUTPUT: «「cdef」» say "foo[bar][baz]".match(/../, :1st); # OUTPUT: «「fo」» say "foo[bar][baz]".match(/../, :2nd); # OUTPUT: «「o[」» say "foo[bar][baz]".match(/../, :3rd); # OUTPUT: «「ba」» say "foo[bar][baz]".match(/../, :4th); # OUTPUT: «「r]」» say "foo[bar][baz]bada".match('ba', :x(2)); # OUTPUT: «(「ba」 「ba」)»
Defined as:
method Numeric(Str:D: --> Numeric:D)
Coerces the string to Numeric using semantics equivalent to val routine. Fails with X::Str::Numeric if the coercion to a number cannot be done.
Only Unicode characters with property Nd, as well as leading and trailing whitespace are allowed, with the special case of the empty string being coerced to 0. Synthetic codepoints (e.g. "7\x[308]") are forbidden.
While Nl and No characters can be used as numeric literals in the language, their conversion via Str.Numeric will fail, by design. See unival if you need to coerce such characters to Numeric.
Defined as:
method Int(Str:D: --> Int:D)
Coerces the string to Int, using the same rules as Str.Numeric.
Defined as:
method Rat(Str:D: --> Rational:D)
Coerces the string to a Rat object, using the same rules as Str.Numeric. If the denominator is larger than 64-bits is it still kept and no degradation to Num occurs.
Defined as:
method Bool(Str:D: --> Bool:D)
Returns False if the string is empty, True otherwise.
multi sub parse-base(Str:D $num, Int:D $radix --> Numeric) multi method parse-base(Str:D $num: Int:D $radix --> Numeric)
Performs the reverse of base by converting a string with a base-$radix number to its Numeric equivalent. Will fail if radix is not in range 2..36 or if the string being parsed contains characters that are not valid for the specified base.
1337.base(32).parse-base(32).say; # OUTPUT: «1337» 'Perl6'.parse-base(30).say; # OUTPUT: «20652936» 'FF.DD'.parse-base(16).say; # OUTPUT: «255.863281»
See also: :16<FF> syntax for number literals
sub parse-names(Str:D $names --> Str:D) method parse-names(Str:D $names: --> Str:D)
DEPRECATED. Use uniparse instead. Existed in Rakudo implementation as a proof of viability implementation before being renamed and will be removed when 6.e language is released.
sub uniparse(Str:D $names --> Str:D) method uniparse(Str:D $names: --> Str:D)
Takes string with comma-separated Unicode names of characters and returns a string composed of those characters. Will fail if any of the characters' names are empty or not recognized. Whitespace around character names is ignored.
say "I {uniparse 'TWO HEARTS'} Perl"; # OUTPUT: «I 💕 Perl» 'TWO HEARTS, BUTTERFLY'.uniparse.say; # OUTPUT: «💕🦋»
Note that unlike \c[...] construct available in string interpolation, uniparse does not accept decimal numerical values. Use chr routine to convert those:
say "\c[1337]"; # OUTPUT: «Թ» say '1337'.chr; # OUTPUT: «Թ»
Note: before being standardized in 2017.12, this routine was known under its working name of parse-names. This denomination will be removed in the 6.e version.
multi sub split( Str:D $delimiter, Str:D $input, $limit = Inf, :$skip-empty, :$v, :$k, :$kv, :$p)
multi sub split(Regex:D $delimiter, Str:D $input, $limit = Inf, :$skip-empty, :$v, :$k, :$kv, :$p)
multi sub split(List:D $delimiters, Str:D $input, $limit = Inf, :$skip-empty, :$v, :$k, :$kv, :$p)
multi method split(Str:D: Str:D $delimiter, $limit = Inf, :$skip-empty, :$v, :$k, :$kv, :$p)
multi method split(Str:D: Regex:D $delimiter, $limit = Inf, :$skip-empty, :$v, :$k, :$kv, :$p)
multi method split(Str:D: List:D $delimiters, $limit = Inf, :$skip-empty, :$v, :$k, :$kv, :$p)
Splits a string up into pieces based on delimiters found in the string.
If DELIMITER is a string, it is searched for literally and not treated as a regex. If DELIMITER is the empty string, it effectively returns all characters of the string separately (plus an empty string at the begin and at the end). If PATTERN is a regular expression, then that will be used to split up the string. If DELIMITERS is a list, then all of its elements will be considered a delimiter (either a string or a regular expression) to split the string on.
The optional LIMIT indicates in how many segments the string should be split, if possible. It defaults to Inf (or *, whichever way you look at it), which means "as many as possible". Note that specifying negative limits will not produce any meaningful results.
A number of optional named parameters can be specified, which alter the result being returned. The :v, :k, :kv and :p named parameters all perform a special action with regards to the delimiter found.
:skip-empty
If specified, do not return empty strings before or after a delimiter.
:v
Also return the delimiter. If the delimiter was a regular expression, then this will be the associated Match object. Since this stringifies as the delimiter string found, you can always assume it is the delimiter string if you're not interested in further information about that particular match.
:k
Also return the index of the delimiter. Only makes sense if a list of delimiters was specified: in all other cases, this will be 0.
:kv
Also return both the index of the delimiter, as well as the delimiter.
:p
Also return the index of the delimiter and the delimiter as a Pair.
Examples:
say split(";", "a;b;c").perl; # OUTPUT: «("a", "b", "c").Seq» say split(";", "a;b;c", :v).perl; # OUTPUT: «("a", ";", "b", ";", "c").Seq» say split(";", "a;b;c", 2).perl; # OUTPUT: «("a", "b;c").Seq» say split(";", "a;b;c", 2, :v).perl; # OUTPUT: «("a", ";", "b;c").Seq» say split(";", "a;b;c,d").perl; # OUTPUT: «("a", "b", "c,d").Seq» say split(/\;/, "a;b;c,d").perl; # OUTPUT: «("a", "b", "c,d").Seq» say split(<; ,>, "a;b;c,d").perl; # OUTPUT: «("a", "b", "c", "d").Seq» say split(/<[;,]>/, "a;b;c,d").perl; # OUTPUT: «("a", "b", "c", "d").Seq» say split(<; ,>, "a;b;c,d", :k).perl; # OUTPUT: «("a", 0, "b", 0, "c", 1, "d").Seq» say split(<; ,>, "a;b;c,d", :kv).perl; # OUTPUT: «("a", 0, ";", "b", 0, ";", "c", 1, ",", "d").Seq» say "".split("x").perl; # OUTPUT: «("",).Seq» say "".split("x", :skip-empty).perl; # OUTPUT: «().Seq» say "abcde".split("").perl; # OUTPUT: «("", "a", "b", "c", "d", "e", "").Seq» say "abcde".split("",:skip-empty).perl; # OUTPUT: «("a", "b", "c", "d", "e").Seq»
multi sub comb(Str:D $matcher, Str:D $input, $limit = Inf) multi sub comb(Regex:D $matcher, Str:D $input, $limit = Inf, Bool :$match) multi sub comb(Int:D $size, Str:D $input, $limit = Inf) multi method comb(Str:D $input:) multi method comb(Str:D $input: Str:D $matcher, $limit = Inf) multi method comb(Str:D $input: Regex:D $matcher, $limit = Inf, Bool :$match) multi method comb(Str:D $input: Int:D $size, $limit = Inf)
Searches for $matcher in $input and returns a Seq of non-overlapping matches limited to at most $limit matches. If $matcher is a Regex, each Match object is converted to a Str, unless $match is set.
If no matcher is supplied, a Seq of characters in the string is returned, as if the matcher was rx/./.
Examples:
say "abc".comb.perl; # OUTPUT: «("a", "b", "c").Seq» say 'abcdefghijk'.comb(3).perl; # OUTPUT: «("abc", "def", "ghi", "jk").Seq» say 'abcdefghijk'.comb(3, 2).perl; # OUTPUT: «("abc", "def").Seq» say comb(/\w/, "a;b;c").perl; # OUTPUT: «("a", "b", "c").Seq» say comb(/\N/, "a;b;c").perl; # OUTPUT: «("a", ";", "b", ";", "c").Seq» say comb(/\w/, "a;b;c", 2).perl; # OUTPUT: «("a", "b").Seq» say comb(/\w\;\w/, "a;b;c", 2).perl; # OUTPUT: «("a;b",).Seq» say comb(/.<(.)>/, "<>[]()").perl; # OUTPUT: «(">", "]", ")").Seq»
If the matcher is an integer value, comb behaves as if the matcher was rx/ . ** {1..$matcher} /, but which is optimized to be much faster.
Note that a Regex matcher may control which portion of the matched text is returned by using features which explicitly set the top-level capture.
Defined as:
multi method lines(Str:D: $limit) multi method lines(Str:D:)
Returns a list of lines (without trailing newline characters), i.e. the same as a call to $input.comb( / ^^ \N* /, $limit ) would.
Examples:
say lines("a\nb").perl; # OUTPUT: «("a", "b").Seq» say lines("a\nb").elems; # OUTPUT: «2» say "a\nb".lines.elems; # OUTPUT: «2» say "a\n".lines.elems; # OUTPUT: «1»
You can limit the number of lines returned by setting the $limit variable to a non-zero, non-Infinity value:
say <not there yet>.join("\n").lines( 2 ); # OUTPUT: «(not there)»
DEPRECATED as of 6.d language, the :count argument was used to return the total number of lines:
say <not there yet>.join("\n").lines( :count ); # OUTPUT: «3»
Use elems call on the returned Seq instead:
say <not there yet>.join("\n").lines.elems; # OUTPUT: «3»
multi method words(Str:D: $limit) multi method words(Str:D:)
Returns a list of non-whitespace bits, i.e. the same as a call to $input.comb( / \S+ /, $limit ) would.
Examples:
say "a\nb\n".words.perl; # OUTPUT: «("a", "b").Seq» say "hello world".words.perl; # OUTPUT: «("hello", "world").Seq» say "foo:bar".words.perl; # OUTPUT: «("foo:bar",).Seq» say "foo:bar\tbaz".words.perl; # OUTPUT: «("foo:bar", "baz").Seq»
It can also be used as a subroutine, turning the first argument into the invocant. $limit is optional, but if it is provided (and not equal to Inf), it will return only the first $limit words.
say words("I will be very brief here", 2); # OUTPUT: «(I will)»
multi sub flip(Str:D --> Str:D) multi method flip(Str:D: --> Str:D)
Returns the string reversed character by character.
Examples:
"Perl".flip; # RESULT: «lreP» "ABBA".flip; # RESULT: «ABBA»
multi method starts-with(Str:D: Str(Cool) $needle --> Bool:D)
Returns True if the invocant is identical to or starts with $needle.
say "Hello, World".starts-with("Hello"); # OUTPUT: «True» say "https://perl6.org/".starts-with('ftp'); # OUTPUT: «False»
multi method ends-with(Str:D: Str(Cool) $needle --> Bool:D)
Returns True if the invocant is identical to or ends with $needle.
say "Hello, World".ends-with('Hello'); # OUTPUT: «False» say "Hello, World".ends-with('ld'); # OUTPUT: «True»
multi method subst(Str:D: $matcher, $replacement, *%opts)
Returns the invocant string where $matcher is replaced by $replacement (or the original string, if no match was found).
There is an in-place syntactic variant of subst spelled s/matcher/replacement/ and with adverb following the s or inside the matcher.
$matcher can be a Regex, or a literal Str. Non-Str matcher arguments of type Cool are coerced to Str for literal matching. If a Regex $matcher is used, the $/ special variable will be set to Nil (if no matches occurred), a Match object, or a List of Match objects (if multi-match options like :g are used).
my $some-string = "Some foo"; my $another-string = $some-string.subst(/foo/, "string"); # gives 'Some string' $some-string.=subst(/foo/, "string"); # in-place substitution. $some-string is now 'Some string'
The replacement can be a Callable in which the current Match object will be placed in the $/ variable, as well as the $_ topic variable. Using a Callable as replacement is how you can refer to any of the captures created in the regex:
# Using capture from $/ variable (the $0 is the first positional capture) say 'abc123defg'.subst(/(\d+)/, { " before $0 after " }); # OUTPUT: «abc before 123 after defg» # Using capture from $/ variable (the $<foo> is a named capture) say 'abc123defg'.subst(/$<foo>=\d+/, { " before $<foo> after " }); # OUTPUT: «abc before 123 after defg» # Using WhateverCode to operate on the Match given in $_: say 'abc123defg'.subst(/(\d+)/, "[ " ~ *.flip ~ " ]"); # OUTPUT: «abc[ 321 ]defg» # Using a Callable to generate substitution without involving current Match: my $i = 41; my $str = "The answer is secret."; say $str.subst(/secret/, {++$i}); # The answer to everything # OUTPUT: «The answer is 42.»
The following adverbs are supported
short | long | meaning |
---|---|---|
:g | :global | tries to match as often as possible |
:nth(Int|Callable|Whatever) | only substitute the nth match; aliases: :st, :nd, :rd, and :th | |
:ss | :samespace | preserves whitespace on substitution |
:ii | :samecase | preserves case on substitution |
:mm | :samemark | preserves character marks (e.g. 'ü' replaced with 'o' will result in 'ö') |
:x(Int|Range|Whatever) | substitute exactly $x matches |
Note that only in the s/// form :ii implies :i and :ss implies :s. In the method form, the :s and :i modifiers must be added to the regex, not the subst method call.
Here are other examples of usage:
my $str = "Hey foo foo foo"; $str.subst(/foo/, "bar", :g); # global substitution - returns Hey bar bar bar $str.subst(/foo/, "no subst", :x(0)); # targeted substitution. Number of times to substitute. Returns back unmodified. $str.subst(/foo/, "bar", :x(1)); #replace just the first occurrence. $str.subst(/foo/, "bar", :nth(3)); # replace nth match alone. Replaces the third foo. Returns Hey foo foo bar
The :nth adverb has readable English-looking variants:
say 'ooooo'.subst: 'o', 'x', :1st; # OUTPUT: «xoooo» say 'ooooo'.subst: 'o', 'x', :2nd; # OUTPUT: «oxooo» say 'ooooo'.subst: 'o', 'x', :3rd; # OUTPUT: «ooxoo» say 'ooooo'.subst: 'o', 'x', :4th; # OUTPUT: «oooxo»
NOTE: .subst-mutate is deprecated in the 6.d version, and will be removed in future ones. You can use subst with .= method call assignment operator or s/// substitution operator instead.
Where subst returns the modified string and leaves the original unchanged, it is possible to mutate the original string by using subst-mutate. If the match is successful, the method returns a Match object representing the successful match, otherwise returns Nil. If :nth (or one of its aliases) with Iterable value, :g, :global, or :x arguments are used, returns a List of Match objects, or an empty List if no matches occurred.
my $some-string = "Some foo"; my $match = $some-string.subst-mutate(/foo/, "string"); say $some-string; # OUTPUT: «Some string» say $match; # OUTPUT: «「foo」» $some-string.subst-mutate(/<[oe]>/, '', :g); # remove every o and e, notice the :g named argument from .subst
If a Regex $matcher is used, the $/ special variable will be set to Nil (if no matches occurred), a Match object, or a List of Match objects (if multi-match options like :g are used).
multi sub substr(Str:D $s, $from, $chars? --> Str:D) multi sub substr(Str:D $s, Range $from-to --> Str:D) multi method substr(Str:D $s: $from, $chars? --> Str:D) multi method substr(Str:D $s: Range $from-to --> Str:D)
Returns a substring of the original string, between the indices specified by $from-to's endpoints (coerced to Int) or from index $from and of length $chars.
Both $from and $chars can be specified as Callable, which will be invoked with the length of the original string and the returned value will be used as the value for the argument. If $from or $chars are not Callable, they'll be coerced to Int.
If $chars is omitted or is larger than the available characters, the string from $from until the end of the string is returned. If $from-to's starting index or $from is less than zero, X::OutOfRange exception is thrown. The $from-to's ending index is permitted to extend past the end of string, in which case it will be equivalent to the index of the last character.
say substr("Long string", 3..6); # RESULT: «g st» say substr("Long string", 6, 3); # RESULT: «tri» say substr("Long string", 6); # RESULT: «tring» say substr("Long string", 6, *-1); # RESULT: «trin» say substr("Long string", *-3, *-1); # RESULT: «in»
multi method substr-eq(Str:D: Str(Cool) $test-string, Int(Cool) $from --> Bool) multi method substr-eq(Cool:D: Str(Cool) $test-string, Int(Cool) $from --> Bool)
Returns True if the $test-string exactly matches the String object, starting from the given initial index $from. For example, beginning with the string "foobar", the substring "bar" will match from index 3:
my $string = "foobar"; say $string.substr-eq("bar", 3); # OUTPUT: «True»
However, the substring "barz" starting from index 3 won't match even though the first three letters of the substring do match:
my $string = "foobar"; say $string.substr-eq("barz", 3); # OUTPUT: «False»
Naturally, to match the entire string, one merely matches from index 0:
my $string = "foobar"; say $string.substr-eq("foobar", 0); # OUTPUT: «True»
Since this method is inherited from the Cool type, it also works on integers. Thus the integer 42 will match the value 342 starting from index 1:
my $integer = 342; say $integer.substr-eq(42, 1); # OUTPUT: «True»
As expected, one can match the entire value by starting at index 0:
my $integer = 342; say $integer.substr-eq(342, 0); # OUTPUT: «True»
Also using a different value or an incorrect starting index won't match:
my $integer = 342; say $integer.substr-eq(42, 3); # OUTPUT: «False» say $integer.substr-eq(7342, 0); # OUTPUT: «False»
method substr-rw($from, $length = *)
A version of substr that returns a Proxy functioning as a writable reference to a part of a string variable. Its first argument, $from specifies the index in the string from which a substitution should occur, and its last argument, $length specifies how many characters are to be replaced. If not specified, $length defaults to the length of the string.
For example, in its method form, if one wants to take the string "abc" and replace the second character (at index 1) with the letter "z", then one does this:
my $string = "abc"; $string.substr-rw(1, 1) = "z"; $string.say; # OUTPUT: «azc»
Note that new characters can be inserted as well:
my $string = 'azc'; $string.substr-rw(2, 0) = "-Zorro-"; # insert new characters BEFORE the character at index 2 $string.say; # OUTPUT: «az-Zorro-c»
substr-rw also has a function form, so the above examples can also be written like so:
my $string = "abc"; substr-rw($string, 1, 1) = "z"; $string.say; # OUTPUT: «azc» substr-rw($string, 2, 0) = "-Zorro-"; $string.say; # OUTPUT: «az-Zorro-c»
It is also possible to alias the writable reference returned by substr-rw for repeated operations:
my $string = "A character in the 'Flintstones' is: barney"; $string ~~ /(barney)/; my $ref := substr-rw($string, $0.from, $0.to-$0.from); $string.say; # OUTPUT: «A character in the 'Flintstones' is: barney» $ref = "fred"; $string.say; # OUTPUT: «A character in the 'Flintstones' is: fred» $ref = "wilma"; $string.say; # OUTPUT: «A character in the 'Flintstones' is: wilma»
multi sub samemark(Str:D $string, Str:D $pattern --> Str:D) method samemark(Str:D: Str:D $pattern --> Str:D)
Returns a copy of $string with the mark/accent information for each character changed such that it matches the mark/accent of the corresponding character in $pattern. If $string is longer than $pattern, the remaining characters in $string receive the same mark/accent as the last character in $pattern. If $pattern is empty no changes will be made.
Examples:
say 'åäö'.samemark('aäo'); # OUTPUT: «aäo» say 'åäö'.samemark('a'); # OUTPUT: «aao» say samemark('Pêrl', 'a'); # OUTPUT: «Perl» say samemark('aöä', ''); # OUTPUT: «aöä»
method succ(Str:D --> Str:D)
Returns the string incremented by one.
String increment is "magical". It searches for the last alphanumeric sequence that is not preceded by a dot, and increments it.
'12.34'.succ; # RESULT: «13.34» 'img001.png'.succ; # RESULT: «img002.png»
The actual increment step works by mapping the last alphanumeric character to a character range it belongs to, and choosing the next character in that range, carrying to the previous letter on overflow.
'aa'.succ; # RESULT: «ab» 'az'.succ; # RESULT: «ba» '109'.succ; # RESULT: «110» 'α'.succ; # RESULT: «β» 'a9'.succ; # RESULT: «b0»
String increment is Unicode-aware, and generally works for scripts where a character can be uniquely classified as belonging to one range of characters.
method pred(Str:D: --> Str:D)
Returns the string decremented by one.
String decrementing is "magical" just like string increment (see succ). It fails on underflow
'b0'.pred; # RESULT: «a9» 'a0'.pred; # Failure 'img002.png'.pred; # RESULT: «img001.png»
multi sub ord(Str:D --> Int:D) multi method ord(Str:D: --> Int:D)
Returns the codepoint number of the base characters of the first grapheme in the string.
Example:
ord("A"); # 65 "«".ord; # 171
multi method ords(Str:D: --> Seq)
Returns a list of Unicode codepoint numbers that describe the codepoints making up the string.
Example:
"aå«".ords; # (97 229 171)
Strings are represented as graphemes. If a character in the string is represented by multiple codepoints, then all of those codepoints will appear in the result of ords. Therefore, the number of elements in the result may not always be equal to chars, but will be equal to codes; codes computes the codepoints in a different way, so the result might be faster.
The codepoints returned will represent the string in NFC. See the NFD, NFKC, and NFKD methods if other forms are required.
multi method trans(Str:D: Pair:D \what, *%n --> Str) multi method trans(Str:D: *@changes, :complement(:$c), :squash(:$s), :delete(:$d) --> Str)
Replaces one or many characters with one or many characters. Ranges are supported, both for keys and values. Regexes work as keys. In case a list of keys and values is used, substrings can be replaced as well. When called with :complement anything but the matched value or range is replaced with a single value; with :delete the matched characters without corresponding replacement are removed. Combining :complement and :delete will remove anything but the matched values, unless replacement characters have been specified, in which case, :delete would be ignored. The adverb :squash will reduce repeated matched characters to a single character.
Example:
my $str = 'say $x<b> && $y<a>'; $str.=trans( '<' => '«' ); $str.=trans( '<' => '«', '>' => '»' ); $str.=trans( [ '<' , '>' , '&' ] => [ '<', '>', '&' ]); $str.=trans( ['a'..'y'] => ['A'..'z'] ); "abcdefghij".trans(/<[aeiou]> \w/ => ''); # RESULT: «cdgh» "a123b123c".trans(['a'..'z'] => 'x', :complement); # RESULT: «axxxbxxxc» "a123b123c".trans('23' => '', :delete); # RESULT: «a1b1c» "aaa1123bb123c".trans('a'..'z' => 'A'..'Z', :squash); # RESULT: «A1123B123C» "aaa1123bb123c".trans('a'..'z' => 'x', :complement, :squash); # RESULT: «aaaxbbxc»
Please note that the behavior of the two versions of the multi method is slightly different. The first form will transpose only one character if the origin is also one character:
say "abcd".trans( "a" => "zz" ); # OUTPUT: «zbcd» say "abcd".trans( "ba" => "yz" ); # OUTPUT: «zycd»
In the second case, behavior is as expected, since the origin is more than one char long. However, if the Pair in the multi method does not have a Str as an origin or target, it is handled to the second multi method, and behavior changes:
say "abcd".trans: ["a"] => ["zz"]; # OUTPUT: «zzbcd»
In this case, neither origin nor target in the Pair are Str; the method with the Pair signature then calls the second, making this call above equivalent to "abcd".trans: ["a"] => ["zz"], (with the comma behind, making it a Positional, instead of a Pair), resulting in the behavior shown as output.
multi method indent(Int $steps where { $_ == 0 } ) multi method indent(Int $steps where { $_ > 0 } ) multi method indent($steps where { .isa(Whatever) || .isa(Int) && $_ < 0 } )
Indents each line of the string by $steps. If $steps is negative, it outdents instead. If $steps is *, then the string is outdented to the margin:
" indented by 2 spaces\n indented even more".indent(*) eq "indented by 2 spaces\n indented even more"
method trim(Str:D: --> Str)
Remove leading and trailing whitespace. It can be used both as a method on strings and as a function. When used as a method it will return the trimmed string. In order to do in-place trimming, one needs to write .=trim
my $line = ' hello world '; say '<' ~ $line.trim ~ '>'; # OUTPUT: «<hello world>» say '<' ~ trim($line) ~ '>'; # OUTPUT: «<hello world>» $line.trim; say '<' ~ $line ~ '>'; # OUTPUT: «< hello world >» $line.=trim; say '<' ~ $line ~ '>'; # OUTPUT: «<hello world>»
See also trim-trailing and trim-leading.
method trim-trailing(Str:D: --> Str)
Removes the whitespace characters from the end of a string. See also trim.
method trim-leading(Str:D: --> Str)
Removes the whitespace characters from the beginning of a string. See also trim.
method NFC(Str:D: --> NFC:D)
Returns a codepoint string in NFC format (Unicode Normalization Form C / Composed).
method NFD(Str:D: --> NFD:D)
Returns a codepoint string in NFD format (Unicode Normalization Form D / Decomposed).
method NFKC(Str:D: --> NFKC:D)
Returns a codepoint string in NFKC format (Unicode Normalization Form KC / Compatibility Composed).
method NFKD(Str:D: --> NFKD:D)
Returns a codepoint string in NFKD format (Unicode Normalization Form KD / Compatibility Decomposed).
multi method ACCEPTS(Str:D: $other)
Returns True if the string is the same as $other.
Defined as:
method Capture()
Throws X::Cannot::Capture.
multi sub val(Str:D $MAYBEVAL, :$val-or-fail)
Given a Str that may be parsable as a numeric value, it will attempt to construct the appropriate allomorph, returning one of IntStr, NumStr, RatStr or ComplexStr or a plain Str if a numeric value cannot be parsed. If the :val-or-fail adverb is provided it will return an X::Str::Numeric rather than the original string if it cannot parse the string as a number.
say val("42").^name; # OUTPUT: «IntStr» say val("42e0").^name; # OUTPUT: «NumStr» say val("42.0").^name; # OUTPUT: «RatStr» say val("42+0i").^name; # OUTPUT: «ComplexStr»
While characters belonging to the Unicode categories Nl (number letters) and No (other numbers) can be used as numeric literals in the language, they will not be converted to a number by val, by design. See unival if you need to convert such characters to Numeric.
Contains the result of a string transformation.
StrDistance objects are used to represent the return of the string transformation operator.
say (($ = "fold") ~~ tr/old/new/).^name; # OUTPUT: «StrDistance»
A StrDistance object will stringify to the resulting string after the transformation, and will numify to the distance between the two strings.
my $str = "fold"; my $str-dist = ($str ~~ tr/old/new/); say ~$str-dist; # OUTPUT: «fnew» say +$str-dist; # OUTPUT: «3»
This is actually a class attribute, and called as a method returns the string before the transformation:
say $str-dist.before; # OUTPUT: «fold»
Also a class attribute, returns the string after the transformation:
say $str-dist.after; # OUTPUT: «fnew»
Returns True if before is different from after.
Returns the distance as a number.
Defined as:
multi method Int(StrDistance:D:)
Returns the distance between the string before and after the transformation.
Defined as:
multi method Str(StrDistance:D: --> Str)
Returns an after string value.
my $str-dist = ($str ~~ tr/old/new/); say $str-dist.Str; # OUTPUT: «fnew» say ~$str-dist; # OUTPUT: «fnew»
String or object that can act as a string
role Stringy { ... }
Common role for string types (such as Str).
Subroutine
class Sub is Routine { }
A type for subroutines and operators. Subs are created with the sub declarator keyword followed by an optional identifier. This short tutorial explains how operators are declared. For details of a sub's parameter list, see Signature.
Note that subs that go by the same name as coercers will not take precedence over them. Use the &-sigil to call them.
sub Int(Str $s){'what?'}; say [Int, Int('42'),&Int('42')]; # OUTPUT: «[(Int) 42 what?]»
Subs can be nested and scoped with my and our, whereby my is the default. A sub declared with my cannot be reached from any outer scope. An our scoped sub will not redefine a sub of the same name in the outer scope. Any sub can be accessed via a closure from any outer scope. For instance, in this example
sub can-be-seener( $whatever ) { my sub can-be-seen ( $objection ) { return $whatever but $objection; } return &can-be-seen } my $objectioner = can-be-seener( "Really?"); say $objectioner(42).Int; # OUTPUT: «42»
$objectioner will contain the can-be-seen subroutine, even if it has been declared in another scope; calling it with 42 will return "Really?" with the number 42 mixed in, as shown in the last sentence.
Operators are also Subs. Their definition includes the category they belong to and their code, precedence and associativity. The syntax used in their definition is an example of extended identifiers.
A Trait is a sub that is applied at compile time to various objects like classes, routines or containers. It is declared with the trait_mod declarator followed by a colon and a string literal containing the name of the trait. A single positional parameter defines the type of the object that the trait is applied to. A single named argument defines the secondary name and may carry arguments when the trait is called. Traits are a special grammar category and are allowed to be placed after most language object names or parameter lists.
say 'start'; multi sub trait_mod:<is>(Sub $s, :$foo){ say "⟨is foo⟩ has been called with ⟨$foo⟩ on {$s.WHICH}"; } sub bar() is foo<oi‽> { say 'bar has been called' } bar(); # OUTPUT: «⟨is foo⟩ has been called with ⟨oi‽⟩ on Sub|47563000startbar has been called»
Use destructuring to call traits with complex arguments.
multi trait_mod:<is>(Variable $a, :@foo [$firstpos, *@restpos, :$named, *%restnameds]) { say [$firstpos, @restpos, $named, %restnameds] } my $x is foo[1,2,3,:named<a>, :2b, :3c] = 1 # OUTPUT: «[1 [2 3] a {b => 2, c => 3}]»
Despite its funky syntax, a trait is just a normal Sub. We can apply traits to it (or even themselves) and we can apply traits to objects at runtime.
multi sub trait_mod:<is> (Sub $s, :$foo) is foo { say 'is foo called' } sub bar {} &trait_mod:<is>(&bar, :foo); # OUTPUT: «is foo calledis foo called»
Member function that is not inherited by subclasses
class Submethod is Routine {}
A Submethod is a method that is not inherited by child classes. They are typically used for per-class initialization and tear-down tasks which are called explicitly per class in an inheritance tree, usually for enforcing a particular order. For example object construction with the BUILD submethod happens from the least-derived to most-derived, so that the most-derived (child) classes can depend on the parent already being initialized.
Submethods are of type Submethod, and are declared with the submethod declarator:
class Area { has $.size; submethod BUILD(:$x, :$y, :$z) { $!size = $x * $y * $z; } }
Defined as:
multi method gist(Submethod:D:)
Returns the name of the submethod.
Live Supply factory
class Supplier { }
This is a factory for live Supply objects, which provides the mechanism for emitting new values onto the supplies:
my $supplier = Supplier.new; my $supply_1 = $supplier.Supply; $supply_1.tap(-> $v { say "One $v" }); my $supply_2 = $supplier.Supply; $supply_2.tap(-> $v { say "Two $v" }); $supplier.emit(42);
Will output:
One 42 Two 42
on demand supplies are created by the factory methods of the Supply class or by the supply keyword. A mixture of a live and on-demand Supply can be created with a Supplier::Preserving.
method new()
The Supplier constructor.
method Supply(Supplier:D: --> Supply)
This creates a new Supply object to which any values which are emitted on this supplier are passed. This is the factory for all live supplies.
method emit(Supplier:D: Mu \value)
Sends the given value to all of the taps on all of the supplies created by Supply on this Supplier.
method done(Supplier:D:)
Calls the done callback on all the taps that have one.
my $supplier = Supplier.new; my $supply = $supplier.Supply; $supply.tap(-> $v { say $v }, done => { say "no more answers" }); $supplier.emit(42); $supplier.done;
Will output:
42 no more answers
multi method quit(Supplier:D: Exception $ex) multi method quit(Supplier:D: Str() $message)
Calls the quit callback on all the taps that have one, passing the exception to them. If called with a Str the exception will be an X::AdHoc with the supplied message.
This is meant for shutting down a supply with an error.
Cached live Supply factory
class Supplier::Preserving is Supplier { }
This is a factory for live Supply objects, which provides the mechanism for emitting new values onto the supplies, whereby values are kept when no consumer has tapped into the Supply. Any tapping will consume the already stored and future values.
Starting a preserving Supply and consuming its values after it is done:
my $p = Supplier::Preserving.new; start for ^3 { $p.emit($_); LAST { say „done after { now - BEGIN now}s“; $p.done; } } sleep 2; react { whenever $p.Supply { $_.say; } whenever Promise.in(2) { done } } say „also done after { now - BEGIN now }s“
Will output:
done after 0.0638467s 0 1 2 also done after 4.0534119s
method new()
The Supplier constructor.
Asynchronous data stream with multiple subscribers
class Supply {}
A supply is a thread-safe, asynchronous data stream like a Channel, but it can have multiple subscribers (taps) that all get the same values flowing through the supply.
It is a thread-safe implementation of the Observer Pattern, and central to supporting reactive programming in Perl 6.
There are two types of Supplies: live and on demand. When tapping into a live supply, the tap will only see values that are flowing through the supply after the tap has been created. Such supplies are normally infinite in nature, such as mouse movements. Closing such a tap does not stop mouse events from occurring, it just means that the values will go by unseen. All tappers see the same flow of values.
A tap on an on demand supply will initiate the production of values, and tapping the supply again may result in a new set of values. For example, Supply.interval produces a fresh timer with the appropriate interval each time it is tapped. If the tap is closed, the timer simply stops emitting values to that tap.
A live Supply is obtained from the Supplier factory method Supply. New values are emitted by calling emit on the Supplier object.
my $supplier = Supplier.new; my $supply = $supplier.Supply; $supply.tap(-> $v { say "$v" }); $supplier.emit(42); # Will cause the tap to output "42"
The live method returns True on live supplies. Factory methods such as interval, from-list will return on demand supplies.
A live Supply that keeps values until tapped the first time can be created with Supplier::Preserving.
Further examples can be found in the concurrency page.
method tap(Supply:D: &emit = -> $ { }, :&done, :&quit, :&tap --> Tap:D)
Creates a new tap (a kind of subscription if you will), in addition to all existing taps. The first positional argument is a piece of code that will be called when a new value becomes available through the emit call.
The &done callback can be called in a number of cases: if a supply block is being tapped, when a done routine is reached; if a supply block is being tapped, it will be automatically triggered if the supply block reaches the end; if the done method is called on the parent Supplier (in the case of a supply block, if there are multiple Suppliers referenced by whenever, they must all have their done method invoked for this to trigger the &done callback of the tap as the block will then reach its end).
The &quit callback is called if the tap is on a supply block which exits with an error. It is also called if the quit method is invoked on the parent Supplier (in the case of a supply block any one Supplier quitting with an uncaught exception will call the &quit callback as the block will exit with an error). The error is passed as a parameter to the callback.
The &tap callback is called once the Tap object is created, which is passed as a parameter to the callback. The callback is called ahead of emit/done/quit, providing a reliable way to get the Tap object. One case where this is useful is when the Supply begins emitting values synchronously, since the call to .tap won't return the Tap object until it is done emitting, preventing it from being stopped if needed.
Method tap returns an object of type Tap, on which you can call the close method to cancel the subscription.
my $s = Supply.from-list(0 .. 5); my $t = $s.tap(-> $v { say $v }, done => { say "no more ticks" });
Produces:
0 1 2 3 4 5 no more ticks
method act(Supply:D: &act --> Tap:D)
Creates a tap on the given supply with the given code. Differently from tap, the given code is guaranteed to be only executed by one thread at a time.
Defined as:
method Capture(Supply:D --> Capture:D)
Equivalent to calling .List.Capture on the invocant.
method Channel(Supply:D: --> Channel:D)
Returns a Channel object that will receive all future values from the supply, and will be closed when the Supply is done, and quit (shut down with error) when the supply is quit.
method Promise(Supply:D: --> Promise:D)
Returns a Promise that will be kept when the Supply is done. If the Supply also emits any values, then the Promise will be kept with the final value. Otherwise, it will be kept with Nil. If the Supply ends with a quit instead of a done, then the Promise will be broken with that exception.
my $supplier = Supplier.new; my $s = $supplier.Supply; my $p = $s.Promise; $p.then(-> $v { say "got $v.result()" }); $supplier.emit('cha'); # not output yet $supplier.done(); # got cha
The Promise method is most useful when dealing with supplies that will tend to produce just one value, when only the final value is of interest, or when only completion (successful or not) is relevant.
method live(Supply:D: --> Bool:D)
Returns True if the supply is "live", that is, values are emitted to taps as soon as they arrive. Always returns True in the default Supply (but for example on the supply returned from Supply.from-list it's False).
say Supplier.new.Supply.live; # OUTPUT: «True»
method schedule-on(Supply:D: Scheduler $scheduler)
Runs the emit, done and quit callbacks on the specified scheduler.
This is useful for GUI toolkits that require certain actions to be run from the GUI thread.
method wait(Supply:D:)
Taps the Supply it is called on, and blocks execution until the either the supply is done (in which case it evaluates to the final value that was emitted on the Supply, or Nil if not value was emitted) or quit (in which case it will throw the exception that was passed to quit).
my $s = Supplier.new; start { sleep 1; say "One second: running."; sleep 1; $s.emit(42); $s.done; } $s.Supply.wait; say "Two seconds: done";
method list(Supply:D: --> List:D)
Taps the Supply it is called on, and returns a lazy list that will be reified as the Supply emits values. The list will be terminated once the Supply is done. If the Supply quits, then an exception will be thrown once that point in the lazy list is reached.
method grab(Supply:D: &when-done --> Supply:D)
Taps the Supply it is called on. When it is done, calls &when-done and then emits the list of values that it returns on the result Supply. If the original Supply quits, then the exception is immediately conveyed on the return Supply.
my $s = Supply.from-list(4, 10, 3, 2); my $t = $s.grab(&sum); $t.tap(&say); # OUTPUT: «19»
method reverse(Supply:D: --> Supply:D)
Taps the Supply it is called on. Once that Supply emits done, all of the values it emitted will be emitted on the returned Supply in reverse order. If the original Supply quits, then the exception is immediately conveyed on the return Supply.
my $s = Supply.from-list(1, 2, 3); my $t = $s.reverse; $t.tap(&say); # OUTPUT: «321»
method sort(Supply:D: &custom-routine-to-use? --> Supply:D)
Taps the Supply it is called on. Once that Supply emits done, all of the values that it emitted will be sorted, and the results emitted on the returned Supply in the sorted order. Optionally accepts a comparator Block. If the original Supply quits, then the exception is immediately conveyed on the return Supply.
my $s = Supply.from-list(4, 10, 3, 2); my $t = $s.sort(); $t.tap(&say); # OUTPUT: «23410»
method from-list(Supply:U: +@values --> Supply:D)
Creates an on-demand supply from the values passed to this method.
my $s = Supply.from-list(1, 2, 3); $s.tap(&say); # OUTPUT: «123»
method share(Supply:D: --> Supply:D)
Creates a live supply from an on-demand supply, thus making it possible to share the values of the on-demand supply on multiple taps, instead of each tap seeing its own copy of all values from the on-demand supply.
# this says in turn: "first 1" "first 2" "second 2" "first 3" "second 3" my $s = Supply.interval(1).share; $s.tap: { "first $_".say }; sleep 1.1; $s.tap: { "second $_".say }; sleep 2
method flat(Supply:D: --> Supply:D)
Creates a supply on which all of the values seen in the given supply are flattened before being emitted again.
method do(Supply:D: &do --> Supply:D)
Creates a supply to which all values seen in the given supply, are emitted again. The given code, executed for its side-effects only, is guaranteed to be only executed by one thread at a time.
method on-close(Supply:D: &on-close --> Supply:D)
Returns a new Supply which will run &on-close whenever a Tap of that Supply is closed. This includes if further operations are chained on to the Supply. (for example, $supply.on-close(&on-close).map(*.uc)). When using a react or supply block, using the CLOSE phaser is usually a better choice.
my $s = Supplier.new; my $tap = $s.Supply.on-close({ say "Tap closed" }).tap( -> $v { say "the value is $v" }, done => { say "Supply is done" }, quit => -> $ex { say "Supply finished with error $ex" }, ); $s.emit('Perl 6'); $tap.close; # OUTPUT: «Tap closed»
method interval(Supply:U: $interval, $delay = 0, :$scheduler = $*SCHEDULER --> Supply:D)
Creates a supply that emits a value every $interval seconds, starting $delay seconds from the call. The emitted value is an integer, starting from 0, and is incremented by one for each value emitted.
Implementations may treat too-small values as lowest resolution they support, possibly warning in such situations; e.g. treating 0.0001 as 0.001. For 6.d language version, the minimal value specified is 0.001.
method grep(Supply:D: Mu $test --> Supply:D)
Creates a new supply that only emits those values from the original supply that smartmatch against $test.
my $supplier = Supplier.new; my $all = $supplier.Supply; my $ints = $all.grep(Int); $ints.tap(&say); $supplier.emit($_) for 1, 'a string', 3.14159; # prints only 1
method map(Supply:D: &mapper --> Supply:D)
Returns a new supply that maps each value of the given supply through &mapper and emits it to the new supply.
my $supplier = Supplier.new; my $all = $supplier.Supply; my $double = $all.map(-> $value { $value * 2 }); $double.tap(&say); $supplier.emit(4); # RESULT: «8»
method batch(Supply:D: :$elems, :$seconds --> Supply:D)
Creates a new supply that batches the values of the given supply by either the number of elements in the batch (using :elems) or the maximum number of seconds (using the :seconds) or both. Any remaining values are emitted in a final batch when the supply is done.
method elems(Supply:D: $seconds? --> Supply:D)
Creates a new supply in which changes to the number of values seen are emitted. It optionally also takes an interval (in seconds) if you only want to be updated every so many seconds.
method head(Supply:D: Int(Cool) $number = 1 --> Supply:D)
Creates a "head" supply with the same semantics as List.head.
my $s = Supply.from-list(4, 10, 3, 2); my $hs = $s.head(2); $hs.tap(&say); # OUTPUT: «410»
method tail(Supply:D: Int(Cool) $number = 1 --> Supply:D)
Creates a "tail" supply with the same semantics as List.tail.
my $s = Supply.from-list(4, 10, 3, 2); my $ts = $s.tail(2); $ts.tap(&say); # OUTPUT: «32»
method rotor(Supply:D: @cycle --> Supply:D)
Creates a "rotoring" supply with the same semantics as List.rotor.
method delayed(Supply:D: $seconds, :$scheduler = $*SCHEDULER --> Supply:D)
Creates a new supply in which all values flowing through the given supply are emitted, but with the given delay in seconds.
method throttle(Supply:D: $limit, # values / time or simultaneous processing $seconds or $callable, # time-unit / code to process simultaneously $delay = 0, # initial delay before starting, in seconds :$control, # supply to emit control messages on (optional) :$status, # supply to tap status messages from (optional) :$bleed, # supply to bleed messages to (optional) :$vent-at, # bleed when so many buffered (optional) :$scheduler, # scheduler to use, default $*SCHEDULER --> Supply:D)
Produces a Supply from a given Supply, but makes sure the number of messages passed through, is limited.
It has two modes of operation: per time-unit or by maximum number of execution of a block of code: this is determined by the second positional parameter.
The first positional parameter specifies the limit that should be applied.
If the second positional parameter is a Callable, then the limit indicates the maximum number of parallel processes executing the Callable, which is given the value that was received. The emitted values in this case will be the Promises that were obtained from starting the Callable.
If the second positional parameter is a numeric value, it is interpreted as the time-unit (in seconds). If you specify .1 as the value, then it makes sure you don't exceed the limit for every tenth of a second.
If the limit is exceeded, then incoming messages are buffered until there is room to pass on / execute the Callable again.
The third positional parameter is optional: it indicates the number of seconds the throttle will wait before passing on any values.
The :control named parameter optionally specifies a Supply that you can use to control the throttle while it is in operation. Messages that can be sent, are strings in the form of "key:value". Please see below for the types of messages that you can send to control the throttle.
The :status named parameter optionally specifies a Supply that will receive any status messages. If specified, it will at least send one status message after the original Supply is exhausted. See status message below.
The :bleed named parameter optionally specifies a Supply that will receive any values that were either explicitly bled (with the bleed control message), or automatically bled (if there's a vent-at active).
The :vent-at named parameter indicates the number of values that may be buffered before any additional value will be routed to the :bleed Supply. Defaults to 0 if not specified (causing no automatic bleeding to happen). Only makes sense if a :bleed Supply has also been specified.
The :scheduler named parameter indicates the scheduler to be used. Defaults to $*SCHEDULER.
These messages can be sent to the :control Supply. A control message consists of a string of the form "key: value", e.g. "limit: 4".
limit
Change the number of messages (as initially given in the first positional) to the value given.
bleed
Route the given number of buffered messages to the :bleed Supply.
vent-at
Change the maximum number of buffered values before automatic bleeding takes place. If the value is lower than before, will cause immediate rerouting of buffered values to match the new maximum.
status
Send a status message to the :status Supply with the given id.
The status return message is a hash with the following keys:
allowed
The current number of messages / callables that is still allowed to be passed / executed.
bled
The number of messages routed to the :bleed Supply.
buffered
The number of messages currently buffered because of overflow.
emitted
The number of messages emitted (passed through).
id
The id of this status message (a monotonically increasing number). Handy if you want to log status messages.
limit
The current limit that is being applied.
vent-at
The maximum number of messages that may be buffered before they're automatically re-routed to the :bleed Supply.
Have a simple piece of code announce when it starts running asynchronously, wait a random amount of time, then announce when it is done. Do this 6 times, but don't let more than 3 of them run simultaneously.
my $s = Supply.from-list(^6); # set up supply my $t = $s.throttle: 3, # only allow 3 at a time { # code block to run say "running $_"; # announce we've started sleep rand; # wait some random time say "done $_" # announce we're done } # don't need ; because } at end of line $t.wait; # wait for the supply to be done
and the result of one run will be:
running 0 running 1 running 2 done 2 running 3 done 1 running 4 done 4 running 5 done 0 done 3 done 5
method stable(Supply:D: $time, :$scheduler = $*SCHEDULER --> Supply:D)
Creates a new supply that only passes on a value flowing through the given supply if it wasn't superseded by another value in the given $time (in seconds). Optionally uses another scheduler than the default scheduler, using the :scheduler parameter.
To clarify the above, if, during the timeout $time, additional values are emitted to the Supplier all but the last one will be thrown away. Each time an additional value is emitted to the Supplier, during the timeout, $time is reset.
This method can be quite useful when handling UI input, where it is not desired to perform an operation until the user has stopped typing for a while rather than on every keystroke.
my $supplier = Supplier.new; my $supply1 = $supplier.Supply; $supply1.tap(-> $v { say "Supply1 got: $v" }); $supplier.emit(42); my Supply $supply2 = $supply1.stable(5); $supply2.tap(-> $v { say "Supply2 got: $v" }); sleep(3); $supplier.emit(43); # will not be seen by $supply2 but will reset $time $supplier.emit(44); sleep(10); # OUTPUT: «Supply1 got: 42Supply1 got: 43Supply1 got: 44Supply2 got: 44»
As can be seen above, $supply1 received all values emitted to the Supplier while $supply2 only received one value. The 43 was thrown away because it was followed by another 'last' value 44 which was retained and sent to $supply2 after approximately eight seconds, this due to the fact that the timeout $time was reset after three seconds.
method reduce(Supply:D: &with --> Supply:D)
Creates a "reducing" supply with the same semantics as List.reduce.
my $supply = Supply.from-list(1..5).reduce({$^a + $^b}); $supply.tap(-> $v { say "$v" }); # OUTPUT: «15»
method produce(Supply:D: &with --> Supply:D)
Creates a "producing" supply with the same semantics as List.produce.
my $supply = Supply.from-list(1..5).produce({$^a + $^b}); $supply.tap(-> $v { say "$v" }); # OUTPUT: «1361015»
method lines(Supply:D: :$chomp = True --> Supply:D)
Creates a supply that will emit the characters coming in line by line from a supply that's usually created by some asynchronous I/O operation. The optional :chomp parameter indicates whether to remove line separators: the default is True.
method words(Supply:D: --> Supply:D)
Creates a supply that will emit the characters coming in word for word from a supply that's usually created by some asynchronous I/O operation.
my $s = Supply.from-list("Hello Word!".comb); my $ws = $s.words; $ws.tap(&say); # OUTPUT: «HelloWord!»
method unique(Supply:D: :$as, :$with, :$expires --> Supply:D)
Creates a supply that only provides unique values, as defined by the optional :as and :with parameters (same as with List.unique). The optional :expires parameter how long to wait (in seconds) before "resetting" and not considering a value to have been seen, even if it's the same as an old value.
method squish(Supply:D: :$as, :$with --> Supply:D)
Creates a supply that only provides unique values, as defined by the optional :as and :with parameters (same as with List.squish).
method max(Supply:D: &custom-routine-to-use = &infix:<cmp> --> Supply:D)
Creates a supply that only emits values from the given supply if they are larger than any value seen before. In other words, from a continuously ascending supply it will emit all the values. From a continuously descending supply it will only emit the first value. The optional parameter specifies the comparator, just as with Any.max.
method min(Supply:D: &custom-routine-to-use = &infix:<cmp> --> Supply:D)
Creates a supply that only emits values from the given supply if they are smaller than any value seen before. In other words, from a continuously descending supply it will emit all the values. From a continuously ascending supply it will only emit the first value. The optional parameter specifies the comparator, just as with Any.min.
method minmax(Supply:D: &custom-routine-to-use = &infix:<cmp> --> Supply:D)
Creates a supply that emits a Range every time a new minimum or maximum values is seen from the given supply. The optional parameter specifies the comparator, just as with Any.minmax.
method skip(Supply:D: Int(Cool) $number = 1 --> Supply:D)
Returns a new Supply which will emit all values from the given Supply except for the first $number values, which will be thrown away.
my $supplier = Supplier.new; my $supply = $supplier.Supply; $supply = $supply.skip(3); $supply.tap({ say $_ }); $supplier.emit($_) for 1..10; # OUTPUT: «45678910»
method start(Supply:D: &startee --> Supply:D)
Creates a supply of supplies. For each value in the original supply, the code object is scheduled on another thread, and returns a supply either of a single value (if the code succeeds), or one that quits without a value (if the code fails).
This is useful for asynchronously starting work that you don't block on.
Use migrate to join the values into a single supply again.
method migrate(Supply:D: --> Supply:D)
Takes a Supply which itself has values that are of type Supply as input. Each time the outer Supply emits a new Supply, this will be tapped and its values emitted. Any previously tapped Supply will be closed. This is useful for migrating between different data sources, and only paying attention to the latest one.
For example, imagine an application where the user can switch between different stocks. When they switch to a new one, a connection is established to a web socket to get the latest values, and any previous connection should be closed. Each stream of values coming over the web socket would be represented as a Supply, which themselves are emitted into a Supply of latest data sources to watch. The migrate method could be used to flatten this supply of supplies into a single Supply of the current values that the user cares about.
Here is a simple simulation of such a program:
my Supplier $stock-sources .= new; sub watch-stock($symbol) { $stock-sources.emit: supply { say "Starting to watch $symbol"; whenever Supply.interval(1) { emit "$symbol: 111." ~ 99.rand.Int; } CLOSE say "Lost interest in $symbol"; } } $stock-sources.Supply.migrate.tap: *.say; watch-stock('GOOG'); sleep 3; watch-stock('AAPL'); sleep 3;
Which produces output like:
Starting to watch GOOG GOOG: 111.67 GOOG: 111.20 GOOG: 111.37 Lost interest in GOOG Starting to watch AAPL AAPL: 111.55 AAPL: 111.6 AAPL: 111.6
method merge(Supply @*supplies --> Supply:D)
Creates a supply to which any value seen from the given supplies, is emitted. The resulting supply is done Only when all given supplies are done. Can also be called as a class method.
method zip(Supply @*supplies, :&with = &[,] --> Supply:D)
Creates a supply that emits combined values as soon as there is a new value seen on all of the supplies. By default, Lists are created, but this can be changed by specifying your own combiner with the :with parameter. The resulting supply is done as soon as any of the given supplies are done. Can also be called as a class method.
method zip-latest(Supply @*supplies, :&with = &[,], :$initial --> Supply:D)
Creates a supply that emits combined values as soon as there is a new value seen on any of the supplies. By default, Lists are created, but this can be changed by specifying your own combiner with the :with parameter. The optional :initial parameter can be used to indicate the initial state of the combined values. By default, all supplies have to have at least one value emitted on them before the first combined values is emitted on the resulting supply. The resulting supply is done as soon as any of the given supplies are done. Can also be called as a class method.
sub signal(*@signals, :$scheduler = $*SCHEDULER)
Creates a supply for the Signal enums (such as SIGINT) specified, and an optional :scheduler parameter. Any signals received, will be emitted on the supply. For example:
signal(SIGINT).tap( { say "Thank you for your attention"; exit 0 } );
would catch Control-C, thank you, and then exit.
To go from a signal number to a Signal, you can do something like this:
signal(Signal(2)).tap( -> $sig { say "Received signal: $sig" } );
The list of supported signals can be found by checking Signal::.keys (as you would any enum). For more details on how enums work see enum.
Note: Rakudo versions up to 2018.05 had a bug due to which numeric values of signals were incorrect on some systems. For example, Signal(10) was returning SIGBUS even if it was actually SIGUSR1 on a particular system. That being said, using signal(SIGUSR1) was working as expected on all Rakudo versions except 2018.04, 2018.04.1 and 2018.05, where the intended behavior can be achieved by using signal(SIGBUS) instead. These issues are resolved in Rakudo releases after 2018.05.
method watch-path($path --> Supply:D)
Creates a supply to which the OS will emit values to indicate changes on the filesystem for the given path. Also has a shortcut with the watch method on an IO object, like this:
IO::Notification.watch-path(".").act( { say "$^file changed" } ); ".".IO.watch.act( { say "$^file changed" } ); # same
Information related to the build system
Built-in class for providing built system related information. Usually accessed through dynamic variables mixing this role such as the $*KERNEL, $*VM, or $*PERL.
Instance method returning the "auth" (as in "author" or "authority") of the object. Returns "unknown" if the "auth" could not be established.
Instance returning a hash with object configuration information. Subject to change without notice, but can be helpful in environments where only one type of virtual machine is in use, or to find about the configuration of any other object that mixes in this role.
Instance method returning the "desc" (as in "description") of the VM object. Returns a Str type object if the "desc" could not be established.
Instance method returning the name of the object.
Instance method returning the signature of the object. Returns a Blob type object if the signature could not be established.
Instance method returning the version of the object as a Version object. Returns a Version object "unknown" if the version could not be established.
method gist( Systemic:D: )
Instance method returning the name and version of the object.
say $*PERL.gist; # OUTPUT: «Perl 6 (6.c)»
$*PERL is an object of the Perl type, which mixes in this role and thus implements this method.
method Str
Instance method returning the name of the object.
say $*PERL.Str; # OUTPUT: «Perl 6»
Subscription to a Supply
class Tap {}
A Tap is a subscription to a Supply.
my $s = Supplier.new; my $tap = $s.Supply.on-close({ say "Tap closed" }).tap( -> $v { say "the value is $v" }, done => { say "Supply is done" }, quit => -> $ex { say "Supply finished with error $ex" }, ); # later $tap.close;
method close(Tap:D:)
Closes the tap.
Collect performance state for analysis
class Telemetry { }
Note: This class is a Rakudo-specific feature and not standard Perl 6.
On creation, a Telemetry object contains a snapshot of various aspects of the current state of the virtual machine. This is in itself useful, but generally one needs two snapshots for the difference (which is a Telemetry::Period object).
The Telemetry object is really a collection of snapshots taken by different "instruments". By default, the Telemetry::Instrument::Usage and Telemetry::Instrument::ThreadPool instruments are activated.
The Telemetry (and Telemetry::Period) object also Associative. This means that you can treat a Telemetry object as a read-only Hash, with all of the data values of the instruments as keys.
You can determine which instruments Telemetry should use by setting the $*SAMPLER dynamic variable, which is a Telemetry::Sampler object.
Currently, the following instruments are supported by the Rakudo core:
Telemetry::Instrument::Usage
Provides (in alphabetical order): cpu, cpu-sys, cpu-user, cpus, id-rss, inb, invcsw, is-rss, ix-rss, majf, max-rss, minf, mrcv, msnd, nsig, nswp, volcsw, outb, util% and wallclock. For complete documentation of the meaning of these data values, see Telemetry::Instrument::Usage.
Telemetry::Instrument::Thread
Provides (in alphabetical order): tad, tcd, thid, tjd, tsd and tys. For complete documentation of the meaning of these data values, see Telemetry::Instrument::Thread.
Telemetry::Instrument::ThreadPool
Provides (in alphabetical order): atc, atq, aw, gtc, gtq, gw, s, ttc, ttq and tw. For complete documentation of the meaning of these data values, see Telemetry::Instrument::ThreadPool.
Telemetry::Instrument::AdHoc
Does not provide any data by itself: one must indicate which variables are to be monitored, which will then become available as methods with the same name on the instrument. For complete documentation, see Telemetry::Instrument::AdHoc.
sub T()
Shortcut for Telemetry.new. It is exported by default. Since the Telemetry class also provides an Associative interface, one can easily interpolate multiple values in a single statement:
use Telemetry; say "Used {T<max-rss cpu>} (KiB CPU) so far";
multi sub snap(--> Nil) multi sub snap(@s --> Nil)
The snap subroutine is shorthand for creating a new Telemetry object and pushing it to an array for later processing. It is exported by default.
use Telemetry; my @t; for ^5 { snap(@t); # do some stuff LAST snap(@t); }
If no array is specified, it will use an internal array for convenience.
sub snapper($sleep = 0.1, :$stop, :$reset --> Nil)
The snapper routine starts a separate thread that will call snap repeatedly until the end of program. It is exported by default.
By default, it will call snap every 0.1 second. The only positional parameter is taken to be the delay between snaps.
Please see the snapper module for externally starting a snapper without having to change the code. Simply adding -Msnapper as a command line parameter, will then start a snapper for you.
multi sub periods( --> Seq) multi sub periods(@s --> Seq)
The periods subroutine processes an array of Telemetry objects and generates a Seq of Telemetry::Period objects out of that. It is exported by default.
.<cpu wallclock>.say for periods(@t); # OUTPUT: # ==================== # (164 / 160) # (23 / 21) # (17 / 17) # (15 / 16) # (29 / 28)
If no array is specified, it will use the internal array of snap without parameters and will reset that array upon completion (so that new snaps can be added again).
use Telemetry; for ^5 { snap; LAST snap; } say .<cpu wallclock>.join(" / ") for periods; # OUTPUT: # ==================== # 172 / 168 # 24 / 21 # 17 / 18 # 17 / 16 # 27 / 27
If only one snap was done, another snap will be done to create at least one Telemetry::Period object.
multi sub report(:@columns, :$legend, :$header-repeat, :$csv, :@format)
The report subroutine generates a report about an array of Telemetry objects. It is exported by default. These can have been created by regularly calling snap, or by having a snapper running. If no positional parameter is used, it will assume the internal array to which the parameterless snap pushes.
Below are the additional named parameters of report.
:columns
Specify the names of the columns to be included in the report. Names can be specified with the column name (e.g. gw). If not specified, defaults to what is specified in the RAKUDO_REPORT_COLUMNS environment variable. If that is not set either, defaults to:
wallclock util% max-rss gw gtc tw ttc aw atc
:header-repeat
Specifies after how many lines the header should be repeated in the report. If not specified, defaults to what is specified in the RAKUDO_REPORT_HEADER_REPEAT environment variable. If that is not set either, defaults to 32.
:legend
Specifies whether a legend should be added to the report. If not specified, defaults to what is specified in the RAKUDO_REPORT_LEGEND environment variable. If that is not set either, defaults to True.
If there are snaps available in the internal array at the end of the program, then report will be automatically generated and printed on STDERR.
Start a thread taking repeated system state snapshots.
This module contains no subroutines or methods or anything. It is intended as a shortcut for starting the snapper subroutine of the Telemetry module, allowing taking snapshots of the execution of a program without needing to change the program. Simple loading the module with -Msnapper will do all that is needed to start the snapper, and have a report printed on STDERR upon completion of the program.
The RAKUDO_SNAPPER environment variable can be set to indicate the time between snapshots. If not specified, it will default to 0.1 seconds.
Instrument for collecting Thread data
class Telemetry::Instrument::Thread { }
Note: This class is a Rakudo-specific feature and not standard Perl 6.
Objects of this class are generally not created by themselves, but rather through making a snapshot.
This class provides the following data points (in alphabetical order):
tad
The number of threads that ended with an exception (threads-aborted).
tcd
The number of threads that completed without any problem (threads-completed).
thid
Highest OS thread ID seen (thread-highest-id).
tjd
The number of threads that were joined (threads-joined).
tsd
The number of threads that were started (threads-started).
tyd
The number of times a thread was yielded (threads-yielded).
Instrument for collecting ThreadPoolScheduler data
class Telemetry::Instrument::ThreadPool { }
Note: This class is a Rakudo-specific feature and not standard Perl 6.
Objects of this class are generally not created by themselves, but rather through making a snapshot.
This class provides the following data points (in alphabetical order):
atc
The number of tasks completed by affinity thread workers (affinity-tasks-completed).
atq
The number of tasks queued for execution for affinity thread workers (affinity-tasks-queued).
aw
The number of affinity thread workers (affinity-workers).
gtc
The number of tasks completed by general workers (general-tasks-completed).
gtq
The number of tasks queued for execution by general worker (general-tasks-queued).
gw
The number of general workers (general-workers).
s
The number of supervisor threads running, usually 0 or 1 (supervisor>).
ttc
The number of tasks completed by timer workers (timer-tasks-completed).
ttq
The number of tasks queued for execution by timer workers (timer-tasks-queued).
tw
The number of timer workers (timer-workers).
Instrument for collecting getrusage data
class Telemetry::Instrument::Usage { }
Note: This class is a Rakudo-specific feature and not standard Perl 6.
Objects of this class are generally not created by themselves, but rather through making a snapshot.
This class provides the following generally usable readings (in alphabetical order):
cpu
The total amount of CPU time (in microseconds), essentially the sum of cpu-user and cpu-sys.
cpu-sys
The number of microseconds of CPU used by the system.
cpu-user
The number of microseconds of CPU used by the user program.
cpus
The number of CPU's active, essentially cpu divided by wallclock.
max-rss
The maximum resident set size (in KiB).
util%
Percentage of CPU utilization, essentially 100 * cpus / number of CPU cores.
wallclock
The time the program has been executing (in microseconds).
Less useful readings
The following readings may or may not contain sensible information, mostly depending on hardware and OS being used. Please check your local getrusage documentation for their exact meaning:
name getrusage struct name ==== ===================== max-rss ru_maxrss ix-rss ru_ixress id-rss ru_idrss is-rss ru_isrss minf ru_minflt majf ru_majflt nswp ru_nswap inb ru_inblock outb ru_oublock msnd ru_msgsnd mrcv ru_msgrcv nsig ru_nsignals volcsw ru_nvcsw invcsw ru_nivcsw
Performance data over a period
class Telemetry::Period is Telemetry { }
Note: This class is a Rakudo-specific feature and not standard Perl 6.
# basic usage use Telemetry; my $t0 = Telemetry.new; # execute some code my $t1 = Telemetry.new; my $period = $t1 - $t0; # creates Telemetry::Period object say "Code took $period<wallclock> microseconds to execute";
A Telemetry::Period object contains the difference between two Telemetry objects. It is generally not created by calling .new, but it can be if needed. For all practical purposes, it is the same as the Telemetry object, but the meaning of the values is different (and the values are generally much smaller, as they usually are the difference of two big values of the Telemetry objects from which it was created).
Telemetry instrument pod
class Telemetry::Sampler { }
Note: This class is a Rakudo-specific feature and not standard Perl 6.
use Telemetry; $*SAMPLER.set-instruments(<Usage ThreadPool>); # default setting
One usually does not create any Telemetry::Sampler objects: when the Telemetry module is loaded, a Telemetry::Sampler object is automatically created in the $*SAMPLER dynamic variable.
An object of the Telemetry::Sampler class knows about which instruments to use when making a snapshot.
method new(Telemetry::Sampler: @instruments --> Telemetry::Sampler:D)
The new method takes a list of instruments. If no instruments are specified, then it will look at the RAKUDO_TELEMETRY_INSTRUMENTS environment variable to find specification of instruments. If that is not available either, then Telemetry::Instrument::Usage and Telemetry::Instrument::ThreadPool will be assumed.
Instruments can be specified by either the type object of the instrument class (e.g. Telemetry::Instrument::Usage) or by a string, in which case it will be automatically prefixed with "Telemetry::Instrument::", so "Usage" would be the same as Telemetry::Instrument::Usage.
method set-instruments(Telemetry::Sampler:D @instruments --> Nil)
Allows one to change the instruments on an existing Instrument::Sampler object. Generally only used by calling it on the $*SAMPLER dynamic variable. Takes the same parameters as new, except that specifying no instruments will actually remove all of the instruments, effectively blocking any snap taking.
Writing and running tests
This module provides a testing framework, and is used in the official suite that tests the specification. All its functions emit output conforming to the Test Anything Protocol.
Defined as:
multi sub plan(Cool:D :skip-all($reason)!) multi sub plan($number_of_tests)
Specify the count of tests -- usually written at the beginning of a test file.
plan 15; # expect to run 15 tests
In subtests, plan is used to specify the count of tests within the subtest.
If a plan is used, it's not necessary to specify the end of testing with done-testing.
You can also provide a :skip-all named argument instead of a test count, to indicate that you want to skip all of the tests. Such a plan will call exit, unless used inside of a subtest.
plan :skip-all<These tests are only for Windows> unless $*DISTRO.is-win; plan 1; ok dir 'C:/'; # this won't get run on non-Windows
If used in a subtest, it will instead return from that subtest's Callable. For that reason, to be able to use :skip-all inside a subtest, you must use a sub instead of a regular block:
plan 2; subtest "Some Windows tests" => sub { # <-- note the `sub`; can't use bare block plan :skip-all<We aren't on Windows> unless $*DISTRO.is-win; plan 1; ok dir 'C:/'; # this won't get run on non-Windows } ok 42; # this will run everywhere and isn't affected by skip-all inside subtest
Note that plan with :skip-all is to avoid performing any tests without marking the test run as failed (i.e. the plan is to not run anything and that's all good). Use skip-rest to skip all further tests, once the run has started (i.e. planned to run some tests, maybe even ran some, but now we're skipping all the rest of them). Use bail-out to fail the test run without running any further tests (i.e. things are so bad, there's no point in running anything else; we've failed).
Defined as:
sub done-testing()
Specify that testing has finished. Use this function when you don't have a plan with the number of tests to run. A plan is not required when using done-testing.
It's recommended that the done-testing function be removed and replaced with a plan function when all tests are finalized. Use of plan can help detect test failures otherwise not reported because tests were accidentally skipped due to bugs in the tests or bugs in the compiler. For example:
sub do-stuff {@}; use Test; ok .is-prime for do-stuff; done-testing; # output: 1..0
The above example is where a done-testing fails. do-stuff() returned nothing and tested nothing, even though it should've returned results to test. But the test suite doesn't know how many tests were meant to be run, so it passes.
Adding plan gives a true picture of the test:
sub do-stuff {@}; use Test; plan 1; ok .is-prime for do-stuff; # output: 1..1 # Looks like you planned 1 test, but ran 0
Note that leaving the done-testing in place will have no effect on the new test results, but it should be removed for clarity.
Defined as:
multi sub ok(Mu $cond, $desc = '')
The ok function marks a test as passed if the given $value evaluates to True. The nok function marks a test as passed if the given value evaluates to False. Both functions accept an optional description of the test as second parameter.
my $response; my $query; ...; ok $response.success, 'HTTP response was successful'; nok $query.error, 'Query completed without error';
In principle, you could use ok for every kind of comparison test, by including the comparison in the expression passed to $value:
sub factorial($x) { ... }; ok factorial(6) == 720, 'Factorial - small integer';
However, where possible it's better to use one of the specialized comparison test functions below, because they can print more helpful diagnostics output in case the comparison fails.
Defined as:
multi sub nok(Mu $cond, $desc = '')
The nok function marks a test as passed if the given value evaluates to False. It also accepts an optional description of the test as second argument.
my $response; my $query; ...; ok $response.success, 'HTTP response was successful'; nok $query.error, 'Query completed without error';
Defined as
multi sub is(Mu $got, Mu:U $expected, $desc = '') multi sub is(Mu $got, Mu:D $expected, $desc = '')
Marks a test as passed if $value and $expected compare positively with the eq operator, unless $expected is a type object, in which case === operator will be used instead; accepts an optional description of the test as the last argument.
NOTE: eq operator the is() uses stringifies, which means is() is not a good function for testing more complex things, such as lists: is (1, (2, (3,))), [1, 2, 3] passes the test, even though the operands are vastly different. For those cases, use is-deeply routine
my $pdf-document; sub factorial($x) { ... }; ...; is $pdf-document.author, "Joe", 'Retrieving the author field'; is factorial(6), 720, 'Factorial - small integer'; my Int $a; is $a, Int, 'The variable $a is an unassigned Int';
Note: if only whitespace differs between the values, is() will output failure message differently, to show the whitespace in each values. For example, in the output below, the second test shows the literal \t in the got: line:
is "foo\tbar", "foo\tbaz"; # expected: 'foo baz'# got: 'foo bar' is "foo\tbar", "foo bar"; # expected: "foo bar"# got: "foo\tbar"
Defined as:
multi sub isnt(Mu $got, Mu:U $expected, $desc = '') multi sub isnt(Mu $got, Mu:D $expected, $desc = '')
Marks a test as passed if $value and $expected are not equal using the same rules as is(). The function accepts an optional description of the test.
isnt pi, 3, 'The constant π is not equal to 3'; my Int $a = 23; $a = Nil; isnt $a, Nil, 'Nil should not survive being put in a container';
Defined as:
multi sub is_approx(Mu $got, Mu $expected, $desc = '')
NOTE: Deprecated as of version 6.d. Please use is-approx instead.
Checks if result and the expected value are approximately equal to a certain degree of tolerance, fixed to 1e-5 or one-millionth of the expected value is its value is less than that.
use Test; is_approx(1e4, 1e4-1e-6, "Real close"); # OUTPUT: «ok 1 - Real close»
(This will print also a deprecation notice if you're using 6.d)
Defined as:
multi sub is-approx(Numeric $got, Numeric $expected, $desc = '')
multi sub is-approx(Numeric $got, Numeric $expected, Numeric $abs-tol, $desc = '')
multi sub is-approx(Numeric $got, Numeric $expected, $desc = '', Numeric :$rel-tol is required)
multi sub is-approx(Numeric $got, Numeric $expected, $desc = '', Numeric :$abs-tol is required)
multi sub is-approx(Numeric $got, Numeric $expected, $desc = '', Numeric :$rel-tol is required, Numeric :$abs-tol is required)
Marks a test as passed if the $value and $expected numerical values are approximately equal to each other. The subroutine can be called in numerous ways that let you test using relative tolerance ($rel-tol) or absolute tolerance ($abs-tol) of different values.
If no tolerance is set, the function will base the tolerance on the absolute value of $expected: if it's smaller than 1e-6, use absolute tolerance of 1e-5; if it's larger, use relative tolerance of 1e-6.
my Numeric ($value, $expected, $abs-tol, $rel-tol) = ... is-approx $value, $expected; is-approx $value, $expected, 'test description'; is-approx $value, $expected, $abs-tol; is-approx $value, $expected, $abs-tol, 'test description'; is-approx $value, $expected, :$rel-tol; is-approx $value, $expected, :$rel-tol, 'test description'; is-approx $value, $expected, :$abs-tol; is-approx $value, $expected, :$abs-tol, 'test description'; is-approx $value, $expected, :$abs-tol, :$rel-tol; is-approx $value, $expected, :$abs-tol, :$rel-tol, 'test description';
When an absolute tolerance is set, it's used as the actual maximum value by which the $value and $expected can differ. For example:
is-approx 3, 4, 2; # success is-approx 3, 6, 2; # fail is-approx 300, 302, 2; # success is-approx 300, 400, 2; # fail is-approx 300, 600, 2; # fail
Regardless of values given, the difference between them cannot be more than 2.
When a relative tolerance is set, the test checks the relative difference between values. Given the same tolerance, the larger the numbers given, the larger the value they can differ by can be.
For example:
is-approx 10, 10.5, :rel-tol<0.1>; # success is-approx 10, 11.5, :rel-tol<0.1>; # fail is-approx 100, 105, :rel-tol<0.1>; # success is-approx 100, 115, :rel-tol<0.1>; # fail
Both versions use 0.1 for relative tolerance, yet the first can differ by about 1 while the second can differ by about 10. The function used to calculate the difference is:
|value - expected| rel-diff = ──────────────────────── max(|value|, |expected|)
and the test will fail if rel-diff is higher than $rel-tol.
is-approx $value, $expected, :rel-tol<.5>, :abs-tol<10>;
When both absolute and relative tolerances are specified, each will be tested independently, and the is-approx test will succeed only if both pass.
Defined as:
sub is-approx-calculate ($got,$expected,$abs-tol where { !.defined or $_ >= 0 },$rel-tol where { !.defined or $_ >= 0 },$desc)
This is the actual routine called by is-approx when absolute and relative tolerance are specified. They are tested independently, and the test succeeds only if both pass.
Defined as:
multi sub is-deeply(Seq:D $got, Seq:D $expected, $reason = '') multi sub is-deeply(Seq:D $got, Mu $expected, $reason = '') multi sub is-deeply(Mu $got, Seq:D $expected, $reason = '') multi sub is-deeply(Mu $got, Mu $expected, $reason = '')
Marks a test as passed if $value and $expected are equivalent, using the same semantics as the eqv operator. This is the best way to check for equality of (deep) data structures. The function accepts an optional description of the test as the last argument.
use Test; plan 1; sub string-info(Str() $_) { Map.new: ( length => .chars, char-counts => Bag.new-from-pairs: ( letters => +.comb(/<:letter>/), digits => +.comb(/<:digit>/), other => +.comb(/<.-:letter-:digit>/), )) } is-deeply string-info('42 Butterflies ♥ Perl'), Map.new(( :21length, char-counts => Bag.new-from-pairs: ( :15letters, :2digits, :4other, ) )), 'string-info gives right info';
Note: for historical reasons, Seq:D arguments to is-deeply get converted to Lists. If you want to ensure strict Seq comparisons, use cmp-ok $got, 'eqv', $expected, $desc instead.
multi sub cmp-ok(Mu $got is raw, $op, Mu $expected is raw, $desc = '')
Compares $value and $expected with the given $comparison comparator and passes the test if the comparison yields a True value. The description of the test is optional.
The $comparison comparator can be either a Callable or a Str containing an infix operator, such as '==', a '~~', or a user-defined infix.
cmp-ok 'my spelling is apperling', '~~', /perl/, "bad speller";
Metaoperators cannot be given as a string; pass them as a Callable instead:
cmp-ok <a b c>, &[!eqv], <b d e>, 'not equal';
A Callable $comparison lets you use custom comparisons:
sub my-comp { $^a / $^b < rand }; cmp-ok 1, &my-comp, 2, 'the dice giveth and the dice taketh away' cmp-ok 2, -> $a, $b { $a.is-prime and $b.is-prime and $a < $b }, 7, 'we got primes, one larger than the other!';
Defined as:
multi sub isa-ok(Mu $var, Mu $type, $desc = "The object is-a '$type.perl()'")
Marks a test as passed if the given object $value is, or inherits from, the given $expected-type. For convenience, types may also be specified as a string. The function accepts an optional description of the test, which defaults to a string that describes the object.
class Womble {} class GreatUncleBulgaria is Womble {} my $womble = GreatUncleBulgaria.new; isa-ok $womble, Womble, "Great Uncle Bulgaria is a womble"; isa-ok $womble, 'Womble'; # equivalent
Defined as:
multi sub can-ok(Mu $var, Str $meth,$desc = "..." )
Marks a test as passed if the given $variable can run the given $method-name. The function accepts an optional description. For instance:
class Womble {}; my $womble = Womble.new; # with automatically generated test description can-ok $womble, 'collect-rubbish'; # => An object of type 'Womble' can do the method 'collect-rubbish' # with human-generated test description can-ok $womble, 'collect-rubbish', "Wombles can collect rubbish"; # => Wombles can collect rubbish
Defined as:
multi sub does-ok(Mu $var, Mu $type, $desc = "...")
Marks a test as passed if the given $variable can do the given $role. The function accepts an optional description of the test.
# create a Womble who can invent role Invent { method brainstorm { say "Aha!" } } class Womble {} class Tobermory is Womble does Invent {} # ... and later in the tests use Test; my $tobermory = Tobermory.new; # with automatically generated test description does-ok $tobermory, Invent; # => The object does role Type does-ok $tobermory, Invent, "Tobermory can invent"; # => Tobermory can invent
Defined as:
sub like(Str() $got, Regex:D $expected,$desc = "text matches $expected.perl()")
Use it this way:
like 'foo', /fo/, 'foo looks like fo';
Marks a test as passed if the $value, when coerced to a string, matches the $expected-regex. The function accepts an optional description of the test with a default value printing the expected match.
Defined as:
multi sub unlike(Str() $got, Regex:D $expected,$desc = "text does not match $expected.perl()")
Used this way:
unlike 'foo', /bar/, 'foo does not look like bar';
Marks a test as passed if the $value, when coerced to a string, does not match the $expected-regex. The function accepts an optional description of the test, which defaults to printing the text that did not match.
Defined as:
multi sub use-ok(Str $code, $desc = "$code module can be use-d ok")
Marks a test as passed if the given $module loads correctly.
use-ok 'Full::Qualified::ModuleName';
Defined as:
multi sub dies-ok(Callable $code, $reason = '')
Marks a test as passed if the given $code throws an exception.
The function accepts an optional description of the test.
sub saruman(Bool :$ents-destroy-isengard) { die "Killed by Wormtongue" if $ents-destroy-isengard; } dies-ok { saruman(ents-destroy-isengard => True) }, "Saruman dies";
Defined as:
multi sub lives-ok(Callable $code, $reason = '')
Marks a test as passed if the given $code does not throw an exception.
The function accepts an optional description of the test.
sub frodo(Bool :$destroys-ring) { die "Oops, that wasn't supposed to happen" unless $destroys-ring; } lives-ok { frodo(destroys-ring => True) }, "Frodo survives";
Defined as:
multi sub eval-dies-ok(Str $code, $reason = '')
Marks a test as passed if the given $string throws an exception when evaled as code.
The function accepts an optional description of the test.
eval-dies-ok q[my $joffrey = "nasty"; die "bye bye Ned" if $joffrey ~~ /nasty/], "Ned Stark dies";
Defined as:
multi sub eval-lives-ok(Str $code, $reason = '')
Marks a test as passed if the given $string does not throw an exception when evaled as code.
The function accepts an optional description of the test.
eval-lives-ok q[my $daenerys-burns = False; die "Oops, Khaleesi now ashes" if $daenerys-burns], "Dany is blood of the dragon";
Defined as:
sub throws-like($code, $ex_type, $reason?, *%matcher)
Marks a test as passed if the given $code throws the specific exception expected exception type $ex_type. The code $code may be specified as something Callable or as a string to be EVALed. The exception may be specified as a type object or as a string containing its type name.
If an exception was thrown, it will also try to match the matcher hash, where the key is the name of the method to be called on the exception, and the value is the value it should have to pass. For example:
sub frodo(Bool :$destroys-ring) { fail "Oops. Frodo dies" unless $destroys-ring }; throws-like { frodo }, Exception, message => /dies/;
The function accepts an optional description of the test as the third positional argument.
The routine makes Failures fatal. If you wish to avoid that, use no fatal pragma and ensure the tested code does not sink the possible Failures. If you wish to test that the code returns a Failure instead of throwing, use fails-like routine instead.
sub fails-not-throws { +"a" } # test passes, even though it's just a Failure and would not always throw: throws-like { fails-not-throws }, Exception; # test detects nothing thrown, because our Failure wasn't sunk or made fatal: throws-like { no fatal; my $ = fails-not-throws; Nil }, Exception;
Please note that you can only use the string form (for EVAL) if you are not referencing any symbols in the surrounding scope. If you are, you should encapsulate your string with a block and an EVAL instead. For instance:
throws-like { EVAL q[ fac("foo") ] }, X::TypeCheck::Argument;
Defined as:
sub fails-like ( \test where Callable:D|Str:D, $ex-type, $reason?, *%matcher)
Same interface as throws-like, except checks that the code returns a Failure instead of throwing. If the code does throw or if the returned Failure has already been handled, that will be considered as a failed test.
fails-like { +"a" }, X::Str::Numeric, :message(/'Cannot convert string to number'/), 'converting non-numeric string to number fails';
Defined as:
multi sub subtest(Pair $what) multi sub subtest($desc, &subtests) multi sub subtest(&subtests, $desc = '')
The subtest function executes the given block, consisting of usually more than one test, possibly including a plan or done-testing, and counts as one test in plan, todo, or skip counts. It will pass the test only if all tests in the block pass. The function accepts an optional description of the subtest.
class Womble {} class GreatUncleBulgaria is Womble { has $.location = "Wimbledon Common"; has $.spectacles = True; } subtest { my $womble = GreatUncleBulgaria.new; isa-ok $womble, Womble, "Correct type"; is $womble.location, "Wimbledon Common", "Correct location"; ok $womble.spectacles, "Correct eyewear"; }, "Check Great Uncle Bulgaria";
You can also place the description as the first positional argument, or use a Pair with description as the key and subtest's code as the value. This can be useful for subtests with large bodies.
subtest 'A bunch of tests', { plan 42; ... ... } subtest 'Another bunch of tests' => { plan 72; ... ... }
Defined as:
multi sub todo($reason, $count = 1)
Sometimes tests just aren't ready to be run, for instance a feature might not yet be implemented, in which case tests can be marked as todo. Or it could be the case that a given feature only works on a particular platform - in which case one would skip the test on other platforms.
Mark $count tests as TODO, giving a $reason as to why. By default only one test will be marked TODO.
sub my-custom-pi { 3 }; todo 'not yet precise enough'; # Mark the test as TODO. is my-custom-pi(), pi, 'my-custom-pi'; # Run the test, but don't report # failure in test harness.
The result from the test code above will be something like:
not ok 1 - my-custom-pi# TODO not yet precise enough # Failed test 'my-custom-pi' # at test-todo.t line 7 # expected: '3.14159265358979' # got: '3'
Note that if you todo a subtest, all of the failing tests inside of it will be automatically marked TODO as well and will not count towards your original TODO count.
Defined as:
multi sub skip() multi sub skip($reason, $count = 1)
Skip $count tests, giving a $reason as to why. By default only one test will be skipped. Use such functionality when a test (or tests) would die if run.
sub num-forward-slashes($arg) { ... } ; if $*KERNEL ~~ 'linux' { is num-forward-slashes("/a/b"), 2; is num-forward-slashes("/a//b".IO.cleanup), 2; } else { skip "Can't use forward slashes on Windows", 2; }
Note that if you mark a test as skipped, you must also prevent that test from running.
Defined as:
sub skip-rest($reason = '<unknown>')
Skip the remaining tests. If the remainder of the tests in the test file would all fail due to some condition, use this function to skip them, providing an optional $reason as to why.
my $location; sub womble { ... }; ...; unless $location ~~ "Wimbledon Common" { skip-rest "We can't womble, the remaining tests will fail"; exit; } # tests requiring functional wombling ok womble(); # ...
Note that skip-rest requires a plan to be set, otherwise the skip-rest call will throw an error. Note that skip-rest does not exit the test run. Do it manually, or use conditionals to avoid running any further tests.
See also plan :skip-all('...') to avoid running any tests at all and bail-out to abort the test run and mark it as failed.
sub bail-out ($desc?)
If you already know the tests will fail, you can bail out of the test run using bail-out():
my $has-db-connection; ... $has-db-connection or bail-out 'Must have database connection for testing';
The function aborts the current test run, signaling failure to the harness. Takes an optional reason for bailing out. The subroutine will call exit(), so if you need to do a clean-up, do it before calling bail-out().
If you want to abort the test run, but without marking it as failed, see skip-rest or plan :skip-all('...')
Defined as:
multi sub pass($desc = '')
The pass function marks a test as passed. flunk marks a test as not passed. Both functions accept an optional test description.
pass "Actually, this test has passed"; flunk "But this one hasn't passed";
Since these subroutines do not provide indication of what value was received and what was expected, they should be used sparingly, such as when evaluating a complex test condition.
multi sub flunk($reason = '')
The opposite of pass, makes a test fail with an optional message.
sub diag($message)
Display diagnostic information in a TAP-compatible manner on the standard error stream. This is usually used when a particular test has failed to provide information that the test itself did not provide. Or it can be used to provide visual markers on how the testing of a test-file is progressing (which can be important when doing stress testing).
diag "Yay! The tests got to here!";
Concurrent execution of code (low-level)
class Thread {}
A thread is a sequence of instructions that can (potentially) run in parallel to others. Class Thread provides a bit of abstraction over threads provided by the underlying virtual machines (which in turn might or might not be operating system threads).
Since threads are fairly low-level, most applications should use other primitives, like start, which also runs in parallel and returns a Promise.
my @threads = (^10).map: { Thread.start( name => "Sleepsorter $_", sub { my $rand = (^10).pick; sleep $rand; say $rand; }, ); } .finish for @threads;
The current thread is available in the dynamic variable $*THREAD.
method new(:&code!, Bool :$app_lifetime = False, Str :$name = '<anon>' --> Thread:D)
Creates and returns a new Thread, without starting it yet. &code is the code that will be run in a separate thread.
$name is a user-specified string that identifies the thread.
If $app_lifetime is set to True, then the thread is killed when the main thread of the process terminates. If set to False, the process will only terminate when the thread has finished.
method start(Thread:U: &code, Bool :$app_lifetime = False, Str :$name = '<anon>' --> Thread:D)
Creates, runs and returns a new Thread. Note that it can (and often does) return before the thread's code has finished running.
method run(Thread:D:)
Runs the thread, and returns the invocant. It is an error to run a thread that has already been started.
method id(Thread:D: --> Int:D)
Returns a numeric, unique thread identifier.
method finish(Thread:D)
Waits for the thread to finish. This is called join in other programming systems.
method join(Thread:D)
Waits for the thread to finish.
method yield(Thread:U)
Tells the scheduler to prefer another thread for now.
Thread.yield;
method app_lifetime(Thread:D: --> Bool:D)
Returns False unless the named parameter :app_lifetime is specifically set to True during object creation. If the method returns False it means that the process will only terminate when the thread has finished while True means that the thread will be killed when the main thread of the process terminates.
my $t1 = Thread.new(code => { for 1..5 -> $v { say $v }}); my $t2 = Thread.new(code => { for 1..5 -> $v { say $v }}, :app_lifetime); say $t1.app_lifetime; # OUTPUT: «False» say $t2.app_lifetime; # OUTPUT: «True»
method name(Thread:D: --> Str:D)
Returns the user defined string, which can optionally be set during object creation in order to identify the Thread, or '<anon>' if no such string was specified.
my $t1 = Thread.new(code => { for 1..5 -> $v { say $v }}); my $t2 = Thread.new(code => { for 1..5 -> $v { say $v }}, name => 'my thread'); say $t1.name; # OUTPUT: «<anon>» say $t2.name; # OUTPUT: «my thread»
method Numeric(Thread:D: --> Int:D)
Returns a numeric, unique thread identifier, i.e. the same as id.
method Str(Thread:D: --> Str:D)
Returns a string which contains the invocants thread id and name.
my $t = Thread.new(code => { for 1..5 -> $v { say $v }}, name => 'calc thread'); say $t.Str; # OUTPUT: «Thread<3>(calc thread)»
method is-initial-thread(--> Bool)
Returns a Bool indicating whether the current thread (if called as a class method) or the Thread object on which it is called, is the initial thread the program started on.
say Thread.is-initial-thread; # True if this is the initial thread say $*THREAD.is-initial-thread; # True if $*THREAD is the initial thread
Please note there is no guarantee that this is actually the main thread from the OS's point of view. Also note that if you need this other than from a pure introspection / debugging point of view, that there are probably better ways to achieve what you're trying to achieve.
sub full-barrier()
Performs a full memory barrier, preventing re-ordering of reads/writes. Required for implementing some lock-free data structures and algorithms.
Scheduler that distributes work among a pool of threads
class ThreadPoolScheduler does Scheduler {}
The ThreadPoolScheduler has a range of number of threads that it maintains, and it distributes work among those threads. When the upper limit of threads isn't reached yet, and there is work pending, it spawns new threads to handle the work.
method new(Int :$initial_threads = 0, Int :$max_threads=16)
Creates a new ThreadPoolScheduler object with the given range of threads to maintain.
Unsigned integer (arbitrary-precision)
The UInt is defined as a subset of Int:
my subset UInt of Int where {not .defined or $_ >= 0};
Consequently, it cannot be instantiated or subclassed; however, that shouldn't affect most normal uses.
Some examples of its behavior and uses:
say UInt ~~ Int; # OUTPUT: «True» my UInt $u = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff; # 64-bit unsigned value say $u.base(16); # OUTPUT: «FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF» (32 digits) ++$u; say $u.base(16); # OUTPUT: «100000000000000000000000000000000» (33 digits!) my Int $i = $u; say $i.base(16); # same as above say $u.^name; # OUTPUT: «Int» - UInt is a subset, so the type is still Int. say $i.^name; # OUTPUT: «Int» # Difference in assignment my UInt $a = 5; # nothing wrong my UInt $b = -5; # Exception about failed type check my UInt $c = 0; --$c; # Exception again CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $b; expected UInt but got Int (-5)» # Non-assignment operations are fine my UInt $d = 0; say $d - 3; # OUTPUT: «-3»
A string of Unicode codepoints
class Uni does Positional[uint32] does Stringy { }
Unlike Str, which is made of Grapheme clusters, Uni is string strictly made of Unicode codepoints. That is, base characters and combining characters are separate elements of a Uni instance.
Uni presents itself with a list-like interface of integer Codepoints.
Typical usage of Uni is through one of its subclasses, NFC, NFD, NFKD and NFKC, which represent strings in one of the Unicode Normalization Forms of the same name.
method new(*@codes --> Uni:D)
Creates a new Uni instance from the given codepoint numbers.
method NFC(Uni:D: --> NFC:D)
Returns a NFC (Normal Form Composed)-converted version of the invocant.
method NFD(Uni:D: --> NFD:D)
Returns a NFD (Normal Form Decomposed)-converted version of the invocant.
method NFKC(Uni:D: --> NFKC:D)
Returns a NFKC (Normal Form Compatibility Composed)-converted version of the invocant.
method NFKD(Uni:D: --> NFKD:D)
Returns a NFKD (Normal Form Compatibility Decomposed)-converted version of the invocant.
method codes(Uni:D: --> Int:D)
Returns the number of codepoints in the invocant.
method elems(Uni:D: --> Int:D)
Returns the number of codepoints in the invocant.
Perl 6 Virtual Machine related information
class VM does Systemic { }
Built-in class for providing information about the virtual machine in which Perl 6 is running. Usually accessed through the $*VM dynamic variable.
Defined as:
multi method osname(VM:U:) multi method osname(VM:D:)
Instance / Class method returning the name of the Operating System, as known by the configuration of the VM object / currently running virtual machine.
Instance method returning a string of the extension that should be used for precompiled files of the VM object.
Instance method returning a string of the value of the compilation target that should be used when precompiling source-files with the VM object.
Instance method returning a string of the path in which the virtual machine of the VM object is installed.
Unique identification for value types
class ValueObjAt is ObjAt { }
A subclass of ObjAt that should be used to indicate that a class produces objects that are value types (in other words: are immutable after they have been initialized.
my %h = a => 42; # mutable Hash say %h.WHICH; # OUTPUT: «ObjAt.new("Hash|1402...888")» my %m is Map = a => 42; # immutable Map say %m.WHICH; # OUTPUT: «ValueObjAt.new("Map|AAF...09F61F")»
If you create a class that should be considered a value type, you should add a WHICH method to that class that returns a ValueObjAt object, for instance:
class YourClass { has $.foo; # note these are not mutable has $.bar; method WHICH() { ValueObjAt.new("YourClass|$!foo|$!bar"); } }
Note that it is customary to always start the identifying string with the name of the object, followed by a "|". This to prevent confusion with other classes that may generate similar string values: the name of the class should then be enough of a differentiator to prevent collisions.
Object representation of a variable for use in traits
class Variable {}
Variables have a wealth of compile-time information, but at runtime, accesses to a variable usually act on the value stored inside it, not the variable itself. The runtime class of a variable is Scalar.
Class Variable holds the compile-time information that traits can use to introspect and manipulate variables.
Sets the default value with which a variable is initialized, and to which it is reset when Nil is assigned to it. Trait arguments are evaluated at compile time. Closures won't do what you expect: they are stored as is and need to be called by hand.
my Int $x is default(42); say $x; # OUTPUT: «42» $x = 5; say $x; # OUTPUT: «5» # explicit reset: $x = Nil; say $x; # OUTPUT: «42»
The trait is default can be used also with subscripting things like arrays and hashes:
my @array is default( 'N/A' ); @array[22].say; # OUTPUT: N/A @array = Nil; @array.say; # OUTPUT: [N/A] @array[4].say; # OUTPUT: N/A my %hash is default( 'no-value-here' ); %hash<non-existent-key>.say; # OUTPUT: no-value-here %hash<foo> = 'bar'; %hash<>.say; # OUTPUT: {foo => bar} %hash<wrong-key>.say; # OUTPUT: no-value-here
multi sub trait_mod:<is>(Variable:D, :$dynamic)
Marks a variable as dynamic, that is, accessible from inner dynamic scopes without being in an inner lexical scope.
sub introspect() { say $CALLER::x ; } my $x is dynamic = 23; introspect; # OUTPUT: «23» { # not dynamic my $x; introspect() # dies with an exception of type X::Caller::NotDynamic }
The is dynamic trait is a rather cumbersome way of creating and accessing dynamic variables. A much easier way is to use the * twigil:
sub introspect() { say $*x ; } my $*x = 23; introspect; # OUTPUT: «23» { # not dynamic my $x; introspect() # dies with an exception of type X::Dynamic::NotFound }
multi sub trait_mod:<of>(Mu:U $target, Mu:U $type)
Sets the type constraint of a container bound to a variable.
my $i of Int = 42; $i = "forty plus two"; CATCH { default { say .^name, ' ', .Str } } # OUTPUT: «X::TypeCheck::Assignment Type check failed in assignment to $i; expected Int but got Str ("forty plus two")»
You can use any value defined in compile time as a type constraint, including constants:
constant \T = Int; my $i of T = 42;
which would be equivalent to the previous definition.
method name(Variable:D: str)
Returns the name of the variable, including the sigil.
Module version descriptor
class Version { }
Version objects identify version of software components (and potentially other entities). Perl 6 uses them internally for versioning modules.
A version consists of several parts, which are visually represented by joining them with a dot. A version part is usually an integer, a string like alpha, or a Whatever-star *. The latter is used to indicate that any version part is acceptable in another version that is compared to the current one.
say v1.0.1 ~~ v1.*; # OUTPUT: «True» say v1.0.1 ~~ v1.*.1; # OUTPUT: «True»
The first part of version literals contains v and a number; this might be followed by alphanumeric and Whatever parts and trailed by +. Multiple parts are separate with a dot .. A trailing + indicates that higher versions are OK in comparisons:
say v1.2 ~~ v1.0; # OUTPUT: «False» say v1.2 ~~ v1.0+; # OUTPUT: «True» say v0.and.anything.else ~~ v0+; # OUTPUT: «True»
In comparisons, order matters, and every part is compared in turn.
say v1.2 cmp v2.1; # OUTPUT: «Less»
The + suffix is always taken into account in comparisons:
say v1.0.1+ <=> v1.0.1; # OUTPUT: «More»
And * (Whatever) is too, and considered always Less than whatever digit is in the corresponding part, even if * is trailed by +:
say v1.* <=> v1.0; # OUTPUT: «Less» say v1.* <= v1.0; # OUTPUT: «True» say v1.*+ <= v1.0; # OUTPUT: «True»
Please note that method calls, including pseudo methods like WHAT, require version literals either to be enclosed with parentheses or use some other method to separate them from the dot that denotes a method call, like in these examples:
say (v0.and.some.*.stuff).parts; # OUTPUT: «(0 and some * stuff)» say v0.and.some.*.stuff .parts; # OUTPUT: «(0 and some * stuff)»
method new(Str:D $s)
Creates a Version from a string $s. The string is combed for the numeric, alphabetic, and wildcard components of the version object. Any characters other than alphanumerics and asterisks are assumed to be equivalent to a dot. A dot is also assumed between any adjacent numeric and alphabetic characters.
method parts(Version:D: --> List:D)
Returns the list of parts that make up this Version object
my $v1 = v1.0.1; my $v2 = v1.0.1+; say $v1.parts; # OUTPUT: «(1 0 1)» say $v2.parts; # OUTPUT: «(1 0 1)»
The + suffix is not considered a part of the Version object, and thus not returned by this method, as shown above in the $v2 variable.
method plus(Version:D: --> Bool:D)
Returns True if comparisons against this version allow larger versions too.
my $v1 = v1.0.1; my $v2 = v1.0.1+; say $v1.plus; # OUTPUT: «False» say $v2.plus; # OUTPUT: «True»
method Str(Version:D: --> Str:D)
Returns a string representation of the invocant.
my $v1 = v1.0.1; my $v2 = Version.new('1.0.1'); say $v1.Str; # OUTPUT: «1.0.1» say $v2.Str; # OUTPUT: «1.0.1»
method gist(Version:D: --> Str:D)
Returns a string representation of the invocant, just like Str, prepended with a lower-case v.
my $v1 = v1.0.1; my $v2 = Version.new('1.0.1'); say $v1.gist; # OUTPUT: «v1.0.1» say $v2.gist; # OUTPUT: «v1.0.1»
Defined as:
method Capture()
Throws X::Cannot::Capture.
Placeholder for the value of an unspecified argument
class Whatever { }
Whatever is a class whose objects don't have any explicit meaning; it gets its semantics from other routines that accept Whatever-objects as markers to do something special. Using the * literal as an operand creates a Whatever object.
Much of *'s charm comes from Whatever-currying. When * is used in term position, that is, as an operand, in combination with most operators, the compiler will transform the expression into a closure of type WhateverCode, which is actually a Block that can be used wherever Callables are accepted.
my $c = * + 2; # same as -> $x { $x + 2 }; say $c(4); # OUTPUT: «6»
Multiple * in one expression generate closures with as many arguments:
my $c = * + *; # same as -> $x, $y { $x + $y }
Using * in complex expressions will also generate closures:
my $c = 4 * * + 5; # same as -> $x { 4 * $x + 5 }
Calling a method on * also creates a closure:
<a b c>.map: *.uc; # same as <a b c>.map: -> $char { $char.uc }
As mentioned before, not all operators and syntactic constructs curry * (or Whatever-stars) to WhateverCode. In the following cases, * will remain a Whatever object.
Exception | Example | What it does |
---|---|---|
comma | 1, *, 2 | generates a List with a * element |
range operators | 1 .. * | Range.new(:from(1), :to(*)); |
series operator | 1 ... * | infinite list |
assignment | $x = * | assign * to $x |
binding | $x := * | bind * to $x |
list repetition | 1 xx * | generates an infinite list |
The range operators are handled specially. They do not curry with Whatever-stars, but they do curry with WhateverCode
say (1..*).^name; # OUTPUT: «Range» say ((1..*-1)).^name; # OUTPUT: «WhateverCode»
This allows all these constructs to work:
.say for 1..*; # infinite loop
and
my @a = 1..4; say @a[0..*]; # OUTPUT: «(1 2 3 4)» say @a[0..*-2]; # OUTPUT: «(1 2 3)»
Because Whatever-currying is a purely syntactic compiler transform, you will get no runtime currying of stored Whatever-stars into WhateverCodes.
my $x = *; $x + 2; # Not a closure, dies because it can't coerce $x to Numeric CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Multi::NoMatch: Cannot resolve caller Numeric(Whatever: ); # none of these signatures match: # (Mu:U \v: *%_)»
The use cases for stored Whatever-stars involve those curry-exception cases mentioned above. For example, if you want an infinite series by default.
my $max = potential-upper-limit() // *; my $series = known-lower-limit() ... $max;
A stored * will also result in the generation of a WhateverCode in the specific case of smartmatch. Note that this is not actually the stored * which is being curried, but rather the * on the left-hand side.
my $constraint = find-constraint() // *; my $maybe-always-matcher = * ~~ $constraint;
If this hypothetical find-constraint were to have found no constraint, $maybe-always-matcher would evaluate to True for anything.
$maybe-always-matcher(555); # True $maybe-always-matcher(Any); # True
HyperWhatever's functionality is similar to Whatever, except it refers to multiple values, instead of a single one.
multi method ACCEPTS(Whatever:D: Mu $other) multi method ACCEPTS(Whatever:U: Mu $other)
If the invocant is an instance, always returns True. If the invocant is a type object, performs a typecheck.
say 42 ~~ (*); # OUTPUT: «True» say 42 ~~ Whatever; # OUTPUT: «False»
Defined as:
method Capture()
Throws X::Cannot::Capture.
Code object constructed by Whatever-currying
class WhateverCode is Code { }
WhateverCode objects are the result of Whatever-currying. See the Whatever documentation for details.
When you wish to control how a method or function interprets any Whatever star, you may use multi dispatch with Whatever and WhateverCode parameters to do so, as in the following example:
class Cycle { has $.pos; has @.vals; } multi sub get-val(Cycle $c, Int $idx) { $c.vals[$idx % $c.vals.elems] } # Define what to do with a stand-alone * as the second argument multi sub get-val(Cycle $c, Whatever $idx) { get-val($c, $c.pos); } # Define what to do with a * WhateverCode in an expression multi sub get-val(Cycle $c, WhateverCode $idx) { get-val($c, $idx($c.pos)); } my Cycle $c .= new(:pos(2), :vals(0..^10)); say get-val($c, 3); # OUTPUT: «3» say get-val($c, *); # OUTPUT: «2» say get-val($c, *-1); # OUTPUT: «1»
The WhateverCode does the Callable role, so it should be possible to introspect the type of Callable it contains; for instance, continuing the previous example, we can add a multi that handles a WhateverCode with two arguments via checking the signature:
# Define what to do with two * in an expression multi sub get-val(Cycle $c, WhateverCode $idx where { .arity == 2 }) { get-val($c, $idx($c.pos, $c.vals.elems)); } say get-val($c, * + * div 2); # 2 + 10/2 = 7
Note, though, that subexpressions may impose their own Whatever star rules:
my @a = (0, 1, 2); say get-val($c, @a[*-1]) # 2, because the star belongs to the Array class
This can make the ownership of Whatever stars become confusing rather quickly, so be careful not to overdo it.
You may instead type-constrain using Callable type in order to accept any Callable, including WhateverCode:
sub run-with-rand (Callable $code) { $code(rand) }; run-with-rand *.say; # OUTPUT: «0.773672071688484» run-with-rand {.say}; # OUTPUT: «0.38673179353983» run-with-rand sub { $^v.say }; # OUTPUT: «0.0589543603685792»
Type-constraining with &-sigiled parameter works equally well and is shorter to type:
sub run-with-rand (&code) { code time };
Error with a custom message
class X::AdHoc is Exception { }
X::AdHoc is the type into which objects are wrapped if they are thrown as exceptions, but don't inherit from Exception.
Its benefit over returning non-Exception objects is that it gives access to all the methods from class Exception, like backtrace and rethrow.
You can obtain the original object with the payload method.
try { die [404, 'File not found']; # throw non-exception object } print "Got HTTP code ", $!.payload[0], # 404 " and backtrace ", $!.backtrace.Str;
Note that young code will often be prototyped using X::AdHoc and then later be revised to use more specific subtypes of Exception. As such it is usually best not to explicitly rely on receiving an X::AdHoc – in many cases using the string returned by the .message method, which all Exceptions must have, is preferable. Please note that we need to explicitly call .Str to stringify the backtrace correctly.
Returns the original object which was passed to die.
Defined as
method Numeric()
Converts the payload to Numeric and returns it
Defined as
method from-slurpy (|cap)
Creates a new exception from a capture and returns it. The capture will have the SlurpySentry role mixed in, so that the .message method behaves in a different when printing the message.
try { X::AdHoc.from-slurpy( 3, False, "Not here" ).throw }; print $!.payload.^name; # OUTPUT: «Capture+{X::AdHoc::SlurpySentry}» print $!.message; # OUTPUT: «3FalseNot here»
The SlurpySentry role joins the elements of the payload, instead of directly converting them to a string.
Compilation error due to augmenting an anonymous package
class X::Anon::Augment does X::Comp { }
Compile time error thrown when trying to augment an anonymous package.
For example
use MONKEY-TYPING; augment class { }
Dies with
Cannot augment anonymous class
method package-kind returns Str:D
Returns the kind of package (module, class, grammar, ...) that the code tried to augment.
Compilation error due to declaring an anonymous multi
class X::Anon::Multi does X::Comp { }
Compile time error thrown when an anonymous multi is being declared.
For example
multi method () { }
dies with
Cannot put multi on anonymous method
method multiness(--> Str:D)
Returns a string describing the multiness that the original code used, for example "multi" or "proto".
method routine-type(--> Str:D)
Returns a string describing the type of routine that was declared, for example "sub" or "method".
Exception thrown when trying to assign to something read-only
class X::Assignment::RO is Exception {}
Code like
sub f() { 42 }; f() = 'new value'; # throws an X::Assignment::RO CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Any»
throws an exception of type X::Assignment::RO.
method typename(X::Assignment::RO:D: --> Str)
Returns the type name of the value on the left-hand side
Compilation error due to declaring an attribute outside of a package
class X::Attribute::NoPackage does X::Comp { }
Compile time error thrown when an attribute is declared where it does not make sense (for example in the mainline).
For example
has $.x;
Dies with
You cannot declare attribute '$.x' here; maybe you'd like a class or a role?
method name(--> Str:D)
Returns the name of the attribute
Compilation error due to declaring an attribute in an ineligible package
class X::Attribute::Package does X::Comp { }
Compile time error, thrown when the compiler encounters an attribute declaration inside a package that does not support attributes.
For example
module A { has $.x }
dies with
A module cannot have attributes, but you tried to declare '$.x'
method name(--> Str:D)
Returns the name of the attribute that triggered this error.
method package-kind(--> Str:D)
Returns the kind of package (package, module) that doesn't support attributes.
Compilation error due to not declaring an attribute with the
class X::Attribute::NoPackage does X::MOP { }
Compile time error thrown when a required attribute is not assigned when creating an object.
For example
my class Uses-required { has $.req is required }; my $object = Uses-required.new()
Dies with
OUTPUT: «(exit code 1) The attribute '$!req' is required, but you did not provide a value for it.»
method name(--> Str:D)
Returns the name of the attribute.
method why(--> Str:D)
Returns the reason why that attribute is required, and it will be included in the message if provided. That reason is taken directly from the is required trait.
my class Uses-required { has $.req is required("because yes") }; my $object = Uses-required.new(); │ # OUTPUT: # «(exit code 1) The attribute '$!req' is required because because yes, # but you did not provide a value for it.»
Compilation error due to an undeclared attribute
class X::Attribute::Undeclared is X::Undeclared { }
Thrown when code refers to an attribute that has not been declared.
For example the code
class A { method m { $!notthere } }
Produces the error
Attribute $!notthere not declared in class A
Returns the kind of package the attribute was used in (for example class, grammar)
Returns the name of the package in which the offensive attribute reference was performed.
Compilation error due to augmenting a non-existing type
class X::Augment::NoSuchType does X::Comp { }
Thrown when trying to augment a type which doesn't exist.
For example
use MONKEY-TYPING; augment class NoSuch { }
dies with
You tried to augment class NoSuch, but it does not exist
method package-kind(--> Str:D)
Returns the kind of package (class, grammar) that is being tried to augment
Returns the name that was tried to augment, but which doesn't exist.
Error due to binding to something that is not a variable or container
class X::Bind is Exception {}
If you write code like this:
floor(1.1) := 42;
it dies with an X::Bind exception:
Cannot use bind operator with this left-hand side
Compilation error due to binding to a natively typed variable
class X::Bind::NativeType does X::Comp { }
Compile-time error thrown when trying to bind to a natively typed variable.
Since native variables explicitly don't have the concept of a container at runtime, it does not make sense to support both binding and assignment; Perl 6 supports only assignment (which makes more sense, because native types are value types).
For example the code
my int $x := 3;
dies with
Cannot bind to natively typed variable '$x'; use assignment instead
and can be fixed by writing it as
my int $x = 3;
method name(--> Str:D)
Returns the name of the variable.
Error due to binding to a slice
class X::Bind::Slice is Exception {}
When you try to bind to an array or hash slice:
my @a; @a[0, 1] := [42]; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Bind::Slice: Cannot bind to Array slice»
and
my %h; %h<a b> := {}; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Bind::Slice: Cannot bind to Hash slice»
you get an exception of type ::Bind::Slice
method type(X::Bind::Slice:D:)
returns the type object of the thing that you tried to slice-bind, for example Array, List or Hash.
Error while trying to access a non dynamic variable through CALLER
class X::Caller::NotDynamic is Exception { }
Thrown when trying to access a non dynamic variable through CALLER
A typical error message is
Cannot access '$x' through CALLER, because it is not declared as dynamic
Returns the name of the symbol that was passed to CALLER.
Error due to calling receive on a closed channel
class X::Channel::ReceiveOnClosed {}
This exception is thrown when a calling receive on a Channel that has been closed:
my $s = Channel.new; $s.close; $s.receive; # Cannot receive a message on a closed channel CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Channel::ReceiveOnClosed: Cannot receive a message on a closed channel»
method Channel(X::Channel::ReceiveOnClosed:D: --> Channel:D)
Returns the Channel object on which the receive method was called.
Error due to calling send on a closed channel
class X::Channel::SendOnClosed {}
This exception is thrown when a calling send on a Channel that has been closed:
my $s = Channel.new; $s.close; $s.send(42); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Channel::SendOnClosed: Cannot send a message on a closed channel»
method Channel(X::Channel::SendOnClosed:D: --> Channel:D)
Returns the Channel object on which the send method was called.
Common role for compile-time errors
role X::Comp is Exception { }
Common role for compile-time errors.
Note that since the backtrace of a compile time error generally shows routines from the compiler, not from user-space programs, the Backtrace returned from the backtrace method is not very informative. Instead the exception carries its own filename, line and column attributes and public accessors.
If an error occurs while creating an object (like a class or routine) at compile time, generally the exception associated with it does not hold a reference to the object (for example a class would not be fully composed, and thus not usable). In those cases the name of the would-be-created object is included in the error message instead.
The filename in which the compilation error occurred
The line number in which the compilation error occurred.
The column number of location where the compilation error occurred. (Rakudo does not implement that yet).
Compilation error due to composing an ineligible type
class X::Composition::NotComposable is Exception { }
Thrown when trying to compose a type into a target type, but the composer type cannot be used for composition (roles and enums are generally OK).
For example
class A { } class B does A { }
dies with
===SORRY!=== A is not composable, so B cannot compose it
because does is reserved for role composition, and A is not a role, nor something that knows how to turn into a role.
The fix is to either make A a role, or use inheritance (class B is A { }) instead.
method target-name(--> Str:D)
Returns the name of the type that should be composed, but failed.
method composer(--> Mu)
Returns the type that should be composed into the target, but which isn't a role.
Error due to passing positional arguments to a default constructor
class X::Constructor::Positional is Exception { }
Thrown from Mu.new when positional arguments are passed to it.
For example
class A { }; A.new(2, 3); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Constructor::Positional: Default constructor for 'A' only takes named arguments»
Role for control exceptions
role X::Control is Exception { }
This role turns an exception into a control exception, such as CX::Next or CX::Take. It has got no code other than the definition.
Since Rakudo 2019.03, throwing an object that mixes in this role X::Control can raise a control exception which is caught by the CONTROL phaser instead of CATCH. This allows to define custom control exceptions.
For example, the custom CX::Oops control exception we define below:
class CX::Vaya does X::Control { has $.message } sub ea { CONTROL { default { say "Controlled { .^name }: { .message }" } } CX::Vaya.new( message => "I messed up!" ).throw; } ea; # OUTPUT: «Controlled CX::Vaya: I messed up!»
Error due to calling a loop control command in an ineligible scope
class X::ControlFlow is Exception { }
Thrown when a control flow construct (such as next or redo) is called outside the dynamic scope of an enclosing construct that is supposed to catch them.
For example
last; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::ControlFlow: last without loop construct»
method illegal returns Str:D
Returns the name of the control flow command that was called.
method enclosing returns Str:D
Returns the name of the missing enclosing construct.
Error due to calling return outside a routine
class X::ControlFlow::Return is X::ControlFlow { }
Thrown when a return is called from outside a routine.
return; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::ControlFlow::Return: Attempt to return outside of any Routine»
Error due to using both time zone offset and :timezone
class X::DateTime::TimezoneClash does X::Temporal is Exception { }
This exception is thrown when code tries to create a DateTime object specifying both a time zone offset and the named argument :timezone.
say DateTime.new('2015-12-24T12:23:00+0200'); # works say DateTime.new('2015-12-24T12:23:00', timezone => 7200); # works say DateTime.new('2015-12-24T12:23:00+0200', timezone => 7200); # exception
method message()
Returns 'DateTime.new(Str): :timezone argument not allowed with a timestamp offset'
Compilation error due to a declaration with an ineligible scope
class X::Declaration::Scope does X::Comp { }
Compile time error thrown when a declaration does not harmonize with the declared scope.
For example
has sub f() { }
dies with
===SORRY!=== Cannot use 'has' with sub declaration
method scope(--> Str:D)
Returns a string representation of the scope, usually the same keyword that is used for the declaration ("my", "our", "has", ...);
method declaration(--> Str:D)
Describes the symbol that has been declared in a wrong scope.
Compilation error due to declaring a multi with an ineligible scope
class X::Declaration::Scope::Multi is X::Declaration::Scope { }
Thrown when a multi is declared with an incompatible scope.
For example our multi sub foo() { } dies with
===SORRY!=== Cannot use 'our' with individual multi candidates. Please declare an our-scoped proto instead
Error due to mixing into a type object
class X::Does::TypeObject is Exception {}
When you try to add one or more roles to a type object with does after it has been composed, an error of type X::Does::TypeObject is thrown:
Mu does Numeric; # Cannot use 'does' operator with a type object.
The correct way to apply roles to a type is at declaration time:
class GrassmannNumber does Numeric { ... }; role AlgebraDebugger does IO { ... }; grammar IntegralParser does AlgebraParser { ... };
Roles may only be runtime-mixed into defined object instances:
GrassmannNumber.new does AlgebraDebugger;
(This restriction may be worked around by using augment or supersede, or with dark Metamodel magics, but this will likely result in a significant performance penalty.)
method type(X::Does::TypeObject:D: --> Mu:U)
Returns the type object into which the code tried to mix in a role.
Runtime error thrown when a dynamic variable does not exist
class X::Dynamic::NotFound is Exception {}
This exception is raised when a dynamic variable that has not been declared is used.
$*dynamic-not-found = 33; # OUTPUT: «Dynamic variable $*dynamic-not-found not found»
method name(--> Str:D)
Returns the name of the variable that has not been found.
Error due to specifying an unknown language for EVAL
class X::Eval::NoSuchLang is Exception { }
Error thrown when EVAL($str, :$lang) specifies a language that the compiler does not know how to handle.
For example
EVAL 'boo', lang => "bar"; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Eval::NoSuchLang: No compiler available for language 'bar'»
method lang()
Returns the language that EVAL did not know how to handle.
Compilation error due to exporting the same symbol twice
class X::Export::NameClash does X::Comp { }
Compile time error thrown when a symbol is exported twice.
For example
sub f() is export { }; { sub f() is export { } }
dies with
===SORRY!=== A symbol '&f' has already been exported
Returns the symbol that is exported twice.
IO related error
role X::IO does X::OS {}
Common role for IO related errors.
This role does not provide any additional methods.
Error while trying to change the working directory
class X::IO::Chdir does X::IO is Exception { }
Error class when a chdir call failed.
For example
chdir '/home/other'
throws
Failed to change the working directory to '/home/other': permission denied
Returns the path that was passed to the failed chdir call.
Error while trying to change file permissions
class X::IO::Chmod does X::IO is Exception { }
Error class for failed chmod calls.
A typical error message is
Failed to set the mode of '/home/other' to '0o777': Permission denied
Error while trying to copy a file
class X::IO::Copy does X::IO is Exception { }
Error class for failed file copy operations. A typical error message is
Failed to copy 'source' to 'destination': permission denied
Returns the source of the failed copy operation
Returns the destination of the failed copy operation
Error while trying to determine the current working directory
class X::IO::Cwd does X::IO is Exception { }
Error class when the runtime fails to determine the current directory.
A typical error message is
Failed to get the working directory: permission denied
Error while trying to get a directory's contents
class X::IO::Dir does X::IO is Exception { }
Error class that is thrown when a dir call fails.
A typical error message is
Failed to get the directory contents of '/tmp/': No such file or directory
Returns the path that dir failed to read.
Error while doing file tests on a non existing path
class X::IO::DoesNotExist does X::IO is Exception { }
Thrown when doing file test operations on a non existing path.
A typical error message is
Failed to find 'euler-5.p6' while trying to do '.f'
Returns the path that was passed to the failed call.
Returns a string describing the failed operation.
Error while trying to create a link
class X::IO::Link does X::IO is Exception { }
Error class for failed link operation.
A typical error message is
Failed to create link called 'my-link' on target 'does-not exist': Failed to link file
Returns the name of the link target, i.e. the existing file.
Returns the name of the link that could not be created.
Error while trying to create a directory
class X::IO::Mkdir does X::IO is Exception { }
Error class for failed mkdir operations.
A typical error message is
Failed to create directory 'destination' with mode '0o755': File exists
Returns the path that the mkdir operation failed to create.
Returns the permissions mask of the failed mkdir operation as an Int.
Error while trying to move a file
class X::IO::Move does X::IO is Exception { }
Error class for a failed file move operation. A typical error message is
Failed to move '/tmp/alpha.p6' to 'test.p6': :createonly specified and destination exists
Returns the source of the failed move operation
Returns the destination of the failed move operation
Error while trying to rename a file or directory
class X::IO::Rename does X::IO is Exception { }
Error class for failed file or directory rename operations. A typical error message is
Failed to rename 'source' to 'destination': is a directory
Returns the source of the failed rename operation
Returns the destination of the failed rename operation
Error while trying to remove a directory
my class X::IO::Rmdir does X::IO is Exception { }
Error class for failed rmdir operations.
A typical error message is
Failed to remove the directory 'lib': Directory not empty
Returns the path rmdir failed to remove
Error while trying to create a symbolic link
class X::IO::Symlink does X::IO is Exception { }
Error class for failed symlink creation.
A typical error message is
Failed to create symlink called 'euler' on target '/home/myhome/euler-1.p6': Failed to symlink file: file already exist
Returns the path that symlink failed to create.
Returns the path that symlink failed to create a link to.
Error while trying to remove a file
class X::IO::Unlink does X::IO is Exception { }
Error class for failed unlink operation.
A typical error message is
Failed to remove the file 'secret': Permission defined
Returns the path that unlink failed to delete.
Error due to inheriting from a type that's not composed yet
class X::Inheritance::NotComposed is Exception {}
When you try to inherit from a class that hasn't been composed, an exception of type X::Inheritance::NotComposed is thrown.
Usually this happens because it's not yet fully parsed, or that is stubbed:
For example
class A { ... }; # literal ... for stubbing class B is A { };
dies with
===SORRY!=== 'B' cannot inherit from 'A' because 'A' isn't composed yet (maybe it is stubbed)
The second common way to trigger this error is by trying to inherit from a class from within the class body.
For example
class Outer { class Inner is Outer { } }
dies with
===SORRY!=== 'Outer::Inner' cannot inherit from 'Outer' because 'Outer' isn't composed yet (maybe it is stubbed)
method child-name(X::Inheritance::NotComposed:D: --> Str:D)
Returns the name of the type that tries to inherit.
method parent-name(X::Inheritance::NotComposed:D: --> Str:D)
Returns the name of the parent type that the type tries to inherit from
Compilation error due to inheriting from an ineligible type
class X::Inheritance::Unsupported does X::Comp { }
Compile time error thrown when trying to inherit from a type that does not support inheritance (like a package or an enum).
For example
enum A <Ax Ay>; class B is A { };
dies with
===SORRY!=== A does not support inheritance, so B cannot inherit from it
The name of the type that tries to inherit.
The type object that the child tried to inherit from.
Error due to calling a qualified method from an ineligible class
class X::Method::InvalidQualifier is Exception { }
Thrown when a method is call in the form $invocant.TheClass::method if <$invocant> does not conform to TheClass.
For example
1.Str::split(/a/); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Method::InvalidQualifier: Cannot dispatch to method split on Str because it is not inherited or done by Int»
method method(--> Str:D)
Returns the name of the (unqualified) method.
Returns the invocant of the failed, qualified method call
Returns the type by which the method call was qualified.
Error due to calling a method that isn't there
class X::Method::NotFound is Exception {}
Thrown when the user tries to call a method that isn't there.
For example
1.no-such
throws
No such method 'no-such' for invocant of type 'Int'
method method(--> Str:D)
Returns the method name that was invoked.
method typename(--> Str:D)
Returns the name of the invocant type.
method private(--> Bool:D)
Returns True for private methods, and False for public methods.
method addendum(--> Str:D)
Returns additional explanations or hints.
Note: addendum was introduced in Rakudo 2019.03.
Compilation error due to calling a private method without permission
class X::Method::Private::Permission does X::Comp { }
Compile time error thrown when the code contains a call to a private method that isn't defined in the current class, and when no appropriate trusts relation is defined that permits the private method call.
For example
1!Int::foo
dies with
===SORRY!=== Cannot call private method 'foo' on package Int because it does not trust GLOBAL
method method(--> Str:D)
The name of the private method
method source-package(--> Mu:D)
Returns the type object that (supposedly) contains the private method.
method calling-package(--> Mu:D)
Returns the package in which the calling code is, and which the source package does not trust.
Compilation error due to an unqualified private method call
class X::Method::Private::Unqualified does X::Comp { }
Compile time error thrown when a private method call on anything but self is not fully qualified.
For example
1!priv
dies with
===SORRY!=== Private method call to priv must be fully qualified with the package containing the method
method method(--> Str:D)
Returns the name of the private method that triggered the error.
Error due to using an ineligible type as a mixin
class X::Mixin::NotComposable is Exception { }
Thrown when a mixin with infix does or but is done with a composer that cannot be used for mixin.
For example
class A { }; 1 but A; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Mixin::NotComposable: Cannot mix in non-composable type A into object of type Int»
The compile-time equivalent of this error is X::Composition::NotComposable
method target()
Returns the target of the failed mixin operation.
method rolish()
Returns the thing that could not act as a role for mixing it in
Error due to use of an unimplemented feature
class X::NYI is Exception { }
Error class for unimplemented features. NYI stands for Not Yet Implemented.
If a Perl 6 compiler is not yet feature complete, it may throw an X::NYI exception when a program uses a feature that it can detect and is somehow specified is not yet implemented.
A full-featured Perl 6 compiler must not throw such exceptions, but still provide the X::NYI class for compatibility reasons.
A typical error message is
HyperWhatever is not yet implemented. Sorry.
method new( :$feature, :$did-you-mean, :$workaround)
This is the default constructor for X:NYI which can take three parameters with obvious meanings.
class Nothing { method ventured( $sub, **@args) { X::NYI.new( feature => &?ROUTINE.name, did-you-mean => "gained", workaround => "Implement it yourself" ).throw; } } my $nothing = Nothing.new; $nothing.ventured("Nothing", "Gained");
In this case, we are throwing an exception that indicates that the ventured routine has not been implemented; we use the generic &?ROUTINE.name to not tie the exception to the method name in case it is changed later on. This code effectively throws this exception
# OUTPUT: # ventured not yet implemented. Sorry. # Did you mean: gained? # Workaround: Implement it yourself # in method ventured at NYI.p6 line 6 # in block <unit> at NYI.p6 line 14
Using the exception properties, it composes the message that we see there.
Returns a Str describing the missing feature.
Returns a Str indicating the optional feature that is already implemented.
It helpfully shows a possible workaround for the missing feature, if it's been declared.
Returns the message including the above properties.
Error due to calling a dispatch command in an ineligible scope
class X::NoDispatcher is Exception { }
When a redispatcher like nextsame is called without being in the dynamic scope of a call where a redispatch is possible, an X::NoDispatcher is thrown.
For example
nextsame; # In the mainline CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::NoDispatcher: nextsame is not in the dynamic scope of a dispatcher»
method redispatcher(--> Str:D)
Returns the name of the redispatcher function that did not succeed.
Error while trying to coerce a number to a Real type
class X::Numeric::Real is Exception { }
Occurs when an attempt to coerce a Numeric to a Real, Num, Int or Rat fails (due to a number with a nonzero imaginary part, for instance).
For example
say (1+2i).Int; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Numeric::Real: Can not convert 1+2i to Int: imaginary part not zero»
method source(--> Numeric:D)
Returns the number that failed to coerce to Real.
method target()
Returns the type to which the coercion was attempted.
method reason(--> Str:D)
Returns the reason that the conversion failed.
Error reported by the operating system
role X::OS { has $.os-error }
Common role for all exceptions that are triggered by some error reported by the operating system (failed IO, system calls, fork, memory allocation).
method os-error(--> Str:D)
Returns the error as reported by the operating system.
Compilation error due to use of obsolete syntax
class X::Obsolete does X::Comp { }
Syntax error thrown when the user is attempting to use constructs from other languages.
For example
m/abc/i
dies with
===SORRY!=== Unsupported use of /i; in Perl 6 please use :i
method old(--> Str:D)
Returns a textual description of the obsolete syntax construct
method replacement(--> Str:D)
Describes what to use instead of the obsolete syntax.
method when(--> Str:D)
Returns a string describing the state of the language (usually " in Perl 6").
Error due to indexing outside of an allowed range
class X::OutOfRange is Exception { }
General error when something (for example an array index) is out of an allowed range.
For example
say 42[2]; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::OutOfRange: Index out of range. Is: 2, should be in 0..0»
since scalars generally act as a one-element list.
method what(--> Str:D)
Verbal description of the thing that was out of range (e.g. "array index", "month").
method got()
Returns the object that was considered out of range (often an integer)
method range(--> Range:D)
Returns a Range object describing the permissible range for the object returned from .got.
method comment(--> Str)
Returns an additional comment that is included in the error message.
Compilation error due to a stubbed package that is never defined
class X::Package::Stubbed does X::Comp { }
Thrown at CHECK time when there are packages stubbed but not later defined.
For example
class A { ... } # literal ... class B { ... } # literal ...
dies with
===SORRY!=== The following packages were stubbed but not defined: A B
method packages(--> Positional:D)
Returns a list of packages that were stubbed but not defined.
Compilation error due to an unallowed default value in a signature
class X::Parameter::Default does X::Comp { }
Compile-time error thrown when a parameter in a signature has default value, but isn't allowed to have one. That is the case with slurpy parameters (because a slurpy always binds successfully, even to zero arguments) and with mandatory parameters.
Example:
sub f($x! = 3) { }
dies with
===SORRY!=== Cannot put default on required parameter $x
And
sub f(*@ = 3) { }
dies with
===SORRY!=== Cannot put default on anonymous slurpy parameter
Returns a string describing how the parameter is qualified that makes it disallow default values, for example "slurpy" or "mandatory".
Returns the parameter name
Compilation error due to a parameter with multiple type constraints
class X::Parameter::MultipleTypeConstraints does X::Comp { }
Compile time error thrown when a parameter has multiple type constraints. This is not allowed in Perl 6.0.
Example:
sub f(Cool Real $x) { }
dies with
Parameter $x may only have one prefix type constraint
Returns the name of the offensive parameter.
Compilation error due to an unallowed placeholder in a signature
class X::Parameter::Placeholder does X::Comp { }
Thrown when a placeholder parameter is used inside a signature where a normal parameter is expected. The reason is often that a named parameter :$param was misspelled as $:param.
For example
sub f($:param) { }
dies with
===SORRY!=== In signature parameter, placeholder variables like $:param are illegal you probably meant a named parameter: ':$param'
The text of the offensive parameter declaration ($:param in the example above).
Suggestion on how to write the parameter declaration instead (:$param in the example above).
Compilation error due to an unallowed twigil in a signature
class X::Parameter::Twigil does X::Comp { }
Thrown when a parameter in a signature has a twigil that it may not have. Only !, . and * as twigils are allowed.
Example:
sub f($=foo) { }
dies with
===SORRY!=== In signature parameter $=foo, it is illegal to use the = twigil
The name of the offensive parameter ($=foo in the example above)
The illegally used twigil.
Compilation error due to passing parameters in the wrong order
class X::Parameter::WrongOrder does X::Comp { }
Compile time error that is thrown when parameters in a signature in the wrong order (for example if an optional parameter comes before a mandatory parameter).
For example
sub f($a?, $b) { }
dies with
===SORRY!=== Cannot put required parameter $b after optional parameters
Returns the kind of misplaced parameter (for example "mandatory", "positional").
Returns the name of the (first) misplaced parameter
Returns a string describing other parameters after which the current parameter was illegally placed (for example "variadic", "positional" or "optional").
Compilation error due to multiple phasers of the same type
class X::Phaser::Multiple does X::Comp { }
Thrown when multiple phasers of the same type occur in a block, but only one is allowed (for example CATCH or CONTROL).
For example
CATCH { }; CATCH { }
dies with
===SORRY!=== Only one CATCH block is allowed
Returns the name of the phaser that occurred more than once.
Error due to a false return value of a PRE/POST phaser
class X::Phaser::PrePost is Exception { }
Thrown when the condition inside a PRE or POST phaser evaluate to a false value.
For example
sub f($x) { PRE { $x ~~ Int } }; f "foo"; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: X::Phaser::PrePost: Precondition '{ $x ~~ Int }' failed«»
method phaser(--> Str:D)
Returns the name of the failed phaser, "PRE" or "POST".
method condition(--> Str:D)
Returns the part of the source code that describes the phaser condition.
Compilation error due to a placeholder in an ineligible block
class X::Placeholder::Block does X::Comp {}
Thrown when a placeholder variable is used in a block that does not allow a signature.
For example
class A { $^foo }
dies with
Placeholder variable $^foo may not be used here because the surrounding block takes no signature
Returns the name of the (first) illegally used placeholder.
Compilation error due to a placeholder in the mainline
class X::Placeholder::Mainline is X::Placeholder::Block { }
Thrown when a placeholder variable is used in the mainline, i.e. outside of any explicit block.
For example
$^x;
dies with
===SORRY!=== Cannot use placeholder parameter $^x outside of a sub or block
Note that this error can also occur when you think something is a block, but it really is a postcircumfix:<{ }>, for example
my %h; say %h{ $^x }; # ^^^^^^^ not a block, so $^x is part of the mainline
Exception thrown by Proc::Async
role X::Proc::Async is Exception { ... }
All exceptions thrown by Proc::Async do this common role.
method proc(X::Proc::Async:D --> Proc::Async)
Returns the object that threw the exception.
Error due to calling start on an already started Proc::Async object
class X::Proc::Async::AlreadyStarted is Exception {}
When you call start twice on the same Proc::Async object, the second invocation will die with an X::Proc::Async::AlreadyStarted exception.
my $proc = Proc::Async.new("echo"); $proc.start; $proc.start; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Proc::Async::AlreadyStarted: Process has already been started»
Error due to trying to bind a handle that is also used
class X::Proc::Async::BindOrUse does X::Proc::Async {}
In general, it occurs when there's some mistake in the direction the stream flows, for instance:
my $p = Proc::Async.new("ls", :w); my $h = "ls.out".IO.open(:w); $p.bind-stdin($h); # Fails with OUTPUT: «Cannot both bind stdin to a handle and also use :w»
In this case, stdin is already bound and cannot be used again; one of them should flow :out and the other one :w to work correctly.
Error due to tapping the same Proc::Async stream for both text and binary reading
class X::Proc::Async::CharsOrBytes is Exception {}
A Proc::Async object allows subscription to the output or error stream either for bytes (Blob) or for text data (Str), but not for both. If you do try both, it throws an exception of type X::Proc::Async::CharsOrBytes.
my $proc = Proc::Async.new('echo'); $proc.stdout.tap(&print); $proc.stdout(:bin).tap(&print); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Proc::Async::CharsOrBytes: Can only tap one of chars or bytes supply for stdout»
method handle(X::Proc::Async::CharsOrBytes:D: --> Str:D)
Returns the name of the handle that was accessed both for text and for binary data, stdout or stderr.
Error due to interacting with a Proc::Async stream before spawning its process
class X::Proc::Async::MustBeStarted is Exception {}
Several methods from Proc::Async expect that the external program has been spawned (by calling .start on it), including say, write, print and close-stdin. If one of those methods is called before .start was called, they throw an exception of type X::Proc::Async::MustBeStarted.
Proc::Async.new('echo', :w).say(42); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Proc::Async::MustBeStarted: Process must be started first before calling 'say'»
method method(X::Proc::Async::MustBeStarted:D --> Str:D)
Returns the name of the method that was illegally called before starting the external program.
Error due to writing to a read-only Proc::Async object
class X::Proc::Async::OpenForWriting is Exception {}
When a Proc::Async object is opened only for reading from the external program (no :w passed to open), and a write operation such as write, print and say is performed, an exception of type X::Proc::Async::OpenForWriting is thrown:
my $proc = Proc::Async.new("echo"); $proc.start; $proc.say(42); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Proc::Async::OpenForWriting: Process must be opened for writing with :w to call 'say'»
To fix that you can use writable commands with :w flag:
my $prog = Proc::Async.new(:w, 'cat'); $prog.stdout.tap( -> $str { print $str; }); my $promise = $prog.start; await $prog.say('foo'); $prog.close-stdin; await $promise;
method method(X::Proc::Async::OpenForWriting:D:)
Returns the method name that was called and which caused the exception.
Error due to tapping a Proc::Async stream after spawning its process
class X::Proc::Async::TapBeforeSpawn is Exception {}
If the stdout or stderr methods of Proc::Async are called after the program has been started, an exception of type X::Proc::Async::TapBeforeSpawn is thrown.
my $proc = Proc::Async.new("echo", "foo"); $proc.start; $proc.stdout.tap(&print); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Proc::Async::TapBeforeSpawn: To avoid data races, you must tap stdout before running the process»
The right way is the reverse order
my $proc = Proc::Async.new("echo", "foo"); $proc.stdout.tap(&print); await $proc.start;
method handle(X::Proc::Async::TapBeforeSpawn:D: --> Str:D)
Returns the name of the handle (stdout or stderr) that was accessed after the program started.
Exception thrown if a Proc object is sunk after the process it ran exited unsuccessfully
class X::Proc::Unsuccessful is Exception {}
method proc(X::Proc::Unsuccessful:D --> Proc)
Returns the object that threw the exception.
Error due to asking why an unbroken promise has been broken.
class X::Promise::CauseOnlyValidOnBroken is Exception { }
This exception is thrown when code expects a Promise to be broken, and asks why it has been broken, but the Promise has in fact, not yet been broken.
method promise()
Returns the Promise that was asked about.
method status()
Returns the status the Promise had at that time.
Error due to directly trying to keep/break a vowed promise.
class X::Promise::Vowed is Exception { }
This exception is thrown when code tries to keep/break an already vowed promise without going through the corresponding Vow object.
method promise()
Returns the vowed Promise.
Compilation error due to declaring an already declared symbol
class X::Redeclaration does X::Comp { }
Thrown when a symbol (variable, routine, type, parameter, ...) is redeclared. Note that redeclarations are generally fine in an inner scope, but if the redeclaration appears in the same scope as the original declaration, it usually indicates an error and is treated as one.
Examples
my $x; my $x;
dies with
===SORRY!=== Redeclaration of symbol $x
It works with routines too:
sub f() { } sub f() { }
dies with
===SORRY!=== Redeclaration of routine f
But those are fine
my $x; sub f() { my $x; # not a redeclaration, # because it's in an inner scope sub f() { }; # same }
Returns the name of the symbol that was redeclared.
Returns the kind of symbol that was redeclared. Usually symbol, but can also be routine, type etc.
Returns a string that is attached to the end of the error message. It usually explains the particular problem in more detail, or suggests way to fix the problem.
Error due to passing an initialization value to an ineligible role
class X::Role::Initialization is Exception { }
Thrown when the SomeRole($init) syntax is used, but SomeRole does not have exactly one public attribute.
For example:
role R { }; "D2" but R(2) CATCH { default { put .^name, ': ', .Str } } # OUTPUT: «X::Role::Initialization: Can only supply an initialization value for a role if it has a single public attribute, but this is not the case for 'R'»
method role()
Returns the role that caused the error.
Error caused by passing NaN to Scheduler.cue as :at, :in, or :every
class X::Scheduler::CueInNaNSeconds is Exception { }
When calling ThreadPoolScheduler.cue or CurrentThreadScheduler.cue with :at, :in, or :every as NaN, this exception gets thrown. For example, the following code:
my Cancellation $c = $*SCHEDULER.cue({ say 'This will never output :('; }, at => NaN);
Throws with:
Cannot pass NaN as a number of seconds to Scheduler.cue
This class only exists in releases 2019.05 and later.
Error due to trying to reuse a consumed sequence
class X::Seq::Consumed is Exception { }
This exception is thrown when a piece of code tries to reuse a Seq which has already been iterated.
Error due to constructing a sequence from ineligible input
class X::Sequence::Deduction is Exception { }
Exception type thrown when the ... sequence operator is being called without an explicit closure, and the sequence cannot be deduced.
Compilation error due to two named parameters with the same name
my class X::Signature::NameClash does X::Comp { }
Compile time error thrown when two named parameters have the same name, potentially through aliases.
For example
sub f(:$a, :a(:@b)) { }
dies with
===SORRY!=== Name a used for more than one named parameter
method name(--> Str:D)
Returns the name that was used for more than one parameter.
Compilation error due to placeholders in a block with a signature
class X::Signature::Placeholder does X::Comp { }
Compile time error thrown when a block has both an explicit signature and placeholder parameters.
For example
sub f() { $^x }
dies with
===SORRY!=== Placeholder variable '$^x' cannot override existing signature
method placeholder(--> Str:D)
Returns the name of a placeholder that was used in a block that already had a signature.
Error while trying to coerce a string to a number
class X::Str::Numeric is Exception { }
Error thrown (or wrapped in a Failure) when a conversion from string to a number fails.
For example
say +"42 answers"; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Str::Numeric: Cannot convert string to number: trailing characters after number in '42⏏ answers' (indicated by ⏏)»
method source(--> Str:D)
Returns the string that was attempted to convert to a number
method pos(--> Int:D)
Gives the position into the string where the parsing failed.
method reason(--> Int:D)
Verbal description of the reason why the conversion failed.
Runtime error due to execution of stub code
class X::StubCode is Exception { }
Thrown when a piece of stub code (created via !!! or ...) is executed.
Returns the custom message provided to !!!, or a reasonable default if none was provided.
Syntax error thrown by the compiler
role X::Syntax does X::Comp { }
Common role for syntax errors thrown by the compiler.
Compilation error due to augmenting a type without the
class X::Syntax::Augment::WithoutMonkeyTyping does X::Syntax { }
Compile time error thrown when augment is used without use MONKEY-TYPING.
Since augment is considered a rather unsafe and impolite action, you have to pre-declare your intent with the use MONKEY-TYPING; pragma.
If you don't do that, like here
augment class Int { };
you get the error
===SORRY!=== augment not allowed without 'use MONKEY-TYPING'
Compilation error due to a malformed inline comment
class X::Syntax::Comment::Embedded does X::Syntax { }
Syntax error thrown when #` is encountered and it is not followed by an opening curly brace.
For example
#`
dies with
===SORRY!=== Opening bracket is required for #` comment
Compilation error due to unrecognized syntax
class X::Syntax::Confused does X::Syntax { }
The most general syntax error, if no more specific error message can be given.
For example
1∞
dies with
===SORRY!=== Confused
Compilation error due to an infix in term position
class X::Syntax::InfixInTermPosition does X::Syntax { }
Syntax error thrown when the parser expects a term, but finds an infix operator instead.
For example
1, => 2;
dies with
===SORRY!=== Preceding context expects a term, but found infix => instead
method infix(--> Str:D)
Returns the symbol of the infix that was found in term position.
Compilation error due to a malformed construct (usually a declarator)
class X::Syntax::Malformed does X::Syntax {}
The Perl 6 compiler throws errors of type X::Syntax::Malformed when it knows what kind of declaration it is parsing, and encounters a syntax error, but can't give a more specific error message.
my Int a; # throws an X::Syntax::Malformed
produces
===SORRY!=== Malformed my at -e:1 ------> my Int ⏏a
method what(X::Syntax::Malformed:D: --> Str)
Returns a description of the thing that was being parsed.
Compilation error due to a missing piece of syntax
class X::Syntax::Missing does X::Syntax { }
Syntax error thrown when the previous piece of syntax requires the existence of another piece of syntax, and that second piece is missing.
For example
for 1, 2, 3;
dies with
===SORRY!=== Missing block
because a for that is not a statement modifier must be followed by a block.
method what(--> Str:D)
Returns a string description of the missing syntax element.
Compilation error due to passing an argument to a negated colonpair
class X::Syntax::NegatedPair does X::Syntax { }
Thrown if a colonpair illegally has a value, for example :!a(1). This is an error because the ! negation implies that the value is False.
A typical error message from this class is Argument not allowed on negated pair with key 'a'.
Returns the key of the pair that caused the error.
Compilation error due to implicitly using a
class X::Syntax::NoSelf does X::Syntax { }
Compile time error thrown when $.foo style calls are used where no invocant is available.
For example the code
$.meth;
in the program body throws the error
===SORRY!=== Variable $.meth used where no 'self' is available
because $.meth is short for $(self.meth), and there is no self available in mainline.
Returns the variable/method call that caused the error.
Compilation error due to an unallowed radix in a number literal
class X::Syntax::Number::RadixOutOfRange does X::Syntax { }
Syntax error that is thrown when the radix of a radix number is not allowed, like :1<1> or :42<ouch> .
method radix(--> Int:D)
The offensive radix.
Compilation error due to use of Perl 5-only syntax
class X::Syntax::P5 does X::Syntax { }
Syntax error thrown when some piece of code is clearly Perl 5, not Perl 6.
For example
for my $a (1, 2) { };
dies with
===SORRY!=== This appears to be Perl 5 code
Compilation error due to an unrecognized regex adverb
class X::Syntax::Regex::Adverb does X::Syntax { }
Syntax error thrown when an unrecognized or illegal regex adverb is encountered.
For example
rx:g/a/
dies with
===SORRY!=== Adverb g not allowed on rx
because :g belongs to a match operation, not a regex itself.
method adverb(--> Str:D)
Returns the illegally used adverb
method construct(--> Str:D)
Returns the name of the construct that adverb was used on (m, ms, rx, s, ss).
Compilation error due to a regex quantifier without preceding atom
class X::Syntax::Regex::SolitaryQuantifier does X::Syntax { }
Syntax error when a stand alone quantifier (without a preceding atom to quantify) is encountered in a regular expression.
For example
/ * /;
dies with
===SORRY!=== Quantifier quantifies nothing
Compilation error due to use of syntax reserved for future use
class X::Syntax::Reserved does X::Syntax { }
Syntax error thrown when a syntax is used which is reserved for future expansion.
For example
my @a();
dies with
===SORRY!=== The () shape syntax in array declarations is reserved
method reserved(--> Str:D)
Returns a text description of the reserved syntax.
method instead(--> Str)
Describes what to use instead of the reserved syntax (if anything).
Compilation error due to invoking
class X::Syntax::Self::WithoutObject does X::Syntax { }
Syntax error thrown when self is referenced in a place where no invocant is available.
For example
self;
outside a class or role declaration dies with
===SORRY!=== 'self' used where no object is available
Compilation error due to a misplaced invocant marker in a signature
class X::Syntax::Signature::InvocantMarker does X::Syntax { }
Syntax error when the invocant in a signature is anywhere else than after the first parameter.
For example
:($a, $b: $c);
dies with
===SORRY!=== Can only use : as invocant marker in a signature after the first parameter
See also: Signature.
Compilation error due to declaring a term without initialization
class X::Syntax::Term::MissingInitializer does X::Syntax { }
Syntax error when a term (a backslash variable) is declared without initialization assignment.
For example
my \foo;
dies with
===SORRY!=== Term definition requires an initializer
Valid code would be
my \foo = 42;
Compilation error due to an
class X::Syntax::UnlessElse does X::Syntax { }
Syntax error thrown when an unless clause is followed by an else clause.
For example
unless 1 { } else { };
dies with
===SORRY!=== "unless" does not take "else", please rewrite using "if"
Compilation error due to declaring a match variable
class X::Syntax::Variable::Match does X::Syntax { }
Syntax error thrown when a match variable like $<thing> was declared.
For example
my $<thing>;
dies with
===SORRY!=== Cannot declare a match variable
Compilation error due to declaring a numeric symbol
class X::Syntax::Variable::Numeric does X::Syntax { }
Syntax error thrown when trying to declare numeric symbols.
For example
my @101;
dies with
===SORRY!=== Cannot declare a numeric variable
method what returns Str:D
Returns a verbal description of the kind of symbol that was declared (variable, parameter, attribute).
Compilation error due to an unallowed twigil in a declaration
class X::Syntax::Variable::Twigil does X::Syntax { }
Syntax error thrown when a variable with a twigil is used in an incompatible declaration.
For example
my $!foo;
dies with
===SORRY!=== Cannot use ! twigil on my variable
method twigil(--> Str:D)
Returns the twigil that was illegally used
method scope(--> Str:D)
Returns the scope that did not harmonize with the twigil.
Error related to DateTime or Date
role X::Temporal is Exception { }
A common exception type for all errors related to DateTime or Date.
Error due to using an invalid format when creating a DateTime or Date
class X::Temporal::InvalidFormat does X::Temporal is Exception { }
This exception is thrown when code tries to create a DateTime or Date object using an invalid format.
my $dt = Date.new("12/25/2015"); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Temporal::InvalidFormat: Invalid Date string '12/25/2015'; use yyyy-mm-dd instead»
Returns the invalid format string (12/25/2015 in the example above)
Returns the target type (Date in the example above)
Returns valid format strings for the target type in question, (yyyy-mm-dd in the example above)
Error due to a failed type check
class X::TypeCheck is Exception { }
Error class thrown when a type check fails.
method operation(--> Str:D)
Returns a string description of the operation that failed, for example "assignment", "binding", "return".
method got()
Returns the object that failed to type check
method expected()
Returns the type object against which the check failed.
Error due to a failed type check during assignment
class X::TypeCheck::Assignment is X::TypeCheck { }
Error class thrown when the type check of an assignment fails.
For example, this will die
my Int $x = "foo"; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $x; expected Int but got Str ("foo")»
though compilers are allowed to detect obvious cases like this example and complain at compile time with a different error.
Error due to a failed type check during binding
class X::TypeCheck::Binding is X::TypeCheck { }
Thrown when the type check of a binding operation fails.
For example:
my Int $x := "foo"; CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Binding: Type check failed in binding; expected Int but got Str ("foo")»
Note that the compiler is free to detect obvious errors at compile time, and complain with a different error at compile time.
Error due to a failed typecheck during
class X::TypeCheck::Return is X::TypeCheck { }
Thrown when a return type check fails.
For example
sub f(--> Int) { "foo" } f(); CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::TypeCheck::Return: Type check failed for return value; expected Int but got Str ("foo")»
Compilation error due to a macro trying to splice a non-AST value
class X::TypeCheck::Splice is X::TypeCheck does X::Comp { }
Compile time error thrown when a Macro or an unquote/hole in a quasi quote does not return an AST.
For example
use experimental :macros; macro quasi-ast { quasi { {{{'not AST'}}} };}; say quasi-ast;
dies with
===SORRY!=== Type check failed in macro application; expected AST but got Str("not AST")
This is because you are purposefully creating something that does not evaluate to an abstract syntax tree. To fix, instead write
use experimental :macros; macro an-ast { quasi { 'yes AST' } } say an-ast; # OUTPUT: «yes AST»
method action(--> Str:D)
Returns a verbal description of the action that triggered the error, "macro application" or "unquote evaluation".
Compilation error due to an undeclared symbol
class X::Undeclared does X::Comp {}
Thrown when the compiler encounters a symbol that has not been declared, but needs to be.
Example
$x;
results in
===SORRY!=== Variable $x is not declared
Returns the name of the undeclared symbol
Returns the kind of symbol that was not declared (for example variable, type, routine).
Since The symbol wasn't declared, the compiler sometimes has to guess (or rather disambiguate) what kind of symbol it encounter that wasn't declared. For example if you write
say a;
Then the disambiguation defaults to reporting a missing subroutine, even though declaring a constant a = 'a' would also make the error go away.
Integer (native storage at the platform's atomic operation size)
class atomicint is Int is repr('P6int') { }
An atomicint is a native integer sized such that CPU-provided atomic operations can be performed upon it. On a 32-bit CPU it will typically be 32 bits in size, and on an a 64-bit CPU it will typically be 64 bits in size. It exists to allow writing portable code that uses atomic operations.
Note: Rakudo releases before 2017.08 had no support for atomicints.
# Would typically only work on a 64-bit machine and VM build. my int64 $active = 0; $active⚛++; # Would typically only work on a 32-bit machine and VM build. my int32 $active = 0; $active⚛++; # Will work portably, though can only portably assume range of 32 bits. my atomicint $active = 0; $active⚛++;
The use of the atomicint type does not automatically provide atomicity; it must be used in conjunction with the atomic operations.
# Correct (will always output 80000) my atomicint $total = 0; await start { for ^20000 { $total⚛++ } } xx 4; say $total; # *** WRONG *** due to lack of use of the atomicint type. # Either works correctly or dies, depending on platform. my int $total = 0; await start { for ^20000 { $total⚛++ } } xx 4; say $total; # *** WRONG *** due to lack of use of the atomic increment operator. my atomicint $total = 0; await start { for ^20000 { $total++ } } xx 4; say $total;
Defined as:
multi sub atomic-assign(atomicint $ is rw, int $value) multi sub atomic-assign(atomicint $ is rw, Int() $value)
Performs an atomic assignment to a native integer, which may be in a lexical, attribute, or native array element. If $value cannot unbox to a 64-bit native integer due to being too large, an exception will be thrown. If the size of atomicint is only 32 bits, then an out of range $value will be silently truncated. The atomic-assign routine ensures that any required barriers are performed such that the changed value will be "published" to other threads.
Defined as:
multi sub atomic-fetch(atomicint $ is rw)
Performs an atomic read of a native integer, which may live in a lexical, attribute, or native array element. Using this routine instead of simply using the variable ensures that the latest update to the variable from other threads will be seen, both by doing any required hardware barriers and also preventing the compiler from lifting reads. For example:
my atomicint $i = 0; start { atomic-assign($i, 1) } while atomic-fetch($i) == 0 { }
Is certain to terminate, while in:
my atomicint $i = 0; start { atomic-assign($i, 1) } while $i == 0 { }
It would be legal for a compiler to observe that $i is not updated in the loop, and so lift the read out of the loop, thus causing the program to never terminate.
Defined as:
multi sub atomic-fetch-inc(atomicint $ is rw)
Performs an atomic increment on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value as seen before incrementing it. Overflow will wrap around silently.
Defined as:
multi sub atomic-fetch-dec(atomicint $ is rw)
Performs an atomic decrement on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value as seen before decrementing it. Overflow will wrap around silently.
Defined as:
multi sub atomic-fetch-add(atomicint $ is rw, int $value) multi sub atomic-fetch-add(atomicint $ is rw, Int() $value)
Performs an atomic addition on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value as seen before the addition was performed. Overflow will wrap around silently. If $value is too big to unbox to a 64-bit integer, an exception will be thrown. If $value otherwise overflows atomicint then it will be silently truncated before the addition is performed.
Defined as:
multi sub atomic-fetch-sub(atomicint $ is rw, int $value) multi sub atomic-fetch-sub(atomicint $ is rw, Int() $value)
Performs an atomic subtraction on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value as seen before the subtraction was performed. Underflow will wrap around silently. If $value is too big to unbox to a 64-bit integer, an exception will be thrown. If $value otherwise overflows atomicint then it will be silently truncated before the subtraction is performed.
multi sub atomic-inc-fetch(atomicint $ is rw)
Performs an atomic increment on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value resulting from the increment. Overflow will wrap around silently.
multi sub atomic-dec-fetch(atomicint $ is rw)
Performs an atomic decrement on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value resulting from the decrement. Overflow will wrap around silently.
Defined as:
multi sub cas(atomicint $target is rw, int $expected, int $value) multi sub cas(atomicint $target is rw, Int() $expected, Int() $value) multi sub cas(atomicint $target is rw, &operation)
Performs an atomic compare and swap of the native integer value in location $target. The first two forms have semantics like:
my int $seen = $target; if $seen == $expected { $target = $value; } return $seen;
Except it is performed as a single hardware-supported atomic instruction, as if all memory access to $target were blocked while it took place. Therefore it is safe to attempt the operation from multiple threads without any other synchronization. For example:
my atomicint $master = 0; await start { if cas($master, 0, 1) == 0 { say "Master!" } } xx 4
Will reliably only ever print Master! one time, as only one of the threads will be successful in changing the 0 into a 1.
Both $expected and $value will be coerced to Int and unboxed if needed. An exception will be thrown if the value cannot be represented as a 64-bit integer. If the size of atomicint is only 32 bits then the values will be silently truncated to this size.
The third form, taking a code object, will first do an atomic fetch of the current value and invoke the code object with it. It will then try to do an atomic compare and swap of the target, using the value passed to the code object as $expected and the result of the code object as $value. If this fails, it will read the latest value, and retry, until a CAS operation succeeds. Therefore, an atomic multiply of an atomicint $i by 2 could be implemented as:
cas $i, -> int $current { $current * 2 }
If another thread changed the value while $current * 2 was being calculated then the block would be called again with the latest value for a further attempt, and this would be repeated until success.
multi sub infix:<⚛=>(atomicint $ is rw, int $value) multi sub infix:<⚛=>(atomicint $ is rw, Int() $value)
Performs an atomic assignment to a native integer, which may be in a lexical, attribute, or native array element. If $value cannot unbox to a 64-bit native integer due to being too large, an exception will be thrown. If the size of atomicint is only 32 bits, then an out of range $value will be silently truncated. The ⚛= operator ensures that any required barriers are performed such that the changed value will be "published" to other threads.
multi sub prefix:<⚛>(atomicint $ is rw)
Performs an atomic read of a native integer, which may live in a lexical, attribute, or native array element. Using this operator instead of simply using the variable ensures that the latest update to the variable from other threads will be seen, both by doing any required hardware barriers and also preventing the compiler from lifting reads. For example:
my atomicint $i = 0; start { $i ⚛= 1 } while ⚛$i == 0 { }
Is certain to terminate, while in:
my atomicint $i = 0; start { $i ⚛= 1 } while $i == 0 { }
It would be legal for a compiler to observe that $i is not updated in the loop, and so lift the read out of the loop, thus causing the program to never terminate.
multi sub prefix:<++⚛>(atomicint $ is rw)
Performs an atomic increment on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value resulting from the increment. Overflow will wrap around silently.
multi sub postfix:<⚛++>(atomicint $ is rw)
Performs an atomic increment on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value as seen before incrementing it. Overflow will wrap around silently.
multi sub prefix:<--⚛>(atomicint $ is rw)
Performs an atomic decrement on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value resulting from the decrement. Overflow will wrap around silently.
multi sub postfix:<⚛-->(atomicint $ is rw)
Performs an atomic decrement on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Returns the value as seen before decrementing it. Overflow will wrap around silently.
Defined as:
multi sub infix:<⚛+=>(atomicint $ is rw, int $value) multi sub infix:<⚛+=>(atomicint $ is rw, Int() $value)
Performs an atomic addition on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Evaluates to the result of the addition. Overflow will wrap around silently. If $value is too big to unbox to a 64-bit integer, an exception will be thrown. If $value otherwise overflows atomicint then it will be silently truncated before the addition is performed.
Defined as:
multi sub infix:<⚛-=>(atomicint $ is rw, int $value) multi sub infix:<⚛-=>(atomicint $ is rw, Int() $value)
Performs an atomic subtraction on a native integer. This will be performed using hardware-provided atomic operations. Since the operation is atomic, it is safe to use without acquiring a lock. Evaluates to the result of the subtraction. Underflow will wrap around silently. If $value is too big to unbox to a 64-bit integer, an exception will be thrown. If $value otherwise overflows atomicint then it will be silently truncated before the subtraction is performed.
Synonym for ⚛-= using U+2212 minus.
Routines not defined within any class or role.
These routines are defined in different files together with a class, but are not actually attached to any particular class or role.
Defined as:
proto sub EVAL($code where Blob|Cool|Callable, Str() :$lang = 'perl6', PseudoStash :$context, *%n)
multi sub EVAL($code, Str :$lang where { ($lang // '') eq 'Perl5' }, PseudoStash :$context)
This routine coerces Cool $code to Str. If $code is a Blob, it'll be processed using the same encoding as the $lang compiler would: for perl6 $lang, uses utf-8; for Perl5, processes using the same rules as perl.
This works as-is with a literal string parameter. More complex input, such as a variable or string with embedded code, is illegal by default. This can be overridden in any of several ways:
use MONKEY-SEE-NO-EVAL; # Or... use MONKEY; # shortcut that turns on all MONKEY pragmas use Test; # any of the above allows: EVAL "say { 5 + 5 }"; # OUTPUT: «10»
In case the MONKEY-SEE-NO-EVAL pragma is not activated, the compiler will complain with a EVAL is a very dangerous function!!! exception. And it is essentially right, since that will run arbitrary code with the same permissions as the program. You should take care of cleaning the code that is going to pass through EVAL if you activate the MONKEY-SEE-NO-EVAL pragma.
Please note that you can interpolate to create routine names using quotation, as can be seen in this example or other ways to interpolate to create identifier names. This only works, however, for already declared functions and other objects and is thus safer to use.
Symbols in the current lexical scope are visible to code in an EVAL.
my $answer = 42; EVAL 'say $answer;'; # OUTPUT: «42»
However, since the set of symbols in a lexical scope is immutable after compile time, an EVAL can never introduce symbols into the surrounding scope.
EVAL 'my $lives = 9'; say $lives; # error, $lives not declared
Furthermore, the EVAL is evaluated in the current package:
module M { EVAL 'our $answer = 42' } say $M::answer; # OUTPUT: «42»
And also in the current language, meaning any added syntax is available:
sub infix:<mean>(*@a) is assoc<list> { @a.sum / @a.elems } EVAL 'say 2 mean 6 mean 4'; # OUTPUT: «4»
An EVAL statement evaluates to the result of the last statement:
sub infix:<mean>(*@a) is assoc<list> { @a.sum / @a.elems } say EVAL 'say 1; 2 mean 6 mean 4'; # OUTPUT: «14»
EVAL is also a gateway for executing code in other languages:
EVAL "use v5.20; say 'Hello from perl5!'", :lang<Perl5>;
You need to have Inline::Perl5 for this to work correctly.
Defined as:
sub EVALFILE($filename where Blob|Cool, :$lang = 'perl6')
Slurps the specified file and evaluates it. Behaves the same way as EVAL with regard to Blob decoding, scoping, and the $lang parameter. Evaluates to the value produced by the final statement in the file.
EVALFILE "foo.p6";
Defined as:
sub mkdir(IO() $path, Int() $mode = 0o777 --> IO::Path:D)
Creates a new directory; see mode for explanation and valid values for $mode. Returns the IO::Path object pointing to the newly created directory on success; fails with X::IO::Mkdir if directory cannot be created.
Also creates parent directories, as needed (similar to *nix utility mkdir with -p option); that is, mkdir "foo/bar/ber/meow" will create foo, foo/bar, and foo/bar/ber directories if they do not exist, as well as foo/bar/ber/meow.
Defined as:
sub chdir(IO() $path, :$d = True, :$r, :$w, :$x --> IO::Path:D)
Changes value of $*CWD variable to the provided $path, optionally ensuring the new path passes several file tests. NOTE: that this routine does NOT alter the process's current directory (see &*chdir).
Returns IO::Path representing new $*CWD on success. On failure, returns Failure and leaves $*CWD untouched. The $path can be any object with an IO method that returns an IO::Path object. The available file tests are:
:d — check .d returns True
:r — check .r returns True
:w — check .w returns True
:x — check .x returns True
By default, only :d test is performed.
chdir '/tmp'; # change $*CWD to '/tmp' and check its .d is True chdir :r, :w, '/tmp'; # … check its .r and .w are True chdir '/not-there'; # returns Failure
Note that the following construct is a mistake:
# WRONG! DO NOT DO THIS! my $*CWD = chdir '/tmp/';
Use indir instead.
Defined as:
PROCESS::<&chdir> = sub (IO() $path --> IO::Path:D) { }
Changes value of $*CWD variable to the provided $path and sets the process's current directory to the value of $path.absolute. NOTE: that in most cases, you want to use chdir routine instead.
Returns an IO::Path representing the new $*CWD on success. On failure, returns Failure and leaves $*CWD untouched. The $path can be any object with an IO method that returns an IO::Path object.
Note that unlike regular chdir, there are no arguments to specify which file tests to perform.
&*chdir('/tmp'); # change $*CWD and process's current directory to '/tmp' &*chdir('/not-there'); # returns Failure
Note that the following construct is a mistake:
# WRONG! DO NOT DO THIS! my $*CWD = &*chdir('/tmp');
Use the following, instead; or see indir if you do not need to change process's current directory:
temp $*CWD; &*chdir('/tmp');
Defined as:
sub chmod(Int() $mode, *@filenames --> List)
Coerces all @filenames to IO::Path and calls IO::Path.chmod with $mode on them. Returns a List containing a subset of @filenames for which chmod was successfully executed.
chmod 0o755, <myfile1 myfile2>; # make two files executable by the owner
Defined as:
sub indir(IO() $path, &code, :$d = True, :$r, :$w, :$x --> Mu)
Takes Callable &code and executes it after locally (to &code) changing $*CWD variable to an IO::Path object based on $path, optionally ensuring the new path passes several file tests. If $path is relative, it will be turned into an absolute path, even if an IO::Path object was given. NOTE: that this routine does NOT alter the process's current directory (see &*chdir). The $*CWD outside of the &code is not affected, even if &code explicitly assigns a new value to $*CWD.
Returns the return value of &code on success. On failure to successfully change $*CWD, returns Failure. WARNING: keep in mind that lazily evaluated things might end up NOT having the $*CWD set by indir in their dynamic scope by the time they're actually evaluated. Either ensure the generators have their $*CWD set or eagerly evaluate them before returning the results from indir:
say indir("/tmp", { gather { take ".".IO } })».CWD; # OUTPUT: «(/home/camelia)» say indir("/tmp", { eager gather { take ".".IO } })».CWD; # OUTPUT: «(/tmp)» say indir("/tmp", { my $cwd = $*CWD; gather { temp $*CWD = $cwd; take ".".IO } })».CWD; # OUTPUT: «(/tmp)»
The routine's $path argument can be any object with an IO method that returns an IO::Path object. The available file tests are:
:d — check .d returns True
:r — check .r returns True
:w — check .w returns True
:x — check .x returns True
By default, only :d test is performed.
say $*CWD; # OUTPUT: «"/home/camelia".IO» indir '/tmp', { say $*CWD }; # OUTPUT: «"/tmp".IO» say $*CWD; # OUTPUT: «"/home/camelia".IO» indir '/not-there', {;}; # returns Failure; path does not exist
Defined as:
multi sub print(**@args --> True) multi sub print(Junction:D --> True)
Prints the given text on standard output (the $*OUT filehandle), coercing non-Str objects to Str by calling .Str method. Junction arguments autothread and the order of printed strings is not guaranteed.
print "Hi there!\n"; # OUTPUT: «Hi there!» print "Hi there!"; # OUTPUT: «Hi there!» print [1, 2, 3]; # OUTPUT: «1 2 3»
To print text and include the trailing newline, use put.
Defined as:
multi sub put(**@args --> True) multi sub put(Junction:D --> True)
Same as print, except it uses print-nl (which prints a newline, by default) at the end. Junction arguments autothread and the order of printed strings is not guaranteed.
put "Hi there!\n"; # OUTPUT: «Hi there!» put "Hi there!"; # OUTPUT: «Hi there!» put [1, 2, 3]; # OUTPUT: «1 2 3»
Defined as:
multi sub say(**@args --> True)
Prints the "gist" of given objects. Same as put, except uses .gist method to obtain string representation of the object.
NOTE: the .gist method of some objects, such as Lists, returns only partial information about the object (hence the "gist"). If you mean to print textual information, you most likely want to use put instead.
say Range; # OUTPUT: «(Range)» say class Foo {}; # OUTPUT: «(Foo)» say 'I ♥ Perl6'; # OUTPUT: «I ♥ Perl6» say 1..Inf; # OUTPUT: «1..Inf»
Defined as:
method note(Mu: -->Bool:D) multi sub note( --> Bool:D) multi sub note(Str:D $note --> Bool:D) multi sub note(**@args --> Bool:D)
Like say, except prints output to $*ERR handle (STDERR). If no arguments are given to subroutine forms, will use string "Noted".
note; # STDERR OUTPUT: «Noted» note 'foo'; # STDERR OUTPUT: «foo» note 1..*; # STDERR OUTPUT: «1..Inf»
multi sub prompt() multi sub prompt($msg)
Prints $msg to $*OUT handle if $msg was provided, then gets a line of input from $*IN handle. By default, this is equivalent to printing $msg to STDOUT, reading a line from STDIN, removing the trailing new line, and returning the resultant string. As of Rakudo 2018.08, prompt will create allomorphs for numeric values, equivalent to calling val prompt.
my $name = prompt "What's your name? "; say "Hi, $name! Nice to meet you!"; my $age = prompt("Say your age (number)"); my Int $years = $age; my Str $age-badge = $age;
In the code above, $age will be duck-typed to the allomorph IntStr if it's entered correctly as a number.
multi sub open(IO() $path, |args --> IO::Handle:D)
Creates a handle with the given $path, and calls IO::Handle.open, passing any of the remaining arguments to it. Note that IO::Path type provides numerous methods for reading and writing from files, so in many common cases you do not need to open files or deal with IO::Handle type directly.
my $fh = open :w, '/tmp/some-file.txt'; $fh.say: 'I ♥ writing Perl code'; $fh.close; $fh = open '/tmp/some-file.txt'; print $fh.readchars: 4; $fh.seek: 7, SeekFromCurrent; say $fh.readchars: 4; $fh.close; # OUTPUT: «I ♥ Perl»
Defined as:
multi sub slurp(IO::Handle:D $fh = $*ARGFILES, |c) multi sub slurp(IO() $path, |c)
Slurps the contents of the entire file into a Str (or Buf if :bin). Accepts :bin and :enc optional named parameters, with the same meaning as open(); possible encodings are the same as in all the other IO methods and are listed in encoding routine. The routine will fail if the file does not exist, or is a directory. Without any arguments, sub slurp operates on $*ARGFILES, which defaults to $*IN in the absence of any filenames.
# read entire file as (Unicode) Str my $text_contents = slurp "path/to/file"; # read entire file as Latin1 Str my $text_contents = slurp "path/to/file", enc => "latin1"; # read entire file as Buf my $binary_contents = slurp "path/to/file", :bin;
Defined as:
multi spurt(IO() $path, |c)
The $path can be any object with an IO method that returns an IO::Path object. Calls IO::Path.spurt on the $path, forwarding any of the remaining arguments.
:enc
The encoding with which the contents will be written.
:append
Boolean indicating whether to append to a (potentially) existing file. If the file did not exist yet, it will be created. Defaults to False.
:createonly
Boolean indicating whether to fail if the file already exists. Defaults to False.
# write directly to a file spurt 'path/to/file', 'default text, directly written'; # write directly with a non-Unicode encoding spurt 'path/to/latin1_file', 'latin1 text: äöüß', :enc<latin1>; spurt 'file-that-already-exists', 'some text'; # overwrite file's contents: spurt 'file-that-already-exists', ' new text', :append; # append to file's contents: say slurp 'file-that-already-exists'; # OUTPUT: «some text new text» # fail when writing to a pre-existing file spurt 'file-that-already-exists', 'new text', :createonly; # OUTPUT: «Failed to open file /home/camelia/file-that-already-exists: file already exists …»
Defined as:
sub run( *@args ($, *@), :$in = '-', :$out = '-', :$err = '-', Bool :$bin = False, Bool :$chomp = True, Bool :$merge = False, Str:D :$enc = 'UTF-8', Str:D :$nl = "\n", :$cwd = $*CWD, Hash() :$env = %*ENV --> Proc:D)
Runs an external command without involving a shell and returns a Proc object. By default, the external command will print to standard output and error, and read from standard input.
run 'touch', '>foo.txt'; # Create a file named >foo.txt run <<rm >foo.txt>>; # Another way to use run, using word quoting for the # arguments
If you want to pass some variables you can still use < >, but try to avoid using « » as it will do word splitting if you forget to quote variables:
my $file = ‘--my arbitrary filename’; run ‘touch’, ‘--’, $file; # RIGHT run <touch -->, $file; # RIGHT run «touch -- "$file"»; # RIGHT but WRONG if you forget quotes run «touch -- $file»; # WRONG; touches ‘--my’, ‘arbitrary’ and ‘filename’ run ‘touch’, $file; # WRONG; error from `touch` run «touch "$file"»; # WRONG; error from `touch`
Note that -- is required for many programs to disambiguate between command-line arguments and filenames that begin with hyphens.
A sunk Proc object for a process that exited unsuccessfully will throw. If you wish to ignore such failures, simply use run in non-sink context:
run 'false'; # SUNK! Will throw run('false').so; # OK. Evaluates Proc in Bool context; no sinking
If you want to capture standard output or error instead of having it printed directly you can use the :out or :err arguments respectively, which will make them available using the Proc.out method:
my $proc = run 'echo', 'Perl 6 is Great!', :out, :err; $proc.out.slurp(:close).say; # OUTPUT: «Perl 6 is Great!» $proc.err.slurp(:close).say; # OUTPUT: «»
You can use these arguments to redirect them to a filehandle, thus creating a kind of pipe:
my $ls-alt-handle = open :w, '/tmp/cur-dir-ls-alt.txt'; my $proc = run "ls", "-alt", :out($ls-alt-handle); # (The file will contain the output of the ls -alt command)
These argument are quite flexible and admit, for instance, handles to redirect them. See Proc and Proc::Async for more details.
See also new for more examples.
multi sub shell($cmd, :$in = '-', :$out = '-', :$err = '-', Bool :$bin, Bool :$chomp = True, Bool :$merge, Str :$enc, Str:D :$nl = "\n", :$cwd = $*CWD, :$env)
Runs a command through the system shell, which defaults to %*ENV<ComSpec> /c in Windows, /bin/sh -c otherwise. All shell meta characters are interpreted by the shell, including pipes, redirects, environment variable substitutions and so on. Shell escapes are a severe security concern and can cause confusion with unusual file names. Use run if you want to be safe.
The return value is of type Proc.
shell 'ls -lR | gzip -9 > ls-lR.gz';
See Proc for more details, for example on how to capture output.
Defined as:
method unpolar(Real $angle) multi sub unpolar(Real $mag, Real $angle)
Returns a Complex with the coordinates corresponding to the angle in radians and magnitude corresponding to the object value or $mag in the case it's being used as a sub
say 1.unpolar(⅓*pi); # OUTPUT: «0.5000000000000001+0.8660254037844386i»
Defined as:
method printf (*@args) multi sub printf(Cool:D $format, *@args)
As a method, takes the object as a format using the same language as Str.sprintf; as a sub, its first argument will be the format string, and the rest of the arguments will be substituted in the format following the format conventions.
"%s is %s".printf("þor", "mighty"); # OUTPUT: «þor is mighty» printf( "%s is %s", "þor", "mighty"); # OUTPUT: «þor is mighty»
Defined as:
method sprintf(*@args) multi sub sprintf(Cool:D $format, *@args)
Formats and outputs a string, following the same language as Str.sprintf, using as such format either the object (if called in method form) or the first argument (if called as a routine)
sprintf( "%s the %d%s", "þor", 1, "st").put; #OUTPUT: «þor the 1st» sprintf( "%s is %s", "þor", "mighty").put; # OUTPUT: «þor is mighty» "%s's weight is %.2f %s".sprintf( "Mjölnir", 3.3392, "kg").put; # OUTPUT: «Mjölnir's weight is 3.34 kg»
This function is mostly identical to the C library's sprintf and printf functions. The only difference between the two functions is that sprintf returns a string while the printf function writes to a filehandle. sprintf returns a Str, not a literal.
The $format is scanned for % characters. Any % introduces a format token. Directives guide the use (if any) of the arguments. When a directive other than % is used, it indicates how the next argument passed is to be formatted into the string to be created.
The directives are:
% | a literal percent sign |
c | a character with the given codepoint |
s | a string |
d | a signed integer, in decimal |
u | an unsigned integer, in decimal |
o | an unsigned integer, in octal |
x | an unsigned integer, in hexadecimal |
e | a floating-point number, in scientific notation |
f | a floating-point number, in fixed decimal notation |
g | a floating-point number, in %e or %f notation |
X | like x, but using uppercase letters |
E | like e, but using an uppercase "E" |
G | like g, but with an uppercase "E" (if applicable) |
b | an unsigned integer, in binary |
Compatibility:
i | a synonym for %d |
D | a synonym for %ld |
U | a synonym for %lu |
O | a synonym for %lo |
F | a synonym for %f |
Modifiers change the meaning of format directives, but are largely no-ops (the semantics are still being determined).
h | interpret integer as native "short" (typically int16) | |
NYI | l | interpret integer as native "long" (typically int32 or int64) |
NYI | ll | interpret integer as native "long long" (typically int64) |
NYI | L | interpret integer as native "long long" (typically uint64) |
NYI | q | interpret integer as native "quads" (typically int64 or larger) |
Between the % and the format letter, you may specify several additional attributes controlling the interpretation of the format. In order, these are:
An explicit format parameter index, such as 2$. By default, sprintf will format the next unused argument in the list, but this allows you to take the arguments out of order:
sprintf '%2$d %1$d', 12, 34; # OUTPUT: «34 12» sprintf '%3$d %d %1$d', 1, 2, 3; # OUTPUT: «3 1 1»
One or more of:
space | prefix non-negative number with a space |
+ | prefix non-negative number with a plus sign |
- | left-justify within the field |
0 | use leading zeros, not spaces, for required padding |
# | ensure the leading "0" for any octal, prefix non-zero hexadecimal with "0x" or "0X", prefix non-zero binary with "0b" or "0B" |
For example:
sprintf '<% d>', 12; # RESULT: «< 12>» sprintf '<% d>', 0; # RESULT: «< 0>"» sprintf '<% d>', -12; # RESULT: «<-12>» sprintf '<%+d>', 12; # RESULT: «<+12>» sprintf '<%+d>', 0; # RESULT: «<+0>"» sprintf '<%+d>', -12; # RESULT: «<-12>» sprintf '<%6s>', 12; # RESULT: «< 12>» sprintf '<%-6s>', 12; # RESULT: «<12 >» sprintf '<%06s>', 12; # RESULT: «<000012>» sprintf '<%#o>', 12; # RESULT: «<014>» sprintf '<%#x>', 12; # RESULT: «<0xc>» sprintf '<%#X>', 12; # RESULT: «<0XC>» sprintf '<%#b>', 12; # RESULT: «<0b1100>» sprintf '<%#B>', 12; # RESULT: «<0B1100>»
When a space and a plus sign are given as the flags at once, the space is ignored:
sprintf '<%+ d>', 12; # RESULT: «<+12>» sprintf '<% +d>', 12; # RESULT: «<+12>»
When the # flag and a precision are given in the %o conversion, the necessary number of 0s is added at the beginning. If the value of the number is 0 and the precision is 0, it will output nothing; precision 0 or smaller than the actual number of elements will return the number with 0 to the left:
say sprintf '<%#.5o>', 0o12; # OUTPUT: «<00012>» say sprintf '<%#.5o>', 0o12345; # OUTPUT: «<012345>» say sprintf '<%#.0o>', 0; # OUTPUT: «<>» zero precision and value 0 results in no output! say sprintf '<%#.0o>', 0o1 # OUTPUT: «<01>»
This flag tells Perl 6 to interpret the supplied string as a vector of integers, one for each character in the string. Perl 6 applies the format to each integer in turn, then joins the resulting strings with a separator (a dot, '.', by default). This can be useful for displaying ordinal values of characters in arbitrary strings:
NYI sprintf "%vd", "AB\x[100]"; # "65.66.256"
You can also explicitly specify the argument number to use for the join string using something like *2$v; for example:
NYI sprintf '%*4$vX %*4$vX %*4$vX', # 3 IPv6 addresses @addr[1..3], ":";
Arguments are usually formatted to be only as wide as required to display the given value. You can override the width by putting a number here, or get the width from the next argument (with * ) or from a specified argument (e.g., with *2$):
sprintf "<%s>", "a"; # RESULT: «<a>» sprintf "<%6s>", "a"; # RESULT: «< a>» sprintf "<%*s>", 6, "a"; # RESULT: «< a>» NYI sprintf '<%*2$s>', "a", 6; # "< a>" sprintf "<%2s>", "long"; # RESULT: «<long>» (does not truncate)
If a field width obtained through * is negative, it has the same effect as the - flag: left-justification.
You can specify a precision (for numeric conversions) or a maximum width (for string conversions) by specifying a . followed by a number. For floating-point formats, except g and G, this specifies how many places right of the decimal point to show (the default being 6). For example:
# these examples are subject to system-specific variation sprintf '<%f>', 1; # RESULT: «"<1.000000>"» sprintf '<%.1f>', 1; # RESULT: «"<1.0>"» sprintf '<%.0f>', 1; # RESULT: «"<1>"» sprintf '<%e>', 10; # RESULT: «"<1.000000e+01>"» sprintf '<%.1e>', 10; # RESULT: «"<1.0e+01>"»
For "g" and "G", this specifies the maximum number of digits to show, including those prior to the decimal point and those after it; for example:
# These examples are subject to system-specific variation. sprintf '<%g>', 1; # RESULT: «<1>» sprintf '<%.10g>', 1; # RESULT: «<1>» sprintf '<%g>', 100; # RESULT: «<100>» sprintf '<%.1g>', 100; # RESULT: «<1e+02>» sprintf '<%.2g>', 100.01; # RESULT: «<1e+02>» sprintf '<%.5g>', 100.01; # RESULT: «<100.01>» sprintf '<%.4g>', 100.01; # RESULT: «<100>»
For integer conversions, specifying a precision implies that the output of the number itself should be zero-padded to this width, where the 0 flag is ignored:
(Note that this feature currently works for unsigned integer conversions, but not for signed integer.)
sprintf '<%.6d>', 1; # <000001> NYI sprintf '<%+.6d>', 1; # <+000001> NYI sprintf '<%-10.6d>', 1; # <000001 > sprintf '<%10.6d>', 1; # < 000001> NYI sprintf '<%010.6d>', 1; # 000001> NYI sprintf '<%+10.6d>', 1; # < +000001> sprintf '<%.6x>', 1; # RESULT: «<000001>» sprintf '<%#.6x>', 1; # RESULT: «<0x000001>» sprintf '<%-10.6x>', 1; # RESULT: «<000001 >» sprintf '<%10.6x>', 1; # RESULT: «< 000001>» sprintf '<%010.6x>', 1; # RESULT: «< 000001>» sprintf '<%#10.6x>', 1; # RESULT: «< 0x000001>»
For string conversions, specifying a precision truncates the string to fit the specified width:
sprintf '<%.5s>', "truncated"; # RESULT: «<trunc>» sprintf '<%10.5s>', "truncated"; # RESULT: «< trunc>»
You can also get the precision from the next argument using .*, or from a specified argument (e.g., with .*2$):
sprintf '<%.6x>', 1; # RESULT: «<000001>» sprintf '<%.*x>', 6, 1; # RESULT: «<000001>» NYI sprintf '<%.*2$x>', 1, 6; # "<000001>" NYI sprintf '<%6.*2$x>', 1, 4; # "< 0001>"
If a precision obtained through * is negative, it counts as having no precision at all:
sprintf '<%.*s>', 7, "string"; # RESULT: «<string>» sprintf '<%.*s>', 3, "string"; # RESULT: «<str>» sprintf '<%.*s>', 0, "string"; # RESULT: «<>» sprintf '<%.*s>', -1, "string"; # RESULT: «<string>» sprintf '<%.*d>', 1, 0; # RESULT: «<0>» sprintf '<%.*d>', 0, 0; # RESULT: «<>» sprintf '<%.*d>', -1, 0; # RESULT: «<0>»
For numeric conversions, you can specify the size to interpret the number as using l, h, V, q, L, or ll. For integer conversions (d u o x X b i D U O), numbers are usually assumed to be whatever the default integer size is on your platform (usually 32 or 64 bits), but you can override this to use instead one of the standard C types, as supported by the compiler used to build Perl 6:
(Note: None of the following have been implemented.)
hh | interpret integer as C type "char" or "unsigned char" |
h | interpret integer as C type "short" or "unsigned short" |
j | interpret integer as C type "intmax_t", only with a C99 compiler (unportable) |
l | interpret integer as C type "long" or "unsigned long" |
q, L, or ll | interpret integer as C type "long long", "unsigned long long", or "quad" (typically 64-bit integers) |
t | interpret integer as C type "ptrdiff_t" |
z | interpret integer as C type "size_t" |
Normally, sprintf takes the next unused argument as the value to format for each format specification. If the format specification uses * to require additional arguments, these are consumed from the argument list in the order they appear in the format specification before the value to format. Where an argument is specified by an explicit index, this does not affect the normal order for the arguments, even when the explicitly specified index would have been the next argument.
So:
my $a = 5; my $b = 2; my $c = 'net'; sprintf "<%*.*s>", $a, $b, $c; # RESULT: «< ne>»
uses $a for the width, $b for the precision, and $c as the value to format; while:
NYI sprintf '<%*1$.*s>', $a, $b;
would use $a for the width and precision and $b as the value to format.
Here are some more examples; be aware that when using an explicit index, the $ may need escaping:
sprintf "%2\$d %d\n", 12, 34; # RESULT: «34 12» sprintf "%2\$d %d %d\n", 12, 34; # RESULT: «34 12 34» sprintf "%3\$d %d %d\n", 12, 34, 56; # RESULT: «56 12 34» NYI sprintf "%2\$*3\$d %d\n", 12, 34, 3; # " 34 12\n" NYI sprintf "%*1\$.*f\n", 4, 5, 10; # "5.0000\n"
Other examples:
NYI sprintf "%ld a big number", 4294967295; NYI sprintf "%%lld a bigger number", 4294967296; sprintf('%c', 97); # RESULT: «a» sprintf("%.2f", 1.969); # RESULT: «1.97» sprintf("%+.3f", 3.141592); # RESULT: «+3.142» sprintf('%2$d %1$d', 12, 34); # RESULT: «34 12» sprintf("%x", 255); # RESULT: «ff»
Special case: sprintf("<b>%s</b>\n", "Perl 6") will not work, but one of the following will:
sprintf Q:b "<b>%s</b>\n", "Perl 6"; # RESULT: «<b>Perl 6</b>» sprintf "<b>\%s</b>\n", "Perl 6"; # RESULT: «<b>Perl 6</b>» sprintf "<b>%s\</b>\n", "Perl 6"; # RESULT: «<b>Perl 6</b>»
Defined as:
multi flat(**@list) multi flat(Iterable \a)
Constructs a list which contains any arguments provided, and returns the result of calling the .flat method (inherited from Any) on that list or Iterable:
say flat 1, (2, (3, 4), $(5, 6)); # OUTPUT: «(1 2 3 4 (5 6))»
Defined as:
multi sub unique(+values, |c)
Returns a sequence of unique values from the invocant/argument list, such that only the first occurrence of each duplicated value remains in the result list. unique uses the semantics of the === operator to decide whether two objects are the same, unless the optional :with parameter is specified with another comparator. The order of the original list is preserved even as duplicates are removed.
Examples:
say <a a b b b c c>.unique; # OUTPUT: «(a b c)» say <a b b c c b a>.unique; # OUTPUT: «(a b c)»
(Use squish instead if you know the input is sorted such that identical objects are adjacent.)
The optional :as parameter allows you to normalize/canonicalize the elements before unique-ing. The values are transformed for the purposes of comparison, but it's still the original values that make it to the result list; however, only the first occurrence will show up in that list:
Example:
say <a A B b c b C>.unique(:as(&lc)) # OUTPUT: «(a B c)»
One can also specify the comparator with the optional :with parameter. For instance if one wants a list of unique hashes, one could use the eqv comparator.
Example:
my @list = %(a => 42), %(b => 13), %(a => 42); say @list.unique(:with(&[eqv])) # OUTPUT: «({a => 42} {b => 13})»
Note: since :with Callable has to be tried with all the items in the list, this makes unique follow a path with much higher algorithmic complexity. You should try to use the :as argument instead, whenever possible.
Defined as:
multi sub repeated(+values, |c)
This returns a sequence of repeated values from the invocant/argument list. It takes the same parameters as unique, but instead of passing through any elements when they're first seen, they're only passed through as soon as they're seen for the second time (or more).
Examples:
say <a a b b b c c>.repeated; # OUTPUT: «(a b b c)» say <a b b c c b a>.repeated; # OUTPUT: «(b c b a)» say <a A B b c b C>.repeated(:as(&lc)); # OUTPUT: «(A b b C)» my @list = %(a => 42), %(b => 13), %(a => 42); say @list.repeated(:with(&[eqv])) # OUTPUT: «({a => 42})»
As in the case of unique the associative argument :as takes a Callable that normalizes the element before comparison, and :with takes a the equality comparison function that is going to be used.
Defined as:
sub squish( +values, |c)
Returns a sequence of values from the invocant/argument list where runs of one or more values are replaced with only the first instance. Like unique, squish uses the semantics of the === operator to decide whether two objects are the same. Unlike unique, this function only removes adjacent duplicates; identical values further apart are still kept. The order of the original list is preserved even as duplicates are removed.
Examples:
say <a a b b b c c>.squish; # OUTPUT: «(a b c)» say <a b b c c b a>.squish; # OUTPUT: «(a b c b a)»
The optional :as parameter, just like with unique, allows values to be temporarily transformed before comparison.
The optional :with parameter is used to set an appropriate comparison operator:
say [42, "42"].squish; # OUTPUT: «(42 42)» # Note that the second item in the result is still Str say [42, "42"].squish(with => &infix:<eq>); # OUTPUT: «(42)» # The resulting item is Int
Defined as
sub emit(\value --> Nil)
If used outside any supply or react block, throws an exception emit without supply or react. Within a Supply block, it will add a message to the stream.
my $supply = supply { for 1 .. 10 { emit($_); } } $supply.tap( -> $v { say "First : $v" });
See also the page for emit methods.
Defined as:
multi sub undefine(Mu \x) multi sub undefine(Array \x) multi sub undefine(Hash \x)
DEPRECATED in 6.d language version and will be removed in 6.e. For Array and Hash, it will become equivalent to assigning Empty; for everything else, equivalent to assigning Nil or Empty in the case of arrays or hashes, whose use is advised.
Routines that change the flow of the program, maybe returning a value.
Defined as:
multi sub exit() multi sub exit(Int(Any) $status)
Exits the current process with return code $status or zero if no value has been specified. The exit value ($status), when different from zero, has to be opportunely evaluated from the process that catches it (e.g., a shell); it is the only way to return an exit code different from zero from a Main.
exit prevents the LEAVE phaser to be executed, but it will run the code in the &*EXIT variable.
exit should be used as last resort only to signal the parent process about an exit code different from zero, and not to terminate exceptionally a method or a sub: use exceptions instead.
Defined as
sub done(--> Nil)
If used outside any supply or react block, throws an exception done without supply or react. Within a Supply block, it will indicate the supply will no longer emit anything. See also documentation on method done.
my $supply = supply { for 1 .. 3 { emit($_); } done; } $supply.tap( -> $v { say "Second : $v" }, done => { say "No more" }); # OUTPUT: OUTPUT: «Second : 1Second : 2Second : 3No More»
The block passed to the done named argument will be run when done is called within the supply block.