Created
March 19, 2024 19:05
-
-
Save gfldex/181ae9de7d76641ca34485d97c5461b0 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Converted POD6 documentation</title> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> | |
<style type="text/css"> | |
body { margin-left: 4em; margin-right: 4em; } | |
p { | |
text-rendering: optimizeLegibility; | |
font-feature-settings: "kern" 1; | |
-webkit-font-feature-settings: "kern" 1; | |
-moz-font-feature-settings: "kern" 1; | |
font-kerning: normal; | |
text-align: justify; | |
} | |
div.pod-content { padding-left: 20em; } | |
div.pod-body { width: 60em } | |
div.marginale { float: right; margin-right: -4em; width: 18em; font-size: 66%; text-align: left; } | |
span.filename { font-family: monospace; font-stretch: condensed; } | |
h1.title { font-size: 200%; } | |
h1 { font-size: 160%; } | |
h2 { font-size: 140%; } | |
h3 { font-size: 120%; } | |
h4 { font-size: 100%; } | |
h5 { font-size: 100%; } | |
h6 { font-size: 100%; } | |
h7 { font-size: 100%; } | |
pre { padding-left: 2em; } | |
ul.toc { list-style-type: none; padding-left: 0; margin-left: 0 } | |
ul.toc ul { list-style-type: none; } | |
ul.toc ul { margin-left: 0; padding-left: 1em; } | |
ul.toc li { margin-left: 0; padding-left: 0em; } | |
ul.toc li.toc-level-1 { padding-left: 1em; } | |
ul.toc li.toc-level-2 { padding-left: 1em; } | |
ul.toc li.toc-level-3 { padding-left: 1em; } | |
ul.toc li.toc-level-4 { padding-left: 1em; } | |
ul.toc li.toc-level-5 { padding-left: 1em; } | |
ul.toc li.toc-level-6 { padding-left: 1em; } | |
ul.toc li.toc-level-7 { padding-left: 1em; } | |
ul.toc li.toc-level-8 { padding-left: 1em; } | |
ul.toc li.toc-level-9 { padding-left: 1em; } | |
ul.toc li.toc-level-10{ padding-left: 1em; } | |
#left-side-menu { | |
width: 20em; margin-left: -22em; | |
float: left; | |
position: fixed; | |
top: 0; | |
overflow: scroll; | |
height: 100%; | |
padding: 0; | |
white-space: nowrap; | |
} | |
#left-side-menu-header { | |
transform: rotate(90deg); | |
transform-origin: left bottom 0; | |
z-index: 1; | |
position: fixed; | |
float: left; | |
top: 0; | |
margin-left: -23.5em; | |
} | |
#left-side-menu-header span.selection { padding-left: 1em; padding-right: 1em; } | |
.code { font-family: monospace; background-color: #f9f9f9; } | |
ul.numbered { | |
list-style: none; | |
} | |
span.numbered-prefix { | |
float: left; | |
} | |
span.numbered-prefix::after { | |
content: ")\00a0"; | |
} | |
@media print { | |
div.pod-content { padding-left: 0; width: 100% } | |
div.pod-body { width: 90%; } | |
#left-side-menu { | |
width: unset; | |
margin-left: unset; | |
float: unset; | |
position: unset; | |
top: unset; | |
overflow: unset; | |
height: unset; | |
padding: unset; | |
white-space: unset; | |
} | |
div.left-side-menu-header, #index { display: none; } | |
} | |
</style> | |
</head> | |
<body> | |
<div class="pod-content"> | |
<!-- /HomePage.pod6 --><div class="pod-body"><a id="_HomePage.pod6"></a><img style="float: right; margin: 0 0 1em 1em; width:261px" src="/images/Camelia.svg" alt="" id="home_logo"/> Welcome to the official documentation of the <a href="https://raku.org">Raku™</a> programming language! Browse the sections below or use the search in the top navigation. <hr/> <dl> <dt><a href="/language.html">Language Reference & Tutorials</a></dt> <dd> A collection of documents describing, in detail, the various conceptual parts of the language. <!-- If you're new to Raku, language>intro is a good place to start. --> </dd> <dt><a href="/type.html">Type Reference</a></dt> <dd> Index of built-in classes, roles and enums. </dd> <dt><a href="/routine.html">Routine Reference</a></dt> <dd> Index of built-in subroutines and methods. </dd> <dt><a href="/programs.html">Raku Programs</a></dt> <dd> A collection of documents describing the variables that affect the the Raku executable, how to run the p6doc documentation front-end, how to debug Raku programs, and how to hack on Raku source code. </dd> <dt><a href="/language/faq">FAQs (Frequently Asked Questions)</a></dt> <dd> A collection of questions that have cropped up often, along with answers. </dd> <dt><a href="/language/community">Community</a></dt> <dd> Information about the Raku development community, email lists, IRC and IRC bots, and blogs </dd> </dl> <hr/> <p>The Raku homepage offers <a href="https://raku.org/resources/">a comprehensive list of Raku resources</a>, including tutorials, and how-tos.</p> <p>You may be interested in the <a href="https://raku.org/community/">Community</a> page on the main Raku website.</p> <p> Raku compiler developers may also be interested in <a href="https://github.com/Raku/roast">The Raku Specification</a>. </p> <p>Part of this official documentation has been translated into Chinese. Here's the <a href='https://github.com/ohmycloud/perl6doc-zh/blob/master/index.adoc'>index to the pages that have been translated</a>.</p> | |
</div> | |
<!-- /language/101-basics.pod6 --><div class="pod-body"><a id="_language_101-basics.pod6"></a><a name="t1"></a><h1 class="title">1 Raku™ by example 101</h1> <p class="subtitle">A basic introductory example of a Raku program</p> <p>Suppose that you host a table tennis tournament. The referees tell you the results of each game in the format <span class="code">Player1 Player2 | 3:2</span>, which means that <span class="code">Player1</span> won against <span class="code">Player2</span> 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.</p> | |
<p>The input data (stored in a file called <span class="code">scores.txt</span>) looks like this:</p> | |
<pre class="code">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 | |
</pre> | |
<p>The first line is the list of players. Every subsequent line records a result of a match.</p> | |
<p>Here's one way to solve that problem in Raku:</p> | |
<pre class="code">use v6; | |
# start by printing out the header. | |
say "Tournament Results:\n"; | |
my $file = open 'scores.txt'; # get filehandle and... | |
my @names = $file.get.words; # ... get players. | |
my %matches; | |
my %sets; | |
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}++; | |
} | |
} | |
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"; | |
} | |
</pre> | |
<p>This produces the output:</p> | |
<pre class="code">Tournament Results: | |
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 | |
</pre> | |
<a name="t1.1"></a> <h1 id="_language_101-basics.pod6-Pragma_v6">Pragma <a name="1"></a><span class="code">v6</span></h1> | |
<pre class="code">use v6; | |
</pre> | |
<p>Every Raku program should begin with a line similar to <span class="code">use v6;</span>. This line tells the compiler which version of Raku the program expects. For instance, 6.c is an example of a Raku version. Should you accidentally run the file with Perl, you'll get a helpful error message.</p> | |
<a name="t1.2"></a> <h1 id="_language_101-basics.pod6-Statements"><a name="2"></a>Statements</h1> | |
<pre class="code"># start by printing out the header. | |
say "Tournament Results:\n"; | |
</pre> | |
<p>A Raku program consists of zero or more statements. A <i>statement</i> ends with a semicolon or a curly brace at the end of a line.</p> | |
<p>In Raku, single line comments start with a single hash character <span class="code">#</span> and extend until the end of the line. Raku also supports <a href="#_language_syntax.pod6-Multi-line_/_embedded_comments">multi-line/embedded comments</a>. The compiler doesn't evaluate comments as program text and they're only intended for human readers.</p> | |
<a name="t1.3"></a> <h1 id="_language_101-basics.pod6-Lexical_scope_and_block"><a name="3"></a>Lexical scope and <a name="4"></a>block</h1> | |
<pre class="code">my $file = open 'scores.txt'; | |
</pre> | |
<p><span class="code">my</span> 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 <span class="code">{ }</span>.</p> | |
<a name="t1.3.1"></a> <h2 id="_language_101-basics.pod6-Sigils_and_identifiers"><a name="5"></a>Sigils and <a name="6"></a>identifiers</h2> | |
<p>A variable name begins with a <i>sigil</i>, which is a non-alpha-numeric symbol such as <span class="code">$</span>, <span class="code">@</span>, <span class="code">%</span>, or <span class="code">&</span> — or occasionally the double colon <span class="code">::</span>. 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 <i>identifier</i>, which may consist of letters, digits and the underscore. Between letters you can also use a dash <span class="code">-</span> or an apostrophe <span class="code">'</span>, so <span class="code">isn't</span> and <span class="code">double-click</span> are valid identifiers.</p> | |
<a name="t1.3.2"></a> <h2 id="_language_101-basics.pod6-Scalar"><a name="7"></a>Scalar</h2> | |
<p>Sigils indicate the default access method for a variable. Variables with the <span class="code">@</span> sigil are accessed positionally; variables with the <span class="code">%</span> sigil are accessed by string key. The <span class="code">$</span> 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 <span class="code">Array</span> or a <span class="code">Hash</span>; the <span class="code">$</span> sigil signifies that it should be treated as a single value, even in a context that expects multiple values (as with an <span class="code">Array</span> or <span class="code">Hash</span>).</p> | |
<a name="t1.3.3"></a> <h2 id="_language_101-basics.pod6-Filehandle_and_assignment"><a name="8"></a>Filehandle and <a name="9"></a>assignment</h2> | |
<p>The built-in function <span class="code">open</span> opens a file, here named <span class="code">scores.txt</span>, and returns a <i>filehandle</i> — an object representing that file. The assignment operator <span class="code">=</span> <i>assigns</i> that filehandle to the variable on the left, which means that <span class="code">$file</span> now stores the filehandle.</p> | |
<a name="t1.3.4"></a> <h2 id="_language_101-basics.pod6-String_literals"><a name="10"></a>String literals</h2> | |
<p><span class="code">'scores.txt'</span> is a <i>string literal</i>. 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 <span class="code">open</span>.</p> | |
<a name="t1.4"></a> <h1 id="_language_101-basics.pod6-Arrays,_methods_and_invocants"><a name="11"></a>Arrays, <a name="12"></a>methods and <a name="13"></a>invocants</h1> | |
<pre class="code">my @names = $file.get.words; | |
</pre> | |
<p>The right-hand side calls a <i>method</i> — a named group of behavior — named <span class="code">get</span> on the filehandle stored in <span class="code">$file</span>. The <span class="code">get</span> method reads and returns one line from the file, removing the line ending. If you print the contents of <span class="code">$file</span> after calling <span class="code">get</span>, you will see that the first line is no longer in there. <span class="code">words</span> is also a method, called on the string returned from <span class="code">get</span>. <span class="code">words</span> decomposes its <i>invocant</i> — the string on which it operates — into a list of words, which here means strings separated by whitespace. It turns the single string <span class="code">'Beth Ana Charlie Dave'</span> into the list of strings <span class="code">'Beth', 'Ana', 'Charlie', 'Dave'</span>.</p> | |
<p>Finally, this list gets stored in the <a href="#_type_Array.pod6">Array</a> <span class="code">@names</span>. The <span class="code">@</span> sigil marks the declared variable as an <span class="code">Array</span>. Arrays store ordered lists.</p> | |
<a name="t1.5"></a> <h1 id="_language_101-basics.pod6-Hashes"><a name="14"></a>Hashes</h1> | |
<pre class="code">my %matches; | |
my %sets; | |
</pre> | |
<p>These two lines of code declare two hashes. The <span class="code">%</span> sigil marks each variable as a <span class="code">Hash</span>. A <span class="code">Hash</span> is an unordered collection of key-value pairs. Other programming languages call that a <i>hash table</i>, <i>dictionary</i>, or <i>map</i>. You can query a hash table for the value that corresponds to a certain <span class="code">$key</span> with <span class="code">%hash{$key}</span>.</p> | |
<p>In the score counting program, <span class="code">%matches</span> stores the number of matches each player has won. <span class="code">%sets</span> stores the number of sets each player has won. Both of these hashes are indexed by the player's name.</p> | |
<a name="t1.6"></a> <h1 id="_language_101-basics.pod6-for_and_blocks"><a name="15"></a><span class="code">for</span> and blocks</h1> | |
<pre class="code">for $file.lines -> $line { | |
... | |
} | |
</pre> | |
<p><span class="code">for</span> produces a loop that runs the <i>block</i> delimited by curly braces once for each item of the list, setting the variable <span class="code">$line</span> to the current value of each iteration. <span class="code">$file.lines</span> produces a list of the lines read from the file <span class="code">scores.txt</span>, starting with the second line of the file since we already called <span class="code">$file.get</span> once, and going all the way to the end of the file.</p> | |
<p>During the first iteration, <span class="code">$line</span> will contain the string <span class="code">Ana Dave | 3:0</span>; during the second, <span class="code">Charlie Beth | 3:1</span>, and so on.</p> | |
<pre class="code">my ($pairing, $result) = $line.split(' | '); | |
</pre> | |
<p><span class="code">my</span> can declare multiple variables simultaneously. The right-hand side of the assignment is a call to a method named <span class="code">split</span>, passing along the string <span class="code">' | '</span> as an argument.</p> | |
<p><span class="code">split</span> decomposes its invocant into a list of strings, so that joining the list items with the separator <span class="code">' | '</span> produces the original string.</p> | |
<p><span class="code">$pairing</span> gets the first item of the returned list, and <span class="code">$result</span> the second.</p> | |
<p>After processing the first line, <span class="code">$pairing</span> will hold the string <span class="code">Ana Dave</span> and <span class="code">$result</span> will hold <span class="code">3:0</span>.</p> | |
<p>The next two lines follow the same pattern:</p> | |
<pre class="code">my ($p1, $p2) = $pairing.words; | |
my ($r1, $r2) = $result.split(':'); | |
</pre> | |
<p>The first extracts and stores the names of the two players in the variables <span class="code">$p1</span> and <span class="code">$p2</span>. The second extracts the results for each player and stores them in <span class="code">$r1</span> and <span class="code">$r2</span>.</p> | |
<p>After processing the first line of the file, the variables contain the values:</p> | |
<table> | |
<tr><td>Variable</td> <td>Contents</td></tr> | |
<tr><td>$line</td> <td>'Ana Dave | 3:0'</td></tr> | |
<tr><td>$pairing</td> <td>'Ana Dave'</td></tr> | |
<tr><td>$result</td> <td>'3:0'</td></tr> | |
<tr><td>$p1</td> <td>'Ana'</td></tr> | |
<tr><td>$p2</td> <td>'Dave'</td></tr> | |
<tr><td>$r1</td> <td>'3'</td></tr> | |
<tr><td>$r2</td> <td>'0'</td></tr> | |
</table> <p>The program then counts the number of sets each player has won:</p> | |
<pre class="code">%sets{$p1} += $r1; | |
%sets{$p2} += $r2; | |
</pre> | |
<p>The above two statements involve the <span class="code">+=</span> compound assignment operator. They are a variant of the following two statements that use the simple assignment operator <span class="code">=</span> and that may be easier to understand at first sight:</p> | |
<pre class="code">%sets{$p1} = %sets{$p1} + $r1; | |
%sets{$p2} = %sets{$p2} + $r2; | |
</pre> | |
<p>For your program, the shorthand version using the <span class="code">+=</span> compound assignment operator is preferred over the longhand version using the simple assignment operator <span class="code">=</span>. This is not only because the shorter version requires less typing, but also because the <span class="code">+=</span> operator silently initializes undefined values of the hash's key-value pairs to zero. In other words: by using <span class="code">+=</span>, there is no need to include a separate statement like <span class="code">%sets{$p1} = 0</span> before you can meaningfully add <span class="code">$r1</span> to it. We'll look at this is behavior in a bit more detail below.</p> | |
<a name="t1.6.1"></a> <h2 id="_language_101-basics.pod6-Any_and_+="><a name="16"></a><span class="code">Any</span> and <a name="17"></a><span class="code">+=</span></h2> | |
<pre class="code">%sets{$p1} += $r1; | |
%sets{$p2} += $r2; | |
</pre> | |
<p><span class="code">%sets{$p1} += $r1</span> means <i>increase the value in the variable on the left by $r1</i>. In the first iteration <span class="code">%sets{$p1}</span> is not yet defined, so it defaults to a special value called <span class="code">Any</span>. The <span class="code">+=</span> operator conveniently treats the undefined value <span class="code">Any</span> as a number with the value <span class="code">0</span>, allowing it to sensibly add some other value to it. To perform the addition, the strings <span class="code">$r1</span>, <span class="code">$r2</span>, etc. are automatically converted to numbers, as addition is a numeric operation.</p> | |
<a name="t1.6.2"></a> <h2 id="_language_101-basics.pod6-Fat_arrow,_pairs_and_autovivification"><a name="18"></a>Fat arrow, <a name="19"></a>pairs and <a name="20"></a>autovivification</h2> | |
<p>Before these two lines execute, <span class="code">%sets</span> 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 behavior is known as <i>autovivification</i>. After these two lines have run for the first time, <span class="code">%sets</span> contains <span class="code">'Ana' => 3, 'Dave' => 0</span>. (The fat arrow <span class="code">=></span> separates the key and the value in a <span class="code">Pair</span>.)</p> | |
<a name="t1.6.3"></a> <h2 id="_language_101-basics.pod6-Postincrement_and_preincrement"><a name="21"></a>Postincrement and <a name="22"></a>preincrement</h2> | |
<pre class="code">if $r1 > $r2 { | |
%matches{$p1}++; | |
} else { | |
%matches{$p2}++; | |
} | |
</pre> | |
<p>If <span class="code">$r1</span> is numerically larger than <span class="code">$r2</span>, <span class="code">%matches{$p1}</span> increments by one. If <span class="code">$r1</span> is not larger than <span class="code">$r2</span>, <span class="code">%matches{$p2}</span> increments. Just as in the case of <span class="code">+=</span>, if either hash value did not exist previously, it is autovivified by the increment operation.</p> | |
<p><span class="code">$thing++</span> is a variant of <span class="code">$thing += 1</span>; it differs from the latter in that the return value of the expression is <span class="code">$thing</span> <i>before</i> the increment, and not the incremented value. As in many other programming languages, you can use <span class="code">++</span> as a prefix. Then it returns the incremented value: <span class="code">my $x = 1; say ++$x</span> prints <span class="code">2</span>.</p> | |
<a name="t1.7"></a> <h1 id="_language_101-basics.pod6-Topic_variable"><a name="23"></a>Topic variable</h1> | |
<pre class="code">my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse; | |
</pre> | |
<p>This line consists of three individually simple steps. An array's <span class="code">sort</span> 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 <i>scores</i> of the players, not their names. The <span class="code">sort</span> method's argument is a <i>block</i> 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 <i>topic variable</i> <span class="code">$_</span>.</p> | |
<a name="t1.7.1"></a> <h2 id="_language_101-basics.pod6-Blocks">Blocks</h2> | |
<p>You have seen blocks before: both the <span class="code">for</span> loop <span class="code">-> $line { ... } </span> and the <span class="code">if</span> statement worked on blocks. A block is a self-contained piece of Raku code with an optional signature (the <span class="code">-> $line </span> part).</p> | |
<p>The simplest way to sort the players by score would be <span class="code">@names.sort({ %matches{$_} })</span>, 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.</p> | |
<a name="t1.7.2"></a> <h2 id="_language_101-basics.pod6-Stable_sort">Stable sort</h2> | |
<p>When two array items have the same value, <span class="code">sort</span> leaves them in the same order as it found them. Computer scientists call this a <i>stable sort</i>. The program takes advantage of this property of Raku's <span class="code">sort</span> to achieve the goal by sorting twice: first by the number of sets won (the secondary criterion), then by the number of matches won (the primary criterion).</p> | |
<p>After the first sorting step, the names are in the order <span class="code">Beth Charlie Dave Ana</span>. 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.</p> | |
<p><span class="code">sort</span> sorts in ascending order, from smallest to largest. This is the opposite of the desired order. Therefore, the code calls the <span class="code">.reverse</span> method on the result of the second sort, and stores the final list in <span class="code">@sorted</span>.</p> | |
<a name="t1.8"></a> <h1 id="_language_101-basics.pod6-Standard_output">Standard output</h1> | |
<pre class="code">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"; | |
} | |
</pre> | |
<p>To print out the players and their scores, the code loops over <span class="code">@sorted</span>, setting <span class="code">$n</span> to the name of each player in turn. Read this code as "For each element of sorted, set <span class="code">$n</span> to the element, then execute the contents of the following block." The variable <span class="code">$match-noun</span> will store either the string <i>match</i> if the player has won a single match or <i>matches</i> if the player has won zero or more matches. In order to do this, the <i>ternary</i> operator (<span class="code">?? !!</span>) is used. If <span class="code">%matches{$n} == 1</span> evaluates to <span class="code">True</span>, then <i>match</i> is returned. Otherwise, <i>matches</i> is returned. Either way, the returned value is stored in <span class="code">$match-noun</span>. The same approach applies to <span class="code">$set-noun</span>.</p> | |
<p>The statement <span class="code">say</span> prints its arguments to the standard output (the screen, normally), followed by a newline. (Use <span class="code">print</span> if you don't want the newline at the end.)</p> | |
<p>Note that <span class="code">say</span> will truncate certain data structures by calling the <span class="code">.gist</span> method so <span class="code">put</span> is safer if you want exact output.</p> | |
<a name="t1.8.1"></a> <h2 id="_language_101-basics.pod6-Variable_interpolation"><a name="24"></a>Variable interpolation</h2> | |
<p>When you run the program, you'll see that <span class="code">say</span> doesn't print the contents of that string verbatim. In place of <span class="code">$n</span> it prints the contents of the variable <span class="code">$n</span> — a player's name stored in <span class="code">$n</span>. This automatic substitution of code with its contents is called <i>interpolation</i>. This interpolation happens only in strings delimited by double quotes <span class="code">"..."</span>. Single quoted strings <span class="code">'...'</span> do not interpolate:</p> | |
<a name="t1.8.2"></a> <h2 id="_language_101-basics.pod6-Double-quoted_strings_and_single-quoted_strings"><a name="25"></a>Double-quoted strings and <a name="26"></a>single-quoted strings</h2> | |
<pre class="code">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» | |
</pre> | |
<p>Double quoted strings in Raku can interpolate variables with the <span class="code">$</span> sigil as well as blocks of code in curly braces. Since any arbitrary Raku code can appear within curly braces, <span class="code">Array</span>s and <span class="code">Hash</span>es may be interpolated by placing them within curly braces.</p> | |
<p>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.</p> | |
<p>Let's see an example of this now.</p> | |
<p>In this example, you will see some special syntax that makes it easier to make a list of strings. This is the <span class="code"><...></span> <a href="#_language_operators.pod6-index-entry-qw-quote-words-quote-words">quote-words</a> 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 <span class="code">"..."</span>.</p> | |
<pre class="code">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 | |
</pre> | |
<p>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 operator — a bracketing pair that follows a statement. It's also ok to have a method call between the variable name and the postcircumfix.</p> | |
<a name="t1.9"></a> <h1 id="_language_101-basics.pod6-Zen_slices">Zen slices</h1> | |
<pre class="code">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» | |
</pre> | |
<a name="t1.10"></a> <h1 id="_language_101-basics.pod6-Exercises">Exercises</h1> | |
<p><b>1.</b> 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, so in principle we could safely remove it.</p> | |
<p>How can you make the program run if you do not use the <span class="code">@names</span> variable? Hint: <span class="code">%hash.keys</span> returns a list of all keys stored in <span class="code">%hash</span>.</p> | |
<p><b>Answer:</b> After removing the first line in <span class="code">scores.txt</span>, remove the line <span class="code">my @names = $file.get.words;</span> (which would read it), and change:</p> | |
<pre class="code">my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse; | |
</pre> | |
<p>... into:</p> | |
<pre class="code">my @sorted = %sets.keys.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse; | |
</pre> | |
<p><b>2.</b> Instead of deleting the redundant <span class="code">@names</span> 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?</p> | |
<p>Hint: Try using <a href="#_language_operators.pod6-infix_(elem),_infix_∈">membership operators</a>.</p> | |
<p><b>Answer:</b> Change <span class="code">@names</span> to <span class="code">@valid-players</span>. When looping through the lines of the file, check to see that <span class="code">$p1</span> and <span class="code">$p2</span> are in <span class="code">@valid-players</span>. Note that for membership operators you can also use <span class="code">(elem)</span> and <span class="code">!(elem)</span>.</p> | |
<pre class="code">...; | |
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!"; | |
} | |
... | |
} | |
</pre> | |
</div> | |
<!-- /language/5to6-nutshell.pod6 --><div class="pod-body"><a id="_language_5to6-nutshell.pod6"></a><a name="t2"></a><h1 class="title">2 Perl to Raku guide - in a nutshell</h1> <p class="subtitle">How do I do what I used to do? (Raku in a nutshell)</p> <p>Note: Some references to Perl 6 still apply in the Raku infrastructure, but the changeover from the name Perl 6 to Raku is ongoing and the references will be changed as soon as they become operative in the latest release of Raku (and some volunteer changes them!).</p> | |
<p>This page attempts to provide a fast-path to the changes in syntax and semantics from Perl to Raku. Whatever worked in Perl and must be written differently in Raku, should be listed here (whereas many <i>new</i> Raku features and idioms need not).</p> | |
<p>Hence this should not be mistaken for a beginner tutorial or a promotional overview of Raku; it is intended as a technical reference for Raku learners with a strong Perl background and for anyone porting Perl code to Raku (though note that <a href="#1-Automated translation">#Automated translation</a> might be more convenient).</p> | |
<p>A note on semantics; when we say "now" in this document, we mostly just mean "now that you are trying out Raku." We don't mean to imply that Perl is now suddenly obsolete. Quite the contrary, most of us love Perl, and we expect Perl to continue in use for a good many years. Indeed, one of our more important goals has been to make interaction between Perl and Raku run smoothly. However, we do also like the design decisions in Raku, which are certainly newer and arguably better integrated than many of the historical design decisions in Perl. So many of us do hope that over the next decade or two, Raku 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.</p> | |
<a name="t2.1"></a> <h1 id="_language_5to6-nutshell.pod6-CPAN">CPAN</h1> | |
<p>See <a href="#_routine_https:__modules.raku.org_.pod6">https://modules.raku.org/</a>.</p> | |
<p>If the module that you were using has not been converted to Raku, and no alternative is listed in this document, then its use under Raku may not have been addressed yet.</p> | |
<p>The <a href="#_routine_https:__github.com_niner_Inline-Perl5_.pod6">Inline::Perl5</a> project makes it possible to <span class="code">use</span> Perl modules directly from Raku code by using an embedded instance of the <span class="code">perl</span> interpreter to run Perl code.</p> | |
<p>This is as simple as:</p> | |
<pre class="code"># the :from<Perl5> makes Raku load Inline::Perl5 first (if installed) | |
# and then load the Scalar::Util module from Perl | |
use Scalar::Util:from<Perl5> <looks_like_number>; | |
say looks_like_number "foo"; # 0 | |
say looks_like_number "42"; # 1 | |
</pre> | |
<p>A number of Perl modules have been ported to Raku, trying to maintain the API of these modules as much as possible, as part of the CPAN Butterfly Plan. These can be found at <a href="#_routine_https:__modules.raku.org_t_CPAN5.pod6">https://modules.raku.org/t/CPAN5</a>.</p> | |
<p>Many Perl built-in functions (about a 100 so far) have been ported to Raku with the same semantics. Think about the <span class="code">shift</span> function in Perl having magic shifting from <span class="code">@_</span> or <span class="code">@ARGV</span> by default, depending on context. These can be found at <a href="#_routine_https:__modules.raku.org_t_Perl5.pod6">https://modules.raku.org/t/Perl5</a> as separately loadable modules, and in the <a href="#_routine_https:__modules.raku.org_dist_P5built-ins.pod6">P5built-ins</a> bundle to get them all at once.</p> | |
<a name="t2.2"></a> <h1 id="_language_5to6-nutshell.pod6-Syntax">Syntax</h1> | |
<p>There are a few differences in syntax between the two languages, starting with how identifiers are defined.</p> | |
<a name="t2.2.1"></a> <h2 id="_language_5to6-nutshell.pod6-Identifiers">Identifiers</h2> | |
<p>Raku allows the use of dashes (<span class="code">-</span>), underscores (<span class="code">_</span>), apostrophes (<span class="code">'</span>), and alphanumerics in identifiers:</p> | |
<pre class="code">sub test-doesn't-hang { ... } | |
my $ความสงบ = 42; | |
my \Δ = 72; say 72 - Δ;</pre> | |
<a name="t2.2.2"></a> <h2 id="_language_5to6-nutshell.pod6-->_Method_calls"><span class="code">-></span> Method calls</h2> | |
<p>If you've read any Raku code at all, it's immediately obvious that method call syntax now uses a dot instead of an arrow:</p> | |
<pre class="code">$person->name # Perl | |
</pre> | |
<pre class="code">$person.name # Raku | |
</pre> | |
<p>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 <span class="code">~</span> operator, if you were wondering.)</p> | |
<p>To call a method whose name is not known until runtime:</p> | |
<pre class="code">$object->$methodname(@args); # Perl | |
</pre> | |
<pre class="code">$object."$methodname"(@args); # Raku | |
</pre> | |
<p>If you leave out the quotes, then Raku expects <span class="code">$methodname</span> to contain a <span class="code">Method</span> object rather than the simple string name of the method. Yes, <b>everything</b> in Raku can be considered an object.</p> | |
<a name="t2.2.3"></a> <h2 id="_language_5to6-nutshell.pod6-Whitespace">Whitespace</h2> | |
<p>Perl allows a surprising amount of flexibility in the use of whitespace, even with strict mode and warnings turned on:</p> | |
<pre class="code"># unidiomatic but valid Perl | |
say"Hello ".ucfirst ($people | |
[$ i] | |
-> | |
name)."!"if$greeted[$i]<1; | |
</pre> | |
<p>Raku 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; Raku is designed to be more concise in concepts than in keystrokes.</p> | |
<p>As a result, there are various places in the syntax where whitespace is optional in Perl, but is either mandatory or forbidden in Raku. 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:</p> | |
<ul><li><p><i>No space allowed before the opening parenthesis of an argument list.</i></p> | |
<pre class="code">substr ($s, 4, 1); # Perl (in Raku this would try to pass a single | |
# argument of type List to substr) | |
</pre> | |
<pre class="code">substr($s, 4, 1); # Raku | |
substr $s, 4, 1; # Raku - alternative parentheses-less style | |
</pre> | |
<p>Should this really be a problem for you, then you might want to have a look at the <span class="code">Slang::Tuxic</span> module in the Raku ecosystem: it changes the grammar of Raku in such a way that you <b>can</b> have a space before the opening parenthesis of an argument list.</p> | |
</li></ul> <ul><li><p><i>Space is <b>required</b> immediately after keywords</i></p> | |
<pre class="code">my($alpha, $beta); # Perl, tries to call my() sub in Raku | |
</pre> | |
<pre class="code">my ($alpha, $beta); # Raku | |
</pre> | |
<pre class="code">if($a < 0) { ... } # Perl, dies in Raku | |
</pre> | |
<pre class="code">if ($a < 0) { ... } # Raku | |
if $a < 0 { ... } # Raku, more idiomatic | |
</pre> | |
<pre class="code">while($x-- > 5) { ... } # Perl, dies in Raku | |
</pre> | |
<pre class="code">while ($x-- > 5) { ... } # Raku | |
while $x-- > 5 { ... } # Raku, more idiomatic | |
</pre> | |
</li></ul> <ul><li><p><i>No space allowed after a prefix operator, or before a postfix/postcircumfix operator (including array/hash subscripts).</i></p> | |
<pre class="code">$seen {$_} ++; # Perl | |
</pre> | |
<pre class="code">%seen{$_}++; # Raku | |
</pre> | |
</li></ul> <ul><li><p><i>Space required before an infix operator if it would conflict with an existing postfix/postcircumfix operator.</i></p> | |
<pre class="code">$n<1; # Perl (in Raku this would conflict with postcircumfix < >) | |
</pre> | |
<pre class="code">$n < 1; # Raku | |
</pre> | |
</li></ul> <ul><li><p><i>However, whitespace <b>is allowed</b> before the period of a method call!</i></p> | |
<pre class="code"># Perl | |
my @books = $xml | |
->parse_file($file) # some comment | |
->findnodes("/library/book"); | |
</pre> | |
<pre class="code"># Raku | |
my @books = $xml | |
.parse-file($file) # some comment | |
.findnodes("/library/book"); | |
</pre> | |
</li></ul> <p>However, note that you can use <a href="#_language_syntax.pod6-Unspace">unspace</a> to add whitespace in Raku code in places where it is otherwise not allowed.</p> | |
<p>See also <a href="#_language_syntax.pod6-Lexical_conventions">other lexical conventions in the syntax page</a>.</p> | |
<a name="t2.2.4"></a> <h2 id="_language_5to6-nutshell.pod6-Sigils">Sigils</h2> | |
<p>In Perl, arrays and hashes use changing sigils depending on how they are being accessed. In Raku the sigils are invariant, no matter how the variable is being used - you can think of them as part of the variable's name.</p> | |
<a name="t2.2.4.1"></a> <h3 id="_language_5to6-nutshell.pod6-$_Scalar"><span class="code">$</span> Scalar</h3> | |
<p>The <span class="code">$</span> sigil is now always used with "scalar" variables (e.g. <span class="code">$name</span>), and no longer for <a href="#1-[]_Array_indexing/slicing">array indexing</a> and <a href="#1-{}_Hash_indexing/slicing">Hash indexing</a>. That is, you can still use <span class="code">$x[1]</span> and <span class="code">$x{"foo"}</span>, but it will act on <span class="code">$x</span>, with no effect on a similarly named <span class="code">@x</span> or <span class="code">%x</span>. Those would now be accessed with <span class="code">@x[1]</span> and <span class="code">%x{"foo"}</span>.</p> | |
<a name="t2.2.4.2"></a> <h3 id="_language_5to6-nutshell.pod6-@_Array"><span class="code">@</span> Array</h3> | |
<p>The <span class="code">@</span> sigil is now always used with "array" variables (e.g. <span class="code">@months</span>, <span class="code">@months[2]</span>, <span class="code">@months[2, 4]</span>), and no longer for <a href="#1-{}_Hash_indexing/slicing">value-slicing hashes</a>.</p> | |
<a name="t2.2.4.3"></a> <h3 id="_language_5to6-nutshell.pod6-%_Hash"><span class="code">%</span> Hash</h3> | |
<p>The <span class="code">%</span> sigil is now always used with "hash" variables (e.g. <span class="code">%calories</span>, <span class="code">%calories<apple></span>, <span class="code">%calories<pear plum></span>), and no longer for <a href="#1-[]_Array_indexing/slicing">key/value-slicing arrays</a>.</p> | |
<a name="t2.2.4.4"></a> <h3 id="_language_5to6-nutshell.pod6-&_Sub"><span class="code">&</span> Sub</h3> | |
<p>The <span class="code">&</span> 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":</p> | |
<pre class="code">my $sub = \&foo; # Perl | |
</pre> | |
<pre class="code">my $sub = &foo; # Raku | |
</pre> | |
<pre class="code">callback => sub { say @_ } # Perl - can't pass built-in sub directly | |
</pre> | |
<pre class="code">callback => &say # Raku - & gives "noun" form of any sub | |
</pre> | |
<p>Since Raku does not allow adding/removing symbols in a lexical scope once it has finished compiling, there is no equivalent to Perl's <span class="code">undef &foo;</span>, and the closest equivalent to Perl's <span class="code">defined &foo</span> would be <span class="code">defined ::('&foo')</span> (which uses the "dynamic symbol lookup" syntax). However, you can declare a mutable named subroutine with <span class="code">my &foo;</span> and then change its meaning at runtime by assigning to <span class="code">&foo</span>.</p> | |
<p>In Perl, the ampersand sigil can additionally be used to call subroutines in special ways with subtly different behavior compared to normal sub calls. In Raku those special forms are no longer available:</p> | |
<ul><li><p><span class="code">&foo(...)</span> <i>for circumventing a function prototype</i></p> | |
<p>In Raku 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:</p> | |
<pre class="code"># Perl: | |
first_index { $_ > 5 } @values; | |
&first_index($coderef, @values); # (disabling the prototype that parses a | |
# literal block as the first argument) | |
</pre> | |
<pre class="code"># Raku: | |
first { $_ > 5 }, @values, :k; # the :k makes first return an index | |
first $coderef, @values, :k; | |
</pre> | |
</li></ul> <ul><li><p><span class="code">&foo;</span> <i>and</i> <span class="code">goto &foo;</span> <i>for re-using the caller's argument list / replacing the caller in the call stack</i>. Raku can use either <a href="#_language_functions.pod6-index-entry-dispatch_callsame"><span class="code">callsame</span></a> for re-dispatching or <a href="#_language_functions.pod6-index-entry-dispatch_nextsame"><span class="code">nextsame</span></a> and <a href="#_language_functions.pod6-index-entry-dispatch_nextwith"><span class="code">nextwith</span></a>, which have no exact equivalent in Perl.</p> | |
<pre class="code">sub foo { say "before"; &bar; say "after" } # Perl | |
</pre> | |
<pre class="code">sub foo { say "before"; bar(|@_); say "after" } # Raku - have to be explicit | |
</pre> | |
<pre class="code">sub foo { say "before"; goto &bar } # Perl | |
</pre> | |
<pre class="code">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 | |
</pre> | |
</li></ul> <a name="t2.2.4.5"></a> <h3 id="_language_5to6-nutshell.pod6-*_Glob"><span class="code">*</span> Glob</h3> | |
<p>In Perl, the <span class="code">*</span> sigil referred to the GLOB structure that Perl uses to store non-lexical variables, filehandles, subs, and formats.</p> | |
<p><div class="marginale">This should not be confused with the Perl built-in <span class="code">glob()</span> function, which reads filenames from a directory.</div></p> | |
<p>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.</p> | |
<pre class="code"># Perl - ancient method | |
sub read_2 { | |
local (*H) = @_; | |
return scalar(<H>), scalar(<H>); | |
} | |
open FILE, '<', $path or die; | |
my ($line1, $line2) = read_2(*FILE); | |
</pre> | |
<p>You should refactor your Perl code to remove the need for the GLOB, before translating into Raku.</p> | |
<pre class="code"># Perl - 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); | |
</pre> | |
<p>And here's just one possible Raku translation:</p> | |
<pre class="code"># Raku | |
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); | |
</pre> | |
<a name="t2.2.5"></a> <h2 id="_language_5to6-nutshell.pod6-[]_Array_indexing/slicing">[] Array indexing/slicing</h2> | |
<p>Index and slice operations on arrays no longer inflect the variable's <a href="#1-@_Array">sigil</a>, and adverbs can be used to control the type of slice:</p> | |
<ul><li><p><i>Indexing</i></p> | |
<pre class="code">say $months[2]; # Perl | |
</pre> | |
<pre class="code">say @months[2]; # Raku - @ instead of $ | |
</pre> | |
</li></ul> <ul><li><p><i>Value-slicing</i></p> | |
<pre class="code">say join ',', @months[6, 8..11]; # Perl and Raku | |
</pre> | |
</li></ul> <ul><li><p><i>Key/value-slicing</i></p> | |
<pre class="code">say join ',', %months[6, 8..11]; # Perl | |
</pre> | |
<pre class="code">say join ',', @months[6, 8..11]:kv; # Raku - @ instead of %; use :kv adverb | |
</pre> | |
</li></ul> <p>Also note that the subscripting square brackets are now a normal postcircumfix operator rather than a special syntactic form, and thus <a href="#1-exists">checking for existence of elements</a> and <a href="#1-delete">unsetting elements</a> is done with adverbs.</p> | |
<p>An array's biggest index is now available with the <span class="code">.end</span> method:</p> | |
<pre class="code">say $#item; # Perl | |
</pre> | |
<pre class="code">say @item.end; # Raku | |
</pre> | |
<a name="t2.2.6"></a> <h2 id="_language_5to6-nutshell.pod6-{}_Hash_indexing/slicing">{} Hash indexing/slicing</h2> | |
<p>Index and slice operations on hashes no longer inflect the variable's <a href="#1-%_Hash">sigil</a>, 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 <span class="code">qw//</span> quoting construct):</p> | |
<ul><li><p><i>Indexing</i></p> | |
<pre class="code">say $calories{"apple"}; # Perl | |
</pre> | |
<pre class="code">say %calories{"apple"}; # Raku - % instead of $ | |
</pre> | |
<pre class="code">say $calories{apple}; # Perl | |
</pre> | |
<pre class="code">say %calories<apple>; # Raku - angle brackets; % instead of $ | |
say %calories«"$key"»; # Raku - double angles interpolate as a list of Str | |
</pre> | |
</li></ul> <ul><li><p><i>Value-slicing</i></p> | |
<pre class="code">say join ',', @calories{'pear', 'plum'}; # Perl | |
</pre> | |
<pre class="code">say join ',', %calories{'pear', 'plum'}; # Raku - % instead of @ | |
say join ',', %calories<pear plum>; # Raku (prettier version) | |
my $keys = 'pear plum'; | |
say join ',', %calories«$keys»; # Raku the split is done after interpolation | |
</pre> | |
</li></ul> <ul><li><p><i>Key/value-slicing</i></p> | |
<pre class="code">say join ',', %calories{'pear', 'plum'}; # Perl | |
</pre> | |
<pre class="code">say join ',', %calories{'pear', 'plum'}:kv; # Raku - use :kv adverb | |
say join ',', %calories<pear plum>:kv; # Raku (prettier version) | |
</pre> | |
</li></ul> <p>Also note that the subscripting curly braces are now a normal postcircumfix operator rather than a special syntactic form, and thus <a href="#1-exists">checking for existence of keys</a> and <a href="#1-delete">removing keys</a> is done with adverbs.</p> | |
<a name="t2.2.7"></a> <h2 id="_language_5to6-nutshell.pod6-Creating_references_and_using_them">Creating references and using them</h2> | |
<p>In Perl, references to anonymous arrays and hashes and subs are returned during their creation. References to existing named variables and subs were generated with the <span class="code">\</span> operator. the "referencing/dereferencing" metaphor does not map cleanly to the actual Raku container system, so we will have to focus on the intent of the reference operators instead of the actual syntax.</p> | |
<pre class="code">my $aref = \@aaa ; # Perl | |
</pre> | |
<p>This might be used for passing a reference to a routine, for instance. But in Raku, the (single) underlying object is passed (which you could consider to be a sort of pass by reference).</p> | |
<pre class="code">my @array = 4,8,15; | |
{ $_[0] = 66 }(@array); # run the block with @array aliased to $_ | |
say @array; # OUTPUT: «[66 8 15]» | |
</pre> | |
<p>The underlying <span class="code">Array</span> object of <span class="code">@array</span> is passed, and its first value modified inside the declared routine.</p> | |
<p>In Perl, the syntax for dereferencing an entire reference is the type-sigil and curly braces, with the reference inside the curly braces. In Raku, this concept simply does not apply, since the <i>reference</i> metaphor does not really apply.</p> | |
<p>In Perl, the arrow operator, <span class="code">-></span> , is used for single access to a composite's reference or to call a sub through its reference. In Raku, the dot operator <span class="code">.</span> is always used for object methods, but the rest does not really apply.</p> | |
<pre class="code"># Perl | |
say $arrayref->[7]; | |
say $hashref->{'fire bad'}; | |
say $subref->($foo, $bar); | |
</pre> | |
<p>In relatively recent versions of Perl (5.20 and later), a new feature allows the use of the arrow operator for dereferencing: see <a href="#_routine_https:__metacpan.org_pod_release_SHAY_perl-5.20.1_pod_perl5200delta.pod.pod6-Experimental_Postfix_Dereferencing">Postfix Dereferencing</a>. This can be used to create an array from a scalar. This operation is usually called <i>decont</i>, as in decontainerization, and in Raku methods such as <span class="code">.list</span> and <span class="code">.hash</span> are used:</p> | |
<pre class="code"># Perl 5.20 | |
use experimental qw< postderef >; | |
my @a = $arrayref->@*; | |
my %h = $hashref->%*; | |
my @slice = $arrayref->@[3..7]; | |
</pre> | |
<pre class="code"># Raku | |
my @a = $contains-an-array.list; # or @($arrayref) | |
my %h = $contains-a-hash.hash; # or %($hashref) | |
</pre> | |
<p>The "Zen" slice does the same thing:</p> | |
<pre class="code"># Raku | |
my @a = $contains-an-array[]; | |
my %h = $contains-a-hash{}; | |
</pre> | |
<p>See <a href="#_language_containers.pod6">the "Containers" section of the documentation</a> for more information.</p> | |
<a name="t2.3"></a> <h1 id="_language_5to6-nutshell.pod6-Operators">Operators</h1> | |
<p>See <a href="#_language_operators.pod6">the documentation for operators</a> for full details on all operators.</p> | |
<p>Unchanged:</p> | |
<ul><li><p><span class="code">+</span> Numeric Addition</p> | |
</li></ul> <ul><li><p><span class="code">-</span> Numeric Subtraction</p> | |
</li></ul> <ul><li><p><span class="code">*</span> Numeric Multiplication</p> | |
</li></ul> <ul><li><p><span class="code">/</span> Numeric Division</p> | |
</li></ul> <ul><li><p><span class="code">%</span> Numeric Modulus</p> | |
</li></ul> <ul><li><p><span class="code">**</span> Numeric Exponentiation</p> | |
</li></ul> <ul><li><p><span class="code">++</span> Numeric Increment</p> | |
</li></ul> <ul><li><p><span class="code">--</span> Numeric Decrement</p> | |
</li></ul> <ul><li><p><span class="code">! && || ^</span> Booleans, high-precedence</p> | |
</li></ul> <ul><li><p><span class="code">not and or xor</span> Booleans, low-precedence</p> | |
</li></ul> <ul><li><p><span class="code">== != < > <= >=</span> Numeric comparisons</p> | |
</li></ul> <ul><li><p><span class="code">eq ne lt gt le ge</span> String comparisons</p> | |
</li></ul> <a name="t2.3.1"></a> <h2 id="_language_5to6-nutshell.pod6-,_(Comma)_List_separator"><span class="code">,</span> (Comma) List separator</h2> | |
<p>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 <span class="code">|</span> operator (see also <a href="#_type_Slip.pod6">Slip</a>). For instance:</p> | |
<pre class="code">my @numbers = 100, 200, 300; | |
my @more_numbers = 500, 600, 700; | |
my @all_numbers = |@numbers, 400, |@more_numbers; | |
</pre> | |
<p>That way one can concatenate arrays.</p> | |
<p>Note that one does not need to have any parentheses on the right-hand side: the list separator takes care of creating the list, <b>not</b> the parentheses!</p> | |
<a name="t2.3.2"></a> <h2 id="_language_5to6-nutshell.pod6-<=>_cmp_Three-way_comparisons"><span class="code"><=> cmp</span> Three-way comparisons</h2> | |
<p>In Perl, these operators returned -1, 0, or 1. In Raku, they return <span class="code">Order::Less</span>, <span class="code">Order::Same</span>, or <span class="code">Order::More</span>.</p> | |
<p><span class="code">cmp</span> is now named <span class="code">leg</span>; it forces string context for the comparison.</p> | |
<p><span class="code"><=></span> still forces numeric context.</p> | |
<p><span class="code">cmp</span> in Raku does either <span class="code"><=></span> or <span class="code">leg</span>, depending on the existing type of its arguments.</p> | |
<a name="t2.3.3"></a> <h2 id="_language_5to6-nutshell.pod6-~~_Smartmatch_operator"><span class="code">~~</span> Smartmatch operator</h2> | |
<p>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 and Raku. See <a href="#_routine_~~.pod6">~~</a> and <a href="#_language_operators.pod6-index-entry-smartmatch_operator">the smartmatch operator</a></p> | |
<a name="t2.3.4"></a> <h2 id="_language_5to6-nutshell.pod6-&_|_^_String_bitwise_ops"><span class="code">& | ^</span> String bitwise ops</h2> | |
<a name="t2.3.5"></a> <h2 id="_language_5to6-nutshell.pod6-&_|_^_Numeric_bitwise_ops"><span class="code">& | ^</span> Numeric bitwise ops</h2> | |
<a name="t2.3.6"></a> <h2 id="_language_5to6-nutshell.pod6-&_|_^_Boolean_ops"><span class="code">& | ^</span> Boolean ops</h2> | |
<p>In Perl, <span class="code">& | ^</span> were invoked according to the contents of their arguments. For example, <span class="code">31 | 33</span> returns a different result than <span class="code">"31" | "33"</span>.</p> | |
<p>In Raku, those single-character ops have been removed, and replaced by two-character ops which coerce their arguments to the needed context.</p> | |
<pre class="code"># 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) | |
</pre> | |
<a name="t2.3.7"></a> <h2 id="_language_5to6-nutshell.pod6-<<_>>_Numeric_shift_left|right_ops"><span class="code"><< >></span> Numeric shift left|right ops</h2> | |
<p>Replaced by <span class="code">+<</span> and <span class="code">+></span> .</p> | |
<pre class="code">say 42 << 3; # Perl | |
</pre> | |
<pre class="code">say 42 +< 3; # Raku | |
</pre> | |
<a name="t2.3.8"></a> <h2 id="_language_5to6-nutshell.pod6-=>_Fat_comma"><span class="code">=></span> Fat comma</h2> | |
<p>In Perl, <span class="code">=></span> acted just like a comma, but also quoted its left-hand side.</p> | |
<p>In Raku, <span class="code">=></span> is the <a href="#_type_Pair.pod6">Pair</a> operator, which is quite different in principle, but works the same in many situations.</p> | |
<p>If you were using <span class="code">=></span> in hash initialization, or in passing arguments to a sub that expects a hashref, then the usage is likely identical.</p> | |
<pre class="code">sub get_the_loot { ... }; # Raku stub | |
# Works in Perl and Raku | |
my %hash = ( AAA => 1, BBB => 2 ); | |
get_the_loot( 'diamonds', { quiet_level => 'very', quantity => 9 }); # Note the curly braces</pre> | |
<p>If you were using <span class="code">=></span> 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 <span class="code">KEY, VALUE, KEY, VALUE</span>, then continuing to use <span class="code">=></span> may break your code. The easiest workaround is to change that <i>fat arrow</i> to a regular comma, and manually add quotes to its left-hand side. Or, you can change the sub's API to <a href="#_type_Signature.pod6-Slurpy_parameters">slurp a hash</a>. A better long-term solution is to change the sub's API to expect <a href="#_type_Pair.pod6">Pair</a>s; however, this requires you to change all sub calls at once.</p> | |
<pre class="code"># Perl | |
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 ); | |
</pre> | |
<pre class="code"># Raku, 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 | |
# Raku, 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 | |
</pre> | |
<a name="t2.3.9"></a> <h2 id="_language_5to6-nutshell.pod6-?_:_Ternary_operator"><span class="code">? :</span> Ternary operator</h2> | |
<p>The conditional operator <span class="code">? :</span> has been replaced by <span class="code">?? !!</span>:</p> | |
<pre class="code">my $result = $score > 60 ? 'Pass' : 'Fail'; # Perl | |
</pre> | |
<pre class="code">my $result = $score > 60 ?? 'Pass' !! 'Fail'; # Raku | |
</pre> | |
<a name="t2.3.10"></a> <h2 id="_language_5to6-nutshell.pod6-._(Dot)_String_concatenation"><span class="code">.</span> (Dot) String concatenation</h2> | |
<p>Replaced by the tilde.</p> | |
<p>Mnemonic: think of "stitching" together the two strings with needle and thread.</p> | |
<pre class="code">$food = 'grape' . 'fruit'; # Perl | |
</pre> | |
<pre class="code">$food = 'grape' ~ 'fruit'; # Raku | |
</pre> | |
<a name="t2.3.11"></a> <h2 id="_language_5to6-nutshell.pod6-x_List_repetition_or_string_repetition_operator"><span class="code">x</span> List repetition or string repetition operator</h2> | |
<p>In Perl, <span class="code">x</span> is the repetition operator, which behaves differently in scalar or list contexts:</p> | |
<ul><li><p>in scalar context <span class="code">x</span> repeats a string;</p> | |
</li></ul> <ul><li><p>in list context <span class="code">x</span> repeats a list, but only if the left argument is parenthesized!</p> | |
</li></ul> <p>Raku uses two different repetition operators to achieve the above:</p> | |
<ul><li><p><span class="code">x</span> for string repetitions (in any context);</p> | |
</li></ul> <ul><li><p><span class="code">xx</span> for list repetitions (in any context).</p> | |
</li></ul> <p>Mnemonic: <span class="code">x</span> is short and <span class="code">xx</span> is long, so <span class="code">xx</span> is the one used for lists.</p> | |
<pre class="code"># Perl | |
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 | |
</pre> | |
<pre class="code"># Raku | |
print '-' x 80; # Unchanged | |
@ones = 1 xx 80; # Parentheses no longer needed | |
@ones = 5 xx @ones; # Parentheses no longer needed | |
</pre> | |
<a name="t2.3.12"></a> <h2 id="_language_5to6-nutshell.pod6-.._..._Two_dots_or_three_dots,_range_op_or_flipflop_op"><span class="code">..</span> <span class="code">...</span> Two dots or three dots, range op or flipflop op</h2> | |
<p>In Perl, <span class="code">..</span> was one of two completely different operators, depending on context.</p> | |
<p>In list context, <span class="code">..</span> is the familiar range operator. Ranges from Perl code should <b>not</b> require translation.</p> | |
<p>In scalar context, <span class="code">..</span> and <span class="code">...</span> were the little-known Flipflop operators. They have been replaced by <span class="code">ff</span> and <span class="code">fff</span>.</p> | |
<a name="t2.3.13"></a> <h2 id="_language_5to6-nutshell.pod6-String_interpolation">String interpolation</h2> | |
<p>In Perl, <span class="code">"${foo}s"</span> deliminates a variable name from regular text next to it. In Raku, simply extend the curly braces to include the sigil too: <span class="code">"{$foo}s"</span>. This is in fact a very simple case of interpolating an expression.</p> | |
<a name="t2.4"></a> <h1 id="_language_5to6-nutshell.pod6-Compound_statements">Compound statements</h1> | |
<p>These statements include conditionals and loops.</p> | |
<a name="t2.4.1"></a> <h2 id="_language_5to6-nutshell.pod6-Conditionals">Conditionals</h2> | |
<a name="t2.4.1.1"></a> <h3 id="_language_5to6-nutshell.pod6-if_elsif_else_unless"><span class="code">if</span> <span class="code">elsif</span> <span class="code">else</span> <span class="code">unless</span></h3> | |
<p>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:</p> | |
<pre class="code">if (my $x = dostuff()) {...} # Perl | |
</pre> | |
<pre class="code">if dostuff() -> $x {...} # Raku | |
</pre> | |
<p>(You can still use the <span class="code">my</span> form in Raku, but it will scope to the outer block, not the inner.)</p> | |
<p>The <span class="code">unless</span> conditional only allows for a single block in Raku; it does not allow for an <span class="code">elsif</span> or <span class="code">else</span> clause.</p> | |
<a name="t2.4.1.2"></a> <h3 id="_language_5to6-nutshell.pod6-given-when"><span class="code">given</span>-<span class="code">when</span></h3> | |
<p>The <span class="code">given</span>-<span class="code">when</span> construct is like a chain of <span class="code">if</span>-<span class="code">elsif</span>-<span class="code">else</span> statements or like the <span class="code">switch</span>-<span class="code">case</span> construct C, for example. It has the general structure:</p> | |
<pre class="code">given EXPR { | |
when EXPR { ... } | |
when EXPR { ... } | |
default { ... } | |
} | |
</pre> | |
<p>In its simplest form, the construct is as follows:</p> | |
<pre class="code">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(); | |
} | |
} | |
</pre> | |
<p>This is simple in the sense that a scalar value is matched in the <span class="code">when</span> statements against <span class="code">$_</span>, which was set by the <span class="code">given</span>. More generally, the matches are actually smartmatches on <span class="code">$_</span> such that lookups using more complex entities such as regexps can be used instead of scalar values.</p> | |
<p>See also the warnings on the smartmatch op above.</p> | |
<a name="t2.4.2"></a> <h2 id="_language_5to6-nutshell.pod6-Loops">Loops</h2> | |
<a name="t2.4.2.1"></a> <h3 id="_language_5to6-nutshell.pod6-while_until"><span class="code">while</span> <span class="code">until</span></h3> | |
<p>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:</p> | |
<pre class="code">while (my $x = dostuff()) {...} # Perl | |
</pre> | |
<pre class="code">while dostuff() -> $x {...} # Raku | |
</pre> | |
<p>(You can still use the <span class="code">my</span> form in Raku, but it will scope to the outer block, not the inner.)</p> | |
<p>Note that reading line-by-line from a filehandle has changed.</p> | |
<p>In Perl, it was done in a <span class="code">while</span> loop using the diamond operator. Using <span class="code">for</span> instead of <span class="code">while</span> was a common bug, because the <span class="code">for</span> causes the whole file to be sucked in at once, swamping the program's memory usage.</p> | |
<p>In Raku, <span class="code">for</span> statement is <b>lazy</b>, so we read line-by-line in a <span class="code">for</span> loop using the <span class="code">.lines</span> method.</p> | |
<pre class="code">while (<IN_FH>) { } # Perl | |
</pre> | |
<pre class="code">for $IN_FH.lines { } # Raku | |
</pre> | |
<p>Also note that in Raku, lines are <span class="code">chomp</span>ed by default.</p> | |
<a name="t2.4.2.2"></a> <h3 id="_language_5to6-nutshell.pod6-do_while/until"><span class="code">do</span> <span class="code">while</span>/<span class="code">until</span></h3> | |
<pre class="code"># Perl | |
do { | |
... | |
} while $x < 10; | |
do { | |
... | |
} until $x >= 10; | |
</pre> | |
<p>The construct is still present, but <span class="code">do</span> was renamed to <span class="code">repeat</span>, to better represent what the construct does:</p> | |
<pre class="code"># Raku | |
repeat { | |
... | |
} while $x < 10; | |
repeat { | |
... | |
} until $x >= 10; | |
</pre> | |
<p>Note that Perl's unadorned <span class="code">do</span> block ('<span class="code">do {...}</span>') behaves the same when used in Raku.</p> | |
<a name="t2.4.2.3"></a> <h3 id="_language_5to6-nutshell.pod6-for_foreach"><span class="code">for</span> <span class="code">foreach</span></h3> | |
<p>Note first this common misunderstanding about the <span class="code">for</span> and <span class="code">foreach</span> 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 compiler looks for the semicolons within the parentheses to determine which type of loop to parse.</p> | |
<p>The C-style three-factor form now uses the <span class="code">loop</span> keyword, and is otherwise unchanged. The parentheses <b>are</b> still required.</p> | |
<pre class="code">for ( my $i = 1; $i <= 10; $i++ ) { ... } # Perl | |
</pre> | |
<pre class="code">loop ( my $i = 1; $i <= 10; $i++ ) { ... } # Raku | |
</pre> | |
<p>The loop-iterator form is named <span class="code">for</span> in Raku and <span class="code">foreach</span> is no longer a keyword. The <span class="code">for</span> loop has the following rules:</p> | |
<ul><li><p>parentheses are optional;</p> | |
</li></ul> <ul><li><p>the iteration variable, if any, has been moved from appearing before the list, to appearing after the list and an added arrow operator;</p> | |
</li></ul> <ul><li><p>the iteration variable is now always lexical: <span class="code">my</span> is neither needed nor allowed;</p> | |
</li></ul> <ul><li><p>the iteration variable is a <i>read-only</i> alias to the current list element (in Perl it is a <i>read-write</i> alias!). If a read-write alias is required, change the <span class="code">-></span> before the iteration variable to a <span class="code"><-></span>. When translating from Perl, inspect the use of the loop variable to decide if read-write is needed.</p> | |
</li></ul> <pre class="code">for my $car (@cars) {...} # Perl; read-write | |
</pre> | |
<pre class="code">for @cars -> $car {...} # Raku; read-only | |
for @cars <-> $car {...} # Raku; read-write | |
</pre> | |
<p>In Raku and unlike Perl, the default topic <span class="code">$_</span> will behave in the same way, becoming read-only when used as a topic variable.</p> | |
<pre class="code">for (@cars) {...} # Perl; $_ is read-write | |
</pre> | |
<pre class="code">for @cars {...} # Raku; $_ is read-only | |
for @cars <-> $_ {...} # Raku; $_ is also read-write | |
</pre> | |
<p>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:</p> | |
<pre class="code">my @array = 1..10; | |
for @array -> $first, $second { | |
say "First is $first, second is $second"; | |
} | |
</pre> | |
<p>For cases in which the number of elements iterated over isn't a multiple of the number of variables after the arrow operator, you can provide variables with default values:</p> | |
<pre class="code">my @array = 1..9; | |
for @array -> $first, $second = 0 { | |
say "First is $first, second is $second"; | |
} | |
</pre> | |
<a name="t2.4.2.4"></a> <h3 id="_language_5to6-nutshell.pod6-each"><span class="code">each</span></h3> | |
<p>Here is the equivalent to Perl’s <span class="code">while…each(%hash)</span> or <span class="code">while…each(@array)</span> (i.e., iterating over both the keys/indices and values of a data structure) in Raku:</p> | |
<pre class="code">while (my ($i, $v) = each(@array)) { ... } # Perl | |
</pre> | |
<pre class="code">for @array.kv -> $i, $v { ... } # Raku | |
</pre> | |
<pre class="code">while (my ($k, $v) = each(%hash)) { ... } # Perl | |
</pre> | |
<pre class="code">for %hash.kv -> $k, $v { ... } # Raku | |
</pre> | |
<a name="t2.4.3"></a> <h2 id="_language_5to6-nutshell.pod6-Flow_control_statements">Flow control statements</h2> | |
<p>Unchanged:</p> | |
<ul><li><p><span class="code">next</span></p> | |
</li></ul> <ul><li><p><span class="code">last</span></p> | |
</li></ul> <ul><li><p><span class="code">redo</span></p> | |
</li></ul> <a name="t2.4.3.1"></a> <h3 id="_language_5to6-nutshell.pod6-continue"><span class="code">continue</span></h3> | |
<p>There is no longer a <span class="code">continue</span> block. Instead, use a <span class="code">NEXT</span> block (phaser) within the body of the loop.</p> | |
<pre class="code"># Perl | |
my $str = ''; | |
for (1..5) { | |
next if $_ % 2 == 1; | |
$str .= $_; | |
} | |
continue { | |
$str .= ':' | |
} | |
</pre> | |
<pre class="code"># Raku | |
my $str = ''; | |
for 1..5 { | |
next if $_ % 2 == 1; | |
$str ~= $_; | |
NEXT { | |
$str ~= ':' | |
} | |
} | |
</pre> | |
<p>Please note that phasers don't really need a block. This can be very handy when you don't want another scope:</p> | |
<pre class="code"># Raku | |
my $str = ''; | |
for 1..5 { | |
next if $_ % 2 == 1; | |
$str ~= $_; | |
NEXT $str ~= ':'; | |
} | |
</pre> | |
<a name="t2.5"></a> <h1 id="_language_5to6-nutshell.pod6-Functions">Functions</h1> | |
NOTE FOR EDITORS: When adding functions, please place them in | |
alphabetical order. | |
<a name="t2.5.1"></a> <h2 id="_language_5to6-nutshell.pod6-Built-ins_with_bare_blocks">Built-ins with bare blocks</h2> | |
<p>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. <span class="code">map</span>, <span class="code">grep</span>, etc.</p> | |
<pre class="code">my @results = grep { $_ eq "bars" } @foo; # Perl | |
</pre> | |
<pre class="code">my @results = grep { $_ eq "bars" }, @foo; # Raku | |
</pre> | |
<a name="t2.5.2"></a> <h2 id="_language_5to6-nutshell.pod6-delete"><span class="code">delete</span></h2> | |
<p>Turned into an adverb of the <a href="#1-{}_Hash_indexing/slicing"><span class="code">{}</span> hash subscripting</a> and <a href="#1-[]_Array_indexing/slicing"><span class="code">[]</span> array subscripting</a> operators.</p> | |
<pre class="code">my $deleted_value = delete $hash{$key}; # Perl | |
</pre> | |
<pre class="code">my $deleted_value = %hash{$key}:delete; # Raku - use :delete adverb | |
</pre> | |
<pre class="code">my $deleted_value = delete $array[$i]; # Perl | |
</pre> | |
<pre class="code">my $deleted_value = @array[$i]:delete; # Raku - use :delete adverb | |
</pre> | |
<a name="t2.5.3"></a> <h2 id="_language_5to6-nutshell.pod6-exists"><span class="code">exists</span></h2> | |
<p>Turned into an adverb of the <a href="#1-{}_Hash_indexing/slicing"><span class="code">{}</span> hash subscripting</a> and <a href="#1-[]_Array_indexing/slicing"><span class="code">[]</span> array subscripting</a> operators.</p> | |
<pre class="code">say "element exists" if exists $hash{$key}; # Perl | |
</pre> | |
<pre class="code">say "element exists" if %hash{$key}:exists; # Raku - use :exists adverb | |
</pre> | |
<pre class="code">say "element exists" if exists $array[$i]; # Perl | |
</pre> | |
<pre class="code">say "element exists" if @array[$i]:exists; # Raku - use :exists adverb | |
</pre> | |
<a name="t2.6"></a> <h1 id="_language_5to6-nutshell.pod6-Regular_expressions_(_regex_/_regexp_)">Regular expressions ( regex / regexp )</h1> | |
<a name="t2.6.1"></a> <h2 id="_language_5to6-nutshell.pod6-Change_=~_and_!~_to_~~_and_!~~_.">Change <span class="code">=~</span> and <span class="code">!~</span> to <span class="code">~~</span> and <span class="code">!~~</span> .</h2> | |
<p>In Perl, matches and substitutions are done against a variable using the <span class="code">=~</span> regexp-binding op.</p> | |
<p>In Raku, the <span class="code">~~</span> smartmatch op is used instead.</p> | |
<pre class="code">next if $line =~ /static/ ; # Perl | |
</pre> | |
<pre class="code">next if $line ~~ /static/ ; # Raku | |
</pre> | |
<pre class="code">next if $line !~ /dynamic/ ; # Perl | |
</pre> | |
<pre class="code">next if $line !~~ /dynamic/ ; # Raku | |
</pre> | |
<pre class="code">$line =~ s/abc/123/; # Perl | |
</pre> | |
<pre class="code">$line ~~ s/abc/123/; # Raku | |
</pre> | |
<p>Alternately, the new <span class="code">.match</span> and <span class="code">.subst</span> methods can be used. Note that <a href="#_routine_subst.pod6"><span class="code">.subst</span> is non-mutating</a>.</p> | |
<a name="t2.6.2"></a> <h2 id="_language_5to6-nutshell.pod6-Captures_start_with_0,_not_1">Captures start with 0, not 1</h2> | |
<pre class="code">/(.+)/ and print $1; # Per | |
</pre> | |
<pre class="code">/(.+)/ and print $0; # Raku | |
</pre> | |
<a name="t2.6.3"></a> <h2 id="_language_5to6-nutshell.pod6-Move_modifiers">Move modifiers</h2> | |
<p>Move any modifiers from the end of the regex to the beginning. This may require you to add the optional <span class="code">m</span> on a plain match like <span class="code">/abc/</span>.</p> | |
<pre class="code">next if $line =~ /static/i ; # Perl | |
</pre> | |
<pre class="code">next if $line ~~ m:i/static/ ; # Raku | |
</pre> | |
<a name="t2.6.4"></a> <h2 id="_language_5to6-nutshell.pod6-Add_:P5_or_:Perl5_adverb">Add :P5 or :Perl5 adverb</h2> | |
<p>If the actual regex is complex, you may want to use it as-is (with some exceptions), by adding the <span class="code">P5</span> modifier.</p> | |
<pre class="code">next if $line =~ m/[aeiou]/ ; # Perl | |
</pre> | |
<pre class="code">next if $line ~~ m:P5/[aeiou]/ ; # Raku, using P5 modifier | |
next if $line ~~ m/ <[aeiou]> / ; # Raku, native new syntax | |
</pre> | |
<p>If the Perl regex has any modifiers, move them from the end and place them after the <span class="code">P5</span> modifier. Each modifier will have to be separated from any others by a colon. For example:</p> | |
<pre class="code">my $a = "abcabc"; | |
my $b = $a; | |
$a =~ s/abcaBc//gi; # Perl 5 | |
$a ~~ s:P5:g:i/ab//; # Raku, using P5 modifier | |
$b ~~ s:gi/ab//; # Raku, native new syntax | |
say $a; | |
say $b; | |
</pre> | |
<p>Another accommodation required with the P5 syntax is to replace curly braces with square brackets when specifying Unicode in the expression:</p> | |
<pre class="code">next if $line =~ m/\x{2043}; | |
next if $line ~~ m:P5/\x[2043]/; | |
next if $line ~~ /\x[2043]/; | |
</pre> | |
<p>Please note that the Perl regular expression syntax dates from many years ago and may lack features that have been added since the beginning of the Raku project. Two such features not yet implemented in Raku for the P5 syntax are the Perl Unicode property matchers <span class="code">\p{}</span> and <span class="code">\P{}</span>.</p> | |
<a name="t2.6.5"></a> <h2 id="_language_5to6-nutshell.pod6-Special_matchers_generally_fall_under_the_<>_syntax">Special matchers generally fall under the <> syntax</h2> | |
<p>There are many cases of special matching syntax that Perl regexes support. They won't all be listed here but often, instead of being surrounded by <span class="code">()</span>, the assertions will be surrounded by <span class="code"><></span>.</p> | |
<p>For character classes, this means that:</p> | |
<ul><li><p><span class="code">[abc]</span> becomes <span class="code"><[abc]></span></p> | |
</li></ul> <ul><li><p><span class="code">[^abc]</span> becomes <span class="code"><-[abc]></span></p> | |
</li></ul> <ul><li><p><span class="code">[a-zA-Z]</span> becomes <span class="code"><[a..zA..Z]></span></p> | |
</li></ul> <ul><li><p><span class="code">[[:upper:]]</span> becomes <span class="code"><:Upper></span></p> | |
</li></ul> <ul><li><p><span class="code">[abc[:upper:]]</span> becomes <span class="code"><[abc]+:Upper></span></p> | |
</li></ul> <p>For lookaround assertions:</p> | |
<ul><li><p><span class="code">(?=[abc])</span> becomes <span class="code"><?[abc]></span></p> | |
</li></ul> <ul><li><p><span class="code">(?=ar?bitrary* pattern)</span> becomes <span class="code"><before ar?bitrary* pattern></span></p> | |
</li></ul> <ul><li><p><span class="code">(?!=[abc])</span> becomes <span class="code"><![abc]></span></p> | |
</li></ul> <ul><li><p><span class="code">(?!=ar?bitrary* pattern)</span> becomes <span class="code"><!before ar?bitrary* pattern></span></p> | |
</li></ul> <ul><li><p><span class="code">(?<=ar?bitrary* pattern)</span> becomes <span class="code"><after ar?bitrary* pattern></span></p> | |
</li></ul> <ul><li><p><span class="code">(?<!ar?bitrary* pattern)</span> becomes <span class="code"><!after ar?bitrary* pattern></span></p> | |
</li></ul> <p>For more info see <a href="#_language_regexes.pod6-Lookahead_assertions">lookahead assertions</a>.</p> | |
<p>(Unrelated to <> syntax, the "lookaround" <span class="code">/foo\Kbar/</span> becomes <span class="code">/foo <( bar )> /</span></p> | |
<ul><li><p><span class="code">(?(?{condition))yes-pattern|no-pattern)</span> becomes <span class="code">[ <?{condition}> yes-pattern | no-pattern ]</span></p> | |
</li></ul> <a name="t2.6.6"></a> <h2 id="_language_5to6-nutshell.pod6-Longest_token_matching_(LTM)_displaces_alternation">Longest token matching (LTM) displaces alternation</h2> | |
<p>In Raku regexes, <span class="code">|</span> does LTM, which decides which alternation wins an ambiguous match based off of a set of rules, rather than about which was written first.</p> | |
<p>The simplest way to deal with this is just to change any <span class="code">|</span> in your Perl regex to a <span class="code">||</span>.</p> | |
<p>However, if a regex written with <span class="code">||</span> is inherited or composed into a grammar that uses <span class="code">|</span> 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, <span class="code">|</span> may be a better choice for grammar reuse.</p> | |
<a name="t2.6.7"></a> <h2 id="_language_5to6-nutshell.pod6-Named_captures">Named captures</h2> | |
<p>These work in a slightly different way; also they only work in the latest versions of Perl.</p> | |
<pre class="code">use v5.22; | |
"þor is mighty" =~ /is (?<iswhat>\w+)/n; | |
say $+{iswhat}; | |
</pre> | |
<p>The <span class="code">iswhat</span> within a non-capturing group is used to actually capture what is behind, and up to the end of the group (the <span class="code">)</span>). The capture goes to the <span class="code">%+</span> hash under the key with the name of the capture. In Raku <a href="#_language_regexes.pod6-Capturing_groups">named captures work this way</a></p> | |
<pre class="code">"þor is mighty" ~~ /is \s+ $<iswhat>=(\w+)/; | |
say $<iswhat>; | |
</pre> | |
<p>An actual assignment is made within the regular expression; that's the same syntax used for the variable outside it.</p> | |
TODO more rules. Use L<< C<translate_regex.pl> from Blue Tiger|https://github.com/Util/Blue_Tiger/>> in the meantime. | |
<a name="t2.6.7.1"></a> <h3 id="_language_5to6-nutshell.pod6-Comments">Comments</h3> | |
<p>As with Perl, comments work as usual in regexes.</p> | |
<pre class="code">/ word #`(match lexical "word") /</pre> | |
<a name="t2.7"></a> <h1 id="_language_5to6-nutshell.pod6-BEGIN,_UNITCHECK,_CHECK,_INIT_and_END">BEGIN, UNITCHECK, CHECK, INIT and END</h1> | |
<p>Except for <span class="code">UNITCHECK</span>, all of these special blocks exist in Raku as well. In Raku, these are called <a href="#_language_phasers.pod6">Phasers</a>. But there are some differences!</p> | |
<a name="t2.7.1"></a> <h2 id="_language_5to6-nutshell.pod6-UNITCHECK_becomes_CHECK">UNITCHECK becomes CHECK</h2> | |
<p>There is currently <b>no</b> direct equivalent of <span class="code">CHECK</span> blocks in Raku. The <span class="code">CHECK</span> phaser in Raku has the same semantics as the <span class="code">UNITCHECK</span> block in Perl: 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 <span class="code">CHECK</span> blocks in Perl. But for compatibility reasons, it was impossible to change the semantics of <span class="code">CHECK</span> blocks in Perl, so a <span class="code">UNITCHECK</span> block was introduced in 5.10. Consequently, it was decided that the Raku <span class="code">CHECK</span> phaser would follow the saner Perl <span class="code">UNITCHECK</span> semantics.</p> | |
<a name="t2.7.2"></a> <h2 id="_language_5to6-nutshell.pod6-No_block_necessary">No block necessary</h2> | |
<p>In Perl, these special blocks <b>must</b> have curly braces, which implies a separate scope. In Raku this is not necessary, allowing these special blocks to share their scope with the surrounding lexical scope.</p> | |
<pre class="code">my $foo; # Perl | |
BEGIN { $foo = 42 } | |
</pre> | |
<pre class="code">BEGIN my $foo = 42; # Raku | |
</pre> | |
<a name="t2.7.3"></a> <h2 id="_language_5to6-nutshell.pod6-Changed_semantics_with_regards_to_precompilation">Changed semantics with regards to precompilation</h2> | |
<p>If you put <span class="code">BEGIN</span> and <span class="code">CHECK</span> phasers in a module that is being precompiled, then these phasers will <b>only</b> be executed during precompilation and <b>not</b> when a precompiled module is being loaded. So when porting module code from Perl, you may need to change <span class="code">BEGIN</span> and <span class="code">CHECK</span> blocks to <span class="code">INIT</span> blocks to ensure that they're run when loading that module.</p> | |
<a name="t2.8"></a> <h1 id="_language_5to6-nutshell.pod6-Pragmas">Pragmas</h1> | |
<a name="t2.8.0.1"></a> <h3 id="_language_5to6-nutshell.pod6-strict"><span class="code">strict</span></h3> | |
<p>Strict mode is now on by default.</p> | |
<a name="t2.8.0.2"></a> <h3 id="_language_5to6-nutshell.pod6-warnings"><span class="code">warnings</span></h3> | |
<p>Warnings are now on by default.</p> | |
<p><span class="code">no warnings</span> is currently <a href="#_language_glossary.pod6-NYI">NYI</a>, but putting things in a <span class="code">quietly</span> {} block will silence.</p> | |
<a name="t2.8.0.3"></a> <h3 id="_language_5to6-nutshell.pod6-autodie"><span class="code">autodie</span></h3> | |
<p>The functions which were altered by <span class="code">autodie</span> to throw exceptions on error, now generally return <span class="code">Failure</span>s by default. You can test a <span class="code">Failure</span> for definedness / truthiness without any problem. If you use the <span class="code">Failure</span> in any other way, then the <span class="code">Exception</span> that was encapsulated by the <span class="code">Failure</span> will be thrown.</p> | |
<pre class="code"># Perl | |
open my $i_fh, '<', $input_path; # Fails silently on error | |
use autodie; | |
open my $o_fh, '>', $output_path; # Throws exception on error | |
</pre> | |
<pre class="code"># Raku | |
my $i_fh = open $input_path, :r; # Returns Failure on error | |
my $o_fh = open $output_path, :w; # Returns Failure on error | |
</pre> | |
<p>Because you can check for truthiness without any problem, you can use the result of an <span class="code">open</span> in an <span class="code">if</span> statement:</p> | |
<pre class="code"># Raku | |
if open($input_path,:r) -> $handle { | |
.say for $handle.lines; | |
} | |
else { | |
# gracefully handle the fact that the open() failed | |
} | |
</pre> | |
<a name="t2.8.0.4"></a> <h3 id="_language_5to6-nutshell.pod6-base,_parent"><span class="code">base</span>, <span class="code">parent</span></h3> | |
<p>Both <span class="code">use base</span> and <span class="code">use parent</span> have been replaced in Raku by the <span class="code">is</span> keyword, in the class declaration.</p> | |
<pre class="code"># Perl | |
package Cat; | |
use base qw(Animal); | |
</pre> | |
<pre class="code"># Raku | |
class Cat is Animal {} | |
</pre> | |
<p>Note that the <span class="code">Animal</span> class must be <b>known</b> at compilation time prior to be able to inherit from it.</p> | |
<a name="t2.8.0.5"></a> <h3 id="_language_5to6-nutshell.pod6-bigint_bignum_bigrat"><span class="code">bigint</span> <span class="code">bignum</span> <span class="code">bigrat</span></h3> | |
<p>No longer relevant.</p> | |
<p><span class="code">Int</span> is now arbitrary precision, as is the numerator of <span class="code">Rat</span> (the denominator is limited to <span class="code">2**64</span>, after which it will automatically upgrade to <span class="code">Num</span> to preserve performance). If you want a <span class="code">Rat</span> with an arbitrary-precision denominator, <span class="code">FatRat</span> is available.</p> | |
<a name="t2.8.0.6"></a> <h3 id="_language_5to6-nutshell.pod6-constant"><span class="code">constant</span></h3> | |
<p>In Raku, <span class="code">constant</span> is a declarator for variables, just like <span class="code">my</span>, except the variable is permanently locked to the result of its initialization expression (evaluated at compile time).</p> | |
<p>So, change the <span class="code">=></span> to <span class="code">=</span>.</p> | |
<pre class="code">use constant DEBUG => 0; # Perl | |
</pre> | |
<pre class="code">constant DEBUG = 0; # Raku | |
</pre> | |
<pre class="code">use constant pi => 4 * atan2(1, 1); # Perl | |
</pre> | |
<pre class="code">tau, pi, e, i; # built-in constants in Raku | |
τ, π, 𝑒 # and their unicode equivalents | |
</pre> | |
<a name="t2.8.0.7"></a> <h3 id="_language_5to6-nutshell.pod6-encoding"><span class="code">encoding</span></h3> | |
<p>Allows you to write your script in non-ascii or non-utf8. Raku uses, for the time being, only utf8 for its scripts.</p> | |
<a name="t2.8.0.8"></a> <h3 id="_language_5to6-nutshell.pod6-integer"><span class="code">integer</span></h3> | |
<p>Perl pragma to use integer arithmetic instead of floating point. There is no such thing in Raku. If you use native integers in your calculations, then this will be the closest thing.</p> | |
<pre class="code">#Raku | |
my int $foo = 42; | |
my int $bar = 666; | |
say $foo * $bar; # uses native integer multiplication | |
</pre> | |
<a name="t2.8.0.9"></a> <h3 id="_language_5to6-nutshell.pod6-lib"><span class="code">lib</span></h3> | |
<p>Manipulate where modules are looked up at compile time. The underlying logic is <b>very</b> different from Perl, but in the case you are using an equivalent syntax, <span class="code">use lib</span> in Raku works the same as in Perl.</p> | |
<a name="t2.8.0.10"></a> <h3 id="_language_5to6-nutshell.pod6-mro"><span class="code">mro</span></h3> | |
<p>No longer relevant.</p> | |
<p>In Raku, 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 <span class="code">mro</span> metamethod thusly:</p> | |
<pre class="code">say Animal.^mro; # .^ indicates calling a metamethod on the object | |
</pre> | |
<a name="t2.8.0.11"></a> <h3 id="_language_5to6-nutshell.pod6-utf8"><span class="code">utf8</span></h3> | |
<p>No longer relevant: in Raku, source code is expected to be in utf8 encoding.</p> | |
<a name="t2.8.0.12"></a> <h3 id="_language_5to6-nutshell.pod6-vars"><span class="code">vars</span></h3> | |
<p>Discouraged in Perl. See <a href="#_routine_https:__perldoc.perl.org_vars.html.pod6">https://perldoc.perl.org/vars.html</a>.</p> | |
<p>You should refactor your Perl code to remove the need for <span class="code">use vars</span>, before translating into Raku.</p> | |
<a name="t2.9"></a> <h1 id="_language_5to6-nutshell.pod6-Command-line_flags">Command-line flags</h1> | |
<p>See <a href="#_routine_https:__github.com_rakudo_rakudo_wiki_Running-rakudo-from-the-command-line.pod6">the command line flags that Rakudo uses</a></p> | |
<p>Unchanged:</p> | |
<p>-c -e -h -I -n -p -v -V</p> | |
<a name="t2.9.0.1"></a> <h3 id="_language_5to6-nutshell.pod6--a"><span class="code">-a</span></h3> | |
<p>Change your code to use <span class="code">.split</span> manually.</p> | |
<a name="t2.9.0.2"></a> <h3 id="_language_5to6-nutshell.pod6--F"><span class="code">-F</span></h3> | |
<p>Change your code to use <span class="code">.split</span> manually.</p> | |
<a name="t2.9.0.3"></a> <h3 id="_language_5to6-nutshell.pod6--l"><span class="code">-l</span></h3> | |
<p>This is now the default behavior.</p> | |
<a name="t2.9.0.4"></a> <h3 id="_language_5to6-nutshell.pod6--M_-m"><span class="code">-M</span> <span class="code">-m</span></h3> | |
<p>Only <span class="code">-M</span> remains. And, as you can no longer use the "no Module" syntax, the use of <span class="code">-</span> with <span class="code">-M</span> to "no" a module is no longer available.</p> | |
<a name="t2.9.0.5"></a> <h3 id="_language_5to6-nutshell.pod6--E"><span class="code">-E</span></h3> | |
<p>Since all features are already enabled, just use lowercase <span class="code">-e</span> .</p> | |
<a name="t2.9.0.6"></a> <h3 id="_language_5to6-nutshell.pod6--d,_-dt,_-d:foo,_-D,_etc."><span class="code">-d</span>, <span class="code">-dt</span>, <span class="code">-d:foo</span>, <span class="code">-D</span>, etc.</h3> | |
<p>Replaced with the <span class="code">++BUG</span> metasyntactic option.</p> | |
<a name="t2.9.0.7"></a> <h3 id="_language_5to6-nutshell.pod6--s">-s</h3> | |
<p>Switch parsing is now done by the parameter list of the <span class="code">MAIN</span> subroutine.</p> | |
<pre class="code"># Perl | |
#!/usr/bin/perl -s | |
if ($xyz) { print "$xyz\n" } | |
./example.pl -xyz=5 | |
5 | |
</pre> | |
<pre class="code"># Raku | |
sub MAIN( Int :$xyz ) { | |
say $xyz if $xyz.defined; | |
} | |
</pre> | |
<pre class="code">raku example.p6 --xyz=5 | |
5 | |
raku example.p6 -xyz=5 | |
5 | |
</pre> | |
<ul><li><p><span class="code">-t</span></p> | |
</li></ul> <p>Removed.</p> | |
<ul><li><p><span class="code">-P</span> <span class="code">-u</span> <span class="code">-U</span> <span class="code">-W</span> <span class="code">-X</span></p> | |
</li></ul> <p>Removed. See <a href="#_routine_https:__design.raku.org_S19.html.pod6-Removed_Syntactic_Features">Removed Syntactic Features</a>.</p> | |
<ul><li><p><span class="code">-w</span></p> | |
</li></ul> <p>This is now the default behavior.</p> | |
<ul><li><p><span class="code">-S</span>, <span class="code">-T</span>.</p> | |
</li></ul> <p>This has been eliminated. Several ways to <a href="#_routine_https:__www.reddit.com_r_perl6_comments_718z4o_taint_mode_for_perl_6_.pod6">replicate "taint" mode are discussed in Reddit</a>.</p> | |
<a name="t2.10"></a> <h1 id="_language_5to6-nutshell.pod6-File-related_operations">File-related operations</h1> | |
<a name="t2.10.1"></a> <h2 id="_language_5to6-nutshell.pod6-Reading_the_lines_of_a_text_file_into_an_array">Reading the lines of a text file into an array</h2> | |
<p>In Perl, a common idiom for reading the lines of a text file goes something like this:</p> | |
<pre class="code">open my $fh, "<", "file" or die "$!"; | |
my @lines = <$fh>; # lines are NOT chomped | |
close $fh; | |
</pre> | |
<p>In Raku, this has been simplified to</p> | |
<pre class="code">my @lines = "file".IO.lines; # auto-chomped</pre> | |
<p>Do <i>not</i> 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.:</p> | |
<pre class="code"># 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</pre> | |
<p>If for some reason you do want to slurp the file first, then you can call the <span class="code">lines</span> method on the result of <span class="code">slurp</span> instead:</p> | |
<pre class="code">my @lines = "test-file".IO.slurp.lines; # also auto-chomps</pre> | |
<p>Also, be aware that <span class="code">$!</span> is not really relevant for file IO operation failures in Raku. An IO operation that fails will return a <span class="code">Failure</span> instead of throwing an exception. If you want to return the failure message, it is in the failure itself, not in <span class="code">$!</span>. To do similar IO error checking and reporting as in Perl:</p> | |
<pre class="code">my $fh = open('./bad/path/to/file', :w) or die $fh;</pre> | |
<p><i>Note</i>: <span class="code">$fh</span> instead of <span class="code">$!</span>. Or, you can set <span class="code">$_</span> to the failure and die with $_:</p> | |
<pre class="code">my $fh = open('./bad/path/to/file', :w) orelse .die; # Raku</pre> | |
<p>Any operation that tries to use the failure will cause the program to fault and terminate. Even just a call to the <span class="code">.self</span> method is sufficient.</p> | |
<pre class="code">my $fh = open('./bad/path/to/file', :w).self;</pre> | |
<a name="t2.10.2"></a> <h2 id="_language_5to6-nutshell.pod6-Capturing_the_standard_output_of_executables.">Capturing the standard output of executables.</h2> | |
<p>Whereas in Perl you would do:</p> | |
<pre class="code">my $arg = 'Hello'; | |
my $captured = `echo \Q$arg\E`; | |
my $captured = qx(echo \Q$arg\E); | |
</pre> | |
<p>Or using <span class="code">String::ShellQuote</span> (because <span class="code">\Q…\E</span> is not completely right):</p> | |
<pre class="code">my $arg = shell_quote 'Hello'; | |
my $captured = `echo $arg`; | |
my $captured = qx(echo $arg); | |
</pre> | |
<p>In Raku, you will probably want to run commands without using the shell:</p> | |
<pre class="code">my $arg = 'Hello'; | |
my $captured = run('echo', $arg, :out).out.slurp; | |
my $captured = run(«echo "$arg"», :out).out.slurp;</pre> | |
<p>You can also use the shell if you really want to:</p> | |
<pre class="code">my $arg = 'Hello'; | |
my $captured = shell("echo $arg", :out).out.slurp; | |
my $captured = qqx{echo $arg};</pre> | |
<p>But beware that in this case there is <b>no protection at all</b>! <span class="code">run</span> does not use the shell, so there is no need to escape the arguments (arguments are passed directly). If you are using <span class="code">shell</span> or <span class="code">qqx</span>, 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.</p> | |
<a name="t2.11"></a> <h1 id="_language_5to6-nutshell.pod6-Environment_variables">Environment variables</h1> | |
<a name="t2.11.1"></a> <h2 id="_language_5to6-nutshell.pod6-Perl_module_library_path">Perl module library path</h2> | |
<p>Perl use <span class="code">PERLLIB</span> and <span class="code">PERL5LIB</span> to specify extra search paths for modules and Both of them are ignored by Raku. Instead, you need to use <a id="i27" name="Reference RAKULIB"></a><span class="indexed"><span class="code">RAKULIB</span></span>. The directory separator also changed from ':' to ','.</p> | |
<pre class="code">$ export PERL5LIB=/module/dir1:/module/dir2; | |
</pre> | |
<p>is</p> | |
<pre class="code">$ export RAKULIB=/module/dir1,/module/dir2; | |
</pre> | |
<p>As with Perl, if you don't specify <span class="code">RAKULIB</span>, you need to specify the library path within the program via the <span class="code">use lib</span> pragma:</p> | |
<pre class="code">use lib '/some/module/lib' | |
</pre> | |
<p>Note that <span class="code">RAKULIB</span> is more of a developer convenience in Raku (as opposed to the equivalent usage of <span class="code">PERL5LIB</span> in Perl) and shouldn't be used by module consumers as it could be removed in the future. This is because Raku's module loading isn't directly compatible with operating system paths.</p> | |
<a name="t2.12"></a> <h1 id="_language_5to6-nutshell.pod6-Misc.">Misc.</h1> | |
<a name="t2.12.1"></a> <h2 id="_language_5to6-nutshell.pod6-'0'_is_True"><span class="code">'0'</span> is True</h2> | |
<p>Unlike Perl, a string containing nothing but zero ('0') is <span class="code">True</span>. As Raku has types in core, that makes more sense. This also means the common pattern:</p> | |
<pre class="code">... if defined $x and length $x; # or just length() in modern perls | |
</pre> | |
<p>In Raku becomes a simple</p> | |
<pre class="code">... if $x; | |
</pre> | |
<a name="t2.12.2"></a> <h2 id="_language_5to6-nutshell.pod6-dump"><span class="code">dump</span></h2> | |
<p>Gone.</p> | |
<p>The Raku design allows for automatic and transparent saving-and-loading of compiled bytecode.</p> | |
<p>Rakudo supports this only for modules so far.</p> | |
<a name="t2.12.3"></a> <h2 id="_language_5to6-nutshell.pod6-AUTOLOAD">AUTOLOAD</h2> | |
<p>The <a href="#_language_typesystem.pod6-index-entry-FALLBACK_(method)"><span class="code">FALLBACK</span> method</a> provides similar functionality.</p> | |
<a name="t2.12.4"></a> <h2 id="_language_5to6-nutshell.pod6-Importing_specific_functions_from_a_module">Importing specific functions from a module</h2> | |
<p>In Perl it is possible to selectively import functions from a given module like so:</p> | |
<pre class="code">use ModuleName qw{foo bar baz}; | |
</pre> | |
<p>In Raku one specifies the functions which are to be exported by using the <span class="code">is export</span> role on the relevant subs; <i>all</i> subs with this role are then exported. Hence, the following module <span class="code">Bar</span> exports the subs <span class="code">foo</span> and <span class="code">bar</span> but not <span class="code">baz</span>:</p> | |
<pre class="code">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" } | |
</pre> | |
<p>To use this module, simply <span class="code">use Bar</span> and the functions <span class="code">foo</span> and <span class="code">bar</span> will be available</p> | |
<pre class="code">use Bar; | |
foo(1); #=> "foo 1" | |
bar(2); #=> "bar 2" | |
</pre> | |
<p>If one tries to use <span class="code">baz</span> an "Undeclared routine" error is raised at compile time.</p> | |
<p>So, how does one recreate the Perl behavior of being able to selectively import functions? By defining an <span class="code">EXPORT</span> sub inside the module which specifies the functions to be exported and removing the <span class="code">module Bar</span> statement.</p> | |
<p>The former module <span class="code">Bar</span> now is merely a file called <span class="code">Bar.rakumod</span> with the following contents:</p> | |
<pre class="code">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" } | |
</pre> | |
<p>Note that the subs are no longer explicitly exported via the <span class="code">is export</span> role, but by an <span class="code">EXPORT</span> 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 <span class="code">@import-list</span> is set by the <span class="code">use</span> statement in the calling code thus allowing us to selectively import the subs made available by the module.</p> | |
<p>So, to import only the <span class="code">foo</span> routine, we do the following in the calling code:</p> | |
<pre class="code">use Bar <foo>; | |
foo(1); #=> "foo 1" | |
</pre> | |
<p>Here we see that even though <span class="code">bar</span> 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:</p> | |
<pre class="code">use Bar <foo>; | |
foo(1); | |
bar(5); #!> "Undeclared routine: bar used at line 3" | |
</pre> | |
<p>However, this will work</p> | |
<pre class="code">use Bar <foo bar>; | |
foo(1); #=> "foo 1" | |
bar(5); #=> "bar 5" | |
</pre> | |
<p>Note also that <span class="code">baz</span> remains unimportable even if specified in the <span class="code">use</span> statement:</p> | |
<pre class="code">use Bar <foo bar baz>; | |
baz(3); #!> "Undeclared routine: baz used at line 2" | |
</pre> | |
<p>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 <span class="code">is export</span> role, Raku automatically creates the <span class="code">EXPORT</span> sub in the correct manner for you, so one should consider very carefully whether or not writing one's own <span class="code">EXPORT</span> routine is worthwhile.</p> | |
<a name="t2.12.5"></a> <h2 id="_language_5to6-nutshell.pod6-Importing_groups_of_specific_functions_from_a_module">Importing groups of specific functions from a module</h2> | |
<p>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 <span class="code">is export</span> in a sub declaration, you are in fact adding this subroutine to the <span class="code">:DEFAULT</span> export group. But you can add a subroutine to another group, or to multiple groups:</p> | |
<pre class="code">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 | |
</pre> | |
<p>So now you can use the <span class="code">Bar</span> module like this:</p> | |
<pre class="code">use Bar; # imports foo / baz | |
use Bar :FNORBL; # imports bar / baz | |
use Bar :ALL; # imports foo / bar / baz | |
</pre> | |
<p>Note that <span class="code">:ALL</span> is an auto-generated group that encompasses <b>all</b> subroutines that have an <span class="code">is export</span> trait.</p> | |
<a name="t2.13"></a> <h1 id="_language_5to6-nutshell.pod6-Core_modules">Core modules</h1> | |
<a name="t2.13.0.1"></a> <h3 id="_language_5to6-nutshell.pod6-Data::Dumper"><span class="code">Data::Dumper</span></h3> | |
<p>In Perl, the <a href="#_routine_https:__metacpan.org_pod_Data::Dumper.pod6">Data::Dumper</a> module was used for serialization, and for debugging views of program data structures by the programmer.</p> | |
<p>In Raku, these tasks are accomplished with the <span class="code">.raku</span> method, which every object has.</p> | |
<pre class="code"># Given: | |
my @array_of_hashes = ( | |
{ NAME => 'apple', type => 'fruit' }, | |
{ NAME => 'cabbage', type => 'no, please no' }, | |
); | |
# Perl | |
use Data::Dumper; | |
$Data::Dumper::Useqq = 1; | |
print Dumper \@array_of_hashes; # Note the backslash. | |
</pre> | |
<pre class="code"># Raku | |
say @array_of_hashes.raku; # .raku on the array, not on its reference. | |
</pre> | |
<p>In Perl, Data::Dumper has a more complex optional calling convention, which allows for naming the VARs.</p> | |
<p>In Raku, 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.</p> | |
<pre class="code"># Given: | |
my ( $foo, $bar ) = ( 42, 44 ); | |
my @baz = ( 16, 32, 64, 'Hike!' ); | |
# Perl | |
use Data::Dumper; | |
print Data::Dumper->Dump( | |
[ $foo, $bar, \@baz ], | |
[ qw( foo bar *baz ) ], | |
); | |
# Output | |
# $foo = 42; | |
# $bar = 44; | |
# @baz = ( | |
# 16, | |
# 32, | |
# 64, | |
# 'Hike!' | |
# ); | |
</pre> | |
<pre class="code"># Raku | |
say [ :$foo, :$bar, :@baz ].raku; | |
# OUTPUT: «["foo" => 42, "bar" => 44, "baz" => [16, 32, 64, "Hike!"]]» | |
</pre> | |
<p>There is also a Rakudo-specific debugging aid for developers called <span class="code">dd</span> (Tiny Data Dumper, so tiny it lost the "t"). This will print the <span class="code">.raku</span> representation plus some extra information that could be introspected, of the given variables on STDERR:</p> | |
<pre class="code"># Raku | |
dd $foo, $bar, @baz; | |
# OUTPUT: «Int $foo = 42Int $bar = 44Array @baz = [16, 32, 64, "Hike!"]» | |
</pre> | |
<a name="t2.13.0.2"></a> <h3 id="_language_5to6-nutshell.pod6-Getopt::Long"><span class="code">Getopt::Long</span></h3> | |
<p>Switch parsing is now done by the parameter list of the <span class="code">MAIN</span> subroutine.</p> | |
<pre class="code"># Perl | |
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. | |
</pre> | |
<pre class="code"># Raku | |
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'); | |
} | |
</pre> | |
<pre class="code">raku example.p6 | |
24 | |
file.dat | |
Verbosity off | |
raku example.p6 --file=foo --length=42 --verbose | |
42 | |
foo | |
Verbosity on | |
raku example.p6 --length=abc | |
Usage: | |
c.p6 [--length=<Int>] [--file=<Any>] [--verbose] | |
</pre> | |
<p>Note that Raku auto-generates a full usage message on error in command-line parsing.</p> | |
<a name="t2.14"></a> <h1 id="_language_5to6-nutshell.pod6-Automated_translation">Automated translation</h1> | |
<p>A quick way to find the Raku version of a Perl construct, is to run it through an automated translator.</p> | |
<p><b>NOTE:</b> None of these translators are yet complete.</p> | |
<a name="t2.14.1"></a> <h2 id="_language_5to6-nutshell.pod6-Blue_Tiger">Blue Tiger</h2> | |
<p>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 regexes into Raku.</p> | |
<p><a href="#_routine_https:__github.com_Util_Blue_Tiger_.pod6">https://github.com/Util/Blue_Tiger/</a></p> | |
<a name="t2.14.2"></a> <h2 id="_language_5to6-nutshell.pod6-Perlito">Perlito</h2> | |
<p>Online translator!</p> | |
<p>This project is a suite of Perl cross-compilers, including Perl to Raku translation. It has a web front-end, and so can be used without installation. It only supports a subset of Perl syntax so far.</p> | |
<p><a href="#_routine_https:__fglock.github.io_Perlito_perlito_perlito5.html.pod6">https://fglock.github.io/Perlito/perlito/perlito5.html</a></p> | |
<a name="t2.14.3"></a> <h2 id="_language_5to6-nutshell.pod6-Perl-ToPerl6">Perl-ToPerl6</h2> | |
<p>The late Jeff Goff's <a href="#_routine_https:__metacpan.org_release_JGOFF_Perl-ToPerl6-0.03.pod6">Perl::ToPerl6</a> module for Perl is designed around Perl::Critic's framework. It aims to convert Perl to compilable (if not necessarily running) Raku 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.</p> | |
<a name="t2.15"></a> <h1 id="_language_5to6-nutshell.pod6-Other_sources_of_translation_knowledge">Other sources of translation knowledge</h1> | |
<ul><li><p><a href="#_routine_https:__perlgeek.de_en_article_5-to-6.pod6">https://perlgeek.de/en/article/5-to-6</a></p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__github.com_Util_Blue_Tiger_.pod6">https://github.com/Util/Blue_Tiger/</a></p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__perl6advent.wordpress.com_2011_12_23_day-23-idiomatic-perl-6_.pod6">https://perl6advent.wordpress.com/2011/12/23/day-23-idiomatic-perl-6/</a></p> | |
</li></ul> <ul><li><p><a href="#_language_5to6-overview.pod6">/language/5to6-overview</a></p> | |
</li></ul></div> | |
<!-- /language/5to6-overview.pod6 --><div class="pod-body"><a id="_language_5to6-overview.pod6"></a><a name="t3"></a><h1 class="title">3 Perl to Raku guide - overview</h1> <p class="subtitle">How do I do what I used to do?</p> <p>These documents should not be mistaken for a beginner tutorial or a promotional overview of Raku (née Perl 6); it is intended as a technical reference for Raku learners with a strong Perl background and for anyone porting Perl code to Raku.</p> | |
<a name="t3.1"></a> <h1 id="_language_5to6-overview.pod6-Raku_in_a_nutshell">Raku in a nutshell</h1> | |
<p><a href="#_language_5to6-nutshell.pod6">Raku in a Nutshell</a> provides a quick overview of things changed in syntax, operators, compound statements, regular expressions, command-line flags, and various other bits and pieces.</p> | |
<a name="t3.2"></a> <h1 id="_language_5to6-overview.pod6-Syntactic_differences">Syntactic differences</h1> | |
<p>The <a href="#_language_5to6-perlsyn.pod6">Syntax section</a> provides an overview of the syntactic differences between Perl and Raku: how it is still mostly free form, additional ways to write comments, and how <span class="code">switch</span> is very much a Raku thing.</p> | |
<a name="t3.3"></a> <h1 id="_language_5to6-overview.pod6-Operators_in_Raku">Operators in Raku</h1> | |
<p>The <a href="#_language_5to6-perlop.pod6">Operators section</a> guides you from the operators in <a href="#_routine_https:__metacpan.org_pod_distribution_perl_pod_perlop.pod.pod6">Perl's perlop</a> to the equivalent in Raku.</p> | |
<a name="t3.4"></a> <h1 id="_language_5to6-overview.pod6-Functions_in_Raku">Functions in Raku</h1> | |
<p>The <a href="#_language_5to6-perlfunc.pod6">Functions section</a> describes all of the Perl functions and their Raku equivalent and any differences in behavior. It also provides references to ecosystem modules that provide the Perl behavior of functions, either existing in Raku with slightly different semantics (such as <span class="code">shift</span>), or non-existing in Raku (such as <span class="code">tie</span>).</p> | |
<a name="t3.5"></a> <h1 id="_language_5to6-overview.pod6-Special_variables_in_Raku">Special variables in Raku</h1> | |
<p>The <a href="#_language_5to6-perlvar.pod6">Special Variables section</a> describes if and how a lot of Perl's special (punctuation) variables are supported in Raku.</p> | |
### Guidelines for contributions: | |
Headers should contain the text that a Perl 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, C<0 + $string> still works, even though | |
we would write it as C<+$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. | |
</div> | |
<!-- /language/5to6-perlfunc.pod6 --><div class="pod-body"><a id="_language_5to6-perlfunc.pod6"></a><a name="t4"></a><h1 class="title">4 Perl to Raku guide - functions</h1> <p class="subtitle">Builtin functions in Perl to Raku</p> <a name="t4.1"></a> <h1 id="_language_5to6-perlfunc.pod6-DESCRIPTION">DESCRIPTION</h1> | |
<p>A (hopefully) comprehensive list of Perl builtin functions with their Raku equivalents with notes on variations between them where necessary.</p> | |
<a name="t4.2"></a> <h1 id="_language_5to6-perlfunc.pod6-NOTE">NOTE</h1> | |
<p>This document is an attempt to guide you from the functions in Perl's <span class="code">perlfunc</span> document to their equivalents in Raku. For full documentation on the Raku functions, follow the links in this document to their respective documentation.</p> | |
<p>One general comment: Raku takes its objects a lot more seriously than Perl. In Raku, 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 <span class="code">function(@args)</span> are now also method calls of the form <span class="code">@args.function</span> (In rare cases, there is <i>only</i> a method call). This should be obvious in the following text, but it probably behooves you to get into that frame of mind now.</p> | |
<p>Also, unless otherwise stated, the use of the term "function" here will mean a function in the style of <span class="code">func(@args)</span>, while "method" will refer to a function in the style of <span class="code">@args.func</span>.</p> | |
<a name="t4.3"></a> <h1 id="_language_5to6-perlfunc.pod6-Alphabetical_listing_of_Perl_functions">Alphabetical listing of Perl functions</h1> | |
<a name="t4.3.1"></a> <h2 id="_language_5to6-perlfunc.pod6-Filetests"><a name="28"></a>Filetests</h2> | |
<ul><li><p>-X FILEHANDLE</p> | |
</li></ul> <ul><li><p>-X EXPR</p> | |
</li></ul> <ul><li><p>-X DIRHANDLE</p> | |
</li></ul> <ul><li><p>-X</p> | |
</li></ul> <p>Raku gives you a couple of options when it comes to file tests. You can do a smartmatch (<span class="code">~~</span>) or you can call a method.</p> | |
<p>In Raku, you don't need to actually open a filehandle in the traditional way (although you can) to do a filetest. You can simply append <span class="code">.IO</span> to the filename. For instance, here is how to check if a file is readable using smartmatch:</p> | |
<pre class="code">'/path/to/file'.IO ~~ :r</pre> | |
<p>You can use an already opened filehandle. Here, using the filehandle <span class="code">$fh</span>, is an example, using the method syntax for the file test:</p> | |
<pre class="code">$fh.r | |
</pre> | |
<p>Most of the former filetests have colon equivalents for use with smartmatch:</p> | |
<table> | |
<tr><td>:e Exists</td></tr> | |
<tr><td>:d Directory</td></tr> | |
<tr><td>:f File</td></tr> | |
<tr><td>:l Symbolic link</td></tr> | |
<tr><td>:r Readable</td></tr> | |
<tr><td>:w Writable</td></tr> | |
<tr><td>:x Executable</td></tr> | |
<tr><td>:s Size</td></tr> | |
<tr><td>:z Zero size</td></tr> | |
</table> <p>All of these tests can be used as methods (without the colon).</p> | |
<p>Three tests, however, <i>only</i> have method equivalents:</p> | |
<pre class="code">$fh.modified; # -M $fh | |
$fh.accessed; # -A $fh | |
$fh.changed; # -C $fh | |
</pre> | |
<p>The remaining filetests in Perl do not appear to be implemented in Raku.</p> | |
<p>The documentation for this can be found at <a href="#_type_IO::Path.pod6-File_test_operators">File test operators</a>.</p> | |
<p>There is more information on reading and writing files at <a href="#_language_io.pod6">io</a>. Also, the section on <span class="code">open()</span> below may be helpful.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5-X.pod6"><span class="code">P5-X</span></a> which exports the behavior as much as possible in Raku.</p> | |
<a name="t4.3.2"></a> <h2 id="_language_5to6-perlfunc.pod6-abs"><a name="29"></a>abs</h2> | |
<ul><li><p>abs VALUE</p> | |
</li></ul> <p>Works as a function (<span class="code">abs($x)</span>), but also as a method. One gotcha, however - method calls bind more tightly than <span class="code">-</span>, so, for example, <span class="code">-15.abs</span> evaluates as <span class="code">-(15.abs)</span> giving you <span class="code">-15</span>. In this example, you would have to do something like <span class="code">(-15).abs</span>.</p> | |
<p><span class="code">abs</span> also operates on <span class="code">$_</span> in the absence of a value, but not as a function, and as a method you need to call it as <span class="code">.abs</span> rather than simply <span class="code">abs</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports an <span class="code">abs</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.3"></a> <h2 id="_language_5to6-perlfunc.pod6-accept"><a name="30"></a>accept</h2> | |
<ul><li><p>accept NEWSOCKET, GENERICSOCKET</p> | |
</li></ul> <p><span class="code">accept</span> is a method you can call on a server, e. g. <span class="code">$server.accept()</span>. Instead of returning a packed address, it returns a socket, most likely an IO::Socket object of some sort.</p> | |
<a name="t4.3.4"></a> <h2 id="_language_5to6-perlfunc.pod6-alarm"><a name="31"></a>alarm</h2> | |
<ul><li><p>alarm SECONDS</p> | |
</li></ul> <p><span class="code">alarm()</span> is no more. But it is possible to have code execute after a certain time has elapsed, or at a given time:</p> | |
<pre class="code">Promise.in(5).then: { say "five seconds have passed" } | |
Promise.at(now + 5).then: { say "five seconds have passed" }</pre> | |
<p>In Raku, this does *not* involve any (dummy) signals.</p> | |
<a name="t4.3.5"></a> <h2 id="_language_5to6-perlfunc.pod6-atan2"><a name="32"></a>atan2</h2> | |
<ul><li><p>atan2 Y, X</p> | |
</li></ul> <p>Available as a function as well as being able to be used as a method. For instance, these are equivalent:</p> | |
<pre class="code">atan2(100); | |
100.atan2;</pre> | |
<a name="t4.3.6"></a> <h2 id="_language_5to6-perlfunc.pod6-bind"><a name="33"></a>bind</h2> | |
<ul><li><p>bind SOCKET, NAME</p> | |
</li></ul> <p>[NEEDS FURTHER RESEARCH] No sign of a socket-related <span class="code">bind()</span> in Raku. At a guess, whatever socket binding is needed happens when you create a new socket object.</p> | |
<a name="t4.3.7"></a> <h2 id="_language_5to6-perlfunc.pod6-binmode"><a name="34"></a>binmode</h2> | |
<ul><li><p>binmode FILEHANDLE</p> | |
</li></ul> <p>Instead of this, you would use <span class="code">:bin</span> as the file mode when opening the socket. E. g. <span class="code">my $fh = open("path/to/file", :bin);</span></p> | |
<a name="t4.3.8"></a> <h2 id="_language_5to6-perlfunc.pod6-bless"><a name="35"></a>bless</h2> | |
<ul><li><p>bless REF, CLASSNAME</p> | |
</li></ul> <p>With the changes in class creation in Raku, this may find less use than in Perl, and is a method as well as a function. The Raku 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 to Raku, it's quite possible you'll want to use <span class="code">new</span> for creating objects rather than <span class="code">bless</span>, although there may be some situations in which the latter may still be useful.</p> | |
<a name="t4.3.9"></a> <h2 id="_language_5to6-perlfunc.pod6-break"><a name="36"></a>break</h2> | |
<ul><li><p>break</p> | |
</li></ul> <p>It does not exist in Raku. For breaking out of <span class="code">given</span> blocks, you should probably take a look at <a href="#_language_control.pod6-index-entry-control_flow__proceed-proceed"><span class="code">proceed</span> and <span class="code">succeed</span></a>.</p> | |
<a name="t4.3.10"></a> <h2 id="_language_5to6-perlfunc.pod6-caller"><a name="37"></a>caller</h2> | |
<ul><li><p>caller EXPR</p> | |
</li></ul> <p>There are a couple different ways to get at caller information in Raku. The basic functionality is provided through <a href="#_routine_callframe.pod6">callframe</a> now. However, Raku 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 <span class="code">caller</span> can return:</p> | |
<pre class="code">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;</pre> | |
<p>Many of the other details returned by <span class="code">caller</span> are specific to Perl and have no meaning in Raku.</p> | |
<p>You can also get some of the information for the current frame or routine frame by using the dynamic variables <a href="#_language_variables.pod6-Compile-time_variables"><span class="code">&?ROUTINE</span></a>, <a href="#_language_variables.pod6-Compile-time_variables"><span class="code">&?BLOCK</span></a>, <a href="#_language_variables.pod6-Compile-time_variables"><span class="code">$?PACKAGE</span></a>, <a href="#_language_variables.pod6-Compile-time_variables"><span class="code">$?FILE</span></a>, and <a href="#_language_variables.pod6-Compile-time_variables"><span class="code">$?LINE</span></a>. For many purposes, <a href="#_type_Backtrace.pod6">Backtrace</a> may provide an easier way to browse through the call stack.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5caller.pod6"><span class="code">P5caller</span></a> which exports a <span class="code">caller</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.11"></a> <h2 id="_language_5to6-perlfunc.pod6-chdir"><a name="38"></a>chdir</h2> | |
<ul><li><p>chdir EXPR</p> | |
</li></ul> <p>Works as it does in Perl but <b>must</b> take an argument. The behavior of <span class="code">chdir()</span> (with regards to looking at HOME and LOGDIR) is not supported.</p> | |
<p>In Raku, <a href="#_routine_chdir.pod6">chdir</a> only changes the <span class="code">$*CWD</span> dynamic variable. It does <b>not</b> actually change the default directory from the OS's point of view; the special dynamic-variable routine <a href="#_routine_&*chdir.pod6"><span class="code">&*chdir</span></a> can be used for that, if needed.</p> | |
<p>This is done this way, because there is no concept of a "default directory per OS thread". And since Raku does not fork, but only does threading, it was felt that the "current directory" concept should be in the <span class="code">$*CWD</span> dynamic variable, which can be lexically scoped, and thus can be thread-safe.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5chdir.pod6"><span class="code">P5chdir</span></a> which exports a <span class="code">chdir</span> function that mimics the original Perl behavior as much as possible, including looking at HOME and LOGDIR.</p> | |
<a name="t4.3.12"></a> <h2 id="_language_5to6-perlfunc.pod6-chmod"><a name="39"></a>chmod</h2> | |
<ul><li><p>chmod LIST</p> | |
</li></ul> <p>Functions as under Perl, with the difference that octal numbers are represented differently (<span class="code">0o755</span> rather than <span class="code">0755</span>). You may also use it as a method, e. g. <span class="code">$fh.chmod(0o755)</span>.</p> | |
<a name="t4.3.13"></a> <h2 id="_language_5to6-perlfunc.pod6-chomp"><a name="40"></a>chomp</h2> | |
<ul><li><p>chomp VARIABLE</p> | |
</li></ul> <p>The behavior of <span class="code">chomp</span> is different than in Perl. It leaves the target unaffected and <i>returns</i> a copy of the target with a final logical newline removed, e.g. <span class="code">$x = "howdy\n";$y = chomp($x);</span> results in <span class="code">$x</span> containing "howdy\n" and <span class="code">$y</span> containing "howdy". Also works as a method, e.g. <span class="code">$y = $x.chomp</span>. As with many other methods, also works with assignment to modify the target in place, e.g. <span class="code">$x.=chomp</span> results in <span class="code">$x</span> containing "howdy".</p> | |
<p>Note that <span class="code">chomp()</span> (without arguments) is not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5chomp.pod6"><span class="code">P5chomp</span></a> which exports a <span class="code">chomp</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.14"></a> <h2 id="_language_5to6-perlfunc.pod6-chop"><a name="41"></a>chop</h2> | |
<ul><li><p>chop VARIABLE</p> | |
</li></ul> <p>As with <span class="code">chomp</span>, in Raku, this returns the chopped string, rather than chopping in place. I. e. <span class="code">$x = "howdy";$y = chop($x);</span> results in <span class="code">$x</span> being "howdy" and <span class="code">$y</span> being "howd". Also works as a method: <span class="code">$y = $x.chop</span>.</p> | |
<p>Note that <span class="code">chop()</span> (without arguments) is not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5chomp.pod6"><span class="code">P5chomp</span></a> which exports a <span class="code">chop</span> function that mimics the original Perl behavior as much as possible.</p> | |
<p>.head2 chown</p> | |
<ul><li><p>chown LIST</p> | |
</li></ul> <p><span class="code">chown</span> is not in Raku.</p> | |
<a name="t4.3.15"></a> <h2 id="_language_5to6-perlfunc.pod6-chr"><a name="42"></a>chr</h2> | |
<ul><li><p>chr NUMBER</p> | |
</li></ul> <p>Similar to the Perl 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:</p> | |
<pre class="code">chr(65); # "A" | |
65.chr; # "A"</pre> | |
<p>Note that <span class="code">chr()</span> (without arguments) is not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5chr.pod6"><span class="code">P5chr</span></a> which exports a <span class="code">chr</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.16"></a> <h2 id="_language_5to6-perlfunc.pod6-chroot"><a name="43"></a>chroot</h2> | |
<ul><li><p>chroot FILENAME</p> | |
</li></ul> <p><span class="code">chroot</span> is not in Raku.</p> | |
<a name="t4.3.17"></a> <h2 id="_language_5to6-perlfunc.pod6-close"><a name="44"></a>close</h2> | |
<ul><li><p>close FILEHANDLE</p> | |
</li></ul> <p>As in Perl, closes a filehandle. Returns a Boolean value. Both <span class="code">close $fh</span> and <span class="code">$fh.close</span> will work.</p> | |
<p>Note that <span class="code">close()</span> (without arguments) is not supported in Raku.</p> | |
<a name="t4.3.18"></a> <h2 id="_language_5to6-perlfunc.pod6-closedir"><a name="45"></a>closedir</h2> | |
<ul><li><p>closedir DIRHANDLE</p> | |
</li></ul> <p>Not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5opendir.pod6"><span class="code">P5opendir</span></a> which exports a <span class="code">closedir</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.19"></a> <h2 id="_language_5to6-perlfunc.pod6-connect"><a name="46"></a>connect</h2> | |
<ul><li><p>connect SOCKET, NAME</p> | |
</li></ul> <p>Use <a href="#_routine_connect.pod6">connect</a> from <a href="#_type_IO::Socket::Async.pod6">IO::Socket::Async</a> for an asynchronous socket or create a <a href="#_type_IO::Socket::INET.pod6">IO::Socket::INET</a> socket for a synchronous one.</p> | |
<a name="t4.3.20"></a> <h2 id="_language_5to6-perlfunc.pod6-continue"><a name="47"></a>continue</h2> | |
<ul><li><p>continue BLOCK</p> | |
</li></ul> <ul><li><p>continue</p> | |
</li></ul> <p>Instead of a <span class="code">continue</span> block, you should use a <span class="code">NEXT</span> block. The closest analog to a bare <span class="code">continue;</span> in Perl appears to be <span class="code">proceed</span>/<span class="code">succeed</span>.</p> | |
<a name="t4.3.21"></a> <h2 id="_language_5to6-perlfunc.pod6-cos"><a name="48"></a>cos</h2> | |
<ul><li><p>cos EXPR</p> | |
</li></ul> <p>Works as in Perl.</p> | |
<p><span class="code">cos</span> also operates on <span class="code">$_</span> in the absence of a value, but not as a function, and as a method you need to call it as <span class="code">.cos</span> rather than simply <span class="code">cos</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports a <span class="code">cos</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.22"></a> <h2 id="_language_5to6-perlfunc.pod6-crypt"><a name="49"></a>crypt</h2> | |
<ul><li><p>crypt PLAINTEXT, SALT</p> | |
</li></ul> <p>Not available in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports a <span class="code">crypt</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.23"></a> <h2 id="_language_5to6-perlfunc.pod6-dbm_functions">dbm functions<a name="50"></a></h2> | |
<ul><li><p>dbmclose HASH</p> | |
</li></ul> <ul><li><p>dbmopen HASH, DBNAME, MASK</p> | |
</li></ul> <p>These functions have largely been superseded in Perl, and are unlikely to ever turn up in Raku (although any assumptions about the Raku database implementation may be premature).</p> | |
<a name="t4.3.24"></a> <h2 id="_language_5to6-perlfunc.pod6-defined"><a name="51"></a>defined</h2> | |
<ul><li><p>defined EXPR</p> | |
</li></ul> <p>Probably does what you expect, but technically it returns <span class="code">False</span> on the type object, and <span class="code">True</span> otherwise. This may make more sense when you realize that <span class="code">$num.raku</span> is the type <span class="code">Any</span> if you haven't assigned anything to it, and the assigned value if you have. It can be used as a method: <span class="code">$num.defined</span>. And any newly created class can have its own <span class="code">.defined</span> method, thereby deciding how and when it should be considered undefined.</p> | |
<p>Note that <span class="code">defined()</span> (without arguments) is not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5defined.pod6"><span class="code">P5defined</span></a> which exports a <span class="code">defined</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.25"></a> <h2 id="_language_5to6-perlfunc.pod6-delete"><a name="52"></a>delete</h2> | |
<ul><li><p>delete EXPR</p> | |
</li></ul> <p>Raku replaces this with the new adverb syntax, specifically the <span class="code">:delete</span> adverb. E. g. <span class="code">my $deleted_value = %hash{$key}:delete;</span> and <span class="code">my $deleted_value = @array[$i]:delete;</span>.</p> | |
<a name="t4.3.26"></a> <h2 id="_language_5to6-perlfunc.pod6-die"><a name="53"></a>die</h2> | |
<ul><li><p>die LIST</p> | |
</li></ul> <p>Works similarly to the Perl version, but Raku's Exception mechanism may give you more power and flexibility than is available in Perl. See <a href="#_language_exceptions.pod6">exceptions</a>. To omit the stacktrace and location, like Perl's <span class="code">die "...\n"</span>, use:</p> | |
<pre class="code">note "..."; | |
exit 1;</pre> | |
<a name="t4.3.27"></a> <h2 id="_language_5to6-perlfunc.pod6-do"><a name="54"></a>do</h2> | |
<ul><li><p>do BLOCK</p> | |
</li></ul> <p>Similar to the Perl version. Note that there must be a space between the <span class="code">do</span> and the block.</p> | |
<ul><li><p>do EXPR</p> | |
</li></ul> <p>Has been replaced in Raku by <span class="code">EVALFILE</span>.</p> | |
<a name="t4.3.28"></a> <h2 id="_language_5to6-perlfunc.pod6-dump"><a name="55"></a>dump</h2> | |
<ul><li><p>dump LABEL</p> | |
</li></ul> <p>According to S29, <span class="code">dump</span> has been... dumped.</p> | |
<a name="t4.3.29"></a> <h2 id="_language_5to6-perlfunc.pod6-each"><a name="56"></a>each</h2> | |
<ul><li><p>each HASH</p> | |
</li></ul> <p>There is no exact equivalent, but you can use <span class="code">%hash.kv</span> which returns a list of keys and values. For example: <span class="code">for %hash.kv -> $k, $v { say "$k: $v" } </span></p> | |
<p>Incidentally, what we have there with the <span class="code">-> </span> 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. <a href="#_routine_https:__design.raku.org_S04.html.pod6-The_for_statement">https://design.raku.org/S04.html#The_for_statement</a> may be of some help here, as well as the design document at <a href="#_routine_https:__design.raku.org_S06.html.pod6-%22Pointy_blocks%22">https://design.raku.org/S06.html#%22Pointy_blocks%22</a>. There is also some information at <a href="#_routine_https:__en.wikibooks.org_wiki_Perl_6_Programming_Blocks_and_Closures.pod6-Pointy_Blocks">https://en.wikibooks.org/wiki/Perl_6_Programming/Blocks_and_Closures#Pointy_Blocks</a></p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5each.pod6"><span class="code">P5each</span></a> which exports an <span class="code">each</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.30"></a> <h2 id="_language_5to6-perlfunc.pod6-eof"><a name="57"></a>eof</h2> | |
<ul><li><p>eof FILEHANDLE</p> | |
</li></ul> <p>In Raku, this is not usable as a function, but only as a method. I. e. <span class="code">$filehandle.eof</span>. Returns <span class="code">True</span> if at end of file.</p> | |
<a name="t4.3.31"></a> <h2 id="_language_5to6-perlfunc.pod6-eval"><a name="58"></a>eval</h2> | |
<ul><li><p>eval EXPR</p> | |
</li></ul> <ul><li><p>eval EXPR</p> | |
</li></ul> <p>The closest replacement is the <a href="#_routine_EVAL.pod6">EVAL</a> function. However, this function has to be allowed explicitly using a pragma to work in the same way. Note that <span class="code">EVAL</span> does not do any <a href="#_language_exceptions.pod6">exception handling</a>!</p> | |
<a name="t4.3.32"></a> <h2 id="_language_5to6-perlfunc.pod6-evalbytes"><a name="59"></a>evalbytes</h2> | |
<ul><li><p>evalbytes EXPR</p> | |
</li></ul> <p>No equivalent.</p> | |
<a name="t4.3.33"></a> <h2 id="_language_5to6-perlfunc.pod6-exec"><a name="60"></a>exec</h2> | |
<ul><li><p>exec LIST</p> | |
</li></ul> <p>Nothing in Raku exactly replicates the Perl <span class="code">exec</span>. <span class="code">shell</span> and <span class="code">run</span> are similar to Perl's <span class="code">system</span>, but <span class="code">exec</span>'s behavior of not returning after executing a system command would have to be emulated by something like <span class="code">shell($command);exit();</span> or possibly <span class="code">exit shell($command);</span>.</p> | |
<p>Neither of these workarounds have the behavior (on Unix-like systems) of <i>replacing</i> 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 <span class="code">exec</span>'s function of returning stale resources to the operating system.</p> | |
<p>If you want <span class="code">exec</span> for these behaviors, you can use an <span class="code">exec*</span> function via the <span class="code">NativeCall</span> interface. Consult your operating system manual pages for <span class="code">exec</span> (or other similarly-named calls such as <span class="code">execl</span>, <span class="code">execv</span>, <span class="code">execvp</span>, or <span class="code">execvpe</span>). (Beware: these calls are not generally portable between Unix-like operating system families.) Given those caveats, the Raku ecosystem <a href="#_routine_https:__modules.raku.org_dist_Native::Exec.pod6"><span class="code">Native::Exec</span></a> module exports an <span class="code">exec</span> function for Unix-like systems.</p> | |
<a name="t4.3.34"></a> <h2 id="_language_5to6-perlfunc.pod6-exists"><a name="61"></a>exists</h2> | |
<ul><li><p>exists EXPR</p> | |
</li></ul> <p>In Raku, this is not a function, but an adverb:</p> | |
<pre class="code">%hash{$key}:exists; | |
@array[$i]:exists; | |
</pre> | |
<a name="t4.3.35"></a> <h2 id="_language_5to6-perlfunc.pod6-exit"><a name="62"></a>exit</h2> | |
<ul><li><p>exit EXPR</p> | |
</li></ul> <p>Appears to do the same thing as in Perl.</p> | |
<a name="t4.3.36"></a> <h2 id="_language_5to6-perlfunc.pod6-exp"><a name="63"></a>exp</h2> | |
<ul><li><p>exp EXPR</p> | |
</li></ul> <p>Same as in Perl.</p> | |
<p><span class="code">exp</span> also operates on <span class="code">$_</span> in the absence of a value, but not as a function, and as a method you need to call it as <span class="code">.exp</span> rather than simply <span class="code">exp</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports an <span class="code">exp</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.37"></a> <h2 id="_language_5to6-perlfunc.pod6-fc"><a name="64"></a>fc</h2> | |
<ul><li><p>fc EXPR</p> | |
</li></ul> <p>Looks like it does the same thing as in Perl except that calling it without arguments is not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5fc.pod6"><span class="code">P5fc</span></a> which exports a <span class="code">fc</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.38"></a> <h2 id="_language_5to6-perlfunc.pod6-fcntl"><a name="65"></a>fcntl</h2> | |
<ul><li><p>fcntl FILEHANDLE, FUNCTION, SCALAR</p> | |
</li></ul> <p>Appears not to be in Raku.</p> | |
<a name="t4.3.39"></a> <h2 id="_language_5to6-perlfunc.pod6-__FILE__">__FILE__<a name="66"></a></h2> | |
<ul><li><p>__FILE__</p> | |
</li></ul> <p>Replaced by <span class="code">$?FILE</span> which is slightly different from <span class="code">__FILE__</span> in that it is always an absolute path, rather than a relative one in the Perl case.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5__FILE__.pod6"><span class="code">P5__FILE__</span></a> which exports a <span class="code">__FILE__</span> term that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.40"></a> <h2 id="_language_5to6-perlfunc.pod6-fileno"><a name="67"></a>fileno</h2> | |
<ul><li><p>fileno FILEHANDLE</p> | |
</li></ul> <p>The <span class="code">native-descriptor</span> method on <span class="code">IO::Handle</span> returns the equivalent of <span class="code">fileno</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5fileno.pod6"><span class="code">P5fileno</span></a> which exports a <span class="code">fileno</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.41"></a> <h2 id="_language_5to6-perlfunc.pod6-flock"><a name="68"></a>flock</h2> | |
<ul><li><p>flock FILEHANDLE, OPERATION</p> | |
</li></ul> <p>Currently unimplemented.</p> | |
<a name="t4.3.42"></a> <h2 id="_language_5to6-perlfunc.pod6-fork"><a name="69"></a>fork</h2> | |
<ul><li><p>fork</p> | |
</li></ul> <p>There is no built-in <span class="code">fork</span> function. While it's possible to call it using NativeCall, it's highly unlikely that the resulting process will be usable.</p> | |
<p>Raku provides extensive support for, and internally uses, threads. However, <span class="code">fork</span> only clones the thread that called <span class="code">fork</span>, 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 Raku program doesn't knowingly start any threads, the compiler may create some of its own in the process of precompilation, and the VMs that Raku 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 <span class="code">fork</span> reliably work in this case.</p> | |
<a name="t4.3.43"></a> <h2 id="_language_5to6-perlfunc.pod6-formats"><a name="70"></a>formats</h2> | |
<ul><li><p>format</p> | |
</li></ul> <ul><li><p>formline PICTURE, LIST</p> | |
</li></ul> <p>Raku does not have built-in formats.</p> | |
<a name="t4.3.44"></a> <h2 id="_language_5to6-perlfunc.pod6-getc"><a name="71"></a>getc</h2> | |
<ul><li><p>getc FILEHANDLE</p> | |
</li></ul> <p>Reads a single character from the input stream as in Perl. May now also be used as a method: <span class="code">$filehandle.getc</span></p> | |
<a name="t4.3.45"></a> <h2 id="_language_5to6-perlfunc.pod6-getpeername"><a name="72"></a>getpeername</h2> | |
<ul><li><p>getpeername SOCKET</p> | |
</li></ul> <p>S29 lists it, but the implementation does not seem clear or, for that matter, implemented.</p> | |
<a name="t4.3.46"></a> <h2 id="_language_5to6-perlfunc.pod6-getpgrp"><a name="73"></a>getpgrp</h2> | |
<ul><li><p>getpgrp PID</p> | |
</li></ul> <p>Will not be implemented.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getpriority.pod6"><span class="code">P5getpriority</span></a> which exports a <span class="code">getpgrp</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.47"></a> <h2 id="_language_5to6-perlfunc.pod6-getppid"><a name="74"></a>getppid</h2> | |
<ul><li><p>getppid PID</p> | |
</li></ul> <p>Will not be implemented.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getpriority.pod6"><span class="code">P5getpriority</span></a> which exports a <span class="code">getppid</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.48"></a> <h2 id="_language_5to6-perlfunc.pod6-getpriority"><a name="75"></a>getpriority</h2> | |
<ul><li><p>getpriority WHICH, WHO</p> | |
</li></ul> <p>Will not be implemented.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getpriority.pod6"><span class="code">P5getpriority</span></a> which exports a <span class="code">getpriority</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.49"></a> <h2 id="_language_5to6-perlfunc.pod6-get_and_set_functions"><a name="76"></a>get and set functions</h2> | |
<ul><li><p>endpwent</p> | |
</li></ul> <ul><li><p>getlogin</p> | |
</li></ul> <ul><li><p>getpwent</p> | |
</li></ul> <ul><li><p>getpwnam NAME</p> | |
</li></ul> <ul><li><p>getpwuid UID</p> | |
</li></ul> <ul><li><p>setpwent</p> | |
</li></ul> <p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getpwnam.pod6"><span class="code">P5getpwnam</span></a> which exports the <span class="code">endpwent</span>, <span class="code">getlogin</span>, <span class="code">getpwent</span>, <span class="code">getpwnam</span>, <span class="code">getpwuid</span> and <span class="code">setpwent</span> functions that mimic the original Perl behavior as much as possible.</p> | |
<ul><li><p>endgrent</p> | |
</li></ul> <ul><li><p>getgrent</p> | |
</li></ul> <ul><li><p>getgrgid GID</p> | |
</li></ul> <ul><li><p>getgrnam NAME</p> | |
</li></ul> <ul><li><p>setgrent</p> | |
</li></ul> <p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getgrnam.pod6"><span class="code">P5getgrnam</span></a> which exports the <span class="code">endgrent</span>, <span class="code">getgrent</span>, <span class="code">getgrgid</span>, <span class="code">getgrnam</span> and <span class="code">setgrent</span> functions that mimic the original Perl behavior as much as possible.</p> | |
<ul><li><p>endnetent</p> | |
</li></ul> <ul><li><p>getnetbyaddr ADDR, ADDRTYPE</p> | |
</li></ul> <ul><li><p>getnetbyname NAME</p> | |
</li></ul> <ul><li><p>getnetent</p> | |
</li></ul> <ul><li><p>setnetent STAYOPEN</p> | |
</li></ul> <p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getnetbyname.pod6"><span class="code">P5getnetbyname</span></a> which exports the <span class="code">endnetent</span>, <span class="code">getnetent</span>, <span class="code">getnetbyaddr</span>, <span class="code">getnetbyname</span> and <span class="code">setnetent</span> functions that mimic the original Perl behavior as much as possible.</p> | |
<ul><li><p>endservent</p> | |
</li></ul> <ul><li><p>getservbyname NAME, PROTO</p> | |
</li></ul> <ul><li><p>getservbyport PORT, PROTO</p> | |
</li></ul> <ul><li><p>getservent</p> | |
</li></ul> <ul><li><p>setservent STAYOPEN</p> | |
</li></ul> <p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getservbyname.pod6"><span class="code">P5getservbyname</span></a> which exports the <span class="code">endservent</span>, <span class="code">getservent</span>, <span class="code">getservbyname</span>, <span class="code">getservbyport</span> and <span class="code">setservent</span> functions that mimic the original Perl behavior as much as possible.</p> | |
<ul><li><p>endprotoent</p> | |
</li></ul> <ul><li><p>getprotobyname NAME</p> | |
</li></ul> <ul><li><p>getprotobynumber NUMBER</p> | |
</li></ul> <ul><li><p>getprotoent</p> | |
</li></ul> <ul><li><p>setprotoent STAYOPEN</p> | |
</li></ul> <p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getprotobyname.pod6"><span class="code">P5getprotobyname</span></a> which exports the <span class="code">endprotoent</span>, <span class="code">getprotoent</span>, <span class="code">getprotobyname</span>, <span class="code">getprotobynumber</span> and <span class="code">setprotoent</span> functions that mimic the original Perl behavior as much as possible.</p> | |
<ul><li><p>gethostbyname NAME</p> | |
</li></ul> <ul><li><p>gethostbyaddr ADDR, ADDRTYPE</p> | |
</li></ul> <ul><li><p>gethostent</p> | |
</li></ul> <ul><li><p>sethostent STAYOPEN</p> | |
</li></ul> <ul><li><p>endhostent</p> | |
</li></ul> <p>[NEEDS FURTHER RESEARCH] Apparently this range of functions are to be handled by roles like User, Group, etc.</p> | |
<a name="t4.3.50"></a> <h2 id="_language_5to6-perlfunc.pod6-getsock*"><a name="77"></a>getsock*</h2> | |
<ul><li><p>getsockname SOCKET</p> | |
</li></ul> <ul><li><p>getsockopt SOCKET, LEVEL, OPTNAME</p> | |
</li></ul> <p>[NEEDS FURTHER RESEARCH] These are likely implemented by some kind of IO::Socket object, but details are unclear.</p> | |
<a name="t4.3.51"></a> <h2 id="_language_5to6-perlfunc.pod6-glob"><a name="78"></a>glob</h2> | |
<ul><li><p>glob EXPR</p> | |
</li></ul> <p>Not available in core, although some of the functionality is offered by <a href="#_routine_dir.pod6">dir</a> routine and its <span class="code">test</span> argument.</p> | |
<p>See <a href="#_routine_https:__modules.raku.org_dist_IO::Glob.pod6"><span class="code">IO::Glob</span> module in ecosystem</a></p> | |
<a name="t4.3.52"></a> <h2 id="_language_5to6-perlfunc.pod6-gmtime"><a name="79"></a>gmtime</h2> | |
<ul><li><p>gmtime EXPR</p> | |
</li></ul> <p>Like the various parts of <span class="code">localtime</span>, <span class="code">gmtime</span>'s functionality appears to in the <span class="code">DateTime</span> object. To get a UTC version of a <span class="code">DateTime</span> object for the current time, for instance, use <span class="code">my $gmtime = DateTime.now.utc</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5localtime.pod6"><span class="code">P5localtime</span></a> which exports a <span class="code">gmtime</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.53"></a> <h2 id="_language_5to6-perlfunc.pod6-goto"><a name="80"></a>goto</h2> | |
<ul><li><p>goto LABEL</p> | |
</li></ul> <ul><li><p>goto EXPR</p> | |
</li></ul> <ul><li><p>goto &NAME</p> | |
</li></ul> <p>The syntax for <span class="code">goto LABEL</span> is already accepted, but the runtime part of <span class="code">goto</span> is not yet implemented. So this will result in a runtime error:</p> | |
<pre class="code">FOO: goto FOO; # Label.goto() not yet implemented. Sorry.</pre> | |
<a name="t4.3.54"></a> <h2 id="_language_5to6-perlfunc.pod6-grep"><a name="81"></a>grep</h2> | |
<ul><li><p>grep BLOCK LIST</p> | |
</li></ul> <ul><li><p>grep EXPR, LIST</p> | |
</li></ul> <p>Still in Raku, with the caveat that the block form now requires a comma after the block. I.e. <span class="code">@foo = grep { $_ = "bars" }, @baz</span>. Can also be used as a method: <span class="code">@foo = @bar.grep(/^f/)</span></p> | |
<a name="t4.3.55"></a> <h2 id="_language_5to6-perlfunc.pod6-hex"><a name="82"></a>hex</h2> | |
<ul><li><p>hex EXPR</p> | |
</li></ul> <p>In Raku an expression <b>must</b> be specified.</p> | |
<p>Replaced by the adverbial form <span class="code">:16</span>. E. g. <span class="code">:16("aF")</span> returns 175. This is Str->Int.</p> | |
<p>The opposite result can be achieved (Int->Str) by using the <span class="code">.base</span> method: <span class="code">0xaF.base(10)</span></p> | |
<p>It just so happens that <span class="code">.Str</span> defaults to base 10, so if you just <span class="code">say 0xaF</span>, that will also print 175, but that may not be immediately obvious, so may not be the best way to go for this.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5hex.pod6"><span class="code">P5hex</span></a> which exports a <span class="code">hex</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.56"></a> <h2 id="_language_5to6-perlfunc.pod6-import"><a name="83"></a>import</h2> | |
<ul><li><p>import LIST</p> | |
</li></ul> <p>Was never a builtin function in Perl in the first place. In Raku, 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 <a href="#_language_5to6-nutshell.pod6-Importing_specific_functions_from_a_module">this section</a>.</p> | |
<a name="t4.3.57"></a> <h2 id="_language_5to6-perlfunc.pod6-index"><a name="84"></a>index</h2> | |
<ul><li><p>index STR, SUBSTR, POSITION</p> | |
</li></ul> <p>Works as in Perl. Can also now be used as a method: <span class="code">"howdy!".index("how"); # 0</span>. Main difference with Perl is that <span class="code">Nil</span> is returned instead of <span class="code">-1</span> when the substring is not found. This is very useful in combination with the <span class="code">with</span> command:</p> | |
<pre class="code">with index("foo","o") -> $index { | |
say "Found it at $index"; | |
} | |
else { | |
say "Not found" | |
}</pre> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5index.pod6"><span class="code">P5index</span></a> which exports an <span class="code">index</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.58"></a> <h2 id="_language_5to6-perlfunc.pod6-int"><a name="85"></a>int</h2> | |
<ul><li><p>int EXPR</p> | |
</li></ul> <p>There is a <span class="code">truncate</span> function in Raku (also usable as a method) that does what Perl's <span class="code">int</span> does. You may want to use that as a direct translation of Perl code, but in Raku, you can just as easily call the <span class="code">.Int</span> method on the number. <span class="code">3.9.Int; # 3</span> and <span class="code">3.9.truncate</span> are equivalent.</p> | |
<p>Please note that <span class="code">int</span> <b>does</b> have a meaning in Raku. It is type that can be used to indicate a native integer:</p> | |
<pre class="code">my int $a = 42; # a native integer, similar to Perl's integer values</pre> | |
<p><span class="code">int</span> also operates on <span class="code">$_</span> in the absence of a value, but not as a function, and as a method you need to call it as <span class="code">.int</span> rather than simply <span class="code">int</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports an <span class="code">int</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.59"></a> <h2 id="_language_5to6-perlfunc.pod6-ioctl"><a name="86"></a>ioctl</h2> | |
<ul><li><p>ioctl FILEHANDLE, FUNCTION, SCALAR</p> | |
</li></ul> <p>Currently unimplemented in Raku.</p> | |
<a name="t4.3.60"></a> <h2 id="_language_5to6-perlfunc.pod6-join"><a name="87"></a>join</h2> | |
<ul><li><p>join EXPR, LIST</p> | |
</li></ul> <p>Works as in Perl, and also works as a method: <span class="code">@x.join(",")</span></p> | |
<a name="t4.3.61"></a> <h2 id="_language_5to6-perlfunc.pod6-keys"><a name="88"></a>keys</h2> | |
<ul><li><p>keys HASH</p> | |
</li></ul> <p>Works as in Perl, and can also be used as a method: <span class="code">%hash.keys</span></p> | |
<a name="t4.3.62"></a> <h2 id="_language_5to6-perlfunc.pod6-kill"><a name="89"></a>kill</h2> | |
<ul><li><p>kill SIGNAL, LIST</p> | |
</li></ul> <ul><li><p>kill SIGNAL</p> | |
</li></ul> <p>No pre-defined core alternative exists. A non-portable method can be to use <a href="#_language_nativecall.pod6">NativeCall</a>:</p> | |
<pre class="code">use NativeCall; | |
sub kill(int32, int32) is native {*}; | |
kill $*PID, 9; # OUTPUT: «Killed»</pre> | |
<p>To kill processes that were started by creating a <a href="#_type_Proc::Async.pod6">Proc::Async</a>, use <a href="#_type_Proc::Async.pod6-method_kill"><span class="code">Proc::Async.kill</span> method</a>.</p> | |
<a name="t4.3.63"></a> <h2 id="_language_5to6-perlfunc.pod6-last"><a name="90"></a>last</h2> | |
<ul><li><p>last LABEL</p> | |
</li></ul> <ul><li><p>last EXPR</p> | |
</li></ul> <ul><li><p>last</p> | |
</li></ul> <p>Same as in Perl.</p> | |
<a name="t4.3.64"></a> <h2 id="_language_5to6-perlfunc.pod6-lc"><a name="91"></a>lc</h2> | |
<ul><li><p>lc EXPR</p> | |
</li></ul> <p>Works as in Perl, and also as a method: <span class="code">"UGH".lc</span>. In Raku an expression <b>must</b> be specified.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5lc.pod6"><span class="code">P5lc</span></a> which exports an <span class="code">lc</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.65"></a> <h2 id="_language_5to6-perlfunc.pod6-lcfirst"><a name="92"></a>lcfirst</h2> | |
<ul><li><p>lcfirst EXPR</p> | |
</li></ul> <p>Does not exist in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5lcfirst.pod6"><span class="code">P5lcfirst</span></a> which exports an <span class="code">lcfirst</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.66"></a> <h2 id="_language_5to6-perlfunc.pod6-length"><a name="93"></a>length</h2> | |
<ul><li><p>length EXPR</p> | |
</li></ul> <p>Replaced by <span class="code">chars</span>, typically used as a method (<span class="code">$string.chars</span>), but also works as a function.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5length.pod6"><span class="code">P5length</span></a> which exports an <span class="code">length</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.67"></a> <h2 id="_language_5to6-perlfunc.pod6-__LINE__"><a name="94"></a>__LINE__</h2> | |
<ul><li><p>__LINE__</p> | |
</li></ul> <p>Replaced by <span class="code">$?LINE</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5__FILE__.pod6"><span class="code">P5__FILE__</span></a> which exports a <span class="code">__LINE__</span> term that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.68"></a> <h2 id="_language_5to6-perlfunc.pod6-link"><a name="95"></a>link</h2> | |
<ul><li><p>link OLDFILE, NEWFILE</p> | |
</li></ul> <p>See <a href="#_routine_link.pod6">link</a></p> | |
<a name="t4.3.69"></a> <h2 id="_language_5to6-perlfunc.pod6-listen"><a name="96"></a>listen</h2> | |
<ul><li><p>listen SOCKET, QUEUESIZE</p> | |
</li></ul> <p>Not clearly documented, but it appears that <span class="code">listen</span> will be a method you would call on some variety of IO::Socket object.</p> | |
<a name="t4.3.70"></a> <h2 id="_language_5to6-perlfunc.pod6-local"><a name="97"></a>local</h2> | |
<ul><li><p>local EXPR</p> | |
</li></ul> <p>The Raku equivalent is <span class="code">temp</span>. Unlike <span class="code">local</span>, however, the value of the given variable is not immediately unset: it retains its original value until assigned to.</p> | |
<a name="t4.3.71"></a> <h2 id="_language_5to6-perlfunc.pod6-localtime"><a name="98"></a>localtime</h2> | |
<ul><li><p>localtime EXPR</p> | |
</li></ul> <p>Most of the functionality of <span class="code">localtime</span> is found in <span class="code">DateTime</span>. The specific parts of <span class="code">localtime</span> can be found as follows:</p> | |
<pre class="code">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 | |
</pre> | |
<p>Please note that ranges are not 0-based in Raku, as shown in the comments in the example.</p> | |
<p>There does not currently appear to be a way to get Perl's <span class="code">$isdst</span>. Also, the result of <span class="code">scalar(localtime)</span> that Perl provides is not available. <span class="code">$d.Str</span> will give something along the lines of "2015-06-29T12:49:31-04:00".</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5localtime.pod6"><span class="code">P5localtime</span></a> which exports a <span class="code">localtime</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.72"></a> <h2 id="_language_5to6-perlfunc.pod6-lock"><a name="99"></a>lock</h2> | |
<ul><li><p>lock THING</p> | |
</li></ul> <p>There currently is no equivalent for this In Raku. There is a <span class="code">Lock</span> class for creating a Lock object, that can be locked/unlocked as needed. But such a lock does not refer to any external objects.</p> | |
<a name="t4.3.73"></a> <h2 id="_language_5to6-perlfunc.pod6-log"><a name="100"></a>log</h2> | |
<ul><li><p>log EXPR</p> | |
</li></ul> <p>Same as in Perl.</p> | |
<p><span class="code">log</span> also operates on <span class="code">$_</span> in the absence of a value, but not as a function, and as a method you need to call it as <span class="code">.log</span> rather than simply <span class="code">log</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports a <span class="code">log</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.74"></a> <h2 id="_language_5to6-perlfunc.pod6-lstat"><a name="101"></a>lstat</h2> | |
<ul><li><p>lstat FILEHANDLE</p> | |
</li></ul> <ul><li><p>lstat EXPR</p> | |
</li></ul> <ul><li><p>lstat DIRHANDLE</p> | |
</li></ul> <ul><li><p>lstat</p> | |
</li></ul> <p>Likely implemented somewhere in one of the <span class="code">IO</span> classes in Raku, but it is not clear where at this time.</p> | |
<a name="t4.3.75"></a> <h2 id="_language_5to6-perlfunc.pod6-m//"><a name="102"></a>m//</h2> | |
<ul><li><p>m//</p> | |
</li></ul> <p>Regular expression syntax is somewhat different in Raku, but the match operator still exists. If you're trying to rewrite some Perl code, the most important difference is that <span class="code">=~</span> is replaced by the smartmatch operator, <span class="code">~~</span>. Similarly, <span class="code">!~</span> is replaced by <span class="code">!~~</span>. Options for regex operators are adverbs and are complicated. For details, see <a href="#_language_regexes.pod6-Adverbs">Adverbs</a></p> | |
<a name="t4.3.76"></a> <h2 id="_language_5to6-perlfunc.pod6-map"><a name="103"></a>map</h2> | |
<ul><li><p>map BLOCK LIST</p> | |
</li></ul> <ul><li><p>map EXPR, LIST</p> | |
</li></ul> <p>As a function, the only difference between Perl and Raku is that, if you're using a block, the block must be followed by a comma. Can also be used as a method: <span class="code">@new = @old.map: { $_ * 2 }</span></p> | |
<a name="t4.3.77"></a> <h2 id="_language_5to6-perlfunc.pod6-mkdir"><a name="104"></a>mkdir</h2> | |
<ul><li><p>mkdir FILENAME, MASK</p> | |
</li></ul> <ul><li><p>mkdir FILENAME</p> | |
</li></ul> <p>Works as in Perl. 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).</p> | |
<ul><li><p>mkdir</p> | |
</li></ul> <p>The zero argument (implicit <span class="code">$_</span>) version is not permitted in Raku.</p> | |
<a name="t4.3.78"></a> <h2 id="_language_5to6-perlfunc.pod6-msg*"><a name="105"></a>msg*</h2> | |
<ul><li><p>msgctl ID, CMD, ARG</p> | |
</li></ul> <ul><li><p>msgget KEY, FLAGS</p> | |
</li></ul> <ul><li><p>msgrcv ID, VAR, SIZE, TYPE, FLAGS</p> | |
</li></ul> <ul><li><p>msgsnd ID, MSG, FLAGS</p> | |
</li></ul> <p>Not builtins in Raku. May appear in an external module at some point. Maybe.</p> | |
<a name="t4.3.79"></a> <h2 id="_language_5to6-perlfunc.pod6-my"><a name="106"></a>my</h2> | |
<ul><li><p>my VARLIST</p> | |
</li></ul> <ul><li><p>my TYPE VARLIST</p> | |
</li></ul> <ul><li><p>my VARLIST : ATTRS</p> | |
</li></ul> <ul><li><p>my TYPE VARLIST : ATTRS</p> | |
</li></ul> <p>Works as in Perl.</p> | |
<a name="t4.3.80"></a> <h2 id="_language_5to6-perlfunc.pod6-next"><a name="107"></a>next</h2> | |
<ul><li><p>next LABEL</p> | |
</li></ul> <ul><li><p>next EXPR</p> | |
</li></ul> <ul><li><p>next</p> | |
</li></ul> <p>The same in Raku.</p> | |
<a name="t4.3.81"></a> <h2 id="_language_5to6-perlfunc.pod6-no"><a name="108"></a>no</h2> | |
<ul><li><p>no MODULE VERSION</p> | |
</li></ul> <ul><li><p>no MODULE LIST</p> | |
</li></ul> <ul><li><p>no MODULE</p> | |
</li></ul> <ul><li><p>no VERSION</p> | |
</li></ul> <p>In Raku, this is usable for pragmas such as <span class="code">strict</span>, but not for modules or versions.</p> | |
<a name="t4.3.82"></a> <h2 id="_language_5to6-perlfunc.pod6-oct"><a name="109"></a>oct</h2> | |
<ul><li><p>oct</p> | |
</li></ul> <p>Replaced by the adverbial form <span class="code">:8</span>. E. g. <span class="code">:8("100")</span> returns 64.</p> | |
<p>If you want to deal with strings that start in <span class="code">0x</span>, <span class="code">0o</span>, or <span class="code">0b</span>, you can just use the <span class="code">prefix:<+></span> operator.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5hex.pod6"><span class="code">P5hex</span></a> which exports an <span class="code">oct</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.83"></a> <h2 id="_language_5to6-perlfunc.pod6-open"><a name="110"></a>open</h2> | |
<ul><li><p>open FILEHANDLE, EXPR</p> | |
</li></ul> <ul><li><p>open FILEHANDLE, MODE, EXPR</p> | |
</li></ul> <ul><li><p>open FILEHANDLE, MODE, EXPR, LIST</p> | |
</li></ul> <ul><li><p>open FILEHANDLE, MODE, REFERENCE</p> | |
</li></ul> <ul><li><p>open FILEHANDLE</p> | |
</li></ul> <p>The most obvious change from Perl is the file mode syntax. To open a file for reading only, you would say <span class="code">open("file", :r)</span>. For write- only, read-write, and append, you would use <span class="code">:w</span>, <span class="code">:rw</span>, and <span class="code">:a</span> respectively. There are also options for encoding and how the filehandle deals with newlines. Details <a href="#_routine_open.pod6">here</a>.</p> | |
<p>Another important change is that filehandles don't get automatically closed on scope exit. It's necessary to call <a href="#_routine_close.pod6">close</a> explicitly.</p> | |
<a name="t4.3.84"></a> <h2 id="_language_5to6-perlfunc.pod6-opendir"><a name="111"></a>opendir</h2> | |
<ul><li><p>opendir DIRHANDLE, EXPR</p> | |
</li></ul> <p>No replacement. See <a href="#_routine_dir.pod6"><span class="code">&dir</span> / <span class="code">IO::Path.dir</span></a> for alternatives.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5opendir.pod6"><span class="code">P5opendir</span></a> which exports an <span class="code">opendir</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.85"></a> <h2 id="_language_5to6-perlfunc.pod6-ord"><a name="112"></a>ord</h2> | |
<ul><li><p>ord EXPR</p> | |
</li></ul> <p>Same as in Perl. May be used as a method: <span class="code">"howdy!".ord; # 104</span></p> | |
<p>Note that <span class="code">ord()</span> (without arguments) is not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5chr.pod6"><span class="code">P5chr</span></a> which exports a <span class="code">ord</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.86"></a> <h2 id="_language_5to6-perlfunc.pod6-our"><a name="113"></a>our</h2> | |
<ul><li><p>our VARLIST</p> | |
</li></ul> <ul><li><p>our TYPE VARLIST</p> | |
</li></ul> <ul><li><p>our VARLIST : ATTRS</p> | |
</li></ul> <ul><li><p>our TYPE VARLIST : ATTRS</p> | |
</li></ul> <p>The same in Raku.</p> | |
<a name="t4.3.87"></a> <h2 id="_language_5to6-perlfunc.pod6-pack"><a name="114"></a>pack</h2> | |
<ul><li><p>pack TEMPLATE, LIST</p> | |
</li></ul> <p>Available in Raku when <span class="code">use experimental :pack</span> has been specified in the scope where <span class="code">pack</span> needs to be called. The template options are currently more restricted than they are in Perl. The current documented list can be found at <a href="#_routine_unpack.pod6">unpack</a>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5pack.pod6"><span class="code">P5pack</span></a> which exports a <span class="code">pack</span> function that mimics the original Perl behavior as much as possible and which has a bigger set of supported features than the experimental Raku version.</p> | |
<a name="t4.3.88"></a> <h2 id="_language_5to6-perlfunc.pod6-package"><a name="115"></a>package</h2> | |
<ul><li><p>package NAMESPACE</p> | |
</li></ul> <ul><li><p>package NAMESPACE VERSION</p> | |
</li></ul> <ul><li><p>package NAMESPACE BLOCK</p> | |
</li></ul> <ul><li><p>package NAMESPACE VERSION BLOCK</p> | |
</li></ul> <p>S10 indicates that <span class="code">package</span> can be used in Raku, but only with a block. I. e. <span class="code">package Foo { ... }</span> means that the code within the block would be in package Foo. There is a special case where a declaration of the form <span class="code">package Foo;</span> as the first statement in a file indicates that the rest of the file is Perl code, but the usefulness of this is unclear. In fact, as modules and classes are declared with distinct keywords (such as <span class="code">class</span>), it's unlikely you will use <span class="code">package</span> directly in Raku.</p> | |
<a name="t4.3.89"></a> <h2 id="_language_5to6-perlfunc.pod6-__PACKAGE__"><a name="116"></a>__PACKAGE__</h2> | |
<ul><li><p>__PACKAGE__</p> | |
</li></ul> <p>Replaced by <span class="code">$?PACKAGE</span> which is slightly different from <span class="code">__PACKAGE__</span> in that it is the actual package object. You should call the <span class="code">.^name</span> method on it to get a string.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5__FILE__.pod6"><span class="code">P5__FILE__</span></a> which exports a <span class="code">__PACKAGE__</span> term that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.90"></a> <h2 id="_language_5to6-perlfunc.pod6-pipe"><a name="117"></a>pipe</h2> | |
<ul><li><p>pipe READHANDLE, WRITEHANDLE</p> | |
</li></ul> <p>Depending on your needs, see <a href="#_type_Channel.pod6"><span class="code">Channel</span></a> to shuttle data between threads (and <a href="#_language_concurrency.pod6">Concurrency tutorial</a> for other options), or see <a href="#_type_Proc.pod6"><span class="code">Proc</span></a> type for piping to and from processes.</p> | |
<a name="t4.3.91"></a> <h2 id="_language_5to6-perlfunc.pod6-pop"><a name="118"></a>pop</h2> | |
<ul><li><p>pop ARRAY</p> | |
</li></ul> <p>Works in Raku, and can also be used as a method. I. e. <span class="code">my $x = pop @a;</span> and <span class="code">my $x = @a.pop;</span> are equivalent.</p> | |
<p>The non-parameter version of <span class="code">pop</span> does not exist. Also, if the array is empty, a Failure will be returned in Raku, which will throw if the value is actually used in a significant way.</p> | |
<p>If you are using only defined values in your array, you can use the <span class="code">with</span> function to handle this case:</p> | |
<pre class="code">with pop @array -> $popped { | |
say "popped '$popped' of the array"; | |
} | |
else { | |
say "there was nothing to pop"; | |
} | |
</pre> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5push.pod6"><span class="code">P5push</span></a> which exports a <span class="code">pop</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.92"></a> <h2 id="_language_5to6-perlfunc.pod6-pos"><a name="119"></a>pos</h2> | |
<ul><li><p>pos SCALAR</p> | |
</li></ul> <p>Not available in Raku. The closest equivalent is the <span class="code">:c</span> adverb, which defaults to <span class="code">$/.to</span> if <span class="code">$/</span> is true, and <span class="code">0</span> if it isn't. For information on <span class="code">:c</span>, see <a href="#_language_regexes.pod6-Continue">Continue</a>.</p> | |
<a name="t4.3.93"></a> <h2 id="_language_5to6-perlfunc.pod6-print"><a name="120"></a>print</h2> | |
<ul><li><p>print FILEHANDLE LIST</p> | |
</li></ul> <ul><li><p>print FILEHANDLE</p> | |
</li></ul> <ul><li><p>print LIST</p> | |
</li></ul> <ul><li><p>print</p> | |
</li></ul> <p><span class="code">print</span> can be used as a function in Raku, writing to standard out. To use <span class="code">print</span> as a function with a filehandle <i>instead</i> of standard out, you can use a method call: <span class="code">$fh.print("howdy!")</span></p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5print.pod6"><span class="code">P5print</span></a> which exports a <span class="code">print</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.94"></a> <h2 id="_language_5to6-perlfunc.pod6-printf"><a name="121"></a>printf</h2> | |
<ul><li><p>printf FORMAT, LIST</p> | |
</li></ul> <ul><li><p>printf</p> | |
</li></ul> <p>Raku version is similar; see <a href="#_routine_sprintf.pod6">sprintf</a> for details on acceptable format directives. To print to a filehandle other than STDOUT, use the <a href="#_routine_printf.pod6"><span class="code">.printf</span></a> method on that filehandle.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5print.pod6"><span class="code">P5print</span></a> which exports a <span class="code">printf</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.95"></a> <h2 id="_language_5to6-perlfunc.pod6-prototype"><a name="122"></a>prototype</h2> | |
<ul><li><p>prototype FUNCTION</p> | |
</li></ul> <p>Not available in Raku. The closest equivalent is <span class="code">.signature</span>. E. g. <span class="code">say &sprintf.signature</span> results in "(Cool $format, *@args)".</p> | |
<a name="t4.3.96"></a> <h2 id="_language_5to6-perlfunc.pod6-push"><a name="123"></a>push</h2> | |
<ul><li><p>push ARRAY, LIST</p> | |
</li></ul> <p>Works as in Perl, as well as being available as a method: <span class="code">@a.push("foo");</span>. <i>Note:</i> the flattening behavior is different in Raku: <span class="code">@b.push: @a</span> will push <span class="code">@a</span> into <span class="code">@b</span> as a single element. See also the <a href="#_type_Array.pod6-method_append">append method</a>.</p> | |
<p>Also note that <span class="code">push</span> in Raku returns the array to which was pushed, contrary to Perl where it returns the new number of elements.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5push.pod6"><span class="code">P5push</span></a> which exports a <span class="code">push</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.97"></a> <h2 id="_language_5to6-perlfunc.pod6-quoting"><a name="124"></a>quoting</h2> | |
<ul><li><p>q/STRING/</p> | |
</li></ul> <ul><li><p>qq/STRING/</p> | |
</li></ul> <ul><li><p>qw/STRING/</p> | |
</li></ul> <ul><li><p>qx/STRING/</p> | |
</li></ul> <p>These survive the transition to Raku. Some notes:</p> | |
<pre class="code">q/.../; # is still equivalent to using single quotes. | |
qq/.../; # is still equivalent to using double quotes. | |
qw/.../; # is more commonly written as <...> in Raku. | |
</pre> | |
<p>There are some added quoting constructs and equivalents, as explained at <a href="#_language_quoting.pod6">quoting</a>.</p> | |
<ul><li><p>qr/STRING/ <a id="i125" name="Other languages qr (Perl)"></a><span class="indexed"></span></p> | |
</li></ul> <p>Has been replaced by <span class="code">rx/.../</span>.</p> | |
<ul><li><p>quotemeta EXPR</p> | |
</li></ul> <p>No direct equivalent, i.e. nothing that just returns the string with all the ASCII non-word characters backslashed. In regexes, however, using <span class="code">$foo</span> will treat <span class="code">$foo</span> as a literal string, and using <span class="code"><$foo> </span> will interpret the contents of <span class="code">$foo</span> 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 <a href="#_routine_https:__design.raku.org_S05.html.pod6-Extensible_metasyntax_(%3C...%3E)">https://design.raku.org/S05.html#Extensible_metasyntax_(%3C...%3E)</a></p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5quotemeta.pod6"><span class="code">P5quotemeta</span></a> which exports a <span class="code">quotemeta</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.98"></a> <h2 id="_language_5to6-perlfunc.pod6-rand"><a name="126"></a>rand</h2> | |
<ul><li><p>rand EXPR</p> | |
</li></ul> <p><span class="code">rand</span> by itself works as it does in Perl, 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 <span class="code">rand(100)</span> is equivalent to <span class="code">100.rand</span> in Raku. Additionally, you can get a random integer by using something like <span class="code">(^100).pick</span>. For <i>why</i> you are able to do that, see <a href="#_language_operators.pod6-prefix_%5E">^ operator</a> and <a href="#_routine_pick.pod6">pick</a>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports a <span class="code">rand</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.99"></a> <h2 id="_language_5to6-perlfunc.pod6-read"><a name="127"></a>read</h2> | |
<ul><li><p>read FILEHANDLE, SCALAR, LENGTH, OFFSET</p> | |
</li></ul> <p><span class="code">read</span> is found in <span class="code">IO::Handle</span> and <span class="code">IO::Socket</span> in Raku. It reads the specified number of bytes (rather than characters) from the relevant handle or socket. The use of an offset available in Perl is not documented to exist at this time.</p> | |
<a name="t4.3.100"></a> <h2 id="_language_5to6-perlfunc.pod6-readdir"><a name="128"></a>readdir</h2> | |
<ul><li><p>readdir DIRHANDLE</p> | |
</li></ul> <p>Not a builtin function. To iterate through the contents of a directory, take a look at <a href="#_type_IO::Path.pod6-routine_dir">dir routine</a>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5opendir.pod6"><span class="code">P5opendir</span></a> which exports a <span class="code">readdir</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.101"></a> <h2 id="_language_5to6-perlfunc.pod6-readline"><a name="129"></a>readline</h2> | |
<ul><li><p>readline</p> | |
</li></ul> <p>Not available in Raku. You most likely want to use the <span class="code">.lines</span> method in some way. For more detailed information on reading from files, see <a href="#_language_io.pod6">io</a>.</p> | |
<a name="t4.3.102"></a> <h2 id="_language_5to6-perlfunc.pod6-readlink"><a name="130"></a>readlink</h2> | |
<ul><li><p>readlink EXPR</p> | |
</li></ul> <p>Appears to be gone from Raku. There <b>is</b> a method <span class="code">resolve</span> in <span class="code">IO::Path</span> that will follow symlinks if the OS / Filesystem supports them.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5readlink.pod6"><span class="code">P5readlink</span></a> which exports a <span class="code">readlink</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.103"></a> <h2 id="_language_5to6-perlfunc.pod6-readpipe"><a name="131"></a>readpipe</h2> | |
<ul><li><p>readpipe EXPR</p> | |
</li></ul> <ul><li><p>readpipe</p> | |
</li></ul> <p>Doesn't appear to be working in Raku, but <span class="code">qx//</span> is functional, so it might be lurking around in some class that isn't obvious.</p> | |
<a name="t4.3.104"></a> <h2 id="_language_5to6-perlfunc.pod6-recv"><a name="132"></a>recv</h2> | |
<ul><li><p>recv SOCKET, SCALAR, LENGTH, FLAGS</p> | |
</li></ul> <p>Appears to be in IO::Socket. Not extensively documented at this time.</p> | |
<a name="t4.3.105"></a> <h2 id="_language_5to6-perlfunc.pod6-redo"><a name="133"></a>redo</h2> | |
<ul><li><p>redo LABEL</p> | |
</li></ul> <ul><li><p>redo EXPR</p> | |
</li></ul> <ul><li><p>redo</p> | |
</li></ul> <p>Unchanged in Raku.</p> | |
<a name="t4.3.106"></a> <h2 id="_language_5to6-perlfunc.pod6-ref"><a name="134"></a>ref</h2> | |
<ul><li><p>ref EXPR</p> | |
</li></ul> <p>Gone. To quote S29, "If you really want the type name, you can use <span class="code">$var.WHAT.^name</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5ref.pod6"><span class="code">P5ref</span></a> which exports a <span class="code">ref</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.107"></a> <h2 id="_language_5to6-perlfunc.pod6-rename"><a name="135"></a>rename</h2> | |
<ul><li><p>rename OLDNAME, NEWNAME</p> | |
</li></ul> <p>Still available in Raku.</p> | |
<a name="t4.3.108"></a> <h2 id="_language_5to6-perlfunc.pod6-requires"><a name="136"></a>requires</h2> | |
<ul><li><p>require VERSION</p> | |
</li></ul> <p>No equivalent.</p> | |
<a name="t4.3.109"></a> <h2 id="_language_5to6-perlfunc.pod6-reset"><a name="137"></a>reset</h2> | |
<ul><li><p>reset EXPR</p> | |
</li></ul> <p>No equivalent.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5reset.pod6"><span class="code">P5reset</span></a> which exports a <span class="code">reset</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.110"></a> <h2 id="_language_5to6-perlfunc.pod6-return"><a name="138"></a>return</h2> | |
<ul><li><p>return EXPR</p> | |
</li></ul> <p>Appears to be available in Raku, although not clearly documented.</p> | |
<a name="t4.3.111"></a> <h2 id="_language_5to6-perlfunc.pod6-reverse"><a name="139"></a>reverse</h2> | |
<ul><li><p>reverse LIST</p> | |
</li></ul> <p>In Raku, this only reverses the elements of a list. <span class="code">reverse(@a)</span> or <span class="code">@a.reverse</span>. To reverse the characters in a string, use the <span class="code">.flip</span> method.</p> | |
<p><span class="code">reverse</span> without parameters is not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5reverse.pod6"><span class="code">P5reverse</span></a> which exports a <span class="code">reverse</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.112"></a> <h2 id="_language_5to6-perlfunc.pod6-rewinddir"><a name="140"></a>rewinddir</h2> | |
<ul><li><p>rewinddir DIRHANDLE</p> | |
</li></ul> <p>Not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5opendir.pod6"><span class="code">P5opendir</span></a> which exports a <span class="code">rewinddir</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.113"></a> <h2 id="_language_5to6-perlfunc.pod6-rindex"><a name="141"></a>rindex</h2> | |
<ul><li><p>rindex STR, SUBSTR, POSITION</p> | |
</li></ul> <p>Works as in Perl, and may also be used as a method. E. g. <span class="code">$x = "babaganush";say $x.rindex("a"); say $x.rindex("a", 3); # 5, 3</span>. Main difference with Perl is that <span class="code">Nil</span> is returned instead of <span class="code">-1</span> when the substring is not found. This is very useful in combination with the <span class="code">with</span> command:</p> | |
<pre class="code">with index("foo","o") -> $index { | |
say "Found it at $index"; | |
} | |
else { | |
say "Not found" | |
}</pre> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5index.pod6"><span class="code">P5index</span></a> which exports a <span class="code">rindex</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.114"></a> <h2 id="_language_5to6-perlfunc.pod6-rmdir"><a name="142"></a>rmdir</h2> | |
<ul><li><p>rmdir FILENAME</p> | |
</li></ul> <p>Works in Raku and can also be used as a method. <span class="code">rmdir "Foo";</span> and <span class="code">"Foo".IO.rmdir;</span> are equivalent.</p> | |
<a name="t4.3.115"></a> <h2 id="_language_5to6-perlfunc.pod6-s///"><a name="143"></a>s///</h2> | |
<ul><li><p>s///</p> | |
</li></ul> <p>Regular expression syntax is somewhat different in Raku, but the substitution operator exists. If you're trying to rewrite some Perl code, the most important difference is that <span class="code">=~</span> is replaced by the smartmatch operator, <span class="code">~~</span>. Similarly, <span class="code">!~</span> is <span class="code">!~~</span>. Options for regex operators are adverbs and are complicated. For details, see <a href="#_language_regexes.pod6-Adverbs">Adverbs page</a></p> | |
<a name="t4.3.116"></a> <h2 id="_language_5to6-perlfunc.pod6-say"><a name="144"></a>say</h2> | |
<ul><li><p>say FILEHANDLE</p> | |
</li></ul> <ul><li><p>say LIST</p> | |
</li></ul> <ul><li><p>say</p> | |
</li></ul> <p><span class="code">say</span> can be used as a function, defaulting to standard out. To use <span class="code">say</span> as a function with a filehandle <i>instead</i> of standard out, you need to put a colon after the filehandle. I. e. <span class="code">say $fh: "Howdy!"</span>. The use of the colon as an "invocant marker" here is discussed at <a href="#_routine_https:__design.raku.org_S03.html.pod6-line_4019">https://design.raku.org/S03.html#line_4019</a>. Alternately, you can use a method call: <span class="code">$fh.say("howdy!")</span></p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5print.pod6"><span class="code">P5print</span></a> which exports a <span class="code">say</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.117"></a> <h2 id="_language_5to6-perlfunc.pod6-scalar"><a name="145"></a>scalar</h2> | |
<ul><li><p>scalar EXPR</p> | |
</li></ul> <p>Gone. Apparently "very" gone.</p> | |
<p>Some functions of the modules created for the CPAN Butterfly Plan accept a <span class="code">:scalar</span> named parameter to indicate that the <span class="code">scalar</span> behavior of the function is required.</p> | |
<a name="t4.3.118"></a> <h2 id="_language_5to6-perlfunc.pod6-seek"><a name="146"></a>seek</h2> | |
<ul><li><p>seek FILEHANDLE, POSITION, WHENCE</p> | |
</li></ul> <p>Not documented in any real way yet, but listed as a method of the <span class="code">IO::Handle</span> class.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5seek.pod6"><span class="code">P5seek</span></a> which exports a <span class="code">seek</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.119"></a> <h2 id="_language_5to6-perlfunc.pod6-seekdir"><a name="147"></a>seekdir</h2> | |
<ul><li><p>seekdir DIRHANDLE, POS</p> | |
</li></ul> <p>Not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5opendir.pod6"><span class="code">P5opendir</span></a> which exports a <span class="code">seekdir</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.120"></a> <h2 id="_language_5to6-perlfunc.pod6-select"><a name="148"></a>select</h2> | |
<ul><li><p>select FILEHANDLE</p> | |
</li></ul> <p>"[S]elect as a global concept is dead." When I asked around about <span class="code">select</span>, I was told that $*OUT and such are overridable in dynamic scope, and that <span class="code">IO::Capture::Simple</span> (at <a href="#_routine_https:__github.com_sergot_IO-Capture-Simple.pod6">https://github.com/sergot/IO-Capture-Simple</a>) may be of use for something you might be doing with the value of <span class="code">select</span>.</p> | |
<a name="t4.3.121"></a> <h2 id="_language_5to6-perlfunc.pod6-semctl">semctl</h2> | |
<ul><li><p>semctl ID, SEMNUM, CMD, ARG</p> | |
</li></ul> <p>No longer in core.</p> | |
<a name="t4.3.122"></a> <h2 id="_language_5to6-perlfunc.pod6-semget"><a name="149"></a>semget</h2> | |
<ul><li><p>semget KEY, NSEMS, FLAGS</p> | |
</li></ul> <p>No longer in core.</p> | |
<a name="t4.3.123"></a> <h2 id="_language_5to6-perlfunc.pod6-semop"><a name="150"></a>semop</h2> | |
<ul><li><p>semop KEY, OPSTRING</p> | |
</li></ul> <p>No longer in core.</p> | |
<a name="t4.3.124"></a> <h2 id="_language_5to6-perlfunc.pod6-send"><a name="151"></a>send</h2> | |
<ul><li><p>send SOCKET, MSG, FLAGS, TO</p> | |
</li></ul> <p>Can be found in the <span class="code">IO::Socket</span> class.</p> | |
<a name="t4.3.125"></a> <h2 id="_language_5to6-perlfunc.pod6-setpgrp"><a name="152"></a>setpgrp</h2> | |
<ul><li><p>setpgrp PID, PGRP</p> | |
</li></ul> <p>Will not be implemented.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getpriority.pod6"><span class="code">P5getpriority</span></a> which exports a <span class="code">setpgrp</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.126"></a> <h2 id="_language_5to6-perlfunc.pod6-setpriority"><a name="153"></a>setpriority</h2> | |
<ul><li><p>setpriority WHICH, WHO, PRIORITY</p> | |
</li></ul> <p>Will not be implemented.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5getpriority.pod6"><span class="code">P5getpriority</span></a> which exports a <span class="code">setpriority</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.127"></a> <h2 id="_language_5to6-perlfunc.pod6-setsockopt"><a name="154"></a>setsockopt</h2> | |
<ul><li><p>setsockopt SOCKET, LEVEL, OPTNAME, OPTVAL</p> | |
</li></ul> <p>Not documented, but probably hiding in an <span class="code">IO</span> class somewhere.</p> | |
<a name="t4.3.128"></a> <h2 id="_language_5to6-perlfunc.pod6-shift"><a name="155"></a>shift</h2> | |
<ul><li><p>shift ARRAY</p> | |
</li></ul> <ul><li><p>shift EXPR</p> | |
</li></ul> <ul><li><p>shift</p> | |
</li></ul> <p>Works in Raku, and can also be used as a method. I. e. <span class="code">my $x = shift @a;</span> and <span class="code">my $x = @a.shift;</span> are equivalent.</p> | |
<p>The non-parameter version of <span class="code">shift</span> does not exist. Also, if the array is empty, a Failure will be returned in Raku, which will throw if the value is actually used in a significant way.</p> | |
<p>If you are using only defined values in your array, you can use the <span class="code">with</span> function to handle this case:</p> | |
<pre class="code">with shift @array -> $shifted { | |
say "shifted '$shifted' of the array"; | |
} | |
else { | |
say "there was nothing to shift"; | |
} | |
</pre> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5shift.pod6"><span class="code">P5shift</span></a> which exports a <span class="code">shift</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.129"></a> <h2 id="_language_5to6-perlfunc.pod6-shm*"><a name="156"></a>shm*</h2> | |
<ul><li><p>shmctl ID, CMD, ARG</p> | |
</li></ul> <ul><li><p>shmget KEY, SIZE, FLAGS</p> | |
</li></ul> <ul><li><p>shmread ID, VAR, POS, SIZE</p> | |
</li></ul> <ul><li><p>shmwrite ID, STRING, POS, SIZE</p> | |
</li></ul> <p>Gone from the core. May turn up in a module somewhere.</p> | |
<a name="t4.3.130"></a> <h2 id="_language_5to6-perlfunc.pod6-shutdown"><a name="157"></a>shutdown</h2> | |
<ul><li><p>shutdown SOCKET, HOW</p> | |
</li></ul> <p>Not documented, but likely moved into <span class="code">IO::Socket</span>.</p> | |
<a name="t4.3.131"></a> <h2 id="_language_5to6-perlfunc.pod6-sin"><a name="158"></a>sin</h2> | |
<ul><li><p>sin EXPR</p> | |
</li></ul> <p>Same as in Perl.</p> | |
<p><span class="code">sin</span> also operates on <span class="code">$_</span> in the absence of a value, but not as a function, and as a method you need to call it as <span class="code">.sin</span> rather than simply <span class="code">sin</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports a <span class="code">sin</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.132"></a> <h2 id="_language_5to6-perlfunc.pod6-sleep"><a name="159"></a>sleep</h2> | |
<ul><li><p>sleep EXPR</p> | |
</li></ul> <p>Still works as in Perl, but is not limited to integer values for seconds. And it always returns Nil.</p> | |
<p>If you're interested in the return values of <span class="code">sleep</span> to ensure sleeping until a specified time, then you should use <span class="code">sleep-until</span> in Raku (which takes an <span class="code">Instant</span>).</p> | |
<p>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 <span class="code">react</span> and <span class="code">whenever</span> with a <span class="code">Supply.interval</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5sleep.pod6"><span class="code">P5sleep</span></a> which exports a <span class="code">sleep</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.133"></a> <h2 id="_language_5to6-perlfunc.pod6-sockets"><a name="160"></a>sockets</h2> | |
<ul><li><p>socket SOCKET, DOMAIN, TYPE, PROTOCOL</p> | |
</li></ul> <ul><li><p>socketpair SOCKET1, SOCKET2, DOMAIN, TYPE, PROTOCOL</p> | |
</li></ul> <p>Not currently documented, but will likely wind up in <span class="code">IO::Socket</span>.</p> | |
<a name="t4.3.134"></a> <h2 id="_language_5to6-perlfunc.pod6-sort"><a name="161"></a>sort</h2> | |
<ul><li><p>sort SUBNAME LIST</p> | |
</li></ul> <p><span class="code">sort</span> exists in Raku, but is somewhat different. <span class="code">$a</span> and <span class="code">$b</span> are no longer special (see <a href="#_language_5to6-perlvar.pod6">Special Variables</a>) and sort routines no longer return positive integers, negative integers, or 0, but rather <span class="code">Order::Less</span>, <span class="code">Order::Same</span>, or <span class="code">Order::More</span> objects. See <a href="#_routine_sort.pod6">sort</a> for details. May also be used as a method I. e. <span class="code">sort(@a)</span> is equivalent to <span class="code">@a.sort</span>.</p> | |
<a name="t4.3.135"></a> <h2 id="_language_5to6-perlfunc.pod6-splice"><a name="162"></a>splice</h2> | |
<ul><li><p>splice ARRAY, OFFSET, LENGTH</p> | |
</li></ul> <ul><li><p>splice ARRAY, OFFSET</p> | |
</li></ul> <ul><li><p>splice ARRAY</p> | |
</li></ul> <ul><li><p>splice EXPR, OFFSET, LENGTH, LIST</p> | |
</li></ul> <ul><li><p>splice EXPR, OFFSET, LENGTH</p> | |
</li></ul> <ul><li><p>splice EXPR, OFFSET</p> | |
</li></ul> <ul><li><p>splice EXPR</p> | |
</li></ul> <p>Available in Raku. Can also be used as a method. <span class="code">splice(@foo, 2, 3, <M N O P>); </span> is equivalent to <span class="code">@foo.splice(2, 3, <M N O P>); </span>.</p> | |
<a name="t4.3.136"></a> <h2 id="_language_5to6-perlfunc.pod6-split"><a name="163"></a>split</h2> | |
<ul><li><p>split /PATTERN/, EXPR, LIMIT</p> | |
</li></ul> <ul><li><p>split /PATTERN/, EXPR</p> | |
</li></ul> <ul><li><p>split /PATTERN/</p> | |
</li></ul> <p>Works mostly as in Perl. 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 <span class="code">//</span> 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 <span class="code">:all</span>, like this: <span class="code">split(';', "a;b;c", :all) # a ; b ; c</span> Empty chunks are not removed from the result list as they are in Perl. For that behavior, see <span class="code">comb</span>. Details on <span class="code">split</span> are <a href="#_routine_split.pod6">here</a>. Unsurprisingly, <span class="code">split</span> also now works as a method: <span class="code">"a;b;c".split(';')</span></p> | |
<ul><li><p>split</p> | |
</li></ul> <p><span class="code">split</span> now requires a pattern. For the equivalent of Perl's behavior of splitting on whitespace when no pattern is specified, use <a href="#_routine_words.pod6">words</a> (or use <span class="code">split</span> with <span class="code">/\s+/</span> as the pattern and <span class="code">:skip-empty</span> as a named argument).</p> | |
<a name="t4.3.137"></a> <h2 id="_language_5to6-perlfunc.pod6-sprintf"><a name="164"></a>sprintf</h2> | |
<ul><li><p>sprintf FORMAT, LIST</p> | |
</li></ul> <p>Works as in Perl. The formats currently available are:</p> | |
<table> | |
<tr><td>%</td> <td>a literal percent sign</td></tr> | |
<tr><td>c</td> <td>a character with the given codepoint</td></tr> | |
<tr><td>s</td> <td>a string</td></tr> | |
<tr><td>d</td> <td>a signed integer, in decimal</td></tr> | |
<tr><td>u</td> <td>an unsigned integer, in decimal</td></tr> | |
<tr><td>o</td> <td>an unsigned integer, in octal</td></tr> | |
<tr><td>x</td> <td>an unsigned integer, in hexadecimal</td></tr> | |
<tr><td>e</td> <td>a floating-point number, in scientific notation</td></tr> | |
<tr><td>f</td> <td>a floating-point number, in fixed decimal notation</td></tr> | |
<tr><td>g</td> <td>a floating-point number, in %e or %f notation</td></tr> | |
<tr><td>X</td> <td>like x, but using uppercase letters</td></tr> | |
<tr><td>E</td> <td>like e, but using an uppercase "E"</td></tr> | |
<tr><td>G</td> <td>like g, but with an uppercase "E" (if applicable)</td></tr> | |
</table> <p>Compatibility:</p> | |
<table> | |
<tr><td>i</td> <td>a synonym for %d</td></tr> | |
<tr><td>D</td> <td>a synonym for %ld</td></tr> | |
<tr><td>U</td> <td>a synonym for %lu</td></tr> | |
<tr><td>O</td> <td>a synonym for %lo</td></tr> | |
<tr><td>F</td> <td>a synonym for %f</td></tr> | |
</table> <p>Perl (non-)compatibility:</p> | |
<table> | |
<tr><td>n</td> <td>produces a runtime exception</td></tr> | |
<tr><td>p</td> <td>produces a runtime exception</td></tr> | |
</table> <p>There are modifiers for integers, but they're mainly no-ops, as the semantics aren't settled:</p> | |
<table> | |
<tr><td>h</td> <td>interpret integer as native "short" (typically int16)</td></tr> | |
<tr><td>l</td> <td>interpret integer as native "long" (typically int32 or int64)</td></tr> | |
<tr><td>ll</td> <td>interpret integer as native "long long" (typically int64)</td></tr> | |
<tr><td>L</td> <td>interpret integer as native "long long" (typically uint64)</td></tr> | |
<tr><td>q</td> <td>interpret integer as native "quads" (typically int64 or larger)</td></tr> | |
</table> <a name="t4.3.138"></a> <h2 id="_language_5to6-perlfunc.pod6-sqrt"><a name="165"></a>sqrt</h2> | |
<ul><li><p>sqrt EXPR</p> | |
</li></ul> <p>Same as in Perl.</p> | |
<p><span class="code">sqrt</span> also operates on <span class="code">$_</span> in the absence of a value, but not as a function, and as a method you need to call it as <span class="code">.sqrt</span> rather than simply <span class="code">sqrt</span>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5math.pod6"><span class="code">P5math</span></a> which exports a <span class="code">sqrt</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.139"></a> <h2 id="_language_5to6-perlfunc.pod6-srand"><a name="166"></a>srand</h2> | |
<ul><li><p>srand EXPR</p> | |
</li></ul> <p>Available in Raku.</p> | |
<a name="t4.3.140"></a> <h2 id="_language_5to6-perlfunc.pod6-stat">stat</h2> | |
<ul><li><p>stat EXPR</p> | |
</li></ul> <ul><li><p>stat DIRHANDLE</p> | |
</li></ul> <ul><li><p>stat</p> | |
</li></ul> <p>Unlikely to be implemented as a built in function since it's POSIX specific, but available through the <span class="code">NativeCall</span> interface.</p> | |
<a name="t4.3.141"></a> <h2 id="_language_5to6-perlfunc.pod6-state"><a name="167"></a>state</h2> | |
<ul><li><p>state VARLIST</p> | |
</li></ul> <ul><li><p>state TYPE VARLIST</p> | |
</li></ul> <ul><li><p>state VARLIST : ATTRS</p> | |
</li></ul> <ul><li><p>state TYPE VARLIST : ATTRS</p> | |
</li></ul> <p>Available in Raku, see <a href="#_syntax_state.pod6">state</a>.</p> | |
<a name="t4.3.142"></a> <h2 id="_language_5to6-perlfunc.pod6-study"><a name="168"></a>study</h2> | |
<ul><li><p>study SCALAR</p> | |
</li></ul> <ul><li><p>study</p> | |
</li></ul> <p><span class="code">study</span> is no more.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5study.pod6"><span class="code">P5study</span></a> which exports a <span class="code">study</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.143"></a> <h2 id="_language_5to6-perlfunc.pod6-sub"><a name="169"></a>sub</h2> | |
<ul><li><p>sub NAME BLOCK</p> | |
</li></ul> <ul><li><p>sub NAME(PROTO) BLOCK</p> | |
</li></ul> <ul><li><p>sub NAME : ATTRS BLOCK</p> | |
</li></ul> <ul><li><p>sub NAME(PROTO) : ATTRS BLOCK</p> | |
</li></ul> <p>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), <span class="code">@_</span> 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 to Raku (although you should probably consider the option of using a signature). For all the gory details, see <a href="#_language_functions.pod6">functions</a>.</p> | |
<a name="t4.3.144"></a> <h2 id="_language_5to6-perlfunc.pod6-__SUB__"><a name="170"></a>__SUB__</h2> | |
<ul><li><p>__SUB__</p> | |
</li></ul> <p>Replaced by <span class="code">&?ROUTINE</span> which is slightly different from <span class="code">__SUB__</span> in that it is the actual <span class="code">Sub</span> (or <span class="code">Method</span>) object. You should call the <span class="code">.name</span> method on it to get a string.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5__FILE__.pod6"><span class="code">P5__FILE__</span></a> which exports a <span class="code">__SUB__</span> term that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.145"></a> <h2 id="_language_5to6-perlfunc.pod6-substr"><a name="171"></a>substr</h2> | |
<ul><li><p>substr EXPR, OFFSET, LENGTH, REPLACEMENT</p> | |
</li></ul> <p>See <a href="#_routine_substr-rw.pod6">substr-rw</a>.</p> | |
<p>Can be used as a function or a method. Can't be used on <span class="code">Str</span> literals, as they are immutable.</p> | |
<pre class="code"> my $a = 'Cheesy'; | |
$a.substr-rw(4,1)="k"; # returns 'k' | |
say $a; # OUTPUT: «Cheeky» | |
substr-rw($a, 0, 3) = "Lea"; | |
say $a; # OUTPUT: «Leaky» | |
</pre> | |
<ul><li><p>substr EXPR, OFFSET, LENGTH</p> | |
</li></ul> <ul><li><p>substr EXPR, OFFSET</p> | |
</li></ul> <p>See <a href="#_routine_substr.pod6">substr</a>.</p> | |
<p>Can be used as a function or a method. <span class="code">substr("hola!", 1, 3)</span> and <span class="code">"hola!".substr(1, 3)</span> both return "ola".</p> | |
<a name="t4.3.146"></a> <h2 id="_language_5to6-perlfunc.pod6-symlink"><a name="172"></a>symlink</h2> | |
<ul><li><p>symlink OLDFILE, NEWFILE</p> | |
</li></ul> <p>See <a href="#_routine_symlink.pod6">symlink</a>.</p> | |
<a name="t4.3.147"></a> <h2 id="_language_5to6-perlfunc.pod6-syscall"><a name="173"></a>syscall</h2> | |
<ul><li><p>syscall NUMBER, LIST</p> | |
</li></ul> <p>Not a builtin in Raku. Most likely out in a module somewhere, but it's currently unclear where.</p> | |
<a name="t4.3.148"></a> <h2 id="_language_5to6-perlfunc.pod6-sys*"><a name="174"></a>sys*</h2> | |
<ul><li><p>sysopen FILEHANDLE, FILENAME, MODE</p> | |
</li></ul> <ul><li><p>sysopen FILEHANDLE, FILENAME, MODE, PERMS</p> | |
</li></ul> <ul><li><p>sysread FILEHANDLE, SCALAR, LENGTH, OFFSET</p> | |
</li></ul> <ul><li><p>sysread FILEHANDLE, SCALAR, LENGTH</p> | |
</li></ul> <ul><li><p>sysseek FILEHANDLE, POSITION, WHENCE</p> | |
</li></ul> <p>As with the non-sys versions of these functions, are probably lurking in the <span class="code">IO</span> classes somewhere.</p> | |
<a name="t4.3.149"></a> <h2 id="_language_5to6-perlfunc.pod6-system"><a name="175"></a>system</h2> | |
<ul><li><p>system LIST</p> | |
</li></ul> <ul><li><p>system PROGRAM LIST</p> | |
</li></ul> <p>For this, you probably want (<a href="#_routine_run.pod6">run</a>) or (<a href="#_routine_shell.pod6">shell routine</a>).</p> | |
<a name="t4.3.150"></a> <h2 id="_language_5to6-perlfunc.pod6-syswrite"><a name="176"></a>syswrite</h2> | |
<ul><li><p>syswrite FILEHANDLE, SCALAR, LENGTH, OFFSET</p> | |
</li></ul> <ul><li><p>syswrite FILEHANDLE, SCALAR, LENGTH</p> | |
</li></ul> <ul><li><p>syswrite FILEHANDLE, SCALAR</p> | |
</li></ul> <p>As with <span class="code">sysopen</span> and friends, this has moved into the <span class="code">IO</span> classes.</p> | |
<a name="t4.3.151"></a> <h2 id="_language_5to6-perlfunc.pod6-tell"><a name="177"></a>tell</h2> | |
<ul><li><p>tell FILEHANDLE</p> | |
</li></ul> <p>As a method on <span class="code">IO::Handle</span>.</p> | |
<a name="t4.3.152"></a> <h2 id="_language_5to6-perlfunc.pod6-telldir"><a name="178"></a>telldir</h2> | |
<ul><li><p>telldir DIRHANDLE</p> | |
</li></ul> <p>Not supported in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5opendir.pod6"><span class="code">P5opendir</span></a> which exports a <span class="code">telldir</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.153"></a> <h2 id="_language_5to6-perlfunc.pod6-tie"><a name="179"></a>tie</h2> | |
<ul><li><p>tie VARIABLE, CLASSNAME, LIST</p> | |
</li></ul> <ul><li><p>tied VARIABLE</p> | |
</li></ul> <p>The Raku alternative to tying a scalar, is the <span class="code">Proxy</span> container. For example:</p> | |
<pre class="code">sub lval() { | |
Proxy.new( | |
FETCH => method () { ...}, | |
STORE => method ($new) { ... } | |
) | |
} | |
</pre> | |
<p>This makes <span class="code">lval</span> a left-value sub. Whenever the value is requested, the <span class="code">FETCH</span> method is called. And whenever it is used in an assignment, the <span class="code">STORE</span> method is called.</p> | |
<p>For arrays and hashes (objects that do the <span class="code">Positional</span> and/or <span class="code">Associative</span> role), one only needs to provide the methods that these roles require to get the functionality that <span class="code">tie</span> provides in Perl. These are documented in the <span class="code">Subscripts</span> section.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5tie.pod6"><span class="code">P5tie</span></a> which exports <span class="code">tie</span> / <span class="code">tied</span> functions that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.154"></a> <h2 id="_language_5to6-perlfunc.pod6-time"><a name="180"></a>time</h2> | |
<ul><li><p>time</p> | |
</li></ul> <p>Number of seconds since epoch (as an <span class="code">Int</span>), same as in Perl.</p> | |
<a name="t4.3.155"></a> <h2 id="_language_5to6-perlfunc.pod6-times"><a name="181"></a>times</h2> | |
<ul><li><p>times</p> | |
</li></ul> <p>Not available in Raku.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5times.pod6"><span class="code">P5times</span></a> which exports a <span class="code">times</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.156"></a> <h2 id="_language_5to6-perlfunc.pod6-tr///"><a name="182"></a>tr///</h2> | |
<ul><li><p>tr///</p> | |
</li></ul> <p>Works similarly to how it does in Perl. 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 Raku, <span class="code">tr///</span> has a method version, called <a href="#_routine_trans.pod6">trans</a>, which offers a few additional features.</p> | |
<p>Perl's <span class="code">/r</span> flag is instead implemented as <span class="code">TR///</span> operator. The <span class="code">y///</span> equivalent does not exist.</p> | |
<a name="t4.3.157"></a> <h2 id="_language_5to6-perlfunc.pod6-truncate"><a name="183"></a>truncate</h2> | |
<ul><li><p>truncate FILEHANDLE, LENGTH</p> | |
</li></ul> <ul><li><p>truncate EXPR, LENGTH</p> | |
</li></ul> <p>Not currently implemented (2018.04).</p> | |
<a name="t4.3.158"></a> <h2 id="_language_5to6-perlfunc.pod6-uc"><a name="184"></a>uc</h2> | |
<ul><li><p>uc EXPR</p> | |
</li></ul> <p>Works as a function and a method. <span class="code">uc("ha")</span> and <span class="code">"ha".uc</span> both return "HA". There is no support for the parameterless version.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5lc.pod6"><span class="code">P5lc</span></a> which exports a <span class="code">uc</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.159"></a> <h2 id="_language_5to6-perlfunc.pod6-ucfirst"><a name="185"></a>ucfirst</h2> | |
<ul><li><p>ucfirst EXPR</p> | |
</li></ul> <ul><li><p>ucfirst</p> | |
</li></ul> <p>Raku has done away with <span class="code">ucfirst</span>. The title case function <a href="#_routine_tc.pod6"><span class="code">tc</span></a> or <a href="#_routine_tclc.pod6"><span class="code">tclc</span></a> probably does what you need; in the first case, it does "title case", which might correspond to different characters in different alphabets; it defaults to upper case if there's no title case mapping. On the other hand, <span class="code">tclc</span> applies <span class="code">tc</span> and then puts the rest of the characters in lower case.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5lcfirst.pod6"><span class="code">P5lcfirst</span></a> which exports a <span class="code">ucfirst</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.160"></a> <h2 id="_language_5to6-perlfunc.pod6-undef"><a name="186"></a>undef</h2> | |
<ul><li><p>undef EXPR</p> | |
</li></ul> <p>There is no <span class="code">undef</span> in Raku. You can't undefine a function, and the closest equivalent value is probably <span class="code">Nil</span>, but you'll likely have no use for that.</p> | |
<p>If you were using something like <span class="code">(undef, $file, $line) = caller;</span>, you would just get the filename and line number directly in Raku instead of discarding the first result of <span class="code">caller</span>. <span class="code">caller</span> has been replaced by <span class="code">callframe</span> in Raku, so the equivalent statement would be <span class="code">($file, $line) = callframe.annotations<file line>;</span></p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5defined.pod6"><span class="code">P5defined</span></a> which exports an <span class="code">undef</span> function that mimics the original Perl behavior as much as possible.</p> | |
Add a note here about Type-based undefined values. | |
<a name="t4.3.161"></a> <h2 id="_language_5to6-perlfunc.pod6-unlink"><a name="187"></a>unlink</h2> | |
<ul><li><p>unlink LIST</p> | |
</li></ul> <p>Still available. Usable as a method: <span class="code">"filename".IO.unlink</span></p> | |
<ul><li><p>unlink</p> | |
</li></ul> <p>The zero argument (implicit <span class="code">$_</span>) version of unlink is not available in Raku.</p> | |
<a name="t4.3.162"></a> <h2 id="_language_5to6-perlfunc.pod6-unpack"><a name="188"></a>unpack</h2> | |
<ul><li><p>unpack TEMPLATE, EXPR</p> | |
</li></ul> <ul><li><p>unpack TEMPLATE</p> | |
</li></ul> <p>Available in Raku when <span class="code">use experimental :pack</span> has been specified in the scope where <span class="code">unpack</span> needs to be called. The template options are currently more restricted than they are in Perl. The current documented list can be found at <a href="#_routine_unpack.pod6">unpack</a>.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5pack.pod6"><span class="code">P5pack</span></a> which exports an <span class="code">unpack</span> function that mimics the original Perl behavior as much as possible and which has a bigger set of supported features than the experimental Raku version.</p> | |
<a name="t4.3.163"></a> <h2 id="_language_5to6-perlfunc.pod6-unshift"><a name="189"></a>unshift</h2> | |
<ul><li><p>unshift ARRAY, LIST</p> | |
</li></ul> <ul><li><p>unshift EXPR, LIST</p> | |
</li></ul> <p>Works as in Perl, as well as being available as a method: <span class="code">@a.unshift("foo");</span>. <i>Note:</i> the flattening behavior is different in Raku: <span class="code">@b.unshift: @a</span> will unshift <span class="code">@a</span> into <span class="code">@b</span> as a single element. See also the <a href="#_type_Array.pod6-routine_prepend">prepend method</a>.</p> | |
<p>Also note that <span class="code">unshift</span> in Raku returns the array to which was pushed, contrary to Perl where it returns the new number of elements.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5shift.pod6"><span class="code">P5shift</span></a> which exports an <span class="code">unshift</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.164"></a> <h2 id="_language_5to6-perlfunc.pod6-untie"><a name="190"></a>untie</h2> | |
<ul><li><p>untie VARIABLE</p> | |
</li></ul> <p>Not supported in Raku, but see <a href="#_language_5to6-perlfunc.pod6-tie">tie</a> for the whole story.</p> | |
<p>The Raku ecosystem has a module <a href="#_routine_https:__modules.raku.org_dist_P5tie.pod6"><span class="code">P5tie</span></a> which exports an <span class="code">untie</span> function that mimics the original Perl behavior as much as possible.</p> | |
<a name="t4.3.165"></a> <h2 id="_language_5to6-perlfunc.pod6-use"><a name="191"></a>use</h2> | |
<ul><li><p>use Module VERSION LIST</p> | |
</li></ul> <ul><li><p>use Module VERSION</p> | |
</li></ul> <ul><li><p>use Module LIST</p> | |
</li></ul> <ul><li><p>use Module</p> | |
</li></ul> <ul><li><p>use VERSION</p> | |
</li></ul> <p>In Perl, this requires a minimum version of the perl executable in order to run. In Raku, this requires a version of the specification, (e.g. <span class="code">6.c</span>), which can be implemented by various Raku executables.</p> | |
<a name="t4.3.166"></a> <h2 id="_language_5to6-perlfunc.pod6-utime"><a name="192"></a>utime</h2> | |
<ul><li><p>utime LIST</p> | |
</li></ul> <p>No equivalent.</p> | |
<a name="t4.3.167"></a> <h2 id="_language_5to6-perlfunc.pod6-values"><a name="193"></a>values</h2> | |
<ul><li><p>values HASH</p> | |
</li></ul> <ul><li><p>values ARRAY</p> | |
</li></ul> <ul><li><p>values EXPR</p> | |
</li></ul> <p>Available in Raku. Can also be used as a method. <span class="code">values %hash</span> is equivalent to <span class="code">%hash.values</span>.</p> | |
<a name="t4.3.168"></a> <h2 id="_language_5to6-perlfunc.pod6-vec"><a name="194"></a>vec</h2> | |
<ul><li><p>vec EXPR, OFFSET, BITS</p> | |
</li></ul> <p>There is no support for vec() in Raku.</p> | |
<p>S29 says "Should replace <span class="code">vec</span> with declared buffer/array of <span class="code">bit</span>, <span class="code">uint2</span>, <span class="code">uint4</span>, etc." Support for <span class="code">bit</span>, <span class="code">uint2</span>, <span class="code">uint4</span> has not landed yet. But support for <span class="code">uint8</span>, <span class="code">int8</span>, <span class="code">uint16</span>, <span class="code">int16</span>, <span class="code">uint32</span>, <span class="code">int32</span>, <span class="code">uint64</span>, <span class="code">int64</span> as well as the system sized <span class="code">uint</span> and <span class="code">int</span> <b>have</b> landed. In scalar forms, as well as in array and shaped array (aka matrix) forms.</p> | |
<a name="t4.3.169"></a> <h2 id="_language_5to6-perlfunc.pod6-wait"><a name="195"></a>wait</h2> | |
<ul><li><p>wait</p> | |
</li></ul> <p>[NEEDS FURTHER RESEARCH] Unclear where this has gone. There's a <span class="code">wait</span> method in <span class="code">Supply</span>, and an <span class="code">await</span> method in both <span class="code">Channel</span> and <span class="code">Promise</span>. Which, if any or all, of these is a direct equivalent of Perl's <span class="code">wait</span> is unclear.</p> | |
<a name="t4.3.170"></a> <h2 id="_language_5to6-perlfunc.pod6-waitpid"><a name="196"></a>waitpid</h2> | |
<ul><li><p>waitpid PID, FLAGS</p> | |
</li></ul> <p>As with <span class="code">wait</span>, the disposition of this is unclear.</p> | |
<a name="t4.3.171"></a> <h2 id="_language_5to6-perlfunc.pod6-wantarray"><a name="197"></a>wantarray</h2> | |
<ul><li><p>wantarray</p> | |
</li></ul> <p>There is no <span class="code">wantarray</span> in Raku; however, there are very easy ways to cover many of the use cases which wantarray filled.</p> | |
<p>First, since Raku does not need special reference syntax to contain a <span class="code">List</span> or <span class="code">Array</span> in a <span class="code">Scalar</span>, simply returning a list may be all that is needed:</p> | |
<pre class="code">sub listofstuff { | |
return 1, 2, 3; | |
} | |
my $a = listofstuff(); | |
print $a; # prints "123" | |
print join("<", listofstuff()) # prints "1<2<3"</pre> | |
<p>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 <span class="code">.Str</span> method for this purpose:</p> | |
<pre class="code">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"</pre> | |
<p>In the above example, the returned list may be lazy, and the <span class="code">.Str</span> method is not called until stringification happens, so no extra work is done to generate something which is not asked for.</p> | |
<p>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 Raku not to do so, even more so because <i>void</i> context does not exist in Raku, with the closest equivalent being <i>sink</i> context, since users can quite easily turn any copy-producing method into a mutator using the <span class="code">.=</span> operator:</p> | |
<pre class="code">my $a = "foo\n"; | |
$a.ords.say; # says "(102 111 111 10)" | |
$a .= chomp; | |
$a.ords.say; # says "(102 111 111)"</pre> | |
<p>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 <span class="code">.sink</span> method, which will be called when the result finds itself in sink context. There are some caveats however, so again, this is not advised:</p> | |
<pre class="code">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"</pre> | |
<a name="t4.3.172"></a> <h2 id="_language_5to6-perlfunc.pod6-warn"><a name="198"></a>warn</h2> | |
<ul><li><p>warn LIST</p> | |
</li></ul> <p><span class="code">warn</span> throws a resumable exception. To simply print a message to <span class="code">$*ERR</span>, you would use the <span class="code">note</span> function. For more on exceptions, see <a href="#_language_exceptions.pod6">Exceptions</a>.</p> | |
<a name="t4.3.173"></a> <h2 id="_language_5to6-perlfunc.pod6-write"><a name="199"></a>write</h2> | |
<ul><li><p>write FILEHANDLE</p> | |
</li></ul> <ul><li><p>write EXPR</p> | |
</li></ul> <ul><li><p>write</p> | |
</li></ul> <p>Formats are gone from Raku, so this no longer works.</p> | |
<a name="t4.3.174"></a> <h2 id="_language_5to6-perlfunc.pod6-y///"><a name="200"></a>y///</h2> | |
<ul><li><p>y///</p> | |
</li></ul> <p>This synonym for <span class="code">tr///</span> is gone. For functionality, see the entry for <span class="code">tr///</span>.</p> | |
</div> | |
<!-- /language/5to6-perlop.pod6 --><div class="pod-body"><a id="_language_5to6-perlop.pod6"></a><a name="t5"></a><h1 class="title">5 Perl to Raku guide - operators</h1> <p class="subtitle">Operators in Perl to Raku: equivalencies and variations</p> <a name="t5.1"></a> <h1 id="_language_5to6-perlop.pod6-DESCRIPTION">DESCRIPTION</h1> | |
<p>A (hopefully) comprehensive list of Perl operators with their Raku equivalents with notes on variations between them where necessary.</p> | |
<a name="t5.2"></a> <h1 id="_language_5to6-perlop.pod6-NOTE">NOTE</h1> | |
<p>This document <i>does not</i> explain the operators in detail. This document is an attempt to guide you from the operators in Perl's <span class="code">perlop</span> document to their equivalents in Raku. For full documentation on the Raku equivalents, please see the <a href="#_language_operators.pod6">Raku documentation</a>.</p> | |
<a name="t5.2.1"></a> <h2 id="_language_5to6-perlop.pod6-Operator_precedence_and_associativity">Operator precedence and associativity</h2> | |
<p>The operator precedence table is somewhat different in Raku than it is in Perl, so it will not be detailed here. If you need to know the precedence and associativity of a given operator in Raku, refer to <a href="#_language_operators.pod6-Operator_precedence">Operator Precedence</a>.</p> | |
<a name="t5.2.2"></a> <h2 id="_language_5to6-perlop.pod6-Terms_and_list_operators">Terms and list operators</h2> | |
<p>The things listed in Perl's <span class="code">perlop</span> document as unary and list operators in this section tend to be things that can also be thought of as functions, such as <span class="code">print</span> and <span class="code">chdir</span>. As such, you can find information about them in the <a href="#_language_5to6-perlfunc.pod6">functions</a> guide. Parentheses are still used for grouping. There is one caveat: in Raku, it's the <span class="code">,</span> (comma) that creates lists, <b>not</b> parentheses. So:</p> | |
<pre class="code">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 | |
</pre> | |
<a name="t5.2.3"></a> <h2 id="_language_5to6-perlop.pod6-The_arrow_operator">The arrow operator</h2> | |
<p>As you typically will not be using references in Raku, 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's <span class="code">$arrayref->[7] </span> becomes <span class="code">$arrayref.[7]</span> in Raku and, similarly, <span class="code">$user->name </span> becomes <span class="code">$user.name</span>. The <span class="code">=> </span> arrow is used for constructing Pairs, see <a href="#_language_terms.pod6-Pair">Pair term documentation</a>.</p> | |
<a name="t5.2.4"></a> <h2 id="_language_5to6-perlop.pod6-Auto-increment_and_auto-decrement">Auto-increment and auto-decrement</h2> | |
<p>Work as in Perl. The one possible caveat is that they function by calling the <span class="code">succ</span> method for <span class="code">++</span> and the <span class="code">pred</span> method for <span class="code">--</span>. For builtin numeric types, this is unlikely to do something unusual, but custom types can define their own <span class="code">succ</span> and <span class="code">pred</span> methods, so in those cases, you should probably take note of what <span class="code">++</span> and <span class="code">--</span> will <i>actually</i> do.</p> | |
<a name="t5.2.5"></a> <h2 id="_language_5to6-perlop.pod6-Exponentiation">Exponentiation</h2> | |
<p>Works as you would expect. The caveat in Perl's perlop about <span class="code">**</span> binding more tightly than unary minus (i. e. "-2**4" evaluates as "-(2**4)" rather than "(-2)**4)") is also true for Raku.</p> | |
<a name="t5.2.6"></a> <h2 id="_language_5to6-perlop.pod6-Symbolic_unary_operators">Symbolic unary operators</h2> | |
<p>As in Perl, unary <span class="code">!</span> and <span class="code">-</span> do logical and arithmetic negation, respectively. <span class="code">?^</span> is used for bitwise logical negation, which the documentation indicates is equivalent to <span class="code">!</span>. It may be relevant to note that these coerce their arguments to <span class="code">Bool</span> and <span class="code">Numeric</span>, respectively.</p> | |
<p>Unary <span class="code">~</span> is the string context operator in Raku, so use prefix <span class="code">+^</span> for bitwise integer negation. Assumes two's complement.</p> | |
<p><span class="code">+</span> <i>does</i> have an effect in Raku, coercing its argument to the Numeric type.</p> | |
<p>Unary <span class="code">\</span> is no more. If you really want to take a "reference" to an existing named variable, you can use item context, like so: <span class="code">$aref = item(@array)</span>, or maybe more familiarly by prefixing with a <span class="code">$</span>: <span class="code">$aref = $@array</span>. Please note that you're not really getting a reference, but a scalar container with the referenced object in it.</p> | |
<p>You can get a "reference" to a named subroutine by using the <span class="code">&</span> sigil: <span class="code">$sref = &foo</span>. Anonymous arrays, hashes, and subs return the underlying object during creation <i>right away</i>: <span class="code">$sref = sub { }</span>.</p> | |
<a name="t5.2.7"></a> <h2 id="_language_5to6-perlop.pod6-Binding_operators">Binding operators</h2> | |
<p><span class="code">=~</span> and <span class="code">!~</span> have been replaced by <span class="code">~~</span> and <span class="code">!~~</span>, respectively. Those of you who consider smartmatching broken in Perl will be happy to hear that it works much better in Raku, as the stronger typing means less guesswork. See <a href="#_language_operators.pod6-index-entry-smartmatch_operator">the smartmatch documentation</a> for a more extensive explanation of how smartmatch works in Raku.</p> | |
<a name="t5.2.8"></a> <h2 id="_language_5to6-perlop.pod6-Multiplicative_operators">Multiplicative operators</h2> | |
<p>Binary <span class="code">*</span>, <span class="code">/</span>, and <span class="code">%</span> do multiplication, division, and modulo, respectively, as in Perl.</p> | |
<p>Binary <span class="code">x</span> is slightly different in Raku, and has a companion. <span class="code">print '-' x 80;</span> gives you a string of 80 dashes, but for the Perl behavior of <span class="code">@ones = (1) x 80;</span> giving you a list of 80 "1"s, you would use <span class="code">@ones = 1 xx 80;</span>.</p> | |
<a name="t5.2.9"></a> <h2 id="_language_5to6-perlop.pod6-Additive_operators">Additive operators</h2> | |
<p>Binary <span class="code">+</span> and <span class="code">-</span> do addition and subtraction, respectively, as you would expect.</p> | |
<p>As <span class="code">.</span> is the method call operator, so binary <span class="code">~</span> acts as the concatenation operator in Raku.</p> | |
<a name="t5.2.10"></a> <h2 id="_language_5to6-perlop.pod6-Shift_operators">Shift operators</h2> | |
<p><span class="code"><< </span> and <span class="code">>> </span> have been replaced by <span class="code">+< </span> and <span class="code">+> </span>.</p> | |
<a name="t5.2.11"></a> <h2 id="_language_5to6-perlop.pod6-Named_unary_operators">Named unary operators</h2> | |
<p>As noted above, you'll find these in the <a href="#_language_5to6-perlfunc.pod6">functions</a> guide.</p> | |
<a name="t5.2.12"></a> <h2 id="_language_5to6-perlop.pod6-Relational_operators">Relational operators</h2> | |
<p>These all work as in Perl.</p> | |
<a name="t5.2.13"></a> <h2 id="_language_5to6-perlop.pod6-Equality_operators">Equality operators</h2> | |
<p><span class="code">==</span> and <span class="code">!=</span> both work as in Perl.</p> | |
<p><span class="code"><=> </span> and <span class="code">cmp</span> have different behavior in Raku. <span class="code"><=> </span> does a numeric comparison, but returns <span class="code">Order::Less</span>, <span class="code">Order::Same</span>, or <span class="code">Order::More</span> instead of Perl's <span class="code">-1</span>, <span class="code">0</span>, or <span class="code">1</span>. To get the Perl behavior (with the change that it returns the <span class="code">Order</span> objects, rather than integers) of <span class="code">cmp</span>, you would use the <span class="code">leg</span> operator.</p> | |
<p><span class="code">cmp</span> does either <span class="code"><=> </span> or <span class="code">leg</span>, depending on the existing type of its arguments.</p> | |
<p><span class="code">~~</span> is the smartmatch operator as in Perl, but it's also <i>just</i> the match operator in Raku, as noted above. For how smartmatching works in Raku, see <a href="#_language_operators.pod6-index-entry-smartmatch_operator">the smartmatch documentation</a>.</p> | |
<a name="t5.2.14"></a> <h2 id="_language_5to6-perlop.pod6-Smartmatch_operator">Smartmatch operator</h2> | |
<p>See <a href="#_language_operators.pod6-index-entry-smartmatch_operator">the smartmatch documentation</a> for a more extensive explanation of how smartmatch works in Raku.</p> | |
<a name="t5.2.15"></a> <h2 id="_language_5to6-perlop.pod6-Bitwise_And">Bitwise And</h2> | |
<p>Binary <span class="code">&</span> is <span class="code">+&</span> in Raku.</p> | |
<a name="t5.2.16"></a> <h2 id="_language_5to6-perlop.pod6-Bitwise_Or_and_Exclusive_Or">Bitwise Or and Exclusive Or</h2> | |
<p>Bitwise OR has changed from <span class="code">|</span> in Perl to <span class="code">+|</span> in Raku. Similarly, bitwise XOR <span class="code">^</span> is <span class="code">+^</span>, except this operates on integers.</p> | |
<a name="t5.2.17"></a> <h2 id="_language_5to6-perlop.pod6-C-style_Logical_And">C-style Logical And</h2> | |
<p>Unchanged.</p> | |
<a name="t5.2.18"></a> <h2 id="_language_5to6-perlop.pod6-C-style_Logical_Or">C-style Logical Or</h2> | |
<p>Unchanged.</p> | |
<a name="t5.2.19"></a> <h2 id="_language_5to6-perlop.pod6-Logical_Defined-Or">Logical Defined-Or</h2> | |
<p>Remains in Raku as <span class="code">//</span>. Returns the first defined operand, or else the last operand. Also, there is a low precedence version, called <span class="code">orelse</span>.</p> | |
<a name="t5.2.20"></a> <h2 id="_language_5to6-perlop.pod6-Range_operators">Range operators</h2> | |
<p>In list context, <span class="code">..</span> 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:</p> | |
<ul><li><p>infix <span class="code">..^</span> which excludes the endpoint;</p> | |
</li></ul> <ul><li><p>infix ^.. which excludes the starting point;</p> | |
</li></ul> <ul><li><p>infix <span class="code">^..^</span> which excludes both the starting and ending points;</p> | |
</li></ul> <ul><li><p>prefix <span class="code">^</span> which starts from zero excluding the endpoint.</p> | |
</li></ul> <p>The following example shows the effects of all the above range operators (please note parentheses are used only to allow the method call):</p> | |
<pre class="code">(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) | |
</pre> | |
<p>In Perl, in scalar context, the operators <span class="code">..</span> and <span class="code">...</span> work as flip-flop operators, even if they are little-known and probably less used. Those operators have been replaced in Raku by <a href="#_routine_ff.pod6">ff</a> and <a href="#_routine_fff.pod6">fff</a> respectively.</p> | |
<a name="t5.2.21"></a> <h2 id="_language_5to6-perlop.pod6-Conditional_operator">Conditional operator</h2> | |
<p>The conditional operator <span class="code">? :</span> has been replaced by <span class="code">?? !!</span>:</p> | |
<pre class="code">$x = $ok ? $yes : $no; # Perl | |
</pre> | |
<pre class="code">$x = $ok ?? $yes !! $no; # Raku | |
</pre> | |
<a name="t5.2.22"></a> <h2 id="_language_5to6-perlop.pod6-Assignment_operators">Assignment operators</h2> | |
<p>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 <span class="code">.=</span> calls a mutating method on the object on the left (which can also be a type-object). This allows for the following useful idiom:</p> | |
<pre class="code">class LongClassName { | |
has $.frobnicate; | |
} | |
my LongClassName $bar .= new( frobnicate => 42 ); # no need to repeat class name | |
</pre> | |
<p>This ensures that <span class="code">$bar</span> will only be able to contain a <span class="code">LongClassName</span> object, as well not having to repeat (and possibly misspell) the class name.</p> | |
<p><span class="code">~=</span> is the string concatenation assignment, as you might expect with the changes in <span class="code">.</span> and <span class="code">~</span>. Also, the bitwise assignment operators are likely not separated into numeric and string versions (<span class="code">&=</span>, etc., vs. <span class="code">&.=</span>, etc.), as that feature is currently experimental in Perl itself - although, again, this is not specifically documented.</p> | |
<a name="t5.2.23"></a> <h2 id="_language_5to6-perlop.pod6-Comma_operator">Comma operator</h2> | |
<p>The comma operator works mostly as expected, but technically it creates <a href="#_type_List.pod6">Lists</a>) or separates arguments in function calls. Also, there is a <span class="code">:</span> variant that turns function calls into method calls - see <a href="#_language_operators.pod6-infix_%3A">this page</a>.</p> | |
<p>The <span class="code">=> </span> operator, or <i>fat arrow</i>, works similarly to the Perl "fat comma" in that it allows an unquoted (ordinary) identifier on its left side, but in Raku constructs <a href="#_type_Pair.pod6">Pair</a> objects, rather than just functioning as a separator. If you are trying to just literally translate a line of Perl code to Raku, it should behave as expected. To read Raku, take a look at <a href="#_language_glossary.pod6-Adverbial_pair">Adverbial Pair</a> which will explain a new syntax.</p> | |
<a name="t5.2.24"></a> <h2 id="_language_5to6-perlop.pod6-List_operators_(rightward)">List operators (rightward)</h2> | |
<p>Like the Named Unary Operators, you'll find these discussed under <a href="#_language_5to6-perlfunc.pod6">Functions</a>.</p> | |
<a name="t5.2.25"></a> <h2 id="_language_5to6-perlop.pod6-Logical_Not">Logical Not</h2> | |
<p>The lower precedence version of <span class="code">!</span>. As with <span class="code">!</span>, coerces its argument to <span class="code">Bool</span>.</p> | |
<a name="t5.2.26"></a> <h2 id="_language_5to6-perlop.pod6-Logical_And">Logical And</h2> | |
<p>Lower precedence version of <span class="code">&&</span> as in Perl.</p> | |
<a name="t5.2.27"></a> <h2 id="_language_5to6-perlop.pod6-Logical_or_and_Exclusive_Or">Logical or and Exclusive Or</h2> | |
<p><span class="code">or</span> is the low precedence version of <span class="code">||</span>, and <span class="code">xor</span> is the low precedence version of <span class="code">^^</span>.</p> | |
<p>Additionally, there is a low precedence version of <span class="code">//</span>, called <span class="code">orelse</span>.</p> | |
<a name="t5.2.28"></a> <h2 id="_language_5to6-perlop.pod6-Quote_and_quote-like_operators">Quote and quote-like operators</h2> | |
<p>For all the gory details on quoting constructs, see <a href="#_language_quoting.pod6">quoting</a>.</p> | |
<p>There is a quoting operator that allows absolute literal strings: <span class="code">Q</span> or <span class="code">「…」</span>, although the latter might be difficult to find on your keyboard, depending on your keyboard... Backslash escapes do <i>not</i> apply in <span class="code">Q</span> quoted strings. E. g. <span class="code">Q{This is still a closing curly brace → \}</span> renders "This is still a closing curly brace → \".</p> | |
<p><span class="code">q</span> does what you expect, allowing backslash escapes. E. g. <span class="code">q{This is not a closing curly brace → \}, but this is → }</span> returning "This is not a closing curly brace → }, but this is →". As in Perl, you can get this behavior with single quotes.</p> | |
<p><span class="code">qq</span> 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 <a href="#_language_subscripts.pod6-index-entry-Zen_slices">zen-slice</a>) to get them to interpolate. E.g. <span class="code">@a = <1 2 3>; say qq/@a[] [email protected]/; </span> results in "1 2 3 [email protected]". Hashes interpolate in the same manner: <span class="code">%a = 1 => 2, 3 => 4;say "%a{}"; </span> 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 <span class="code">Pair</span>s, and a hash acts as list of <span class="code">Pair</span>s when stringified). You can also interpolate Raku code in strings using curly braces. For all the details, see <a href="#_language_quoting.pod6-Interpolation%3A_qq">Interpolation</a>.</p> | |
<p><span class="code">qw</span> works as in Perl, and can also be rendered as <span class="code"><...> </span>. E. g. <span class="code">qw/a b c/</span> is equivalent to <span class="code"><a b c> </span>.</p> | |
<p>There is also a version of <span class="code">qw</span> that interpolates, which is <span class="code">qqw</span>. So <span class="code">my $a = 42;say qqw/$a b c/;</span> gives you "42 b c".</p> | |
<p>Shell quoting is available through <span class="code">qx</span>, but you should note that backticks do not do shell quoting as in Perl, and Perl variables are <i>not</i> interpolated in <span class="code">qx</span> strings. If you need to interpolate Perl variables in a shell command string, you can use <span class="code">qqx</span> instead.</p> | |
<p>The <span class="code">qr</span> operator is gone from Raku.</p> | |
<p><span class="code">tr///</span> works similarly to how it does in Perl. 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. <span class="code">tr///</span> has a method version, which is better documented, called <span class="code">.trans</span>. <span class="code">.trans</span> uses a list of pairs, as follows: <span class="code">$x.trans(['a'..'c'] => ['A'..'C'], ['d'..'q'] => ['D'..'Q'], ['r'..'z'] => ['R'..'Z']); </span> A much more extensive description of the uses of <span class="code">.trans</span> can be found at <a href="#_routine_https:__design.raku.org_S05.html.pod6-Transliteration">https://design.raku.org/S05.html#Transliteration</a>. The <span class="code">y///</span> equivalent has been done away with.</p> | |
<p>Heredocs are specified differently in Raku. You use <span class="code">:to</span> with your quoting operator, e. g. <span class="code">q:to/END/;</span> would start a heredoc ending with "END". Similarly, you get escaping and interpolation based on your quoting operator, i. e. literals with <span class="code">Q</span>, backslash escapes with <span class="code">q</span>, and interpolation with <span class="code">qq</span>.</p> | |
<a name="t5.2.29"></a> <h2 id="_language_5to6-perlop.pod6-I/O_operators">I/O operators</h2> | |
<p>The full details on Input/Output in Raku can be found at <a href="#_language_io.pod6">io</a>.</p> | |
<p>As <span class="code"><...> </span> is the quote-words construct in Raku, <span class="code"><> </span> is not used for reading lines from a file. You can do that by either making an <span class="code">IO</span> object from a file name or using an open filehandle and then, in either case, calling <span class="code">.lines</span> on it. I. e. either <span class="code">my @a = "filename".IO.lines;</span> or <span class="code">my $fh = open "filename", :r;my @a = $fh.lines;</span> (In the latter case, we are using <span class="code">:r</span> to specifically open the file for reading). To do this in an iterative manner, you can use a <span class="code">for</span> loop this way:</p> | |
<pre class="code">for 'huge-csv'.IO.lines -> $line { | |
# Do something with $line | |
} | |
</pre> | |
<p>Note the use of <span class="code">-> </span> there. That's part of the Block syntax, and in Raku is needed for <span class="code">if</span>, <span class="code">for</span>, <span class="code">while</span>, etc.</p> | |
<p>If you want to slurp the entire file into a scalar, you would - surprise! - use the <span class="code">.slurp</span> method. For instance</p> | |
<pre class="code">my $x = "filename".IO.slurp; | |
# ... or ... | |
my $fh = open "filename", :r; | |
my $x = $fh.slurp; | |
</pre> | |
<p>As noted in the <a href="#_language_5to6-perlvar.pod6">Special Variables</a> guide, the <span class="code">ARGV</span> magic input filehandle has been replaced by <span class="code">$*ARGFILES</span>, and the <span class="code">@ARGV</span> array of command line arguments has been replaced by <span class="code">@*ARGS</span>.</p> | |
<a name="t5.2.30"></a> <h2 id="_language_5to6-perlop.pod6-No-ops">No-ops</h2> | |
<p><span class="code">1 while foo();</span> works in the same way as it does in Perl, however it generates a warning. In Raku the idiom is now written as <span class="code">Nil while foo();</span> instead.</p> | |
<a name="t5.2.31"></a> <h2 id="_language_5to6-perlop.pod6-Bitwise_string_operators">Bitwise string operators</h2> | |
<p>Documented individually above, but to summarize...</p> | |
<p>Bitwise integer negation is prefix <span class="code">+^</span>. Bitwise Boolean negation is <span class="code">?^</span>.</p> | |
<p>Bitwise and is <span class="code">+&</span>.</p> | |
<p>Bitwise integer or is <span class="code">+|</span>. Bitwise integer xor is infix <span class="code">+^</span>. Bitwise Boolean or is <span class="code">?|</span>.</p> | |
<p>Left shift and right shift are <span class="code">+< </span> and <span class="code">+> </span>.</p> | |
</div> | |
<!-- /language/5to6-perlsyn.pod6 --><div class="pod-body"><a id="_language_5to6-perlsyn.pod6"></a><a name="t6"></a><h1 class="title">6 Perl to Raku guide - syntax</h1> <p class="subtitle">Syntactic differences between Perl and Raku</p> <p>perlsyn - Perl syntax</p> | |
<a name="t6.1"></a> <h1 id="_language_5to6-perlsyn.pod6-DESCRIPTION">DESCRIPTION</h1> | |
<p>A (hopefully) comprehensive description of the differences between Perl and Raku with regards to the syntax elements described in the perlsyn document.</p> | |
<a name="t6.2"></a> <h1 id="_language_5to6-perlsyn.pod6-NOTE">NOTE</h1> | |
<p>I will <i>not</i> be explaining Raku syntax in detail. This document is an attempt to guide you from how things work in Perl to the equivalents in Raku. For full documentation on the Raku syntax, please see the Raku documentation.</p> | |
<a name="t6.3"></a> <h1 id="_language_5to6-perlsyn.pod6-Free_form">Free form</h1> | |
<p>Raku is still <i>largely</i> free form. However, there are a few instances where the presence or lack of whitespace is now significant. For instance, in Perl, you can omit a space following a keyword (e. g. <span class="code">while($x < 5)</span> or <span class="code">my($x, $y)</span>). In Raku, that space is required, thus <span class="code">while ($x < 5)</span> or <span class="code">my ($x, $y)</span>. In Raku, however, you can omit the parentheses altogether: <span class="code">while $x < 5 </span>. This holds for <span class="code">if</span>, <span class="code">for</span>, etc.</p> | |
<p>Oddly, in Perl, you can leave spaces between an array or hash and its subscript, and before a postfix operator. So <span class="code">$seen {$_} ++</span> is valid. No more. That would now have to be <span class="code">%seen{$_}++</span>.</p> | |
<p>If it makes you feel better, you can use backslashes to "unspace" whitespace, so you can use whitespace where it would otherwise be forbidden.</p> | |
<p>See <a href="#_language_5to6-nutshell.pod6-Whitespace">Whitespace</a> for details.</p> | |
<a name="t6.3.1"></a> <h2 id="_language_5to6-perlsyn.pod6-Declarations">Declarations</h2> | |
<p>As noted in the <a href="#_language_5to6-perlfunc.pod6">Functions</a> guide, there is no <span class="code">undef</span> in Raku. A declared, but uninitialized scalar variable will evaluate to its type. In other words, <span class="code">my $x;say $x;</span> will give you "(Any)". <span class="code">my Int $y;say $y;</span> will give you "(Int)".</p> | |
<a name="t6.3.2"></a> <h2 id="_language_5to6-perlsyn.pod6-Comments">Comments</h2> | |
<p><span class="code">#</span> starts a comment that runs to the end of the line as in Perl.</p> | |
<p>Embedded comments start with a hash character and a backtick (<span class="code">#`</span>), followed by an opening bracketing character, and continue to the matching closing bracketing character. Like so:</p> | |
<pre class="code">if #`( why would I ever write an inline comment here? ) True { | |
say "something stupid"; | |
} | |
</pre> | |
<p>As in Perl, you can use pod directives to create multiline comments, with <span class="code">=begin comment</span> before and <span class="code">=end comment</span> after the comment.</p> | |
<a name="t6.3.3"></a> <h2 id="_language_5to6-perlsyn.pod6-Truth_and_falsehood">Truth and falsehood</h2> | |
<p>The one difference between Perl truth and Raku truth is that, unlike Perl, Raku treats the string <span class="code">"0"</span> as true. Numeric <span class="code">0</span> is still false, and you can use prefix <span class="code">+</span> to coerce string <span class="code">"0"</span> to numeric to get it to be false. Raku, 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.</p> | |
<a name="t6.3.4"></a> <h2 id="_language_5to6-perlsyn.pod6-Statement_modifiers">Statement modifiers</h2> | |
<p>Mostly, statement modifiers still work, with a few exceptions.</p> | |
<p>First, <span class="code">for</span> loops are exclusively what were known in Perl as <span class="code">foreach</span> loops and <span class="code">for</span> is not used for C-style <span class="code">for</span> loops in Raku. To get that behavior, you want <span class="code">loop</span>. <span class="code">loop</span> cannot be used as a statement modifier.</p> | |
<p>In Raku, you cannot use the form <span class="code">do {...} while $x</span>. You will want to replace <span class="code">do</span> in that form with <span class="code">repeat</span>. Similarly for <span class="code">do {...} until $x</span>.</p> | |
<a name="t6.3.5"></a> <h2 id="_language_5to6-perlsyn.pod6-Compound_statements">Compound statements</h2> | |
<p>The big change from Perl is that <span class="code">given</span> is not experimental or disabled by default in Raku. For the details on <span class="code">given</span> see <a href="#_language_control.pod6-given">this page</a>.</p> | |
<a name="t6.3.6"></a> <h2 id="_language_5to6-perlsyn.pod6-Loop_control">Loop control</h2> | |
<p><span class="code">next</span>, <span class="code">last</span>, and <span class="code">redo</span> have not changed from Perl to Raku.</p> | |
<p><span class="code">continue</span>, however, does not exist in Raku. You would use a <span class="code">NEXT</span> block in the body of the loop.</p> | |
<pre class="code"># Perl | |
my $str = ''; | |
for (1..5) { | |
next if $_ % 2 == 1; | |
$str .= $_; | |
} | |
continue { | |
$str .= ':' | |
} | |
</pre> | |
<pre class="code"># Raku | |
my $str = ''; | |
for 1..5 { | |
next if $_ % 2 == 1; | |
$str ~= $_; | |
NEXT { | |
$str ~= ':' | |
} | |
} | |
</pre> | |
<a name="t6.3.7"></a> <h2 id="_language_5to6-perlsyn.pod6-For_loops">For loops</h2> | |
<p>As noted above, C-style <span class="code">for</span> loops are not called <span class="code">for</span> loops in Raku. They are just <span class="code">loop</span> loops. To write an infinite loop, you do not need to use the C idiom of <span class="code">loop (;;) {...}</span>, but may just omit the spec completely: <span class="code">loop {...}</span></p> | |
<a name="t6.3.8"></a> <h2 id="_language_5to6-perlsyn.pod6-Foreach_loops">Foreach loops</h2> | |
<p>In Perl, <span class="code">for</span>, in addition to being used for C-style <span class="code">for</span> loops, is a synonym for <span class="code">foreach</span>. In Raku, <span class="code">for</span> is just used for <span class="code">foreach</span> style loops.</p> | |
<a name="t6.3.9"></a> <h2 id="_language_5to6-perlsyn.pod6-Switch_statements">Switch statements</h2> | |
<p>Raku has actual switch statements, provided by <span class="code">given</span> with the individual cases handled by <span class="code">when</span> and <span class="code">default</span>. The basic syntax is:</p> | |
<pre class="code">given EXPR { | |
when EXPR { ... } | |
when EXPR { ... } | |
default { ... } | |
} | |
</pre> | |
<p>The full details can be found <a href="#_language_control.pod6-given">here</a>.</p> | |
<a name="t6.3.10"></a> <h2 id="_language_5to6-perlsyn.pod6-Goto">Goto</h2> | |
<p><span class="code">goto</span> is currently not implemented (yet). Labels <b>are</b> implemented, and can be used as a target for <span class="code">next</span>, <span class="code">last</span> and <span class="code">redo</span>:</p> | |
<pre class="code">FOO: # Labels end with colons, like in Perl | |
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 | |
</pre> | |
<p>For what is planned for <span class="code">goto</span>, see <a href="#_routine_https:__design.raku.org_S04.html.pod6-The_goto_statement">https://design.raku.org/S04.html#The_goto_statement</a>.</p> | |
<a name="t6.3.11"></a> <h2 id="_language_5to6-perlsyn.pod6-Ellipsis_statement">Ellipsis statement</h2> | |
<p><span class="code">...</span> (along with <span class="code">!!!</span> and <span class="code">???</span>) are used to create stub declarations. This is a bit more complicated than the use of <span class="code">...</span> in Perl, so you'll probably want to look at <a href="#_routine_https:__design.raku.org_S06.html.pod6-Stub_declarations">https://design.raku.org/S06.html#Stub_declarations</a> for the gory details. That said, there doesn't seem to be an <i>obvious</i> reason why it shouldn't still fulfill the role it did in Perl, despite its role being expanded in Raku.</p> | |
<a name="t6.3.12"></a> <h2 id="_language_5to6-perlsyn.pod6-PODs:_embedded_documentation">PODs: embedded documentation</h2> | |
<p>Pod has changed between Perl and Raku. Probably the biggest difference is that you need to enclose your pod between <span class="code">=begin pod</span> and <span class="code">=end pod</span> 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 <span class="code">X<> </span> codes, and it's not clear how to get a literal "|" into them. Your best bet may be to use the Raku interpreter to check your pod. You can do this by using the <span class="code">--doc</span> switch. E. g. <span class="code">raku --doc Whatever.pod</span>. This will output any problems to standard error. (Depending on how/where you've installed <span class="code">raku</span>, you may need to specify the location of <span class="code">Pod::To::Text</span>.) Details on Raku-style pod is at <a href="#_routine_https:__design.raku.org_S26.html.pod6">https://design.raku.org/S26.html</a>.</p> | |
</div> | |
<!-- /language/5to6-perlvar.pod6 --><div class="pod-body"><a id="_language_5to6-perlvar.pod6"></a><a name="t7"></a><h1 class="title">7 Perl to Raku guide - special variables</h1> <p class="subtitle">A comparison of special variables in Perl and Raku</p> <a name="t7.1"></a> <h1 id="_language_5to6-perlvar.pod6-DESCRIPTION">DESCRIPTION</h1> | |
<p>A (hopefully) comprehensive list of Perl Special Variables with their Raku equivalents with notes on variations between them where necessary.</p> | |
<a name="t7.2"></a> <h1 id="_language_5to6-perlvar.pod6-NOTE">NOTE</h1> | |
<p>This document is an attempt to guide the reader from the <i>Special Variables</i> in Perl to their equivalents in Raku. For full documentation on the Raku <i>Special Variables</i>, please see the Raku documentation for each of them.</p> | |
<a name="t7.3"></a> <h1 id="_language_5to6-perlvar.pod6-SPECIAL_VARIABLES">SPECIAL VARIABLES</h1> | |
<p><a id="i201" name="Other languages Special Variables (Perl)"></a><span class="indexed"></span></p> | |
<a name="t7.3.1"></a> <h2 id="_language_5to6-perlvar.pod6-General_variables">General variables</h2> | |
<a name="t7.3.1.1"></a> <h3 id="_language_5to6-perlvar.pod6-$ARG,_$_"><a name="202"></a>$ARG, $_</h3> | |
<p>Thankfully, <span class="code">$_</span> is the general default variable as in Perl. The main difference in Raku is that you can now call methods on it. For instance, Perl's <span class="code">say $_</span> can be rendered in Raku as <span class="code">$_.say</span>. 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 <span class="code">.say</span>.</p> | |
<a name="t7.3.1.2"></a> <h3 id="_language_5to6-perlvar.pod6-@ARG,_@_"><a name="203"></a>@ARG, @_</h3> | |
<p>As Raku now has function signatures, your arguments can go there, rather than depending on <span class="code">@_</span> for them. In fact, if you use a function signature, use of <span class="code">@_</span> will spit at you telling it cannot override an existing signature.</p> | |
<p>If, however, you do not use a function signature, <span class="code">@_</span> will contain the arguments you pass to the function as it did in Perl. Again, as with <span class="code">$_</span>, you can call methods on it. Unlike <span class="code">$_</span> you cannot assume <span class="code">@_</span> as the default variable for those methods to operate on (i. e. <span class="code">@_.shift</span> works, <span class="code">.shift</span> does not).</p> | |
<a name="t7.3.1.3"></a> <h3 id="_language_5to6-perlvar.pod6-$LIST_SEPARATOR,_$""><a name="204"></a>$LIST_SEPARATOR, $"</h3> | |
<p>Currently, there is no equivalent of the List Separator variable in Raku. Design document <a href="#_routine_https:__design.raku.org_S28.html.pod6">S28</a> says there isn't one, so you probably don't want to hold your breath.</p> | |
<a name="t7.3.1.4"></a> <h3 id="_language_5to6-perlvar.pod6-$PROCESS_ID,_$PID,_$$"><a name="205"></a>$PROCESS_ID, $PID, $$</h3> | |
<p><span class="code">$$</span> is replaced in Raku by <span class="code">$*PID</span></p> | |
<a name="t7.3.1.5"></a> <h3 id="_language_5to6-perlvar.pod6-$PROGRAM_NAME,_$0"><a name="206"></a>$PROGRAM_NAME, $0</h3> | |
<p>You can access the program name in Raku via <span class="code">$*PROGRAM-NAME</span>.</p> | |
<p>Note: <span class="code">$0</span> in Raku is the variable holding the first captured value from a regexp match (i. e. capture variables now start from <span class="code">$0</span> rather than <span class="code">$1</span>).</p> | |
<a name="t7.3.1.6"></a> <h3 id="_language_5to6-perlvar.pod6-$REAL_GROUP_ID,_$GID,_$(">$REAL_GROUP_ID, $GID, $(</h3> | |
<p>In Raku the group information is handled by <span class="code">$*GROUP</span>, which holds an object of type <a href="#_type_IntStr.pod6">IntStr</a> and therefore can be used either within a string or a numeric context. The group id is therefore obtained via <span class="code">+$*GROUP</span>, while the group name via <span class="code">~$*GROUP</span>.</p> | |
<a name="t7.3.1.7"></a> <h3 id="_language_5to6-perlvar.pod6-$EFFECTIVE_GROUP_ID,_$EGID,_$)">$EFFECTIVE_GROUP_ID, $EGID, $)</h3> | |
<p>The effective group id does not appear to be currently provided by Raku.</p> | |
<a name="t7.3.1.8"></a> <h3 id="_language_5to6-perlvar.pod6-$REAL_USER_ID,_$UID,_$<">$REAL_USER_ID, $UID, $<</h3> | |
<p>In Raku the user information is handled by <span class="code">$*USER</span>, which holds an object of type <a href="#_type_IntStr.pod6">IntStr</a> 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 <span class="code">$*GROUP</span> object). The user id is therefore obtained via <span class="code">+$*USER</span>, while the username via <span class="code">~$*USER</span>.</p> | |
<a name="t7.3.1.9"></a> <h3 id="_language_5to6-perlvar.pod6-$EFFECTIVE_USER_ID,_$EUID,_$>">$EFFECTIVE_USER_ID, $EUID, $></h3> | |
<p>The effective user id does not appear to be currently provided by Raku.</p> | |
<a name="t7.3.1.10"></a> <h3 id="_language_5to6-perlvar.pod6-$SUBSCRIPT_SEPARATOR,_$SUBSEP,_$;">$SUBSCRIPT_SEPARATOR, $SUBSEP, $;</h3> | |
<p>The subscript separator variable is not included in Raku. Frankly, if your Perl code is using this, it's almost certainly really, really old.</p> | |
<a name="t7.3.1.11"></a> <h3 id="_language_5to6-perlvar.pod6-$a,_$b">$a, $b</h3> | |
<p><span class="code">$a</span> and <span class="code">$b</span> have no special meaning in Raku. <span class="code">sort()</span> does not use them for anything special. They're just regular old variables.</p> | |
<p>This feature has been extended by having blocks with placeholder parameters which are more versatile. Placeholder variables are created with the <span class="code">^</span> twigil (e. g. <span class="code">$^z</span>. 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 <span class="code">($^q, $^z, $^a)</span>, they will be <i>assigned</i> in the order <span class="code">($^a, $^q, $^z)</span>. Ergo:</p> | |
<pre class="code">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» | |
</pre> | |
<p>For more on placeholder variables, see <a href="#_language_variables.pod6-The_^_twigil">this page</a></p> | |
<a name="t7.3.1.12"></a> <h3 id="_language_5to6-perlvar.pod6-%ENV">%ENV</h3> | |
<p>%ENV has been replaced by %*ENV in Raku. Note that the keys of this hash may not be exactly the same between Perl and Raku. For example, <span class="code">OLDPWD</span> is missing from Raku's %ENV.</p> | |
<a name="t7.3.1.13"></a> <h3 id="_language_5to6-perlvar.pod6-$OLD_PERL_VERSION,_$]">$OLD_PERL_VERSION, $]</h3> | |
<p>The running version of Raku is kept by <span class="code">$*RAKU</span> special variable, that is an object. The running version is retrieved via <span class="code">$*RAKU.version</span>, which returns something like <span class="code">v6.d</span>; the full stringified version of the Raku interpreter is obtained via <span class="code">$*RAKU.gist</span>, which returns something like <span class="code">Raku (6.d)</span>.</p> | |
<a name="t7.3.1.14"></a> <h3 id="_language_5to6-perlvar.pod6-$SYSTEM_FD_MAX,_$^F">$SYSTEM_FD_MAX, $^F</h3> | |
<p>Although the design documents (S28) indicate that this will likely become <span class="code">$*SYS_FD_MAX</span>, this has not yet been implemented.</p> | |
<a name="t7.3.1.15"></a> <h3 id="_language_5to6-perlvar.pod6-@F">@F</h3> | |
<p>[NEEDS FURTHER RESEARCH] A bit confusing at this point. Design doc S28 indicates that <span class="code">@F</span> in Perl is replaced by <span class="code">@_</span> in Raku, but it's unclear just how that works. On the other hand, it's currently something of a moot point, as the Perl to Raku Translation doc indicates that the <span class="code">-a</span> and <span class="code">-F</span> command-line switches are not yet implemented in rakudo.</p> | |
<a name="t7.3.1.16"></a> <h3 id="_language_5to6-perlvar.pod6-@INC"><a name="207"></a>@INC</h3> | |
<p>No longer exists in Raku. 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 Raku.</p> | |
<pre class="code"># Print out a list of compunit repositories | |
.say for $*REPO.repo-chain;</pre> | |
<a name="t7.3.1.17"></a> <h3 id="_language_5to6-perlvar.pod6-%INC"><a name="208"></a>%INC</h3> | |
<p>No longer exists in Raku. 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:</p> | |
<pre class="code">use Test; | |
use MyModule; | |
say flat $*REPO.repo-chain.map(*.loaded); #-> (MyModule Test) | |
</pre> | |
<a name="t7.3.1.18"></a> <h3 id="_language_5to6-perlvar.pod6-$INPLACE_EDIT,_$^I">$INPLACE_EDIT, $^I</h3> | |
<p>S28 suggests $*INPLACE_EDIT, but it does not yet exist.</p> | |
<a name="t7.3.1.19"></a> <h3 id="_language_5to6-perlvar.pod6-$^M">$^M</h3> | |
<p>S28 suggests $*EMERGENCY_MEMORY, but it does not yet exist.</p> | |
<a name="t7.3.1.20"></a> <h3 id="_language_5to6-perlvar.pod6-$OSNAME,_$^O">$OSNAME, $^O</h3> | |
<p>This is somewhat unclear. It probably depends on what you mean by "the name of the operating system" as design document <a href="#_routine_https:__design.raku.org_S28.html.pod6">S28</a> has three different suggestions, all of which give different answers.</p> | |
<p>There are currently three main objects containing information about the "running environment":</p> | |
<ul><li><p><span class="code">$*KERNEL</span> provides information about the running Operating System kernel;</p> | |
</li></ul> <ul><li><p><span class="code">$*DISTRO</span> provides information about the Operating System distribution;</p> | |
</li></ul> <ul><li><p><span class="code">$*VM</span> provides information about the running backend machine for Raku.</p> | |
</li></ul> <p>All the above objects have methods in common:</p> | |
<ul><li><p><span class="code">version</span> provides the version number for that component;</p> | |
</li></ul> <ul><li><p><span class="code">name</span> provides the mnemonic name for that component;</p> | |
</li></ul> <ul><li><p><span class="code">auth</span> provides the known author(s) for that component.</p> | |
</li></ul> <p>As a short example, the following piece of code prints information about all the above components:</p> | |
<pre class="code">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 | |
</pre> | |
<p>The <span class="code">Str</span> method on all of the above produces the <i>short</i> version of the information, at the current time the <span class="code">name</span>.</p> | |
<p>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.</p> | |
<a name="t7.3.1.21"></a> <h3 id="_language_5to6-perlvar.pod6-%SIG">%SIG</h3> | |
<p>No equivalent variable. To have your code executed on the reception of a signal, you can call the <a href="#_routine_signal.pod6-(Supply)_sub_signal">signal</a> subroutine, which returns a <span class="code">Supply</span> that can be tapped.</p> | |
<pre class="code">$SIG{"INT"} = sub { say "bye"; exit } | |
</pre> | |
<pre class="code">signal(SIGINT).tap: { say "bye"; exit }; loop {} | |
</pre> | |
<p>Or, if you have a generic code that want to know which signal it got:</p> | |
<pre class="code">signal(SIGINT).tap: -> $signal { say "bye with $signal"; exit }; loop {} | |
</pre> | |
<p>A more idiomatic way of using signals in an event driven situation:</p> | |
<pre class="code">react { | |
whenever signal(SIGINT) { | |
say "goodbye"; | |
done | |
} | |
} | |
</pre> | |
<a name="t7.3.1.22"></a> <h3 id="_language_5to6-perlvar.pod6-$BASETIME,_$^T">$BASETIME, $^T</h3> | |
<p>Replaced in Raku by <span class="code">$*INIT-INSTANT</span>. Unlike in Perl, this is not in seconds since epoch, but an <a href="#_type_Instant.pod6">Instant</a> object, which is measured in atomic seconds, with fractions.</p> | |
<a name="t7.3.1.23"></a> <h3 id="_language_5to6-perlvar.pod6-$PERL_VERSION,_$^V">$PERL_VERSION, $^V</h3> | |
<p>As with <span class="code">$]</span> this has been replaced with <span class="code">$*RAKU.version</span>.</p> | |
<a name="t7.3.1.24"></a> <h3 id="_language_5to6-perlvar.pod6-${^WIN32_SLOPPY_STAT}">${^WIN32_SLOPPY_STAT}</h3> | |
<p>There is no analog to this in Raku.</p> | |
<a name="t7.3.1.25"></a> <h3 id="_language_5to6-perlvar.pod6-$EXECUTABLE_NAME,_$^X">$EXECUTABLE_NAME, $^X</h3> | |
<p>This has been replaced by <span class="code">$*EXECUTABLE-NAME</span>. Note that there is also <span class="code">$*EXECUTABLE</span>, which is an <span class="code">IO</span> object in Raku.</p> | |
<a name="t7.3.2"></a> <h2 id="_language_5to6-perlvar.pod6-Variables_related_to_regular_expressions">Variables related to regular expressions</h2> | |
<a name="t7.3.2.1"></a> <h3 id="_language_5to6-perlvar.pod6-Performance_issues">Performance issues</h3> | |
<p>As shown below, <span class="code">$`</span>, <span class="code">$&</span>, and <span class="code">$'</span> are gone from Raku, primarily replaced by variations on <span class="code">$/</span> and, with their elimination, the associated performance issues in Perl do not apply.</p> | |
<a name="t7.3.2.2"></a> <h3 id="_language_5to6-perlvar.pod6-$<digits>_($1,_$2,_...)">$<<i>digits</i>> ($1, $2, ...)</h3> | |
<p>These existing variables do the same thing in Raku as they do in Perl, except that they now start at <span class="code">$0</span> rather than <span class="code">$1</span>. Furthermore, they are synonyms for indexed items in the match variable <span class="code">$/</span>. I. e. <span class="code">$0</span> is equivalent to <span class="code">$/[0]</span>, <span class="code">$1</span> is equivalent to <span class="code">$/[1]</span>, etc.</p> | |
<a name="t7.3.2.3"></a> <h3 id="_language_5to6-perlvar.pod6-$MATCH,_$&">$MATCH, $&</h3> | |
<p><span class="code">$/</span> now contains the <a href="#_type_Match.pod6">match</a> object, so the Perl behavior of <span class="code">$&</span> can be obtained by stringifying it, i. e. <span class="code">~$/</span>.</p> | |
<p>Please note that while <span class="code">$/.Str</span> should also work, <span class="code">~$/</span> is currently the more common idiom.</p> | |
<a name="t7.3.2.4"></a> <h3 id="_language_5to6-perlvar.pod6-${^MATCH}">${^MATCH}</h3> | |
<p>Since the former performance issues are done away with, this variable is not of use in Raku.</p> | |
<a name="t7.3.2.5"></a> <h3 id="_language_5to6-perlvar.pod6-$PREMATCH,_$`">$PREMATCH, $`</h3> | |
<p>Replaced by <span class="code">$/.prematch</span>.</p> | |
<a name="t7.3.2.6"></a> <h3 id="_language_5to6-perlvar.pod6-${^PREMATCH}">${^PREMATCH}</h3> | |
<p>Since the former performance issues are done away with, this variable is not of use in Raku.</p> | |
<a name="t7.3.2.7"></a> <h3 id="_language_5to6-perlvar.pod6-$POSTMATCH,_$'">$POSTMATCH, $'</h3> | |
<p>Replaced by <span class="code">$/.postmatch</span>.</p> | |
<a name="t7.3.2.8"></a> <h3 id="_language_5to6-perlvar.pod6-${^POSTMATCH}">${^POSTMATCH}</h3> | |
<p>Since the former performance issues are done away with, this variable is not of use in Raku.</p> | |
<a name="t7.3.2.9"></a> <h3 id="_language_5to6-perlvar.pod6-$LAST_PAREN_MATCH,_$+">$LAST_PAREN_MATCH, $+</h3> | |
<p>Does not exist in Raku, but you can get the same information using <span class="code">$/[*- 1].Str</span> (<span class="code">$/[*-1]</span> would be the match object, not the actual string).</p> | |
<p>If you want to <i>understand</i> why that works, you can look at these documents:</p> | |
<ul><li><p><a href="#_routine_[ ].pod6">[ ] routine</a></p> | |
</li></ul> <ul><li><p><a href="#_type_Whatever.pod6">Whatever</a></p> | |
</li></ul> <p>...and possibly</p> | |
<ul><li><p><a href="#_routine_https:__design.raku.org_S02.html.pod6-line_1126">https://design.raku.org/S02.html#line_1126</a></p> | |
</li></ul> <p>...though the design documents are not always up to date.</p> | |
<a name="t7.3.2.10"></a> <h3 id="_language_5to6-perlvar.pod6-$LAST_SUBMATCH_RESULT,_$^N">$LAST_SUBMATCH_RESULT, $^N</h3> | |
<p>S28 suggests <span class="code">$*MOST_RECENT_CAPTURED_MATCH</span>, but there does not seem to be any implemented variable that matches <span class="code">$^N</span>.</p> | |
<a name="t7.3.2.11"></a> <h3 id="_language_5to6-perlvar.pod6-@LAST_MATCH_END,_@+">@LAST_MATCH_END, @+</h3> | |
<p>As with most regular expression related variables, this functionality is, at least in part, moved to the <span class="code">$/</span> variable in Raku. Or, in this case, the numbered variables that alias to the indexes of it. The offset is found by using the <span class="code">.to</span> method. I. e. the first offset is <span class="code">$/[0].to</span>, which is synonymous with <span class="code">$0.to</span>. The value Perl provides as <span class="code">$+[0]</span> is provided by <span class="code">$/.to</span>.</p> | |
<a name="t7.3.2.12"></a> <h3 id="_language_5to6-perlvar.pod6-%LAST_PAREN_MATCH,_%+">%LAST_PAREN_MATCH, %+</h3> | |
<p>Once again, we move over to <span class="code">$/</span>. The former <span class="code">$+{$match}</span> is <span class="code">$/{$match}</span>.</p> | |
<a name="t7.3.2.13"></a> <h3 id="_language_5to6-perlvar.pod6-@LAST_MATCH_START,_@-">@LAST_MATCH_START, @-</h3> | |
<p>Similarly to <span class="code">@+</span> being replaced by using the <span class="code">.to</span> method, <span class="code">@-</span> is replaced by using the <span class="code">.from</span> method on <span class="code">$/</span> and its variations. The first offset is <span class="code">$/[0].from</span> or the equivalent <span class="code">$0.from</span>. Perl's <span class="code">$- [0]</span> is <span class="code">$/.from</span>.</p> | |
<a name="t7.3.2.14"></a> <h3 id="_language_5to6-perlvar.pod6-%LAST_MATCH_START,_%-">%LAST_MATCH_START, %-</h3> | |
<p>Much like <span class="code">%+</span>, a use of <span class="code">%-{$match}</span> would be replaced with <span class="code">$/{$match}</span>.</p> | |
<a name="t7.3.2.15"></a> <h3 id="_language_5to6-perlvar.pod6-$LAST_REGEXP_CODE_RESULT,_$^R">$LAST_REGEXP_CODE_RESULT, $^R</h3> | |
<p>No equivalent.</p> | |
<a name="t7.3.2.16"></a> <h3 id="_language_5to6-perlvar.pod6-${^RE_DEBUG_FLAGS}">${^RE_DEBUG_FLAGS}</h3> | |
<p>No equivalent.</p> | |
<a name="t7.3.2.17"></a> <h3 id="_language_5to6-perlvar.pod6-${^RE_TRIE_MAXBUF}">${^RE_TRIE_MAXBUF}</h3> | |
<p>No equivalent.</p> | |
<a name="t7.3.3"></a> <h2 id="_language_5to6-perlvar.pod6-Variables_related_to_filehandles">Variables related to filehandles</h2> | |
<a name="t7.3.3.1"></a> <h3 id="_language_5to6-perlvar.pod6-$ARGV">$ARGV</h3> | |
<p>The name of the current file when reading lines can be obtained through <span class="code">$*ARGFILES.path</span>.</p> | |
<a name="t7.3.3.2"></a> <h3 id="_language_5to6-perlvar.pod6-@ARGV">@ARGV</h3> | |
<p><span class="code">@*ARGS</span> contains the command line arguments.</p> | |
<a name="t7.3.3.3"></a> <h3 id="_language_5to6-perlvar.pod6-ARGV">ARGV</h3> | |
<p>This has been replaced by <span class="code">$*ARGFILES</span>.</p> | |
<a name="t7.3.3.4"></a> <h3 id="_language_5to6-perlvar.pod6-ARGVOUT">ARGVOUT</h3> | |
<p>As the <span class="code">-i</span> command line switch has not yet been implemented, there is not yet an equivalent of <span class="code">ARGVOUT</span>.</p> | |
<a name="t7.3.3.5"></a> <h3 id="_language_5to6-perlvar.pod6-$OUTPUT_FIELD_SEPARATOR,_$OFS,_$,">$OUTPUT_FIELD_SEPARATOR, $OFS, $,</h3> | |
<p>Currently no obvious equivalent.</p> | |
<a name="t7.3.3.6"></a> <h3 id="_language_5to6-perlvar.pod6-$INPUT_LINE_NUMBER">$INPUT_LINE_NUMBER</h3> | |
<a name="t7.3.3.7"></a> <h3 id="_language_5to6-perlvar.pod6-$NR,_$.">$NR, $.</h3> | |
<p>No direct replacement exists.</p> | |
<p>When iterating using <a href="#_routine_lines.pod6">lines</a> method from <a href="#_type_IO::Path.pod6">IO::Path</a> or <a href="#_type_IO::Path.pod6">IO::Handle</a> types, you can call the <span class="code">.kv</span> method on it to get an interleaved list of indexes and values (then iterate by 2 each loop):</p> | |
<pre class="code">for "foo".IO.lines.kv -> $n, $line { | |
say "{$n + 1}: $line" | |
} | |
# OUTPUT: | |
# 1: a | |
# 2: b | |
# 3: c | |
# 4: d | |
</pre> | |
<p>For <a href="#_type_IO::CatHandle.pod6">IO::CatHandle</a> types (of which <a href="#_language_variables.pod6-index-entry-%24%2AARGFILES"><span class="code">$*ARGFILES</span></a> is one), you can use <a href="#_type_IO::CatHandle.pod6-method_on-switch"><span class="code">on-switch</span></a> hook to reset line number on handle switch, and increment it manually. See also <a href="#_routine_https:__modules.raku.org_repo_IO::CatHandle::AutoLines.pod6"><span class="code">IO::CatHandle::AutoLines</span></a> and <a href="#_routine_https:__modules.raku.org_repo_LN.pod6"><span class="code">LN</span></a> modules that simplify this operation.</p> | |
<a name="t7.3.3.8"></a> <h3 id="_language_5to6-perlvar.pod6-$INPUT_RECORD_SEPARATOR,_$RS,_$/">$INPUT_RECORD_SEPARATOR, $RS, $/</h3> | |
<p>This is accessed through the <span class="code">.nl-in</span> method on the filehandle. E. g. <span class="code">$*IN.nl-in</span>.</p> | |
<a name="t7.3.3.9"></a> <h3 id="_language_5to6-perlvar.pod6-$OUTPUT_RECORD_SEPARATOR,_$ORS,_$\">$OUTPUT_RECORD_SEPARATOR, $ORS, $\</h3> | |
<p>This is accessed through the <span class="code">.nl-out</span> method on the filehandle. E. g. <span class="code">$*OUT.nl-out</span>.</p> | |
<a name="t7.3.3.10"></a> <h3 id="_language_5to6-perlvar.pod6-$OUTPUT_AUTOFLUSH,_$|">$OUTPUT_AUTOFLUSH, $|</h3> | |
<p>No global alternative available. TTY handles are unbuffered by default, for others, set <a href="#_routine_out-buffer.pod6">out-buffer</a> to zero or use <span class="code">:!out-buffer</span> with <a href="#_routine_open.pod6">open</a> on a specific <a href="#_type_IO::Handle.pod6">IO::Handle</a>.</p> | |
<a name="t7.3.3.11"></a> <h3 id="_language_5to6-perlvar.pod6-${^LAST_FH}">${^LAST_FH}</h3> | |
<p>Not implemented in Raku.</p> | |
<a name="t7.3.4"></a> <h2 id="_language_5to6-perlvar.pod6-Variables_related_to_formats">Variables related to formats</h2> | |
<p>There are no built-in formats in Raku.</p> | |
<a name="t7.3.5"></a> <h2 id="_language_5to6-perlvar.pod6-Error_variables">Error variables</h2> | |
<p>Because of how error variables have changed in Raku, they will not be detailed here individually.</p> | |
<p>To quote the Raku <a href="#_language_variables.pod6-index-entry-%24!">docs</a>, "$! is the error variable." That's it. All the error variables appear to have been eaten by $!. As with the rest of Raku, it's an object that will return various things depending on the type of error or <a href="#_type_Exception.pod6">exception</a>.</p> | |
<p>In particular, when dealing with <a href="#_type_Exception.pod6">exceptions</a> the <span class="code">$!</span> provides information about the thrown exception, assuming the program has not halted:</p> | |
<pre class="code">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; | |
</pre> | |
<p>and the above code produces the following output</p> | |
<pre class="code">within the catch: | |
X::AdHoc : Boooh | |
outside the catch: | |
X::AdHoc : Boooh | |
</pre> | |
<p>therefore, as stated before, the <span class="code">$!</span> variable holds the exception object.</p> | |
<a name="t7.3.6"></a> <h2 id="_language_5to6-perlvar.pod6-Variables_related_to_the_interpreter_state">Variables related to the interpreter state</h2> | |
<a name="t7.3.6.1"></a> <h3 id="_language_5to6-perlvar.pod6-$COMPILING,_$^C,_$^D,_${^ENCODING},_${^GLOBAL_PHASE}">$COMPILING, $^C, $^D, ${^ENCODING}, ${^GLOBAL_PHASE}</h3> | |
<p>Currently no equivalents for either of these variables.</p> | |
<a name="t7.3.6.2"></a> <h3 id="_language_5to6-perlvar.pod6-$^H,_%^H,_${^OPEN}">$^H, %^H, ${^OPEN}</h3> | |
<p>There may or may not be equivalents of these in Raku, but they're internal and you shouldn't be messing with them in the first place - certainly not if your understanding of Raku requires you to read this document...</p> | |
<a name="t7.3.6.3"></a> <h3 id="_language_5to6-perlvar.pod6-$PERLDB,_$^P">$PERLDB, $^P</h3> | |
<p>The chance of the Raku debugger resembling the Perl debugger is slim at best, and at this point there does not seem to be an equivalent of this variable.</p> | |
<a name="t7.3.6.4"></a> <h3 id="_language_5to6-perlvar.pod6-${^TAINT}">${^TAINT}</h3> | |
<p>S28 claims this variable is "pending". Not currently in Raku.</p> | |
<a name="t7.3.6.5"></a> <h3 id="_language_5to6-perlvar.pod6-${^UNICODE},_${^UTF8CACHE},_${^UTF8LOCALE}">${^UNICODE}, ${^UTF8CACHE}, ${^UTF8LOCALE}</h3> | |
<p>These Unicode-related variables do not appear to exist in Raku, but - maybe? - could have analogs in <span class="code">$?ENC</span> somewhere. This, however, is totally unconfirmed.</p> | |
</div> | |
<!-- /language/about.pod6 --><div class="pod-body"><a id="_language_about.pod6"></a><a name="t8"></a><h1 class="title">8 About the docs</h1> <p class="subtitle">How to contribute to Raku and to the documents, how to generate the docs locally</p> <p>This document collection represents the on-going effort to document the Raku programming language with the goals of being comprehensive, easy to use, easy to navigate, and useful to both newcomers and experienced Raku programmers.</p> | |
<p>An HTML version of the documentation is located online at <a href="#_routine_https:__docs.raku.org.pod6">https://docs.raku.org</a>.</p> | |
<p>The official source for this documentation is located at <a href="#_routine_https:__github.com_Raku_doc.pod6">raku/doc on GitHub</a>.</p> | |
<p>This particular document is a quick overview of the process described in more detail in <a href="#_routine_https:__github.com_Raku_doc_blob_master_CONTRIBUTING.md.pod6">CONTRIBUTING on GitHub</a>. This document also provides a short introduction to writing Raku Pod files, which can be rendered into HTML and other formats.</p> | |
<a name="t8.1"></a> <h1 id="_language_about.pod6-Structure">Structure</h1> | |
<p>All of the documentation is written in Raku Pod and kept in the <span class="code">doc/</span> directory, and the <span class="code">doc/Language/</span> and <span class="code">doc/Type/</span> subdirectories. These files are processed as collections of definitions or "documentables", which are then post-processed and linked together.</p> | |
<a name="t8.2"></a> <h1 id="_language_about.pod6-Generating_HTML_from_Pod">Generating HTML from Pod</h1> | |
<p>To generate HTML from the Pod files, you'll need:</p> | |
<ul><li><p>A recent version of the Rakudo Raku compiler</p> | |
</li></ul> <ul><li><p>The Raku modules Pod::To::HTML, Pod::To::BigPage, and URI::Escape which all can be installed via <a href="#_routine_https:__github.com_ugexe_zef.pod6">zef</a>. For instance, <span class="code">zef install Pod::To::HTML</span> to install Pod::To::HTML.</p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__modules.raku.org_dist_Documentable.pod6"><span class="code">Documentable</span></a>, the document API.</p> | |
</li></ul> <ul><li><p><b>Optional</b>: <a href="#_routine_https:__www.graphviz.org.pod6">GraphViz</a>, for creating graphs of the relationships between Raku types.</p> | |
</li></ul> <ul><li><p><b>Optional</b>: <a href="#_routine_https:__github.com_atom_highlights.pod6">Atom Highlights</a> and <a href="#_routine_https:__atom.io_packages_language-perl6.pod6">language-perl6</a>, for syntax highlighting.</p> | |
</li></ul> <p>To generate the documentation into the <span class="code">html/</span> folder, run:</p> | |
<pre class="code">documentable start -a -v --highlight | |
</pre> | |
<p>To host the documentation from a web server, have Perl and Mojolicious::Lite installed; if you have Perl, run</p> | |
<pre class="code">cpanm --installdeps . | |
</pre> | |
<p>and then run:</p> | |
<pre class="code">perl app.pl daemon | |
</pre> | |
<a name="t8.3"></a> <h1 id="_language_about.pod6-Contributing">Contributing</h1> | |
<p>The documentation is written in Raku Pod.</p> | |
<p>For a quick introduction to Raku Pod, see <a href="#_language_pod.pod6">Raku Pod</a>.</p> | |
<p>For full details about the Raku Pod specification, see <a href="#_routine_https:__design.raku.org_S26.html.pod6">Synopsis 26, Documentation</a>.</p> | |
<a name="t8.3.1"></a> <h2 id="_language_about.pod6-Adding_definitions">Adding definitions</h2> | |
<p>Documentables can be defined using an <span class="code">=headN</span> Pod directive, where <span class="code">N</span> is greater than zero (e.g., <span class="code">=head1</span>, <span class="code">=head2</span>, …).</p> | |
<p>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:</p> | |
<pre class="code"> =head2 <var class="replaceable">My Definition</var> | |
Some paragraphs, followed by some code: | |
=begin code | |
my Code $examples = "amazing"; | |
=end code | |
Mind === blown. | |
=head3 Minor details about <var class="replaceable">My Definition</var> | |
It's fantastic. | |
=head2 And now, for something completely different | |
… | |
</pre> | |
<p>The documentable <var class="replaceable">My Definition</var> extends down to the <span class="code">=head2 And now…</span>.</p> | |
<p>Documentables may contain other documentables. Class documentables, for example, often contain the methods the class implements.</p> | |
<p>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:</p> | |
<pre class="code">=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) | |
</pre> | |
<p>Then the results on the rendered page:</p> | |
<ul><li><p><a id="i209" name="infix þ"></a><span class="indexed"><span class="code">How to use the þ infix</span></span> (This is a special case, which is always considered a definition)</p> | |
</li></ul> <ul><li><p><span class="code">The þ Infix</span></p> | |
</li></ul> <ul><li><p><b>The <span class="code">þ</span> Infix</b></p> | |
</li></ul> <ul><li><p><span class="code">Infix þ</span></p> | |
</li></ul> <ul><li><p><b>Infix <span class="code">þ</span></b></p> | |
</li></ul> <ul><li><p><span class="code">trait is cached</span> (A special case for the <a href="#_language_functions.pod6-Traits">trait</a> documentables)</p> | |
</li></ul> <p>These items should now be searchable by using the search field in the HTML docs.</p> | |
<p>You can add emphasis with bold (<b> B<> </b>) or italicized (<b> I<> </b>), with or without code formatting (<b> C<> </b>). Due to current parser limitations, special steps have to be taken to use <b> X<> </b> with other formatting codes; for example:</p> | |
<pre class="code">=item X<B<foo>|Subroutines,foo> a fancy subroutine | |
</pre> | |
<p>renders like this</p> | |
<ul><li><p><a id="i210" name="Subroutines foo"></a><span class="indexed"><b>foo</b></span> a fancy subroutine</p> | |
</li></ul> <p>Notice that text after a pipe ('|') has no formatting. Also note that <b> C<> </b> preserves spaces and treats text as verbatim.</p> | |
</div> | |
<!-- /language/classtut.pod6 --><div class="pod-body"><a id="_language_classtut.pod6"></a><a name="t9"></a><h1 class="title">9 Classes and objects</h1> <p class="subtitle">A tutorial about creating and using classes in Raku</p> <p><a id="i211" name="Tutorial OOP"></a><span class="indexed"></span> Raku provides a rich built-in syntax for defining and using classes. It makes writing classes expressive and short for most cases, but also provides mechanisms to cover the rare corner cases.</p> | |
<a name="t9.1"></a> <h1 id="_language_classtut.pod6-A_quick_overview">A quick overview</h1> | |
<p>Let's start with an example to give an overview:</p> | |
<pre class="code">class Rectangle { | |
has Int $.length = 1; | |
has Int $.width = 1; | |
method area(--> Int) { | |
return $!length * $!width; | |
} | |
} | |
my $r1 = Rectangle.new(length => 2, width => 3); | |
say $r1.area(); # OUTPUT: «6» | |
</pre> | |
<p>We define a new <i>Rectangle</i> class using the <a href="#_language_objects.pod6-Classes">class</a> keyword. It has two <a href="#_type_Attributes.pod6">attributes</a>, <span class="code">$!length</span> and <span class="code">$!width</span> introduced with the <a href="#_routine_has.pod6">has</a> keyword. Both default to <span class="code">1</span>. Read only accessor methods are automatically generated. (Note the <span class="code">.</span> instead of <span class="code">!</span> in the declaration, which triggers the generation. Mnemonic: <span class="code">!</span> resembles a closed door, <span class="code">.</span> an open one.)</p> | |
<p>The <a href="#_language_objects.pod6-Methods">method</a> named <span class="code">area</span> will return the area of the rectangle.</p> | |
<p>It is rarely necessary to explicitly write a constructor. An automatically inherited default constructor called <a href="#_language_objects.pod6-Object_construction">new</a> will automatically initialize attributes from named parameters passed to the constructor.</p> | |
<a name="t9.2"></a> <h1 id="_language_classtut.pod6-The_Task_example">The Task example</h1> | |
<p>As a more elaborate example the following piece of code implements a dependency handler. It showcases custom constructors, private and public attributes, methods, and various aspects of signatures. It's not a lot of code, and yet the result is interesting and useful. It will be used as an example throughout the following sections.</p> | |
<pre class="code">class Task { | |
has &!callback is built; | |
has Task @!dependencies is built; | |
has Bool $.done; | |
method new(&callback, *@dependencies) { | |
return self.bless(:&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(); | |
</pre> | |
<p><a id="i212" name="classes state"></a><span class="indexed"></span></p> | |
<a name="t9.3"></a> <h1 id="_language_classtut.pod6-Class"><a name="213"></a>Class</h1> | |
<p>Raku, like many other languages, uses the <span class="code">class</span> 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 <span class="code">has</span> keyword, and behaviors, introduced through the <span class="code">method</span> keyword.</p> | |
<a name="t9.4"></a> <h1 id="_language_classtut.pod6-Attributes"><a name="214"></a>Attributes</h1> | |
<p>In the <span class="code">Task</span> class, the first three lines inside the block all declare attributes (called <i>fields</i> or <i>instance storage</i> in other languages) using the <span class="code">has</span> declarator. Just as a <span class="code">my</span> variable cannot be accessed from outside its declared scope, attributes are never directly accessible from outside of the class (this is in contrast to many other languages). This <i>encapsulation</i> is one of the key principles of object oriented design.</p> | |
<a name="t9.4.1"></a> <h2 id="_language_classtut.pod6-Twigil_$!"><a name="215"></a>Twigil <span class="code">$!</span></h2> | |
<p>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):</p> | |
<pre class="code">has &!callback is built; | |
</pre> | |
<p>The <span class="code">&</span> sigil indicates that this attribute represents something invocable. The <span class="code">!</span> character is a <i>twigil</i>, or secondary sigil. A twigil forms part of the name of the variable. In this case, the <span class="code">!</span> twigil emphasizes that this attribute is private to the class. The attribute is <i>encapsulated</i>. Private attributes will not be set by the default constructor by default, which is why we add the <span class="code">is built</span> trait to allow just that. Mnemonic: <span class="code">!</span> looks like a closed door.</p> | |
<p>The second declaration also uses the private twigil:</p> | |
<pre class="code">has Task @!dependencies is built; | |
</pre> | |
<p>However, this attribute represents an array of items, so it requires the <span class="code">@</span> 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 <span class="code">Task</span> class (or some subclass of it).</p> | |
<p><a id="i216" name="Tutorial ."></a><span class="indexed"></span> <a id="i217" name="Tutorial accessors"></a><span class="indexed"></span> <a id="i218" name="Tutorial accessor methods"></a><span class="indexed"></span></p> | |
<a name="t9.4.2"></a> <h2 id="_language_classtut.pod6-Twigil_$.">Twigil <span class="code">$.</span></h2> | |
<p>The third attribute represents the state of completion of a task:</p> | |
<pre class="code">has Bool $.done; | |
</pre> | |
<p>This scalar attribute (with the <span class="code">$</span> sigil) has a type of <span class="code">Bool</span>. Instead of the <span class="code">!</span> twigil, the <span class="code">.</span> twigil is used. While Raku does enforce encapsulation on attributes, it also saves you from writing accessor methods. Replacing the <span class="code">!</span> with a <span class="code">.</span> both declares a private attribute and an accessor method named after the attribute. In this case, both the attribute <span class="code">$!done</span> and the accessor method <span class="code">done</span> are declared. It's as if you had written:</p> | |
<pre class="code">has Bool $!done; | |
method done() { return $!done } | |
</pre> | |
<p>Note that this is not like declaring a public attribute, as some languages allow; you really get <i>both</i> 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.</p> | |
<a name="t9.4.3"></a> <h2 id="_language_classtut.pod6-is_rw_trait"><a name="219"></a><span class="code">is rw</span> trait</h2> | |
<p>Note that using the <span class="code">.</span> 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:</p> | |
<pre class="code">has Bool $.done is rw; | |
</pre> | |
<p>The <span class="code">is rw</span> trait causes the generated accessor method to return a container so external code can modify the value of the attribute.</p> | |
<a name="t9.4.4"></a> <h2 id="_language_classtut.pod6-is_built_trait"><span class="code">is built</span> trait</h2> | |
<pre class="code">has &!callback is built; | |
</pre> | |
<p><a id="i220" name="traits is built"></a><span class="indexed"></span> By default private attributes are not automatically set by the default constructor. (They are private after all.) In the above example we want to allow the user to provide the initial value but keep the attribute otherwise private. The <span class="code">is built</span> trait allows to do just that.</p> | |
<p>One can also use it to do the opposite for public attributes, i.e. prevent them to be automatically initialized with a user provided value, but still generate the accessor method:</p> | |
<pre class="code">has $.done is built(False); | |
</pre> | |
<p>Above declaration makes sure one can't construct finished tasks, but still allow users to look if a task is done.</p> | |
<p>The <span class="code">is built</span> trait was introduced in Rakudo version 2020.01.</p> | |
<a name="t9.4.5"></a> <h2 id="_language_classtut.pod6-is_required_trait"><span class="code">is required</span> trait</h2> | |
<p><a id="i221" name="traits is required"></a><span class="indexed"></span> Providing a value for an attribute during initialization is optional by default. Which in the task example makes sense for all three, the <span class="code">&!callback</span>, the <span class="code">@!dependencies</span> and the <span class="code">$.done</span> attribute. But lets say we want to add another attribute, <span class="code">$.name</span>, that holds a tasks name and we want to force the user to provide a value on initialization. We can do that as follows:</p> | |
<pre class="code">has $.name is required; | |
</pre> | |
<a name="t9.4.6"></a> <h2 id="_language_classtut.pod6-Default_values">Default values</h2> | |
<p>You can also supply default values to attributes (which works equally for those with and without accessors):</p> | |
<pre class="code">has Bool $.done = False; | |
</pre> | |
<p>The assignment is carried out at object build time. The right-hand side is evaluated at that time, and can even reference earlier attributes:</p> | |
<pre class="code">has Task @!dependencies; | |
has $.ready = not @!dependencies; | |
</pre> | |
<p>Writable attributes are accessible through writable containers:</p> | |
<pre class="code">class a-class { | |
has $.an-attribute is rw; | |
} | |
say (a-class.new.an-attribute = "hey"); # OUTPUT: «hey» | |
</pre> | |
<p>This attribute can also be accessed using the <span class="code">.an-attribute</span> or <span class="code">.an-attribute()</span> syntax. See also <a href="#_language_typesystem.pod6-trait_is_rw">the <span class="code">is rw</span> trait on classes</a> for examples on how this works on the whole class.</p> | |
<p><a id="i222" name="Tutorial class variables"></a><span class="indexed"></span></p> | |
<a name="t9.5"></a> <h1 id="_language_classtut.pod6-Class_variables">Class variables</h1> | |
<p>A class declaration can also include <i>class variables</i>, declared with <span class="code">my</span> or <span class="code">our</span>, 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. So <i>class variables</i> act similar to <i>static</i> variables known from other programming languages. They look the same as normal (non class) lexical variables (and in fact they are the same):</p> | |
<pre class="code">class Str-with-ID is Str { | |
my $counter = 0; | |
our $our-counter = 0; | |
has Str $.string; | |
has Int $.ID is built(False); | |
submethod TWEAK() { | |
$counter++; | |
$our-counter++; | |
$!ID = $counter; | |
} | |
} | |
class Str-with-ID-and-tag is Str-with-ID { | |
has Str $.tag; | |
} | |
say Str-with-ID.new(string => 'First').ID; # OUTPUT: «1» | |
say Str-with-ID.new(string => 'Second').ID; # OUTPUT: «2» | |
say Str-with-ID-and-tag.new( string => 'Third', tag => 'Ordinal' ).ID; # OUTPUT: «3» | |
say $Str-with-ID::our-counter; # OUTPUT: «3» | |
</pre> | |
<p><i>Class variables</i> are shared by all subclasses, in this case <span class="code">Str-with-ID-and-tag</span>. Additionally, when the package scope <span class="code">our</span> declarator is used, the variable is visible via their fully qualified name (FQN), while lexically scoped <span class="code">my</span> variables are "private". This is the exact behavior that <span class="code">my</span> and <span class="code">our</span> also show in non class context.</p> | |
<p><a id="i223" name="static"></a><span class="indexed"></span> <i>Class variables</i> act similar to <i>static</i> variables in many other programming languages.</p> | |
<pre class="code">class Singleton { | |
my Singleton $instance; | |
method new {!!!} | |
submethod instance { | |
$instance = Singleton.bless unless $instance; | |
$instance; | |
} | |
} | |
</pre> | |
<p>In this implementation of the <i>Singleton</i> pattern a <i>class variable</i> is used to save the instance.</p> | |
<pre class="code">class HaveStaticAttr { | |
my Int $.foo = 5; | |
} | |
</pre> | |
<p>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. Default values behave as expected and are assigned only once.</p> | |
<a name="t9.6"></a> <h1 id="_language_classtut.pod6-Methods">Methods</h1> | |
<p><a id="i224" name="Tutorial methods"></a><span class="indexed"></span></p> | |
<p>While attributes give objects state, methods give objects behaviors. Back to our <span class="code">Task</span> example. Let's ignore the <span class="code">new</span> method temporarily; it's a special type of method. Consider the second method, <span class="code">add-dependency</span>, which adds a new task to a task's dependency list:</p> | |
<pre class="code">method add-dependency(Task $dependency) { | |
push @!dependencies, $dependency; | |
} | |
</pre> | |
<p><a id="i225" name="Tutorial invocant"></a><span class="indexed"></span> In many ways, this looks a lot like a <span class="code">sub</span> 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 <span class="code">Task</span> class can call it with the <span class="code">.</span> method call operator. Second, a method places its invocant into the special variable <span class="code">self</span>.</p> | |
<p>The method itself takes the passed parameter – which must be an instance of the <span class="code">Task</span> class – and <span class="code">push</span>es it onto the invocant's <span class="code">@!dependencies</span> attribute.</p> | |
<p>The <span class="code">perform</span> method contains the main logic of the dependency handler:</p> | |
<pre class="code">method perform() { | |
unless $!done { | |
.perform() for @!dependencies; | |
&!callback(); | |
$!done = True; | |
} | |
} | |
</pre> | |
<p>It takes no parameters, working instead with the object's attributes. First, it checks if the task has already completed by checking the <span class="code">$!done</span> attribute. If so, there's nothing to do.</p> | |
<p>Otherwise, the method performs all of the task's dependencies, using the <span class="code">for</span> construct to iterate over all of the items in the <span class="code">@!dependencies</span> attribute. This iteration places each item – each a <span class="code">Task</span> object – into the topic variable, <span class="code">$_</span>. Using the <span class="code">.</span> method call operator without specifying an explicit invocant uses the current topic as the invocant. Thus the iteration construct calls the <span class="code">.perform()</span> method on every <span class="code">Task</span> object in the <span class="code">@!dependencies</span> attribute of the current invocant.</p> | |
<p>After all of the dependencies have completed, it's time to perform the current <span class="code">Task</span>'s task by invoking the <span class="code">&!callback</span> attribute directly; this is the purpose of the parentheses. Finally, the method sets the <span class="code">$!done</span> attribute to <span class="code">True</span>, so that subsequent invocations of <span class="code">perform</span> on this object (if this <span class="code">Task</span> is a dependency of another <span class="code">Task</span>, for example) will not repeat the task.</p> | |
<a name="t9.6.1"></a> <h2 id="_language_classtut.pod6-Private_methods"><a name="226"></a>Private methods</h2> | |
<p>Just like attributes, methods can also be private. Private methods are declared with a prefixed exclamation mark. They are called with <span class="code">self!</span> followed by the method's name. In the following implementation of a <span class="code">MP3TagData</span> class to extract <a href="#_routine_https:__en.wikipedia.org_wiki_ID3.pod6">ID3v1</a> metadata from an mp3 file, methods <span class="code">parse-data</span>, <span class="code">can-read-format</span>, and <span class="code">trim-nulls</span> are private methods while the remaining ones are public methods:</p> | |
<pre class="code">class MP3TagData { | |
has $.filename where { .IO ~~ :e }; | |
has Str $.title is built(False); | |
has Str $.artist is built(False); | |
has Str $.album is built(False); | |
has Str $.year is built(False); | |
has Str $.comment is built(False); | |
has Int $.genre is built(False); | |
has Int $.track is built(False); | |
has Str $.version is built(False); | |
has Str $.type is built(False) = 'ID3'; | |
submethod TWEAK { | |
with $!filename.IO.open(:r, :bin) -> $fh { | |
$fh.seek(-128, SeekFromEnd); | |
my $tagdata = $fh.read(128); | |
self!parse-data: $tagdata; | |
$fh.close; | |
} | |
else { | |
warn "Failed to open file." | |
} | |
} | |
method !parse-data($data) { | |
if self!can-read-format($data) { | |
my $offset = $data.bytes - 128; | |
$!title = self!trim-nulls: $data.subbuf($offset + 3, 30); | |
$!artist = self!trim-nulls: $data.subbuf($offset + 33, 30); | |
$!album = self!trim-nulls: $data.subbuf($offset + 63, 30); | |
$!year = self!trim-nulls: $data.subbuf($offset + 93, 4); | |
my Int $track-flag = $data.subbuf($offset + 97 + 28, 1).Int; | |
$!track = $data.subbuf($offset + 97 + 29, 1).Int; | |
($!version, $!comment) = $track-flag == 0 && $!track != 0 | |
?? ('1.1', self!trim-nulls: $data.subbuf($offset + 97, 28)) | |
!! ('1.0', self!trim-nulls: $data.subbuf($offset + 97, 30)); | |
$!genre = $data.subbuf($offset + 97 + 30, 1).Int; | |
} | |
} | |
method !can-read-format(Buf $data --> Bool) { | |
self!trim-nulls($data.subbuf(0..2)) eq 'TAG' | |
} | |
method !trim-nulls(Buf $data --> Str) { | |
$data.decode('utf-8').subst(/\x[0000]+/, '') | |
} | |
} | |
</pre> | |
<p>To call a private method of another class, the caller has to be trusted by the callee. A trust relationship is declared with <a href="#_language_typesystem.pod6-trait_trusts"><span class="code">trusts</span></a> 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. A trust relationship also allows access to private attributes.</p> | |
<pre class="code">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(); | |
</pre> | |
<p>Trust relationships are not subject to inheritance. To trust the global namespace, the pseudo package <span class="code">GLOBAL</span> can be used.</p> | |
<a name="t9.7"></a> <h1 id="_language_classtut.pod6-Construction"><a name="227"></a>Construction</h1> | |
<p>The object construction mechanisms described up to now suffice for most use cases. But if one actually needs to tweak object construction more than said mechanisms allow, it's good to understand how object construction works in more detail.</p> | |
<p>Raku 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 <span class="code">new</span> from the base class <span class="code">Mu</span>, but you are free to override <span class="code">new</span>, as the Task example does:</p> | |
<pre class="code">method new(&callback, *@dependencies) { | |
return self.bless(:&callback, :@dependencies); | |
} | |
</pre> | |
<p><a id="i228" name="Tutorial bless"></a><span class="indexed"></span></p> | |
<a name="t9.7.1"></a> <h2 id="_language_classtut.pod6-bless">bless</h2> | |
<p>The biggest difference between constructors in Raku and constructors in languages such as C# and Java is that rather than setting up state on a somehow already magically created object, Raku constructors create the object themselves. They do this by calling the <a href="#_routine_bless.pod6">bless</a> method, also inherited from <a href="#_type_Mu.pod6">Mu</a>. The <span class="code">bless</span> method expects a set of named parameters to provide the initial values for each attribute.</p> | |
<p>The example's constructor turns positional arguments into named arguments, so that the class can provide a nicer constructor for its users. The first parameter is the callback (the thing which will execute the task). The rest of the parameters are dependent <span class="code">Task</span> instances. The constructor captures these into the <span class="code">@dependencies</span> slurpy array and passes them as named parameters to <span class="code">bless</span> (note that <span class="code">:&callback</span> uses the name of the variable – minus the sigil – as the name of the parameter). One should refrain from putting logic other than reformulating the parameters in the constructor, because constructor methods are not recursively called for parent classes. This is different from e.g. Java.</p> | |
<p>Declaring <span class="code">new</span> as a <span class="code">method</span> and not as a <span class="code">multi method</span> prevents access to the default constructor. +So if you intend to keep the default constructor available, use <span class="code">multi method new</span>.</p> | |
<a name="t9.7.2"></a> <h2 id="_language_classtut.pod6-TWEAK"><a name="229"></a><span class="code">TWEAK</span></h2> | |
<p>After <span class="code">bless</span> has initialized the classes attributes from the passed values, it will in turn call <span class="code">TWEAK</span> for each class in the inheritance hierarchy. <span class="code">TWEAK</span> gets passed all the arguments passed to bless. This is where custom initialization logic should go.</p> | |
<p>Remember to always make <span class="code">TWEAK</span> a <a href="#_type_Submethod.pod6">submethod</a> and not a normal <span class="code">method</span>. If in a class hierarchy a class contains a <span class="code">TWEAK</span> method (declared as a <span class="code">method</span> instead of a <span class="code">submethod</span>) that method is inherited to its subclass and will thus be called twice during construction of the subclass!</p> | |
<a name="t9.7.3"></a> <h2 id="_language_classtut.pod6-BUILD"><a name="230"></a><span class="code">BUILD</span></h2> | |
<p>It is possible to disable the automatic attribute initialization and perform the initialization of attributes oneself. To do so one needs to write a custom <span class="code">BUILD</span> submethod. There are several edge cases one needs to be aware of and take into account though. This is detailed in the <a href="#_language_objects.pod6-Object_construction">Object Construction Reference</a>. Because of the difficulty of using <span class="code">BUILD</span>, it is recommended to only make use of it when none of the other approaches described above suffices.</p> | |
<p><a id="i231" name="Tutorial submethod DESTROY"></a><span class="indexed"></span></p> | |
<a name="t9.8"></a> <h1 id="_language_classtut.pod6-Destruction"><a name="232"></a>Destruction</h1> | |
<p>Raku is a garbage collecting language. This means that one usually doesn't need to care about cleaning up objects, because Raku does so automatically. Raku does not give any guarantees as to when it will clean up a given object though. It usually does a cleanup run only if the runtime needs the memory, so we can't rely on when it's going to happen.</p> | |
<p>To run custom code when an object is cleaned up one can use the <span class="code">DESTROY</span> submethod. It can for example be used to close handles or supplies or delete temporary files that are no longer going to be used. As garbage collection can happen at arbitrary points during the runtime of our program, even in the middle of some totally unrelated piece of code in a different thread, we must make sure to not assume any context in our <span class="code">DESTROY</span> submethod.</p> | |
<pre class="code">my $in_destructor = 0; | |
class Foo { | |
submethod DESTROY { $in_destructor++ } | |
} | |
my $foo; | |
for 1 .. 6000 { | |
$foo = Foo.new(); | |
} | |
say "DESTROY called $in_destructor times"; | |
</pre> | |
<p>This might print something like <span class="code">DESTROY called 5701 times</span> and possibly only kicks in after we have stomped over former instances of <span class="code">Foo</span> a few thousand times. We also can't rely, on the order of destruction.</p> | |
<p>Same as <span class="code">TWEAK</span>: Make sure to always declare <span class="code">DESTROY</span> as a <span class="code">submethod</span>.</p> | |
<a name="t9.9"></a> <h1 id="_language_classtut.pod6-Consuming_our_class">Consuming our class</h1> | |
<p>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:</p> | |
<pre class="code">my $eat = Task.new({ say 'eating dinner. NOM!' }); | |
</pre> | |
<p>An earlier section explained that declaring the class <span class="code">Task</span> 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; <span class="code">new</span> is an example, as it creates a new object rather than modifying or accessing an existing object.</p> | |
<p>Unfortunately, dinner never magically happens. It has dependent tasks:</p> | |
<pre class="code">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' }) | |
) | |
); | |
</pre> | |
<p>Notice how the custom constructor and the sensible use of whitespace makes task dependencies clear.</p> | |
<p>Finally, the <span class="code">perform</span> method call recursively calls the <span class="code">perform</span> method on the various other dependencies in order, giving the output:</p> | |
<pre class="code">making some money | |
going to the store | |
buying food | |
cleaning kitchen | |
making dinner | |
eating dinner. NOM! | |
</pre> | |
<a name="t9.9.1"></a> <h2 id="_language_classtut.pod6-A_word_on_types"><a name="233"></a>A word on types</h2> | |
<p>Declaring a class creates a new <i>type object</i> which, by default, is installed into the current package (just like a variable declared with <span class="code">our</span> scope). This type object is an "empty instance" of the class. For example, types such as <span class="code">Int</span> and <span class="code">Str</span> refer to the type object of one of the Raku built-in classes. One can call methods on these type objects. So there is nothing special with calling the <span class="code">new</span> method on a type object.</p> | |
<p>You can use the <span class="code">.DEFINITE</span> method to find out if what you have is an instance or a type object:</p> | |
<pre class="code">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) | |
</pre> | |
<p>In function signatures one can use so called type "smileys" to only accept instances or type objects:</p> | |
<pre class="code">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!» | |
</pre> | |
<a name="t9.10"></a> <h1 id="_language_classtut.pod6-Inheritance"><a name="234"></a>Inheritance</h1> | |
<p>Object Oriented Programming provides the concept of inheritance as one of the mechanisms for code reuse. Raku 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 <span class="code">method</span> keyword and for methods generated through other means, such as attribute accessors.</p> | |
<pre class="code">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]; | |
} | |
} | |
</pre> | |
<p>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.</p> | |
<pre class="code">my $programmer = Programmer.new( | |
salary => 100_000, | |
known_languages => <Raku Perl Erlang C++>, | |
favorite_editor => 'vim' | |
); | |
say $programmer.code_to_solve('halting problem'), | |
" will get \$ {$programmer.salary()}"; | |
# OUTPUT: «Solving halting problem using vim in Raku will get $100000» | |
</pre> | |
<a name="t9.10.1"></a> <h2 id="_language_classtut.pod6-Overriding_inherited_methods">Overriding inherited methods</h2> | |
<p>Classes can override methods and attributes defined by parent classes by defining their own. The example below demonstrates the <span class="code">Baker</span> class overriding the <span class="code">Cook</span>'s <span class="code">cook</span> method.</p> | |
<pre class="code">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.raku; # OUTPUT: «["spoon", "ladle", "knife", "pan"]» | |
say $cook.cookbooks.raku; # 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.raku; # OUTPUT: «["self cleaning oven"]» | |
say $baker.cookbooks.raku; # OUTPUT: «["The Baker's Apprentice"]» | |
say $baker.salary; # OUTPUT: «50000» | |
</pre> | |
<p>Because the dispatcher will see the <span class="code">cook</span> method on <span class="code">Baker</span> before it moves up to the parent class the <span class="code">Baker</span>'s <span class="code">cook</span> method will be called.</p> | |
<p>To access methods in the inheritance chain, use <a href="#_language_functions.pod6-Re-dispatching">re-dispatch</a> or the <a href="#_type_Metamodel::ClassHOW.pod6-method_can">MOP</a>.</p> | |
<a name="t9.10.2"></a> <h2 id="_language_classtut.pod6-Multiple_inheritance">Multiple inheritance</h2> | |
<p>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. Raku uses the <a href="#_routine_https:__en.wikipedia.org_wiki_C3_linearization.pod6">C3 algorithm</a> to linearize multiple inheritance hierarchies, which is better than depth-first search for handling multiple inheritance.</p> | |
<pre class="code">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 Raku', | |
utensils => ('stainless steel pot', 'knife', 'calibrated oven'), | |
favorite_editor => 'MacVim', | |
known_languages => <Raku> | |
); | |
$geek.cook('pizza'); | |
$geek.code_to_solve('P =? NP'); | |
</pre> | |
<p>Now all the methods made available to the Programmer and the Cook classes are available from the GeekCook class.</p> | |
<p>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 <a href="#_language_objects.pod6-Roles">Roles</a>.</p> | |
<a name="t9.10.3"></a> <h2 id="_language_classtut.pod6-The_also_declarator">The <a name="235"></a><span class="code">also</span> declarator</h2> | |
<p>Classes to be inherited from can be listed in the class declaration body by prefixing the <span class="code">is</span> trait with <span class="code">also</span>. This also works for the role composition trait <span class="code">does</span>.</p> | |
<pre class="code">class GeekCook { | |
also is Programmer; | |
also is Cook; | |
# ... | |
} | |
role A {}; | |
role B {}; | |
class C { | |
also does A; | |
also does B; | |
# ... | |
} | |
</pre> | |
<a name="t9.11"></a> <h1 id="_language_classtut.pod6-Introspection">Introspection</h1> | |
<p>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.</p> | |
<p>Given an object <span class="code">$o</span> and the class definitions from the previous sections, we can ask it a few questions:</p> | |
<pre class="code">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.raku; | |
say $o.^methods(:local)».name.join(', '); | |
</pre> | |
<p>The output might look like this:</p> | |
<pre class="code">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 | |
</pre> | |
<p>The first two tests each smartmatch against a class name. If the object is of that class, or of an inheriting class, it returns <span class="code">True</span>. So the object in question is of class <span class="code">Employee</span> or one that inherits from it, but not <span class="code">GeekCook</span>.</p> | |
<p>The call <span class="code">$o.^name</span> tells us the type of <span class="code">$o</span>; in this case <span class="code">Programmer</span>.</p> | |
<p><span class="code">$o.raku</span> returns a string that can be executed as Raku code, and reproduces the original object <span class="code">$o</span>. While this does not work perfectly in all cases, it is very useful for debugging simple objects. <div class="marginale">For example, closures cannot easily be reproduced this way; if you don't know what a closure is don't worry. Also current implementations have problems with dumping cyclic data structures this way, but they are expected to be handled correctly by <span class="code">.raku</span> at some point.</div></p> | |
<p>The syntax of calling a method with <span class="code">.^</span> instead of a single dot means that it is actually a method call on its <i>metaclass</i>, which is a class managing the properties of the <span class="code">Programmer</span> class – or any other class you are interested in. This metaclass enables other ways of introspection too:</p> | |
<pre class="code">say $o.^attributes.join(', '); | |
say $o.^parents.map({ $_.^name }).join(', '); | |
</pre> | |
<p>Finally <span class="code">$o.^name</span> calls the <span class="code">name</span> method on the metaobject, which unsurprisingly returns the class name.</p> | |
<p>Given an object <span class="code">$mp3</span> and the <span class="code">MP3TagData</span> class definition from the section <a href="#_language_classtut.pod6-Private_methods">Private methods</a>, we can inquire about its public methods with <span class="code">.^methods</span>:</p> | |
<pre class="code">my $mp3 = MP3TagData.new(filename => 'football-head.mp3'); | |
say $mp3.^methods(:local); | |
# OUTPUT: (TWEAK filename title artist album year comment genre track version | |
# type Submethod+{is-hidden-from-backtrace}.new) | |
</pre> | |
<p><a id="i236" name="Syntax ^methods"></a><span class="indexed"></span> <span class="code">$mp3.^methods(:local)</span> produces a list of <a href="#_type_Method.pod6">Method</a>s that can be called on <span class="code">$mp3</span>. The <span class="code">:local</span> named argument limits the returned methods to those defined in the <span class="code">MP3TagData</span> class and excludes the inherited methods; <span class="code">MP3TagData</span> inherits from no class, so providing <span class="code">:local</span> makes no difference.</p> | |
<p><a id="i237" name="Language find_method"></a><span class="indexed"></span> To check if a type object (or an instance object) implements a certain public method, use the <a href="#_routine_find_method.pod6"><span class="code">.^find-method</span></a> metamethod, which returns the method object if it exists. Otherwise, it returns <a href="#_type_Mu.pod6"><span class="code">Mu</span></a>.</p> | |
<pre class="code">say $mp3.^find_method('name'); # OUTPUT: «(Mu)» | |
say $mp3.^find_method('artist'); # OUTPUT: «artist» | |
</pre> | |
<p><a id="i238" name="Language private_methods"></a><span class="indexed"></span> <a id="i239" name="Language find_private_methods"></a><span class="indexed"></span> Type objects can also be introspected for its private methods. However, public and private methods don't use the same APIs, and thus different metamethods must be used: <a href="#_routine_private_methods.pod6"><span class="code">.^private_methods</span></a> and <a href="#_routine_find_private_method.pod6"><span class="code">.^find_private_method</span></a>.</p> | |
<pre class="code">say $mp3.^private_methods; # OUTPUT: «(parse-data can-read-format trim-nulls)» | |
say $mp3.^find_private_method('parse-data'); # OUTPUT: «parse-data» | |
say $mp3.^find_private_method('remove-nulls'); # OUTPUT: «(Mu)» | |
</pre> | |
<p>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 <span class="code">.^name</span>, seeing a construction recipe for it with <span class="code">.raku</span>, and so on, you'll get a good idea of what its return value is. With <span class="code">.^methods</span>, you can learn what you can do with the class.</p> | |
<p>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.</p> | |
<a name="t9.11.1"></a> <h2 id="_language_classtut.pod6-Overriding_default_gist_method"><a name="240"></a>Overriding default gist method</h2> | |
<p>Some classes might need their own version of <span class="code">gist</span>, which overrides the terse way they are printed when called to provide a default representation of the class. For instance, <a href="#_language_exceptions.pod6-Uncaught_exceptions">exceptions</a> might want to write just the <span class="code">payload</span> 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:</p> | |
<pre class="code">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»» | |
</pre> | |
<p>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.</p> | |
</div> | |
<!-- /language/community.pod6 --><div class="pod-body"><a id="_language_community.pod6"></a><a name="t10"></a><h1 class="title">10 Community</h1> <p class="subtitle">Information about the people working on and using Raku</p> <a name="t10.1"></a> <h1 id="_language_community.pod6-Overview">Overview</h1> | |
<p>"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 (circa 2000)</p> | |
<p>"I am in favor of this change [a community driven renaming from Perl 6 to Raku], because it reflects an ancient wisdom: 'No one sews a patch of unshrunk cloth on an old garment, for the patch will pull away from the garment, making the tear worse. Neither do people pour new wine into old wineskins. If they do, the skins will burst; the wine will run out and the wineskins will be ruined. No, they pour new wine into new wineskins, and both are preserved.'" - Larry Wall (<a href="#_routine_https:__github.com_Raku_problem-solving_pull_89.pod6-pullrequestreview-300789072">2019</a>)</p> | |
<a name="t10.2"></a> <h1 id="_language_community.pod6-The_Raku_community">The Raku community</h1> | |
<a name="t10.2.1"></a> <h2 id="_language_community.pod6-Online_communities">Online communities</h2> | |
<p>Online interaction takes place mainly on the Internet Relay Chat, <a href="#_language_glossary.pod6-index-entry-IRC">IRC</a>.</p> | |
<p>The <span class="code">#raku</span> channel was created in October 2019, and will become more active as it becomes the default channel. Eventually, connections to the <span class="code">#perl6</span> will be redirected to <span class="code">#raku</span>, but the historical logs will remain on the <span class="code">#perl6</span> channel. The <a href="#_routine_https:__raku.org_community_irc.pod6"><span class="code">#raku</span></a> channel on <span class="code">libera.chat</span> has a large presence with many developers, who are happy to provide support and answer questions, or just use it as a friendly place to hang out. Check out this <a href="#_routine_http:__www.ircbeginner.com_ircinfo_abbreviations.html.pod6">IRC lingo</a> resource for the abbreviations frequently used there.</p> | |
<p><a href="#_routine_https:__stackoverflow.com_questions_tagged_raku.pod6">StackOverflow</a> is also a great resource for asking questions and helping others with their Raku problems and challenges. More resources can be found in the <a href="#_routine_https:__raku.org_community_.pod6">raku.org community page</a>.</p> | |
<a name="t10.2.2"></a> <h2 id="_language_community.pod6-IRC_bots">IRC bots</h2> | |
<p>The IRC channel has some very interesting bots. This is a full list with the name of the bot, a link to more information and a short description.</p> | |
<ul><li><p><b>benchable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Benchable.pod6">details</a>)</p> | |
<p>An IRC bot for benchmarking code at a given commit of Rakudo. It can be addressed by its full name ('benchable6') or its short name ('bench'). It will run the given code five times and return the minimum amount of time taken.</p> | |
</li></ul> <ul><li><p><b>bisectable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Bisectable.pod6">details</a>)</p> | |
<p>This bot is meant to help you find when something got broken. If you want to know if something has ever worked use Committable instead.</p> | |
</li></ul> <ul><li><p><b>bloatable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Bloatable.pod6">details</a>)</p> | |
<p>An IRC bot for running bloaty on libmoar.so files of MoarVM. It can be addressed by its full name ('bloatable6') or its short name ('bloat' or 'bloaty'). It will run bloaty and pass one or more libmoar.so files from different revisions of MoarVM.</p> | |
</li></ul> <ul><li><p><b>buggable</b> (<a href="#_routine_https:__github.com_zoffixznet_perl6-buggable.pod6">details</a>)</p> | |
<p>RT queue search and utility bot.</p> | |
</li></ul> <ul><li><p><b>camelia</b></p> | |
<p>Raku code evaluation bot. We use this for live testing of code that may be of interest to others; it chats back to the channel. <span class="code">raku: my $a</span> will result in a test against the latest revisions of rakudo and niecza, <span class="code">nqp: say('foo')</span> will test nqp, <span class="code">std: my $a</span> will parse the expression using STD.pm6. For other compilers, try <span class="code">camelia: help</span>.</p> | |
</li></ul> <ul><li><p><b>committable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Committable.pod6">details</a>)</p> | |
<p>An IRC bot for running code at a given commit of Rakudo. It can be addressed by its full name ('committable6') or its short names ('commit', 'c').</p> | |
</li></ul> <ul><li><p><b>coverable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Coverable.pod6">details</a>)</p> | |
<p>An IRC bot for creating a coverage report of the Rakudo (and NQP) source lines that were hit while running the code you give it. The first option is the commit, the second (optional) option is the filter for what lines of the MoarVM-generated coverage log you want, the third is the code to run.</p> | |
</li></ul> <ul><li><p><b>Geth</b> (<a href="#_routine_https:__github.com_Raku_geth.pod6">details</a>)</p> | |
<p>Announces commits made to various projects relevant to Raku, such as implementations of Raku and some of the <a href="#_routine_https:__github.com_Raku_.pod6">repositories owned by Raku</a>.</p> | |
</li></ul> <ul><li><p><b>evalable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Evalable.pod6">details</a>)</p> | |
<p>Evalable is just Committable that defaults to <span class="code">HEAD</span>.</p> | |
</li></ul> <ul><li><p><b>greppable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Greppable.pod6">details</a>)</p> | |
<p>An IRC bot for grepping through the module ecosystem. It can be addressed by its full name ('greppable6') or its short name ('grep').</p> | |
</li></ul> <ul><li><p><b>huggable</b> (<a href="#_routine_https:__github.com_zoffixznet_huggable.pod6">details</a>)</p> | |
<p>Let's you <span class="code">.hug</span> people in the channel.</p> | |
</li></ul> <ul><li><p><b>ilbot</b> (<a href="#_routine_https:__github.com_moritz_ilbot.pod6">details</a>)</p> | |
<p>IRC logging bot.</p> | |
</li></ul> <ul><li><p><b>nativecallable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Nativecallable.pod6">details</a>)</p> | |
<p>an IRC bot for generating Raku NativeCall code from C definitions. It can be addressed by its full name ('nativecallable6') or its short name ('nativecall'). The bot is using <span class="code">App::GPTrixie</span> to do the conversion.</p> | |
</li></ul> <ul><li><p><b>notable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Notable.pod6">details</a>)</p> | |
<p>an IRC bot for for noting things. It can be addressed by its full name ('notable6') or its short name ('note'). There is also a “weekly:” shortcut.</p> | |
</li></ul> <ul><li><p><b>quotable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Quotable.pod6">details</a>) An IRC bot for searching messages in the IRC log. It can be addressed by its full name ('quotable6') or its short name ('quote').</p> | |
</li></ul> <ul><li><p><b>releasable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Releasable.pod6">details</a>)</p> | |
<p>An IRC bot for getting information about the upcoming release. It can be addressed by its full name ('releasable6') or its short name ('release').</p> | |
<p>As a user, you are probably only interested in its only command “status”. It tells when the next release is going to happen and how many blockers are there.</p> | |
</li></ul> <ul><li><p><b>reportable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Reportable.pod6">details</a>)</p> | |
<p>An IRC bot for generating reports of changes in rakudo RT and GitHub issue trackers (which issues were resolved, updated, rejected, etc.). It can be addressed by its full name ('reportable6') or its short name ('report'). It takes snapshots of issue trackers periodically, and then you can ask it to generate a report for two given snapshots.</p> | |
<p>See also: <a href="#_routine_https:__github.com_rakudo_rakudo_wiki_Ticket-updates.pod6">Weekly, Monthly and Yearly reports</a></p> | |
</li></ul> <ul><li><p><b>shareable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Shareable.pod6">details</a>)</p> | |
<p>An IRC bot for making rakudo builds produced by Whateverable publicly available. It can be addressed by its full name ('shareable6').</p> | |
<p>Note that the build will be located in <span class="code">/tmp/whateverable/rakudo-moar/SOME-SHA/</span>. Also, as of today these files are only useful for you if you're on linux x86_64.</p> | |
</li></ul> <ul><li><p><b>SourceBaby</b> (<a href="#_routine_https:__github.com_zoffixznet_perl6-sourceable.pod6">details</a>)</p> | |
<p>Core source code locator</p> | |
</li></ul> <ul><li><p><b>statisfiable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Statisfiable.pod6">details</a>)</p> | |
<p>An IRC bot that can gather stats across rakudo builds. It can be addressed by its full name ('statisfiable6') or its short name ('stat'). For most commands it will reply with a gist that has a graph and the raw data. Note that stats are cached, but it takes some time for it to generate the graph, so be patient.</p> | |
</li></ul> <ul><li><p><b>synopsebot6</b> (<a href="#_routine_https:__github.com_perl6_synopsebot.pod6">details</a>)</p> | |
<p>Creates links to the synopses and turns mentions of RT ticket numbers into clickable RT links.</p> | |
</li></ul> <ul><li><p><b>tellable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Tellable.pod6">details</a>)</p> | |
<p>An IRC bot for passing messages to users who are currently offline. You can also use it to see when was the last time somebody talked.</p> | |
</li></ul> <ul><li><p><b>undersightable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Undersightable.pod6">details</a>)</p> | |
<p>An IRC bot for checking that important things are operating correctly (websites are up, bots are online, released tarballs are correct, etc.). It can be addressed by its fullname ('undersightable6').</p> | |
</li></ul> <ul><li><p><b>unicodable</b> (<a href="#_routine_https:__github.com_Raku_whateverable_wiki_Unicodable.pod6">details</a>)</p> | |
<p>An IRC bot for getting interesting information about Unicode characters. It can be addressed by its full name ('unicodable6') or its short name ('u').</p> | |
</li></ul> <ul><li><p><b>PufferBot</b> (<a href="#_routine_https:__github.com_Kaiepi_p6-RakudoBot.pod6">details</a>)</p> | |
<p>An IRC bot for testing builds of Rakudo on OpenBSD. It can be addressed by its full name ('PufferBot'). Talks only in <a href="#_routine_https:__web.libera.chat_?channel=.pod6-raku-dev">#raku-dev</a>.</p> | |
</li></ul> <ul><li><p><b>BeastieBot</b> (<a href="#_routine_https:__github.com_Kaiepi_p6-RakudoBot.pod6">details</a>)</p> | |
<p>An IRC bot for testing builds of Rakudo on FreeBSD. It can be addressed by its full name ('BeastieBot'). Talks only in <a href="#_routine_https:__web.libera.chat_?channel=.pod6-raku-dev">#raku-dev</a>.</p> | |
</li></ul> <a name="t10.2.3"></a> <h2 id="_language_community.pod6-Offline_communities">Offline communities</h2> | |
<p>Raku is also a common topic at <a href="#_routine_https:__www.perl.org_events.html.pod6">Perl conferences</a> and <a href="#_routine_https:__www.pm.org_.pod6">Perl Monger meetings</a> and <a href="#_routine_https:__perl.meetup.com_.pod6">other meetups</a>. If you prefer in-person meetings, these are warmly recommended!</p> | |
<a name="t10.2.4"></a> <h2 id="_language_community.pod6-Other_resources">Other resources</h2> | |
<p><a href="#_routine_https:__raku.org_.pod6">Camelia</a>, the multi-color butterfly with P 6 in her wings, is the symbol of this diverse and welcoming community.</p> | |
<a name="t10.3"></a> <h1 id="_language_community.pod6-Rakudo_Weekly">Rakudo Weekly</h1> | |
<p>Elizabeth Mattijsen usually posts in <a href="#_routine_https:__rakudoweekly.blog_.pod6">the "Rakudo Weekly" blog</a>, a summary of Raku posts, tweets, comments and other interesting tidbits. If you want a single resource to know what is going on in the Raku community now, this is your best resource.</p> | |
<p>Historical articles (pre name change) can be found archived on <a href="#_routine_https:__p6weekly.wordpress.com_.pod6">the "Perl 6 Weekly" blog</a>.</p> | |
<a name="t10.4"></a> <h1 id="_language_community.pod6-Raku_Advent_calendar">Raku Advent calendar</h1> | |
<p>The Raku community publishes every December an <a href="#_routine_https:__raku-advent.blog_.pod6">Advent Calendar</a>, with Raku tutorials every day until Christmas. Previous calendars (pre name change) are <a href="#_routine_https:__perl6advent.wordpress.com_.pod6">still available</a> and relevant.</p> | |
<p>Organization and assignment of days is done through the different Raku channels and the <a href="#_routine_https:__github.com_Raku_advent.pod6">Raku/advent</a> 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.</p> | |
HOW TO WRITE: One topic/point/idea per sentence, one sentence per line - to make diffs & translation easier. | |
</div> | |
<!-- /language/compilation.pod6 --><div class="pod-body"><a id="_language_compilation.pod6"></a><a name="t11"></a><h1 class="title">11 CompUnits and where to find them</h1> <p class="subtitle">How and when Raku modules are compiled, where they are stored, and how to access them in compiled form.</p> <a name="t11.1"></a> <h1 id="_language_compilation.pod6-Overview">Overview</h1> | |
<p>Programs in Raku, as a member of the Perl language family, tend at the top level to be more at the interpreted end of the interpreted-compiled spectrum. In this tutorial, an 'interpreted' program means that the source code, namely the human-readable text such as <span class="code">say 'hello world';</span>, is immediately processed by the <span class="code">Raku</span> program into code that can be executed by the computer, with any intermediate stages being stored in memory.</p> | |
<p>A compiled program, by contrast, is one where the human readable source is first processed into machine-executable code and some form of this code is stored 'on disk'. In order to execute the program, the machine-readable version is loaded into memory and then run by the computer.</p> | |
<p>Both compiled and interpreted forms have advantages. Briefly, interpreted programs can be 'whipped up' quickly and the source changed quickly. Compiled programs can be complex and take a significant time to pre-process into machine-readable code, but then running them is much faster for a user, who only 'sees' the loading and running time, not the compilation time.</p> | |
<p><span class="code">Raku</span> has both paradigms. At the <b>top level</b> a Raku program is interpreted, but code that is separated out into a Module will be compiled and the preprocessed version is then loaded when necessary. In practice, Modules that have been written by the community will only need to be precompiled once by a user when they are 'installed', for example by a Module manager such as <span class="code">zef</span>. Then they can be <span class="code">use</span>d by a developer in her own program. The effect is to make <span class="code">Raku</span> top level programs run quickly.</p> | |
<p>One of the great strengths of the <span class="code">Perl</span> family of languages was the ability to integrate a whole ecosystem of modules written by competent programmers into a small program. This strength was widely copied and is now the norm for all languages. <span class="code">Raku</span> takes integration even further, making it relatively easy for <span class="code">Raku</span> programs to incorporate system libraries written in other languages into <span class="code">Raku</span> programs, see <a href="#_language_nativecall.pod6">Native Call</a>.</p> | |
<p>The experience from <span class="code">Perl</span> and other languages is that the distributive nature of Modules generate several practical difficulties:</p> | |
<ul><li><p>a popular module may go through several iterations as the API gets improved, without a guarantee that there is backward compatibility. So, if a program relies on some specific function or return, then there has to be a way to specify the <b>Version</b>.</p> | |
</li></ul> <ul><li><p>a module may have been written by Bob, a very competent programmer, who moves on in life, leaving the module unmaintained, so Alice takes over. This means that the same module, with the same name, and the same general API may have two versions in the wild. Alternatively, two developers (e.g., Alice and Bob) who initially cooperated on a module, then part company about its development. Consequently, it sometimes is necessary for there to be a way to define the <b>Auth</b> of the module.</p> | |
</li></ul> <ul><li><p>a module may be enhanced over time and the maintainer keeps two versions up to date, but with different APIs. So it is may be necessary to define the <b>API</b> required.</p> | |
</li></ul> <ul><li><p>when developing a new program a developer may want to have the modules written by both Alice and Bob installed locally. So it is not possible simply to have only one version of a module with a single name installed.</p> | |
</li></ul> <p><span class="code">Raku</span> enables all of these possibilities, allowing for multiple versions, multiple authorities, and multiple APIs to be present, installed, and available locally. The way classes and modules can be accessed with specific attributes is explained <a href="#_language_typesystem.pod6-Versioning,_authorship,_and_API_version.">elsewhere</a>. This tutorial is about how <span class="code">Raku</span> handles these possibilities.</p> | |
<a name="t11.2"></a> <h1 id="_language_compilation.pod6-Introduction">Introduction</h1> | |
<p>Before considering the <span class="code">Raku</span> framework, let's have a look at how languages like <span class="code">Perl</span> or <span class="code">Python</span> handle module installation and loading.</p> | |
<pre class="code">ACME::Foo::Bar -> ACME/Foo/Bar.pm | |
os.path -> os/path.py | |
</pre> | |
<p>In those languages, module names have a 1:1 relation with filesystem paths. We simply replace the double colons or periods with slashes and add a <span class="code">.pm</span> or <span class="code">.py</span>.</p> | |
<p>Note that these are relative paths. Both <span class="code">Python</span> and <span class="code">Perl</span> use a list of include paths, to complete these paths. In <span class="code">Perl</span> they are available in the global <span class="code">@INC</span> array.</p> | |
<pre class="code">@INC | |
/usr/lib/perl5/site_perl/5.22.1/x86_64-linux-thread-multi | |
/usr/lib/perl5/site_perl/5.22.1/ | |
/usr/lib/perl5/vendor_perl/5.22.1/x86_64-linux-thread-multi | |
/usr/lib/perl5/vendor_perl/5.22.1/ | |
/usr/lib/perl5/5.22.1/x86_64-linux-thread-multi | |
/usr/lib/perl5/5.22.1/ | |
</pre> | |
<p>Each of these include directories is checked for whether it contains a relative path determined from the module name. If the shoe fits, the file is loaded.</p> | |
<p>Of course that's a bit of a simplified version. Both languages support caching compiled versions of modules. So instead of just the <span class="code">.pm</span> file <span class="code">Perl</span> first looks for a <span class="code">.pmc</span> file. And <span class="code">Python</span> first looks for <span class="code">.pyc</span> files.</p> | |
<p>Module installation in both cases means mostly copying files into locations determined by the same simple mapping. The system is easy to explain, easy to understand, simple and robust.</p> | |
<a name="t11.2.1"></a> <h2 id="_language_compilation.pod6-Why_change?">Why change?</h2> | |
<p>Why would <span class="code">Raku</span> need another framework? The reason is there are features that those languages lack, namely:</p> | |
<ul><li><p>Unicode module names</p> | |
</li></ul> <ul><li><p>Modules published under the same names by different authors</p> | |
</li></ul> <ul><li><p>Having multiple versions of a module installed</p> | |
</li></ul> <p>The set of 26 Latin characters is too restrictive for virtually all real modern languages, including English, which have diacritics for many commonly-used words.</p> | |
<p>With a 1:1 relation between module names and filesystem paths, you enter a world of pain once you try to support Unicode on multiple platforms and filesystems.</p> | |
<p>Then there's sharing module names between multiple authors. This one may or may not work out well in practice. I can imagine using it for example for publishing a module with some fix until the original author includes the fix in the "official" version.</p> | |
<p>Finally there's multiple versions. Usually people who need certain versions of modules reach for local::lib or containers or some home grown workarounds. They all have their own disadvantages. None of them would be necessary if applications could just say, hey I need good old, trusty version 2.9 or maybe a bug fix release of that branch.</p> | |
<p>If you had any hopes of continuing using the simple name mapping solution, you probably gave up at the versioning requirement. Because, how would you find version 3.2 of a module when looking for a 2.9 or higher?</p> | |
<p>Popular ideas included collecting information about installed modules in JSON files but when those turned out to be toe-nail growing slow, text files were replace by putting the metadata into SQLite databases. However, these ideas can be easily shot down by introducing another requirement: distribution packages.</p> | |
<p>Packages for Linux distributions are mostly just archives containing some files plus some metadata. Ideally the process of installing such a package means just unpacking the files and updating the central package database. Uninstalling means deleting the files installed this way and again updating the package database. Changing existing files on install and uninstall makes packagers' lives much harder, so we really want to avoid that. Also the names of the installed files may not depend on what was previously installed. We must know at the time of packaging what the names are going to be.</p> | |
<a name="t11.2.2"></a> <h2 id="_language_compilation.pod6-Long_names">Long names</h2> | |
<pre class="code">Foo::Bar:auth<cpan:nine>:ver<0.3>:api<1> | |
</pre> | |
<p>Step 0 in getting us back out of this mess is to define a long name. A full module name in <span class="code">Raku</span> consists of the short-name, auth, version and API</p> | |
<p>At the same time, the thing you install is usually not a single module but a distribution which probably contains one or more modules. Distribution names work just the same way as module names. Indeed, distributions often will just be called after their main module. An important property of distributions is that they are immutable. <span class="code">Foo:auth<cpan:nine>:ver<0.3>:api<1> </span> will always be the name for exactly the same code.</p> | |
<a name="t11.2.3"></a> <h2 id="_language_compilation.pod6-$*REPO">$*REPO</h2> | |
<p>In <span class="code">Perl</span> and <span class="code">Python</span> you deal with include paths pointing to filesystem directories. In <span class="code">Raku</span> we call such directories "repositories" and each of these repositories is governed by an object that does the <span class="code">CompUnit::Repository</span> role. Instead of an <span class="code">B<@INC></span> array, there's the <span class="code">$*REPO</span> variable. It contains a single repository object. This object has a <b>next-repo</b> attribute that may contain another repository. In other words: repositories are managed as a <i>linked list</i>. The important difference to the traditional array is, that when going through the list, each object has a say in whether to pass along a request to the next-repo or not. <span class="code">Raku</span> sets up a standard set of repositories, "core", "vendor", and "site". In addition, there is a "home" repository for the current user.</p> | |
<p>Repositories must implement the <span class="code">need</span> method. A <span class="code">use</span> or <span class="code">require</span> statement in <span class="code">Raku</span> code is basically translated to a call to <span class="code">B<$*REPO></span>'s <span class="code">need</span> method. This method may in turn delegate the request to the next-repo.</p> | |
<pre class="code">role CompUnit::Repository { | |
has CompUnit::Repository $.next-repo is rw; | |
method need(CompUnit::DependencySpecification $spec, | |
CompUnit::PrecompilationRepository $precomp, | |
CompUnit::Store :@precomp-stores | |
--> CompUnit:D | |
) | |
{ ... } | |
method loaded( | |
--> Iterable | |
) | |
{ ... } | |
method id( --> Str ) | |
{ ... } | |
} | |
</pre> | |
<a name="t11.2.4"></a> <h2 id="_language_compilation.pod6-Repositories">Repositories</h2> | |
<p>Rakudo comes with several classes that can be used for repositories. The most important ones are <span class="code">CompUnit::Repository::FileSystem</span> and <span class="code">CompUnit::Repository::Installation</span>. The FileSystem repo is meant to be used during module development and actually works just like <span class="code">Perl</span> when looking for a module. It doesn't support versions or <span class="code">auth</span>s and simply maps the short-name to a filesystem path.</p> | |
<p>The Installation repository is where the real smarts are. When requesting a module, you will usually either do it via its exact long name, or you say something along the lines of "give me a module that matches this filter." Such a filter is given by way of a <span class="code">CompUnit::DependencySpecification</span> object which has fields for</p> | |
<ul><li><p>short-name,</p> | |
</li></ul> <ul><li><p>auth-matcher,</p> | |
</li></ul> <ul><li><p>version-matcher and</p> | |
</li></ul> <ul><li><p>api-matcher.</p> | |
</li></ul> <p>When looking through candidates, the Installation repository will smartmatch a module's long name against this DependencySpecification or rather the individual fields against the individual matchers. Thus a matcher may be some concrete value, a version range, or even a regex (though an arbitrary regex, such as <span class="code">.*</span>, would not produce a useful result, but something like <span class="code">3.20.1+</span> will only find candidates higher than 3.20.1).</p> | |
<p>Loading the metadata of all installed distributions would be prohibitively slow. The current implementation of the <span class="code">Raku</span> framework uses the filesystem as a kind of database. However, another implementation may use another strategy. The following description shows how one implementation works and is included here to illustrate what is happening.</p> | |
<p>We store not only a distribution's files but also create indices for speeding up lookups. One of these indices comes in the form of directories named after the short-name of installed modules. However most of the filesystems in common use today cannot handle Unicode names, so we cannot just use module names directly. This is where the now infamous SHA-1 hashes enter the game. The directory names are the ASCII encoded SHA-1 hashes of the UTF-8 encoded module short-names.</p> | |
<p>In these directories we find one file per distribution that contains a module with a matching short name. These files again contain the ID of the dist and the other fields that make up the long name: auth, version, and api. So by reading these files we have a usually short list of auth-version-api triplets which we can match against our DependencySpecification. We end up with the winning distribution's ID, which we use to look up the metadata, stored in a JSON encoded file. This metadata contains the name of the file in the sources/ directory containing the requested module's code. This is what we can load.</p> | |
<p>Finding names for source files is again a bit tricky, as there's still the Unicode issue and in addition the same relative file names may be used by different installed distributions (think versions). So for now at least, we use SHA-1 hashes of the long-names.</p> | |
<a name="t11.2.5"></a> <h2 id="_language_compilation.pod6-Resources">Resources</h2> | |
<pre class="code">%?RESOURCES | |
%?RESOURCES<libraries/p5helper> | |
%?RESOURCES<icons/foo.png> | |
%?RESOURCES<schema.sql> | |
Foo | |
|___ lib | |
| |____ Foo.rakumod | |
| | |
|___ resources | |
|___ schema.sql | |
| | |
|___ libraries | |
|____ p5helper | |
| |___ | |
|___ icons | |
|___ foo.png | |
</pre> | |
<p>It's not only source files that are stored and found this way. Distributions may also contain arbitrary resource files. These could be images, language files or shared libraries that are compiled on installation. They can be accessed from within the module through the <span class="code">%?RESOURCES</span> hash.</p> | |
<p>As long as you stick to the standard layout conventions for distributions, this even works during development without installing anything.</p> | |
<p>A nice result of this architecture is that it's fairly easy to create special purpose repositories.</p> | |
<a name="t11.2.6"></a> <h2 id="_language_compilation.pod6-Dependencies">Dependencies</h2> | |
<p>Luckily precompilation at least works quite well in most cases. Yet it comes with its own set of challenges. Loading a single module is easy. The fun starts when a module has dependencies and those dependencies have again dependencies of their own.</p> | |
<p>When loading a precompiled file in <span class="code">Raku</span> we need to load the precompiled files of all its dependencies, too. And those dependencies <b>must</b> be precompiled, we cannot load them from source files. Even worse, the precomp files of the dependencies <b>must</b> be exactly the same files we used for precompiling our module in the first place.</p> | |
<p>To top it off, precompiled files work only with the exact <span class="code">Raku</span> binary, that was used for compilation.</p> | |
<p>All of that would still be quite manageable if it weren't for an additional requirement: as a user you expect a new version of a module you just installed to be actually used, don't you?</p> | |
<p>In other words: if you upgrade a dependency of a precompiled module, we have to detect this and precompile the module again with the new dependency.</p> | |
<a name="t11.2.7"></a> <h2 id="_language_compilation.pod6-Precomp_stores">Precomp stores</h2> | |
<p>Now remember that while we have a standard repository chain, the user may prepend additional repositories by way of <span class="code">-I</span> on the command line or "use lib" in the code.</p> | |
<p>These repositories may contain the dependencies of precompiled modules.</p> | |
<p>Our first solution to this riddle was that each repository gets its own precomp store where precompiled files are stored. We only ever load precomp files from the precomp store of the very first repository in the chain because this is the only repository that has direct or at least indirect access to all the candidates.</p> | |
<p>If this repository is a FileSystem repository, we create a precomp store in a <span class="code">.precomp</span> directory.</p> | |
<p>While being the safe option, this has the consequence that whenever you use a new repository, we will start out without access to precompiled files.</p> | |
<p>Instead, we will precompile the modules used when they are first loaded.</p> | |
<a name="t11.2.8"></a> <h2 id="_language_compilation.pod6-Credit">Credit</h2> | |
<p>This tutorial is based on a <span class="code">niner</span> <a href="#_routine_http:__niner.name_talks_A%20look%20behind%20the%20curtains%20-%20module%20loading%20in%20Perl%206_.pod6">talk</a>.</p> | |
</div> | |
<!-- /language/concurrency.pod6 --><div class="pod-body"><a id="_language_concurrency.pod6"></a><a name="t12"></a><h1 class="title">12 Concurrency</h1> <p class="subtitle">Concurrency and asynchronous programming</p> <p>In common with most modern programming languages, Raku is designed to support parallelism, asynchronicity and <a href="#_routine_https:__en.wikipedia.org_wiki_Concurrent_computing.pod6">concurrency</a>. Parallelism is about doing multiple things at once. <i>Asynchronous programming</i>, 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.</p> | |
<p>The aim of the Raku 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.</p> | |
I'm not quite clear which specific features should be included below | |
hyper-operators, autothreading junctions? | |
<p>Additionally, certain Raku 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., <a href="#_type_Thread.pod6">Thread</a> and <a href="#_type_Scheduler.pod6">Scheduler</a>) and use the higher-level interfaces.</p> | |
<a name="t12.1"></a> <h1 id="_language_concurrency.pod6-High-level_APIs">High-level APIs</h1> | |
<p><a id="i241" name="Other languages Futures"></a><span class="indexed"></span></p> | |
<a name="t12.1.1"></a> <h2 id="_language_concurrency.pod6-Promises">Promises</h2> | |
<p>A <a href="#_type_Promise.pod6">Promise</a> (also called <i>future</i> 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 <span class="code">Promise</span> starts from a <span class="code">Planned</span> status and can result in either a <span class="code">Kept</span> status, meaning the promise has been successfully completed, or a <span class="code">Broken</span> 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.</p> | |
<pre class="code">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» | |
</pre> | |
<p>Promises gain much of their power by being composable, for example by chaining, usually by the <a href="#_type_Promise.pod6-method_then">then</a> method:</p> | |
<pre class="code">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»</pre> | |
<p>Here the <a href="#_type_Promise.pod6-method_then">then</a> method schedules code to be executed when the first <a href="#_type_Promise.pod6">Promise</a> is kept or broken, itself returning a new <a href="#_type_Promise.pod6">Promise</a> which will be kept with the result of the code when it is executed (or broken if the code fails). <span class="code">keep</span> changes the status of the promise to <span class="code">Kept</span> setting the result to the positional argument. <span class="code">result</span> 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 <span class="code">keep</span>), otherwise it will throw an exception based on the value passed to <span class="code">break</span>. The latter behavior is illustrated with:</p> | |
<pre class="code">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»</pre> | |
<p>Here the <span class="code">break</span> will cause the code block of the <span class="code">then</span> to throw an exception when it calls the <span class="code">result</span> 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 <a href="#_type_Exception.pod6">Exception</a> object will then be available from <span class="code">cause</span>. If the promise had not been broken <span class="code">cause</span> would raise a <a href="#_type_X::Promise::CauseOnlyValidOnBroken.pod6">X::Promise::CauseOnlyValidOnBroken</a> exception.</p> | |
<p>A <a href="#_type_Promise.pod6">Promise</a> can also be scheduled to be automatically kept at a future time:</p> | |
<pre class="code">my $promise1 = Promise.in(5); | |
my $promise2 = $promise1.then(-> $v { say $v.status; 'Second Result' }); | |
say $promise2.result;</pre> | |
<p>The <a href="#_type_Promise.pod6-method_in">method in</a> creates a new promise and schedules a new task to call <span class="code">keep</span> on it no earlier than the supplied number of seconds, returning the new <a href="#_type_Promise.pod6">Promise</a> object.</p> | |
<p>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 <a href="#_type_Promise.pod6-method_start">start method</a> provides a shortcut for that:</p> | |
<pre class="code">my $promise = Promise.start( | |
{ my $i = 0; for 1 .. 10 { $i += $_ }; $i} | |
); | |
say $promise.result; # OUTPUT: «55»</pre> | |
<p>Here the <span class="code">result</span> of the promise returned is the value returned from the code. Similarly if the code fails (and the promise is thus broken), then <span class="code">cause</span> will be the <a href="#_type_Exception.pod6">Exception</a> object that was thrown:</p> | |
<pre class="code">my $promise = Promise.start({ die "Broken Promise" }); | |
try $promise.result; | |
say $promise.cause;</pre> | |
<p>This is considered to be such a commonly required pattern that it is also provided as a keyword:</p> | |
<pre class="code">my $promise = start { | |
my $i = 0; | |
for 1 .. 10 { | |
$i += $_ | |
} | |
$i | |
} | |
my $result = await $promise; | |
say $result;</pre> | |
<p>The subroutine <a href="#_type_Promise.pod6-sub_await">await</a> is almost equivalent to calling <span class="code">result</span> on the promise object returned by <span class="code">start</span> but it will also take a list of promises and return the result of each:</p> | |
<pre class="code">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]»</pre> | |
<p>In addition to <span class="code">await</span>, two class methods combine several <a href="#_type_Promise.pod6">Promise</a> objects into a new promise: <span class="code">allof</span> returns a promise that is kept when all the original promises are kept or broken:</p> | |
<pre class="code">my $promise = Promise.allof( | |
Promise.in(2), | |
Promise.in(3) | |
); | |
await $promise; | |
say "All done"; # Should be not much more than three seconds later</pre> | |
<p>And <span class="code">anyof</span> returns a new promise that will be kept when any of the original promises is kept or broken:</p> | |
<pre class="code">my $promise = Promise.anyof( | |
Promise.in(3), | |
Promise.in(8600) | |
); | |
await $promise; | |
say "All done"; # Should be about 3 seconds later</pre> | |
<p>Unlike <span class="code">await</span> 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:</p> | |
<pre class="code">my @promises; | |
for 1..5 -> $t { | |
push @promises, start { | |
sleep $t; | |
Bool.pick; | |
}; | |
} | |
say await Promise.allof(@promises).then({ so all(@promises>>.result) });</pre> | |
<p>Which will give True if all of the promises were kept with True, False otherwise.</p> | |
<p>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 <a href="#_type_Promise.pod6-method_vow">method vow</a>, 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 <a href="#_type_X::Promise::Vowed.pod6">X::Promise::Vowed</a> will be thrown, as long as the vow object is kept private, the status of the promise is safe:</p> | |
<pre class="code">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»</pre> | |
<p>The methods that return a promise that will be kept or broken automatically such as <span class="code">in</span> or <span class="code">start</span> will do this, so it is not necessary to do it for these.</p> | |
<a name="t12.1.2"></a> <h2 id="_language_concurrency.pod6-Supplies">Supplies</h2> | |
<p>A <a href="#_type_Supply.pod6">Supply</a> 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 <i>event driven</i> or reactive designs.</p> | |
<p>At its simplest, a <a href="#_type_Supply.pod6">Supply</a> is a message stream that can have multiple subscribers created with the method <span class="code">tap</span> on to which data items can be placed with <span class="code">emit</span>.</p> | |
<p>The <a href="#_type_Supply.pod6">Supply</a> can either be <span class="code">live</span> or <span class="code">on-demand</span>. A <span class="code">live</span> supply is like a TV broadcast: those who tune in don't get previously emitted values. An <span class="code">on-demand</span> 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 <span class="code">on-demand</span> supplies, instead, the <span class="code">supply</span> block is run for each tap of the supply.</p> | |
<p>A <span class="code">live</span> <a href="#_type_Supply.pod6">Supply</a> is created by the <a href="#_type_Supplier.pod6">Supplier</a> factory, each emitted value is passed to all the active tappers as they are added:</p> | |
<pre class="code">my $supplier = Supplier.new; | |
my $supply = $supplier.Supply; | |
$supply.tap( -> $v { say $v }); | |
for 1 .. 10 { | |
$supplier.emit($_); | |
}</pre> | |
<p>Note that the <span class="code">tap</span> is called on a <a href="#_type_Supply.pod6">Supply</a> object created by the <a href="#_type_Supplier.pod6">Supplier</a> and new values are emitted on the <a href="#_type_Supplier.pod6">Supplier</a>.</p> | |
<p><a id="i242" name="Reference supply (on-demand)"></a><span class="indexed"></span> An <span class="code">on-demand</span> <a href="#_type_Supply.pod6">Supply</a> is created by the <span class="code">supply</span> keyword:</p> | |
<pre class="code">my $supply = supply { | |
for 1 .. 10 { | |
emit($_); | |
} | |
} | |
$supply.tap( -> $v { say $v });</pre> | |
<p>In this case the code in the supply block is executed every time the <a href="#_type_Supply.pod6">Supply</a> returned by <span class="code">supply</span> is tapped, as demonstrated by:</p> | |
<pre class="code">my $supply = supply { | |
for 1 .. 10 { | |
emit($_); | |
} | |
} | |
$supply.tap( -> $v { say "First : $v" }); | |
$supply.tap( -> $v { say "Second : $v" });</pre> | |
<p>The <span class="code">tap</span> method returns a <a href="#_type_Tap.pod6">Tap</a> 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:</p> | |
<pre class="code">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");</pre> | |
<p>Calling <span class="code">done</span> on the supply object calls the <span class="code">done</span> callback that may be specified for any taps, but does not prevent any further events being emitted to the stream, or taps receiving them.</p> | |
<p>The method <span class="code">interval</span> returns a new <span class="code">on-demand</span> 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 :</p> | |
<pre class="code">my $supply = Supply.interval(2); | |
$supply.tap(-> $v { say $v }); | |
sleep 10;</pre> | |
<p>A second argument can be supplied to <span class="code">interval</span> which specifies a delay in seconds before the first event is fired. Each tap of a supply created by <span class="code">interval</span> has its own sequence starting from 0, as illustrated by the following:</p> | |
<pre class="code">my $supply = Supply.interval(2); | |
$supply.tap(-> $v { say "First $v" }); | |
sleep 6; | |
$supply.tap(-> $v { say "Second $v"}); | |
sleep 10;</pre> | |
<p>A live <span class="code">Supply</span> that keeps values until first tapped can be created with <a href="#_type_Supplier::Preserving.pod6">Supplier::Preserving</a>.</p> | |
<a name="t12.1.2.1"></a> <h3 id="_language_concurrency.pod6-whenever"><a name="243"></a><span class="code">whenever</span></h3> | |
<p>The <span class="code">whenever</span> 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 <a href="#_type_Supply.pod6">Supply</a>, a <a href="#_type_Channel.pod6">Channel</a>, a <a href="#_type_Promise.pod6">Promise</a> or an <a href="#_type_Iterable.pod6">Iterable</a>.</p> | |
<p>Please note that one should keep the code inside the <span class="code">whenever</span> as small as possible, as only one <span class="code">whenever</span> block will be executed at any time. One can use a <span class="code">start</span> block inside the <span class="code">whenever</span> block to run longer running code.</p> | |
<p>In this example we are watching two supplies.</p> | |
<pre class="code">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» | |
</pre> | |
<a name="t12.1.2.2"></a> <h3 id="_language_concurrency.pod6-react"><a name="244"></a><span class="code">react</span></h3> | |
<p>The <span class="code">react</span> keyword introduces a block of code containing one or more <span class="code">whenever</span> 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.</p> | |
<p>Another difference is that a supply block can be used without the <span class="code">whenever</span> keyword, but a react block requires at least one <span class="code">whenever</span> to be of any real use.</p> | |
<pre class="code">react { | |
whenever Supply.interval(2) -> $v { | |
say $v; | |
done() if $v == 4; | |
} | |
}</pre> | |
<p>Here the <span class="code">whenever</span> keyword uses <a href="#_type_Supply.pod6-method_act"><span class="code">.act</span></a> to create a tap on the <a href="#_type_Supply.pod6">Supply</a> from the provided block. The <span class="code">react</span> block is exited when <span class="code">done()</span> is called in one of the taps. Using <span class="code">last</span> to exit the block would produce an error indicating that it's not really a loop construct.</p> | |
<p>An <span class="code">on-demand</span> <a href="#_type_Supply.pod6">Supply</a> can also be created from a list of values that will be emitted in turn, thus the first <span class="code">on-demand</span> example could be written as:</p> | |
<pre class="code">react { | |
whenever Supply.from-list(1..10) -> $v { | |
say $v; | |
} | |
}</pre> | |
<a name="t12.1.2.3"></a> <h3 id="_language_concurrency.pod6-Transforming_supplies">Transforming supplies</h3> | |
<p>An existing supply object can be filtered or transformed, using the methods <span class="code">grep</span> and <span class="code">map</span> respectively, to create a new supply in a manner like the similarly named list methods: <span class="code">grep</span> returns a supply such that only those events emitted on the source stream for which the <span class="code">grep</span> condition is true is emitted on the second supply:</p> | |
<pre class="code">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($_); | |
}</pre> | |
<p><span class="code">map</span> 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 <span class="code">map</span> is emitted:</p> | |
<pre class="code">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($_); | |
}</pre> | |
<a name="t12.1.2.4"></a> <h3 id="_language_concurrency.pod6-Ending_a_supply">Ending a supply</h3> | |
<p>If you need to have an action that runs when the supply finishes, you can do so by setting the <span class="code">done</span> and <span class="code">quit</span> options in the call to <span class="code">tap</span>:</p> | |
<pre class="code">$supply.tap: { ... }, | |
done => { say 'Job is done.' }, | |
quit => { | |
when X::MyApp::Error { say "App Error: ", $_.message } | |
}; | |
</pre> | |
<p>The <span class="code">quit</span> block works very similar to a <span class="code">CATCH</span>. If the exception is marked as seen by a <span class="code">when</span> or <span class="code">default</span> block, the exception is caught and handled. Otherwise, the exception continues to up the call tree (i.e., the same behavior as when <span class="code">quit</span> is not set).</p> | |
<a name="t12.1.2.5"></a> <h3 id="_language_concurrency.pod6-Phasers_in_a_supply_or_react_block">Phasers in a supply or react block</h3> | |
<p>If you are using the <span class="code">react</span> or <span class="code">supply</span> block syntax with <span class="code">whenever</span>, you can add phasers within your <span class="code">whenever</span> blocks to handle the <span class="code">done</span> and <span class="code">quit</span> messages from the tapped supply:</p> | |
<pre class="code">react { | |
whenever $supply { | |
...; # your usual supply tap code here | |
LAST { say 'Job is done.' } | |
QUIT { when X::MyApp::Error { say "App Error: ", $_.message } } | |
} | |
} | |
</pre> | |
<p>The behavior here is the same as setting <span class="code">done</span> and <span class="code">quit</span> on <span class="code">tap</span>.</p> | |
<a name="t12.1.3"></a> <h2 id="_language_concurrency.pod6-Channels">Channels</h2> | |
<p>A <a href="#_type_Channel.pod6">Channel</a> 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 <a href="#_type_Channel.pod6">Channel</a> 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 <a href="#_type_Supply.pod6">Supply</a>.</p> | |
<p>An item is queued onto the <a href="#_type_Channel.pod6">Channel</a> with the <a href="#_type_Channel.pod6-method_send">method send</a>, and the <a href="#_type_Channel.pod6-method_receive">method receive</a> removes an item from the queue and returns it, blocking until a new item is sent if the queue is empty:</p> | |
<pre class="code">my $channel = Channel.new; | |
$channel.send('Channel One'); | |
say $channel.receive; # OUTPUT: «Channel One»</pre> | |
<p>If the channel has been closed with the <a href="#_type_Channel.pod6-method_close">method close</a> then any <span class="code">send</span> will cause the exception <a href="#_type_X::Channel::SendOnClosed.pod6">X::Channel::SendOnClosed</a> to be thrown, and a <span class="code">receive</span> will throw a <a href="#_type_X::Channel::ReceiveOnClosed.pod6">X::Channel::ReceiveOnClosed</a>.</p> | |
<p>The <a href="#_type_Channel.pod6-method_list">method list</a> returns all the items on the <a href="#_type_Channel.pod6">Channel</a> and will block until further items are queued unless the channel is closed:</p> | |
<pre class="code">my $channel = Channel.new; | |
await (^10).map: -> $r { | |
start { | |
sleep $r; | |
$channel.send($r); | |
} | |
} | |
$channel.close; | |
for $channel.list -> $r { | |
say $r; | |
}</pre> | |
<p>There is also the non-blocking <a href="#_type_Channel.pod6-method_poll">method poll</a> that returns an available item from the channel or <a href="#_type_Nil.pod6">Nil</a> if there is no item or the channel is closed. This does mean that the channel must be checked to determine whether it is closed:</p> | |
<pre class="code">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...</pre> | |
<p>The <a href="#_type_Channel.pod6-method_closed">method closed</a> returns a <a href="#_type_Promise.pod6">Promise</a> that will be kept (and consequently will evaluate to True in a Boolean context) when the channel is closed.</p> | |
<p>The <span class="code">.poll</span> method can be used in combination with <span class="code">.receive</span> method, as a caching mechanism where lack of value returned by <span class="code">.poll</span> is a signal that more values need to be fetched and loaded into the channel:</p> | |
<pre class="code">sub get-value { | |
return $c.poll // do { start replenish-cache; $c.receive }; | |
} | |
sub replenish-cache { | |
for ^20 { | |
$c.send: $_ for slowly-fetch-a-thing(); | |
} | |
} | |
</pre> | |
<p>Channels can be used in place of the <a href="#_type_Supply.pod6">Supply</a> in the <span class="code">whenever</span> of a <span class="code">react</span> block described earlier:</p> | |
<pre class="code">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; | |
</pre> | |
<p>It is also possible to obtain a <a href="#_type_Channel.pod6">Channel</a> from a <a href="#_type_Supply.pod6">Supply</a> using the <a href="#_type_Supply.pod6-method_Channel">Channel method</a> which returns a <a href="#_type_Channel.pod6">Channel</a> which is fed by a <span class="code">tap</span> on the <a href="#_type_Supply.pod6">Supply</a>:</p> | |
<pre class="code">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;</pre> | |
<p><span class="code">Channel</span> will return a different <a href="#_type_Channel.pod6">Channel</a> fed with the same data each time it is called. This could be used, for instance, to fan-out a <a href="#_type_Supply.pod6">Supply</a> to one or more <a href="#_type_Channel.pod6">Channel</a>s to provide for different interfaces in a program.</p> | |
<a name="t12.1.4"></a> <h2 id="_language_concurrency.pod6-Proc::Async">Proc::Async</h2> | |
<p><a href="#_type_Proc::Async.pod6">Proc::Async</a> builds on the facilities described to run and interact with an external program asynchronously:</p> | |
<pre class="code">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.</pre> | |
<p>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 <a href="#_type_Proc::Async.pod6-method_start">start</a> is called, which will return a <a href="#_type_Promise.pod6">Promise</a> that will be kept when the program exits. The standard output and standard error of the program are available as <a href="#_type_Supply.pod6">Supply</a> objects from the methods <a href="#_type_Proc::Async.pod6-method_stdout">stdout</a> and <a href="#_type_Proc::Async.pod6-method_stderr">stderr</a> respectively which can be tapped as required.</p> | |
<p>If you want to write to the standard input of the program you can supply the <span class="code">:w</span> adverb to the constructor and use the methods <a href="#_type_Proc::Async.pod6-method_write">write</a>, <a href="#_type_Proc::Async.pod6-method_print">print</a> or <a href="#_type_Proc::Async.pod6-method_say">say</a> to write to the opened pipe once the program has been started:</p> | |
<pre class="code">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.</pre> | |
<p>Some programs (such as <span class="code">grep</span> without a file argument in this example, ) won't exit until their standard input is closed so <a href="#_type_Proc::Async.pod6-method_close-stdin">close-stdin</a> can be called when you are finished writing to allow the <a href="#_type_Promise.pod6">Promise</a> returned by <span class="code">start</span> to be kept.</p> | |
<a name="t12.2"></a> <h1 id="_language_concurrency.pod6-Low-level_APIs">Low-level APIs</h1> | |
<a name="t12.2.1"></a> <h2 id="_language_concurrency.pod6-Threads">Threads</h2> | |
<p>The lowest level interface for concurrency is provided by <a href="#_type_Thread.pod6">Thread</a>. 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.</p> | |
<p>A thread can either be created and then actually run later:</p> | |
<pre class="code">my $thread = Thread.new(code => { for 1 .. 10 -> $v { say $v }}); | |
# ... | |
$thread.run;</pre> | |
<p>Or can be created and run at a single invocation:</p> | |
<pre class="code">my $thread = Thread.start({ for 1 .. 10 -> $v { say $v }});</pre> | |
<p>In both cases the completion of the code encapsulated by the <a href="#_type_Thread.pod6">Thread</a> object can be waited on with the <span class="code">finish</span> method which will block until the thread completes:</p> | |
<pre class="code">$thread.finish; | |
</pre> | |
<p>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.</p> | |
<a name="t12.2.2"></a> <h2 id="_language_concurrency.pod6-Schedulers">Schedulers</h2> | |
<p>The next level of the concurrency API is supplied by classes that implement the interface defined by the role <a href="#_type_Scheduler.pod6">Scheduler</a>. 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 <a href="#_type_Proc::Async.pod6">Proc::Async</a>, <a href="#_type_Promise.pod6">Promise</a> and <a href="#_type_Supply.pod6">Supply</a> allow you to explicitly supply a scheduler.</p> | |
<p>The current default global scheduler is available in the variable <span class="code">$*SCHEDULER</span>.</p> | |
<p>The primary interface of a scheduler (indeed the only method required by the <a href="#_type_Scheduler.pod6">Scheduler</a> interface) is the <span class="code">cue</span> method:</p> | |
<pre class="code">method cue(:&code, Instant :$at, :$in, :$every, :$times = 1; :&catch)</pre> | |
<p>This will schedule the <a href="#_type_Callable.pod6">Callable</a> in <span class="code">&code</span> to be executed in the manner determined by the adverbs (as documented in <a href="#_type_Scheduler.pod6">Scheduler</a>) using the execution scheme as implemented by the scheduler. For example:</p> | |
<pre class="code">my $i = 0; | |
my $cancellation = $*SCHEDULER.cue({ say $i++}, every => 2 ); | |
sleep 20;</pre> | |
<p>Assuming that the <span class="code">$*SCHEDULER</span> 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 <a href="#_type_Cancellation.pod6">Cancellation</a> object which can be used to cancel the scheduled execution before normal completion:</p> | |
<pre class="code">my $i = 0; | |
my $cancellation = $*SCHEDULER.cue({ say $i++}, every => 2 ); | |
sleep 10; | |
$cancellation.cancel; | |
sleep 10;</pre> | |
<p>should only output 0 to 5.</p> | |
<p>Despite the apparent advantage the <a href="#_type_Scheduler.pod6">Scheduler</a> interface provides over that of <a href="#_type_Thread.pod6">Thread</a> 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.</p> | |
<p>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.</p> | |
<a name="t12.2.2.1"></a> <h3 id="_language_concurrency.pod6-ThreadPoolScheduler">ThreadPoolScheduler</h3> | |
<p>The <a href="#_type_ThreadPoolScheduler.pod6">ThreadPoolScheduler</a> 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 <span class="code">cue</span> may queue the code until such time as a thread becomes available.</p> | |
<p>Rakudo allows the maximum number of threads allowed in the default scheduler to be set by the environment variable <span class="code">RAKUDO_MAX_THREADS</span> at the time the program is started.</p> | |
<a name="t12.2.2.2"></a> <h3 id="_language_concurrency.pod6-CurrentThreadScheduler">CurrentThreadScheduler</h3> | |
<p>The <a href="#_type_CurrentThreadScheduler.pod6">CurrentThreadScheduler</a> is a very simple scheduler that will always schedule code to be run straight away on the current thread. The implication is that <span class="code">cue</span> on this scheduler will block until the code finishes execution, limiting its utility to certain special cases such as testing.</p> | |
<a name="t12.2.3"></a> <h2 id="_language_concurrency.pod6-Locks">Locks</h2> | |
<p>The class <a href="#_type_Lock.pod6">Lock</a> 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 (<a href="#_type_Promise.pod6">Promise</a>, <a href="#_type_Supply.pod6">Supply</a> and <a href="#_type_Channel.pod6">Channel</a>) use a <a href="#_type_Lock.pod6">Lock</a> where required it is unlikely that user code will need to use a <a href="#_type_Lock.pod6">Lock</a> directly.</p> | |
<p>The primary interface to <a href="#_type_Lock.pod6">Lock</a> is the method <a href="#_type_Lock.pod6-method_protect">protect</a> which ensures that a block of code (commonly called a "critical section") is only executed in one thread at a time:</p> | |
<pre class="code">my $lock = Lock.new; | |
my $a = 0; | |
await (^10).map: { | |
start { | |
$lock.protect({ | |
my $r = rand; | |
sleep $r; | |
$a++; | |
}); | |
} | |
} | |
say $a; # OUTPUT: «10»</pre> | |
<p><span class="code">protect</span> returns whatever the code block returns.</p> | |
<p>Because <span class="code">protect</span> will block any threads that are waiting to execute the critical section the code should be as quick as possible.</p> | |
<a name="t12.3"></a> <h1 id="_language_concurrency.pod6-Safety_concerns">Safety concerns</h1> | |
<p>Some shared data concurrency issues are less obvious than others. For a good general write-up on this subject see this <a href="#_routine_https:__6guts.wordpress.com_2014_04_17_racing-to-writeness-to-wrongness-leads_.pod6">blog post</a>.</p> | |
<p>One particular issue of note is when container autovivification or extension takes place. When an <a href="#_type_Array.pod6">Array</a> or a <a href="#_type_Hash.pod6">Hash</a> entry is initially assigned the underlying structure is altered and that operation is not async safe. For example, in this code:</p> | |
<pre class="code">my @array; | |
my $slot := @array[20]; | |
$slot = 'foo';</pre> | |
<p>The third line is the critical section as that is when the array is extended. The simplest fix is to use a <a href="#_type_Lock.pod6">Lock</a> to protect the critical section. A possibly better fix would be to refactor the code so that sharing a container is not necessary.</p> | |
</div> | |
<!-- /language/containers.pod6 --><div class="pod-body"><a id="_language_containers.pod6"></a><a name="t13"></a><h1 class="title">13 Containers</h1> <p class="subtitle">A low-level explanation of Raku containers</p> <p>This section explains how raw data, variables and containers relate to each other in Raku. The different types of containers used in Raku 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.</p> | |
<p>For a deeper discussion of the various kinds of <i>ordered</i> containers in Raku, see the overview of <a href="#_language_list.pod6">lists, sequences, and arrays</a>; for <i>unordered</i> containers, see <a href="#_language_setbagmix.pod6">sets, bags, and mixes</a>.</p> | |
<a name="t13.1"></a> <h1 id="_language_containers.pod6-What_is_a_variable?">What is a variable?</h1> | |
<p>Some people like to say "everything is an object", but in fact a variable is not a user-exposed object in Raku.</p> | |
<p>When the compiler encounters a variable scope declaration like <span class="code">my $x</span>, 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.</p> | |
<p>At runtime, a variable appears as an entry in a <i>lexical pad</i>, or <i>lexpad</i> for short. This is a per-scope data structure that stores a pointer for each variable.</p> | |
<p>In the case of <span class="code">my $x</span>, the lexpad entry for the variable <span class="code">$x</span> is a pointer to an object of type <span class="code">Scalar</span>, usually just called <i>the container</i>.</p> | |
<a name="t13.2"></a> <h1 id="_language_containers.pod6-Scalar_containers">Scalar containers</h1> | |
<p>Although objects of type <a href="#_type_Scalar.pod6"><span class="code">Scalar</span></a> are everywhere in Raku, you rarely see them directly as objects, because most operations <i>decontainerize</i>, which means they act on the <span class="code">Scalar</span> container's contents instead of the container itself.</p> | |
<p>In code like</p> | |
<pre class="code">my $x = 42; | |
say $x;</pre> | |
<p>the assignment <span class="code">$x = 42</span> stores a pointer to the <span class="code">Int</span> object 42 in the scalar container to which the lexpad entry for <span class="code">$x</span> points.</p> | |
<p>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 <span class="code">Scalar</span> it means "replace the previously stored value with the new one".</p> | |
<p>Note that subroutine signatures allow passing containers around:</p> | |
<pre class="code">sub f($a is rw) { | |
$a = 23; | |
} | |
my $x = 42; | |
f($x); | |
say $x; # OUTPUT: «23»</pre> | |
<p>Inside the subroutine, the lexpad entry for <span class="code">$a</span> points to the same container that <span class="code">$x</span> points to outside the subroutine. Which is why assignment to <span class="code">$a</span> also modifies the contents of <span class="code">$x</span>.</p> | |
<p>Likewise, a routine can return a container if it is marked as <span class="code">is rw</span>:</p> | |
<pre class="code">my $x = 23; | |
sub f() is rw { $x }; | |
f() = 42; | |
say $x; # OUTPUT: «42»</pre> | |
<p>For explicit returns, <span class="code">return-rw</span> instead of <span class="code">return</span> must be used.</p> | |
<p>Returning a container is how <span class="code">is rw</span> attribute accessors work. So</p> | |
<pre class="code">class A { | |
has $.attr is rw; | |
}</pre> | |
<p>is equivalent to</p> | |
<pre class="code">class A { | |
has $!attr; | |
method attr() is rw { $!attr } | |
}</pre> | |
<p>Scalar containers are transparent to type checks and most kinds of read-only accesses. A <span class="code">.VAR</span> makes them visible:</p> | |
<pre class="code">my $x = 42; | |
say $x.^name; # OUTPUT: «Int» | |
say $x.VAR.^name; # OUTPUT: «Scalar»</pre> | |
<p>And <span class="code">is rw</span> on a parameter requires the presence of a writable Scalar container:</p> | |
<pre class="code">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»</pre> | |
<a name="t13.3"></a> <h1 id="_language_containers.pod6-Callable_containers">Callable containers</h1> | |
<p>Callable containers provide a bridge between the syntax of a <a href="#_type_Routine.pod6">Routine</a> call and the actual call of the method <a href="#_type_Callable.pod6-method_CALL-ME">CALL-ME</a> of the object that is stored in the container. The sigil <span class="code">&</span> is required when declaring the container and has to be omitted when executing the <span class="code">Callable</span>. The default type constraint is <a href="#_type_Callable.pod6">Callable</a>.</p> | |
<pre class="code">my &callable = -> $ν { say "$ν is ", $ν ~~ Int ?? "whole" !! "not whole" } | |
callable(⅓); # OUTPUT: «0.333333 is not whole» | |
callable(3); # OUTPUT: «3 is whole»</pre> | |
<p>The sigil has to be provided when referring to the value stored in the container. This in turn allows <span class="code">Routine</span>s to be used as <a href="#_type_Signature.pod6-Constraining_signatures_of_Callables">arguments</a> to calls.</p> | |
<pre class="code">sub f() {} | |
my &g = sub {} | |
sub caller(&c1, &c2){ c1, c2 } | |
caller(&f, &g);</pre> | |
<a name="t13.4"></a> <h1 id="_language_containers.pod6-Binding">Binding</h1> | |
<p>Next to assignment, Raku also supports <i>binding</i> with the <span class="code">:=</span> 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</p> | |
<pre class="code">my $x := 42;</pre> | |
<p>then the lexpad entry for <span class="code">$x</span> directly points to the <span class="code">Int</span> 42. Which means that you cannot assign to it anymore:</p> | |
<pre class="code">my $x := 42; | |
$x = 23; | |
CATCH { default { say .^name, ': ', .Str } }; | |
# OUTPUT: «X::AdHoc: Cannot assign to an immutable value»</pre> | |
<p>You can also bind variables to other variables:</p> | |
<pre class="code">my $a = 0; | |
my $b = 0; | |
$a := $b; | |
$b = 42; | |
say $a; # OUTPUT: «42»</pre> | |
<p>Here, after the initial binding, the lexpad entries for <span class="code">$a</span> and <span class="code">$b</span> both point to the same scalar container, so assigning to one variable also changes the contents of the other.</p> | |
<p>You've seen this situation before: it is exactly what happened with the signature parameter marked as <span class="code">is rw</span>.</p> | |
<p><a id="i245" name="Language \ (container binding)"></a><span class="indexed"></span> Sigilless variables and parameters with the trait <span class="code">is raw</span> always bind (whether <span class="code">=</span> or <span class="code">:=</span> is used):</p> | |
<pre class="code">my $a = 42; | |
my \b = $a; | |
b++; | |
say $a; # OUTPUT: «43» | |
sub f($c is raw) { $c++ } | |
f($a); | |
say $a; # OUTPUT: «44»</pre> | |
<a name="t13.5"></a> <h1 id="_language_containers.pod6-Scalar_containers_and_listy_things">Scalar containers and listy things</h1> | |
<p>There are a number of positional container types with slightly different semantics in Raku. The most basic one is <a href="#_type_List.pod6">List</a>, which is created by the comma operator.</p> | |
<pre class="code">say (1, 2, 3).^name; # OUTPUT: «List»</pre> | |
<p>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:</p> | |
<pre class="code">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»</pre> | |
<p>So the list doesn't care about whether its elements are values or containers, they just store and retrieve whatever was given to them.</p> | |
<p>Lists can also be lazy; in that case, elements at the end are generated on demand from an iterator.</p> | |
<p>An <span class="code">Array</span> is just like a list, except that it forces all its elements to be containers, which means that you can always assign to elements:</p> | |
<pre class="code">my @a = 1, 2, 3; | |
@a[0] = 42; | |
say @a; # OUTPUT: «[42 2 3]»</pre> | |
<p><span class="code">@a</span> actually stores three scalar containers. <span class="code">@a[0]</span> returns one of them, and the assignment operator replaces the integer value stored in that container with the new one, <span class="code">42</span>.</p> | |
<a name="t13.6"></a> <h1 id="_language_containers.pod6-Assigning_and_binding_to_array_variables">Assigning and binding to array variables</h1> | |
<p>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).</p> | |
<p>Nevertheless, it's easy to observe how different they are:</p> | |
<pre class="code">my $x = 42; say $x.^name; # OUTPUT: «Int» | |
my @a = 42; say @a.^name; # OUTPUT: «Array»</pre> | |
<p>This is because the <span class="code">Scalar</span> container type hides itself well, but <span class="code">Array</span> makes no such effort. Also assignment to an array variable is coercive, so you can assign a non-array value to an array variable.</p> | |
<p>To place a non-<span class="code">Array</span> into an array variable, binding works:</p> | |
<pre class="code">my @a := (1, 2, 3); | |
say @a.^name; # OUTPUT: «List»</pre> | |
<a name="t13.7"></a> <h1 id="_language_containers.pod6-Binding_to_array_elements">Binding to array elements</h1> | |
<p>As a curious side note, Raku supports binding to array elements:</p> | |
<pre class="code">my @a = (1, 2, 3); | |
@a[0] := my $x; | |
$x = 42; | |
say @a; # OUTPUT: «[42 2 3]»</pre> | |
<p>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.</p> | |
<p>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 <a href="#_routine_BIND-KEY.pod6"><span class="code">BIND-KEY</span></a>) is called on the array. This method handles binding to array elements.</p> | |
<p>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.</p> | |
<pre class="code">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»</pre> | |
<p>Operations that mix Lists and Arrays generally protect against such a thing happening accidentally.</p> | |
<a name="t13.8"></a> <h1 id="_language_containers.pod6-Flattening,_items_and_containers">Flattening, items and containers</h1> | |
<p>The <span class="code">%</span> and <span class="code">@</span> sigils in Raku generally indicate multiple values to an iteration construct, whereas the <span class="code">$</span> sigil indicates only one value.</p> | |
<pre class="code">my @a = 1, 2, 3; | |
for @a { }; # 3 iterations | |
my $a = (1, 2, 3); | |
for $a { }; # 1 iteration</pre> | |
<p><span class="code">@</span>-sigiled variables do not flatten in list context:</p> | |
<pre class="code">my @a = 1, 2, 3; | |
my @b = @a, 4, 5; | |
say @b.elems; # OUTPUT: «3»</pre> | |
<p>There are operations that flatten out sublists that are not inside a scalar container: slurpy parameters (<span class="code">*@a</span>) and explicit calls to <span class="code">flat</span>:</p> | |
<pre class="code">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»</pre> | |
<p>You can also use <span class="code">|</span> to create a <a href="#_type_Slip.pod6">Slip</a>, introducing a list into the other.</p> | |
<pre class="code">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)»</pre> | |
<p>In the first case, every element of <span class="code">@l</span> is <i>slipped</i> as the corresponding elements of the resulting list. <span class="code">flat</span>, in the other hand, <i>flattens</i> all elements including the elements of the included array, except for <span class="code">(9 10)</span>.</p> | |
<p>As hinted above, scalar containers prevent that flattening:</p> | |
<pre class="code">sub f(*@x) { @x.elems }; | |
my @a = 1, 2, 3; | |
say f $@a, 4, 5; # OUTPUT: «3»</pre> | |
<p>The <span class="code">@</span> character can also be used as a prefix to coerce the argument to a list, thus removing a scalar container:</p> | |
<pre class="code">my $x = (1, 2, 3); | |
.say for @$x; # 3 iterations</pre> | |
<p>However, the <i>decont</i> operator <span class="code"><></span> is more appropriate to decontainerize items that aren't lists:</p> | |
<pre class="code">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</pre> | |
<p>Methods generally don't care whether their invocant is in a scalar, so</p> | |
<pre class="code">my $x = (1, 2, 3); | |
$x.map(*.say); # 3 iterations</pre> | |
<p>maps over a list of three elements, not of one.</p> | |
<a name="t13.9"></a> <h1 id="_language_containers.pod6-Self-referential_data">Self-referential data</h1> | |
<p>Container types, including <span class="code">Array</span> and <span class="code">Hash</span>, allow you to create self-referential structures.</p> | |
<pre class="code">my @a; | |
@a[0] = @a; | |
put @a.raku; | |
# OUTPUT: «((my @Array_75093712) = [@Array_75093712,])»</pre> | |
<p>Although Raku 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 <a href="#_type_Promise.pod6-method_in">handle</a> timeouts.</p> | |
<a name="t13.10"></a> <h1 id="_language_containers.pod6-Type_constraints">Type constraints</h1> | |
<p>Any container can have a type constraint in the form of a <a href="#_language_typesystem.pod6-Type_objects">type object</a> or a <a href="#_language_typesystem.pod6-subset">subset</a>. Both can be placed between a declarator and the variable name or after the trait <a href="#_type_Variable.pod6-trait_of">of</a>. The constraint is a property of the variable, not the container.</p> | |
<pre class="code">subset Three-letter of Str where .chars == 3; | |
my Three-letter $acronym = "ÞFL";</pre> | |
<p>In this case, the type constraint is the (compile-type defined) subset <span class="code">Three-letter</span>.</p> | |
<p>The default type constraint of a <span class="code">Scalar</span> container is <a href="#_type_Mu.pod6">Mu</a>. Introspection of type constraints on containers is provided by <span class="code">.VAR.of</span> method, which for <span class="code">@</span> and <span class="code">%</span> sigiled variables gives the constraint for values:</p> | |
<pre class="code">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)»</pre> | |
<a name="t13.10.1"></a> <h2 id="_language_containers.pod6-Definedness_constraints">Definedness constraints</h2> | |
<p>A container can also enforce a variable to be defined. Put a smiley in the declaration:</p> | |
<pre class="code">my Int:D $def = 3; | |
say $def; # OUTPUT: «3» | |
$def = Int; # Typecheck failure</pre> | |
^^^ fails at runtime, so xt/example-compilation still passes | |
<p>You'll also need to initialize the variable in the declaration, it can't be left undefined after all.</p> | |
<p>It's also possible to have this constraint enforced in all variables declared in a scope with the <a href="#_language_variables.pod6-Default_defined_variables_pragma">default defined variables pragma</a>. People coming from other languages where variables are always defined will want to have a look.</p> | |
<a name="t13.11"></a> <h1 id="_language_containers.pod6-Custom_containers">Custom containers</h1> | |
<p>To provide custom containers Raku employs the class <a href="#_type_Proxy.pod6"><span class="code">Proxy</span></a>. Its constructor takes two arguments, <span class="code">FETCH</span> AND <span class="code">STORE</span>, that point to methods that are called when values are fetched or stored 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 <a href="#_type_Signature.pod6-Type_captures">type captures</a> to work with types in Raku.</p> | |
<pre class="code">sub lucky(::T $type) { | |
my T $c-value; # closure variable | |
return-rw 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 } };</pre> | |
</div> | |
<!-- /language/contexts.pod6 --><div class="pod-body"><a id="_language_contexts.pod6"></a><a name="t14"></a><h1 class="title">14 Contexts and contextualizers</h1> <p class="subtitle">What are contexts and how to switch into them</p> <p>A context is needed, in many occasions, to interpret the value of a container. In Raku, 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.</p> | |
<a name="t14.1"></a> <h1 id="_language_contexts.pod6-Sink"><a name="246"></a>Sink</h1> | |
<p>The <i>sink</i> context is equivalent to what in other languages is called <span class="code">void</span> 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.</p> | |
<pre class="code">my $sub = -> $a { return $a² }; | |
$sub; # OUTPUT: «WARNINGS:Useless use of $sub in sink context (line 1)» | |
</pre> | |
<p><a id="i247" name="Language sinking"></a><span class="indexed"></span> You can force that sink context on <a href="#_type_Iterator.pod6">Iterator</a>s, by using the <a href="#_routine_sink-all.pod6"><span class="code">sink-all</span></a> method. <a href="#_type_Proc.pod6">Proc</a>s can also be <a href="#_type_Proc.pod6-method_sink">sunk via the <span class="code">sink</span> method</a>, forcing them to raise an exception and not returning anything.</p> | |
<p>In general, blocks will warn if evaluated in sink context; however, <a href="#_language_control.pod6-gather/take">gather/take blocks</a> are explicitly evaluated in sink context, with values returned explicitly using <span class="code">take</span>:</p> | |
<pre class="code">my @results = gather for 1..1 { ^10 .map: *.take }; | |
say @results; # OUTPUT: «[0 1 2 3 4 5 6 7 8 9]» | |
</pre> | |
<p>In this example, <span class="code">for</span> is run in sunk context, and within it, <span class="code">map</span> is too. Results are taken explicitly from the loop via gather/take.</p> | |
<p>In sink context, an object will call its <span class="code">sink</span> method if present:</p> | |
<pre class="code">sub foo { | |
return [<a b c>] does role { | |
method sink { say "sink called" } | |
} | |
} | |
foo; # OUTPUT: «sink called» | |
</pre> | |
<a name="t14.2"></a> <h1 id="_language_contexts.pod6-Number"><a name="248"></a>Number</h1> | |
<p>This context, and probably all other contexts except <i>sink</i> above, are <i>conversion</i> or <i>interpretation</i> 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 <a href="#_type_Str.pod6">Str</a> to <a href="#_type_Numeric.pod6">Numeric</a>, for instance); in other cases simply an interpretation (<a href="#_type_IntStr.pod6">IntStr</a> will be interpreted as <a href="#_type_Int.pod6">Int</a> or as <a href="#_type_Str.pod6">Str</a>).</p> | |
<p><i>Number context</i> is called whenever we need to apply a numerical operation on a variable.</p> | |
<pre class="code">my $stringone = "1 "; | |
my $stringthree = "3 "; | |
say $stringone + $stringthree; # OUTPUT: «4» | |
</pre> | |
<p>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.</p> | |
<p>Numeric context can be forced by using arithmetic operators such as <span class="code">+</span> or <span class="code">-</span>. In that context, the <a href="#_routine_Numeric.pod6"><span class="code">Numeric</span></a> method will be called if available and the value returned used as the numeric value of the object.</p> | |
<pre class="code">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» | |
say +" \n "; # OUTPUT: «0» | |
</pre> | |
<p>Whitespace in any quantity will be converted to 0, as is shown in the last statement. In the case of <i>listy</i> things, the numeric value will be in general equivalent to <span class="code">.elems</span>; in some cases, like <a href="#_routine_Numeric.pod6-(Thread)_method_Numeric">Thread</a>, it will return an unique thread identifier.</p> | |
<a name="t14.3"></a> <h1 id="_language_contexts.pod6-String"><a name="249"></a>String</h1> | |
<p>In a <i>string context</i>, 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.</p> | |
<pre class="code">put $very-complicated-and-hairy-object; # OUTPUT: something meaningful | |
</pre> | |
<p>Or when smartmatching to a regular expression:</p> | |
<pre class="code">put 333444777 ~~ /(3+)/; # OUTPUT: «333»</pre> | |
<p>In general, the <a href="#_routine_Str.pod6"><span class="code">Str</span> routine</a> will be called on a variable to contextualize it; since this method is inherited from <a href="#_type_Mu.pod6">Mu</a>, it is always present, but it is not always guaranteed to work. In some core classes it will issue a warning.</p> | |
<p><a href="#_routine_~.pod6"><span class="code">~</span></a> is the (unary) string contextualizer. As an operator, it concatenates strings, but as a prefix operator it becomes the string context operator.</p> | |
<pre class="code">my @array = [ [1,2,3], [4,5,6]]; | |
say ~@array; # OUTPUT: «1 2 3 4 5 6» | |
</pre> | |
<p>This will happen also in a <a href="#_language_operators.pod6-Reduction_operators"><i>reduction</i></a> context, when <span class="code">[~]</span> is applied to a list</p> | |
<pre class="code">say [~] [ 3, 5+6i, Set(<a b c>), [1,2,3] ]; # OUTPUT: «35+6ic a b1 2 3»</pre> | |
<p>In that sense, empty lists or other containers will stringify to an empty string:</p> | |
<pre class="code">say [~] [] ; # OUTPUT: «»</pre> | |
<p>Since <a href="#_routine_~.pod6-(Operators)_infix_~"><span class="code">~</span> acts also as buffer concatenation operator</a>, 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.</p> | |
<pre class="code">say [~] Buf.new(0x3,0x33), Buf.new(0x2,0x22); | |
# OUTPUT: «Buf:0x<03 33 02 22>»</pre> | |
<p>However,</p> | |
<pre class="code">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 | |
</pre> | |
<p>Since <span class="code">~</span> is putting in string context the second element of this list, <a href="#_routine_~.pod6-(Operators)_infix_~"><span class="code">~</span></a> 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.</p> | |
<pre class="code">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>» | |
</pre> | |
<p>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.</p> | |
<pre class="code">my $described-number = 1i but 'Unity in complex plane'; | |
put $described-number; # OUTPUT: «Unity in complex plane»</pre> | |
<p><span class="code">but</span> creates a mixin, which endows the complex number with a <span class="code">Str</span> method. <span class="code">put</span> contextualizes it into a string, that is, it calls <span class="code">Str</span>, the string contextualizer, with the result shown above.</p> | |
<a name="t14.4"></a> <h1 id="_language_contexts.pod6-Boolean"><a name="250"></a>Boolean</h1> | |
<p>This context will force a variable to be interpreted as <span class="code">True</span> or <span class="code">False</span>.</p> | |
<pre class="code">say "Hey" if 7; # OUTPUT: «Hey» | |
say "Ahoy" if "";</pre> | |
<p>This context appears in expressions such as <span class="code">if</span> or <span class="code">while</span>, and is equivalent to calling <span class="code">so</span> on these values.</p> | |
<pre class="code">say "Hey" if 7.so; # OUTPUT: «Hey» | |
say "Ahoy" if not set().so; # OUTPUT: «Ahoy» | |
</pre> | |
<p>In general, non-zero, non-empty will be converted to <span class="code">True</span>; zero or empty will be equivalent to <span class="code">False</span>. But <span class="code">.so</span> can be defined to return any Boolean value we want, so this is just a rule of thumb.</p> | |
<p>The <a href="#_language_operators.pod6-prefix_?"><span class="code">?</span></a> Boolean context operator and the <a href="#_language_operators.pod6-prefix_!"><span class="code">!</span></a> negated Boolean context operator will force the Boolean context on an object.</p> | |
<pre class="code">say ? 0i; # OUTPUT: «False» | |
say ! :true; # OUTPUT: «False» | |
</pre> | |
<a name="t14.5"></a> <h1 id="_language_contexts.pod6-List"><a name="251"></a>List</h1> | |
<p>There are actually several different <a href="#_language_list.pod6-List_contexts">list contexts</a>, which are better explained in that page. In general, the list contextualizer is the comma <span class="code">,</span></p> | |
<pre class="code">say (3,).^name; # OUTPUT: «List»</pre> | |
<p>and the method called in that case is also <span class="code">.list</span></p> | |
<pre class="code">Any.list.^name; # OUTPUT: «List» | |
say 3.list.^name; # OUTPUT: «List» | |
say (^3).list; # OUTPUT: «(0 1 2)» | |
</pre> | |
<a name="t14.6"></a> <h1 id="_language_contexts.pod6-Item_context">Item context</h1> | |
<p>Item or scalar context will deal with complex pieces of data as if they were a single item. It is forced when you try to assign to a scalar variable</p> | |
<pre class="code">my $scalar-context = <1 2 3>; | |
say "→ $_" for $scalar-context; # OUTPUT: «→ 1 2 3» | |
</pre> | |
<p>It can be induced using the <span class="code">$</span> operator, that acts as the contextualizer operator by calling <span class="code">item</span> as a method or routine</p> | |
<pre class="code">.say for $(1,2,3); # OUTPUT: «(1 2 3)» | |
.say for (1,2,3).item; # OUTPUT: «(1 2 3)» | |
.say for item( 1..3 ); # OUTPUT: «1..3» | |
</pre> | |
<p>Itemization affects only their behavior in list context; however, they will still keep their <span class="code">Positional</span> role or other roles they might have:</p> | |
<pre class="code">$(1,2,3).elems.say; # OUTPUT: «3» | |
say (1,2,3).item[2]; # OUTPUT: «3» | |
say $( key => 'value')<key>; # OUTPUT: «value» | |
</pre> | |
<p>Itemization <i>containerizes</i> values in a data structure keeping them, for instance, from being flattened into the surrounding list or data structure:</p> | |
<pre class="code">.say for (1, $(2,3), 4).flat; # OUTPUT: «1(2 3)4» | |
say (1, $<a b>, 2).elems; # OUTPUT: «3» | |
</pre> | |
<p>The itemizer operator will call the <span class="code">.item</span> method on the object; it can also be called as a subroutine. Since <a href="#_type_Mu.pod6-method_item">that is a method inherited from <span class="code">Mu</span></a>, objects of any class can be itemized.</p> | |
</div> | |
<!-- /language/control.pod6 --><div class="pod-body"><a id="_language_control.pod6"></a><a name="t15"></a><h1 class="title">15 Control flow</h1> <p class="subtitle">Statements used to control the flow of execution</p> <a name="t15.1"></a> <h1 id="_language_control.pod6-Statements"><a name="252"></a>Statements</h1> | |
<p>Raku programs consist of one or more statements. Simple statements are separated by semicolons. The following program will print "Hello" and then "World" on the next line.</p> | |
<pre class="code">say "Hello"; | |
say "World";</pre> | |
<p>In most places where spaces appear in a statement, and before the semicolon, they 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:</p> | |
<pre class="code">say | |
"Hello"; say "World";</pre> | |
<a name="t15.2"></a> <h1 id="_language_control.pod6-Blocks"><a name="253"></a>Blocks</h1> | |
<p>Like many other languages, Raku uses <span class="code">blocks</span> enclosed by <span class="code">{</span> and <span class="code">}</span> to turn a sequence of statements into a [`Block`](https://docs.raku.org/type/Block) that acts as a single one. It is OK to omit the semicolon between the last statement in a block and the closing <span class="code">}</span>.</p> | |
<pre class="code">{ say "Hello"; say "World" }</pre> | |
<p>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.</p> | |
<pre class="code">say 1; # OUTPUT: «1» | |
{ say 2; say 3 }; # OUTPUT: «23» | |
say 4; # OUTPUT: «4»</pre> | |
<p>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 <a href="#_language_functions.pod6-Blocks_and_lambdas">elsewhere</a>. For now it is just important to understand when blocks run and when they do not:</p> | |
<pre class="code">say "We get here"; | |
{ say "then here." }; | |
{ say "not here"; 0; } or die; | |
</pre> | |
<p>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 <span class="code">Block</span> 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 <span class="code">Block</span> object, so it just gets thrown away.</p> | |
<p>Most of the flow control constructs covered below are just ways to tell Raku when, how, and how many times, to enter blocks like that second block.</p> | |
<p>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:</p> | |
<pre class="code"># 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»</pre> | |
<p>...but:</p> | |
<pre class="code">{ 42.say } { 43.say } # Syntax error | |
{ 42.say; } { 43.say } # Also a syntax error, of course | |
</pre> | |
<p>So, be careful when you backspace in a line-wrapping editor:</p> | |
<pre class="code">{ "Without semicolons line-wrapping can be a bit treacherous.".say } \ | |
{ 43.say } # Syntax error | |
</pre> | |
<p>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.</p> | |
<p>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.</p> | |
<pre class="code">class C { | |
say "I live"; | |
die "I will never live!" | |
}; | |
my $c = C.new; │ | |
# OUTPUT: Fails and writes «I liveI will never live! | |
</pre> | |
<p>This block will first run the first statement, and then <span class="code">die</span> printing the second statement. <span class="code">$c</span> will never get a value.</p> | |
<a name="t15.3"></a> <h1 id="_language_control.pod6-Phasers"><a name="254"></a>Phasers</h1> | |
<p>Blocks may have <i>phasers</i>: special labeled blocks that break their execution into phases that run in particular phases. See the page <a href="#_language_phasers.pod6">phasers</a> for the details.</p> | |
<a name="t15.4"></a> <h1 id="_language_control.pod6-do"><a name="255"></a>do</h1> | |
<p>The simplest way to run a block where it cannot be a stand-alone statement is by writing <span class="code">do</span> before it:</p> | |
<pre class="code"># This dies half of the time | |
do { say "Heads I win, tails I die."; Bool.pick } or die; say "I win."; | |
</pre> | |
<p>Note that you need a space between the <span class="code">do</span> and the block.</p> | |
<p>The whole <span class="code">do {...}</span> 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:</p> | |
<pre class="code">False and do { 42.say };</pre> | |
<p>...will not say 42. However, the block is only evaluated once each time the expression it is contained in is evaluated:</p> | |
<pre class="code"># This says "(..1 ..2 ..3)" not "(..1 ...2 ....3)" | |
my $f = "."; say do { $f ~= "." } X~ 1, 2, 3;</pre> | |
<p>In other words, it follows the same <a href="#_language_glossary.pod6-index-entry-Reify">reification</a> rules as everything else.</p> | |
<p>Technically, <span class="code">do</span> is a loop which runs exactly one iteration.</p> | |
<p>A <span class="code">do</span> 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:</p> | |
<pre class="code">3, do if 1 { 2 } ; # OUTPUT: «(3, 2)» | |
3, (if 1 { 2 }) ; # OUTPUT: «(3, 2)» | |
</pre> | |
<pre class="code">3, if 1 { 2 } ; # Syntax error | |
</pre> | |
<a name="t15.5"></a> <h1 id="_language_control.pod6-start"><a name="256"></a>start</h1> | |
<p>The simplest way to run a block <b>asynchronously</b> is by writing <span class="code">start</span> before it:</p> | |
<pre class="code">start { sleep 1; say "done" } | |
say "working"; | |
# working, done | |
</pre> | |
<p>Note that you need a space between the <span class="code">start</span> and the block. In the example above, the <span class="code">start</span> 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:</p> | |
<pre class="code">start { die "We're dead"; } | |
say "working"; | |
sleep 10; | |
</pre> | |
<p>This code will print <span class="code">Unhandled exception in code scheduled on thread 4 We're dead</span> in version 6.d, while it will simply get out after waiting for 10 seconds in version 6.c.</p> | |
<p>The <span class="code">start {...}</span> immediately returns a <span class="code">Promise</span> that can be safely ignored if you are not interested in the result of the block. If you <b>are</b> interested in the final value of the block, you can call the <span class="code">.result</span> method on the returned promise. So:</p> | |
<pre class="code">my $promise = start { sleep 10; 42 } | |
# ... do other stuff | |
say "The result is $promise.result()";</pre> | |
<p>If the code inside the block has not finished, the call to <span class="code">.result</span> will wait until it is done.</p> | |
<p>A <span class="code">start</span> 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.</p> | |
<pre class="code">sub get42 { 42 } | |
my $promise = start get42; | |
say $promise.result; # OUTPUT: «42»</pre> | |
<p>Note that code executed this way does not have access to the special variables <a href="#_syntax_$!.pod6"><span class="code">$!</span></a> and <a href="#_syntax_$$SOLIDUS.pod6"><span class="code">$/</span></a> of its outer block, but receives new ones, so every asynchronous task has its per-task state.</p> | |
<p>Thus, <span class="code">try</span> expressions and regex matches executed in the asynchronous task have their per-task state.</p> | |
<pre class="code">'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»</pre> | |
<a name="t15.6"></a> <h1 id="_language_control.pod6-if"><a name="257"></a>if</h1> | |
<p>To conditionally run a block of code, use an <span class="code">if</span> followed by a condition. The condition, an expression, will be evaluated immediately after the statement before the <span class="code">if</span> finishes. The block attached to the condition will only be evaluated if the condition means <span class="code">True</span> when coerced to <span class="code">Bool</span>. Unlike some languages the condition does not have to be parenthesized, instead the <span class="code">{</span> and <span class="code">}</span> around the block are mandatory:</p> | |
<pre class="code">if 1 { "1 is true".say } ; # says "1 is true" | |
</pre> | |
<pre class="code">if 1 "1 is true".say ; # syntax error, missing block | |
</pre> | |
<pre class="code">if 0 { "0 is true".say } ; # does not say anything, because 0 is false | |
</pre> | |
<pre class="code">if 42.say and 0 { 43.say }; # says "42" but does not say "43" | |
</pre> | |
<p>There is also a form of <span class="code">if</span> called a "statement modifier" form. In this case, the <span class="code">if</span> and the condition come after the code you want to run conditionally. Do note that the condition is still always evaluated first:</p> | |
<pre class="code">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</pre> | |
<p>The statement modifier form is probably best used sparingly.</p> | |
<p>The <span class="code">if</span> statement itself will either <a href="#_type_Slip.pod6">slip</a> us an empty list, if it does not run the block, or it will return the value which the block produces:</p> | |
<pre class="code">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)"</pre> | |
<p>For the statement modifier it is the same, except you have the value of the statement instead of a block:</p> | |
<pre class="code">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</pre> | |
<p>The <span class="code">if</span> does not change the topic (<span class="code">$_</span>) by default. In order to access the value which the conditional expression produced, you have to ask for it more strongly:</p> | |
<pre class="code">$_ = 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"</pre> | |
<a name="t15.6.1"></a> <h2 id="_language_control.pod6-else/elsif"><a name="258"></a><span class="code">else/elsif</span></h2> | |
<p>A compound conditional may be produced by following an <span class="code">if</span> conditional with <span class="code">else</span> to provide an alternative block to run when the conditional expression is false:</p> | |
<pre class="code">if 0 { say "no" } else { say "yes" } ; # says "yes" | |
if 0 { say "no" } else{ say "yes" } ; # says "yes", space is not required | |
</pre> | |
<p>The <span class="code">else</span> cannot be separated from the conditional statement by a semicolon, but as a special case, it is OK to have a newline.</p> | |
<pre class="code">if 0 { say "no" }; else { say "yes" } ; # syntax error | |
</pre> | |
<pre class="code">if 0 { say "no" } | |
else { say "yes" } ; # says "yes" | |
</pre> | |
<p>Additional conditions may be sandwiched between the <span class="code">if</span> and the <span class="code">else</span> using <span class="code">elsif</span>. 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 <span class="code">elsif</span> instead of an <span class="code">else</span> if you want.</p> | |
<pre class="code">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"</pre> | |
<p>You cannot use the statement modifier form with <span class="code">else</span> or <span class="code">elsif</span>:</p> | |
<pre class="code">42.say if 0 else { 43.say } # syntax error | |
</pre> | |
<p>All the same rules for semicolons and newlines apply, consistently</p> | |
<pre class="code">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 | |
</pre> | |
<pre class="code">if 0 { say 0 } elsif 1 { say 1 } else { say "how?" } ; # says "1" | |
</pre> | |
<pre class="code">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"</pre> | |
<p>The whole thing either <a href="#_type_Slip.pod6">slips</a> us an empty list (if no blocks were run) or returns the value produced by the block that did run:</p> | |
<pre class="code">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)"</pre> | |
<p>It's possible to obtain the value of the previous expression inside an <span class="code">else</span>, which could be from <span class="code">if</span> or the last <span class="code">elsif</span> if any are present:</p> | |
<pre class="code">$_ = 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"</pre> | |
<a name="t15.7"></a> <h1 id="_language_control.pod6-unless"><a name="259"></a><span class="code">unless</span></h1> | |
<p>When you get sick of typing "if not (X)" you may use <span class="code">unless</span> to invert the sense of a conditional statement. You cannot use <span class="code">else</span> or <span class="code">elsif</span> with <span class="code">unless</span> because that ends up getting confusing. Other than those two differences <span class="code">unless</span> works the same as <a href="#14-if">#if</a>:</p> | |
<pre class="code">unless 1 { "1 is false".say } ; # does not say anything, since 1 is true | |
</pre> | |
<pre class="code">unless 1 "1 is false".say ; # syntax error, missing block | |
</pre> | |
<pre class="code">unless 0 { "0 is false".say } ; # says "0 is false" | |
</pre> | |
<pre class="code">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)"</pre> | |
<a name="t15.8"></a> <h1 id="_language_control.pod6-with_orwith_without"><a name="260"></a><span class="code">with orwith without</span></h1> | |
<p>The <span class="code">with</span> statement is like <span class="code">if</span>, but tests for definedness rather than truth, and it topicalizes on the condition, much like <span class="code">given</span>:</p> | |
<pre class="code">with "abc".index("a") { .say } # prints 0</pre> | |
<p>Similarly to <span class="code">elsif</span>, <span class="code">orwith</span> may be used to chain definedness tests:</p> | |
<pre class="code"># 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" }</pre> | |
<p>You may intermix <span class="code">if</span>-based and <span class="code">with</span>-based clauses.</p> | |
<pre class="code"># This says "Yes" | |
if 0 { say "No" } orwith Nil { say "No" } orwith 0 { say "Yes" };</pre> | |
<p>As with <span class="code">unless</span>, you may use <span class="code">without</span> to check for undefinedness, but you may not add an <span class="code">else</span> clause:</p> | |
<pre class="code">my $answer = Any; | |
without $answer { warn "Got: {$_.raku}" }</pre> | |
<p>There are also <span class="code">with</span> and <span class="code">without</span> statement modifiers:</p> | |
<pre class="code">my $answer = (Any, True).roll; | |
say 42 with $answer; | |
warn "undefined answer" without $answer;</pre> | |
<p>As with the other chainable constructs, an <span class="code">else</span> completing a <span class="code">with/if</span>..<span class="code">orwith/elsif</span> chain will itself topicalize to the value of the prior (failed) condition's topic (either the topic of <span class="code">with</span> or the final <span class="code">orwith</span> or <span class="code">elsif</span>).</p> | |
<p>In the case of an <span class="code">else</span> following a <span class="code">with</span> or <span class="code">orwith</span>, 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 <a href="#_type_Failure.pod6">Failure</a> values are always undefined:</p> | |
<pre class="code">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}." | |
} | |
</pre> | |
<p>Note that while topicalizing a <a href="#_type_Failure.pod6">Failure</a> marks it <a href="#_type_Failure.pod6-method_handled"><span class="code">handled</span></a>—so you can use the <span class="code">with</span>/<span class="code">else</span> to proceed safely with execution—it doesn't make the <i>Failure value itself</i> safe. Even within the <span class="code">else</span> clause, if you try to use the value directly, it will result in your <span class="code">else</span> clause itself failing (or, in Rakudo, "promoting" the Failure into a thrown exception).</p> | |
<p>But as seen above, you <i>can</i> use the methods of a handled <span class="code">Failure</span> object the <span class="code">else</span> topicalizes, such as <a href="#_type_Failure.pod6-method_exception"><span class="code">exception</span></a>, if you wish to provide diagnostics or interrogate the underlying <a href="#_type_Exception.pod6">Exception</a>.</p> | |
<a name="t15.9"></a> <h1 id="_language_control.pod6-when"><a name="261"></a>when</h1> | |
<p>The <span class="code">when</span> block is similar to an <span class="code">if</span> 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 <span class="code">when</span> block is executed, control is passed to the enclosing block and following statements are ignored; but when the <span class="code">if</span> block is executed, following statements are executed. <div class="marginale">There are other ways to modify their default behavior; they are discussed in other sections.</div> The following examples should illustrate the <span class="code">if</span> or <span class="code">when</span> block's default behavior assuming no special exit or other side effect statements are included in the <span class="code">if</span> or <span class="code">when</span> blocks:</p> | |
<pre class="code">{ | |
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 | |
} | |
</pre> | |
<p>Should the <span class="code">if</span> and <span class="code">when</span> blocks above appear at file scope, following statements would be executed in each case.</p> | |
<p>There is one other feature <span class="code">when</span> has that <span class="code">if</span> doesn't: the <span class="code">when</span>'s Boolean context test defaults to <span class="code">$_ ~~</span> while the <span class="code">if</span>'s does not. That has an effect on how one uses the X in the <span class="code">when</span> block without a value for <span class="code">$_</span> (it's <span class="code">Any</span> in that case and <span class="code">Any</span> smartmatches on <span class="code">True</span>: <span class="code">Any ~~ True</span> yields <span class="code">True</span>). Consider the following:</p> | |
<pre class="code">{ | |
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) | |
} | |
</pre> | |
<p>Finally, <span class="code">when</span>'s statement modifier form does not affect execution of following statements either inside or outside of another block:</p> | |
<pre class="code">say "foo" when X; # if X is true statement is executed | |
# following statements are not affected | |
</pre> | |
<p>Since a successful match will exit the block, the behavior of this piece of code:</p> | |
<pre class="code">$_ = True; | |
my $a; | |
{ | |
$a = do when .so { "foo" } | |
}; | |
say $a; # OUTPUT: «(Any)» | |
</pre> | |
<p>is explained since the <span class="code">do</span> block is abandoned before any value is stored or processed. However, in this case:</p> | |
<pre class="code">$_ = False; | |
my $a; | |
{ | |
$a = do when .so { "foo" } | |
}; | |
say $a; # OUTPUT: «False» | |
</pre> | |
<p>the block is not abandoned since the comparison is false, so <span class="code">$a</span> will actually get a value.</p> | |
<a name="t15.10"></a> <h1 id="_language_control.pod6-for"><a name="262"></a>for</h1> | |
<p>The <span class="code">for</span> loop iterates over a list, running the statements inside a <a href="#_type_Block.pod6">block</a> once on each iteration. If the block takes parameters, the elements of the list are provided as arguments. By default, the block takes one parameter, <span class="code">$_</span>:</p> | |
<pre class="code">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</pre> | |
<p>Pointy block syntax or a <a href="#_language_variables.pod6-The_^_twigil">placeholder</a> may be used to name the parameter:</p> | |
<pre class="code">my @foo = 1..3; | |
for @foo -> $item { print $item } | |
for @foo { print $^item } # same thing</pre> | |
<p>Multiple parameters can be declared, in which case the iterator takes as many elements from the list as needed before running the block.</p> | |
<pre class="code">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" } # OUTPUT: «1 < 1.12 < 2.1»</pre> | |
<p>Parameters of a pointy block can have default values, allowing the code to handle lists with missing elements.</p> | |
<pre class="code">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»</pre> | |
<p>When no parameters are specified for a <span class="code">for</span> loop's block, <span class="code">when</span> can be used within it similarly to how it's used in a <span class="code">given</span> block:</p> | |
<pre class="code"># A solution for FizzBuzz: | |
for 1..100 { | |
when * %% 15 { say 'FizzBuzz' } | |
when * %% 3 { say 'Fizz' } | |
when * %% 5 { say 'Buzz' } | |
default { say $_ } | |
}</pre> | |
<p>If the postfix form of <span class="code">for</span> is used, a block is not required and the topic is set for the statement list.</p> | |
<pre class="code">say „I $_ butterflies!“ for <♥ ♥ ♥>; | |
# OUTPUT: «I ♥ butterflies!I ♥ butterflies!I ♥ butterflies!»</pre> | |
<p>A <span class="code">for</span> 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:</p> | |
<pre class="code">for $*IN.lines -> $line { .say } | |
</pre> | |
<p>Iteration variables are always lexical, so you don't need to use <span class="code">my</span> to give them the appropriate scope. Also, they are read-only aliases. If you need them to be writable, use <span class="code"><-></span> instead of <span class="code">-></span>. Alternatively, you can add the <a href="#_type_Signature.pod6-index-entry-trait_is_rw"><span class="code">is rw</span></a> trait; this performs a binding operation so assigning to the parameter changes the value of the variable at the caller side. If instead you want to modify copies of the arguments within the block, add <a href="#_type_Signature.pod6-index-entry-trait_is_copy"><span class="code">is copy</span></a>.</p> | |
<pre class="code">my @foo = 1..3; | |
for @foo <-> $value { | |
$value = $value %% 2 ?? "Even" !! "Odd" | |
} | |
say @foo; # OUTPUT: «[Odd Even Odd]» | |
@foo = 1..3; | |
for @foo -> $value is rw { | |
$value = $value %% 2 ?? "Even" !! "Odd" | |
} | |
say @foo; # OUTPUT: «[Odd Even Odd]» | |
@foo = 1..3; | |
my @bar; | |
for @foo -> $value is copy { | |
$value = $value %% 2 ?? "Even" !! "Odd"; | |
@bar.push: $value | |
} | |
say @foo; # OUTPUT: «[1 2 3]» | |
say @bar; # OUTPUT: «[Odd Even Odd]» | |
</pre> | |
<p>This rule also applies to the topic variable <span class="code">$_</span>, which by default is a read-write alias; it will become read-only if it's used in a <span class="code">-></span> loop.</p> | |
<pre class="code">my @foo = 1..3; | |
for @foo -> $_ { $_.say } | |
# Error: ...require mutable arguments | |
for @foo -> $_ { $_++ }</pre> | |
<p>A <span class="code">for</span> loop can produce a <span class="code">List</span> 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:</p> | |
<pre class="code">(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]»</pre> | |
<p>This implies that, if the results of the loop are not assigned, they will be in a <a href="#_language_contexts.pod6-index-entry-sink_context">sink context</a>:</p> | |
<pre class="code">class Sunk { | |
has $.titanic; | |
method sink { | |
say "Sinking $!titanic"; | |
} | |
} | |
Sunk.new( :titanic($_) ) for ^3; | |
for 1 { | |
say "About to sink"; | |
Sunk.new( :titanic($_) ); | |
} | |
# OUTPUT: | |
# Sinking 0 | |
# Sinking 1 | |
# Sinking 2 | |
# About to sink | |
# Sinking 1 | |
</pre> | |
<p>The first loop creates three elements but they are in a sink context, so its <span class="code">sink</span> method is called. In the second loop, its last statement will be in a sink context, so it will be also sunk (from version 6.d).</p> | |
<p>The <span class="code">Empty</span> constant will act as a no-op for a loop:</p> | |
<pre class="code">say "Not here" for Empty; | |
</pre> | |
<p>Will not do anything. This constant is <a href="#_syntax_Empty.pod6">equivalent to a empty Slip or List</a>.</p> | |
<p>Undefined values will behave in the same way:</p> | |
<pre class="code">my @array := Empty; | |
.say for @array; | |
say @array; # OUTPUT: «()» | |
</pre> | |
<p>Assigning <span class="code">Empty</span> will effectively undefine an <span class="code">Array</span>, using <span class="code">for</span> over an undefined array will not even enter the loop, as shown, effectively behaving in the same way as above when <span class="code">Empty</span> was used directly.</p> | |
<p>With <span class="code">hyper</span> and <span class="code">race</span>, the <span class="code">for</span> loop is potentially iterated in parallel. See also the documentation for <span class="code">hyper</span> and <span class="code">race</span> in class <a href="#_type_Map.pod6">Map</a>.</p> | |
<pre class="code">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)» | |
</pre> | |
<p>with <span class="code">hyper</span> the order of elements is preserved.</p> | |
<pre class="code">my $primes_r = race for ^10_000 -> $number { $number if $number.is-prime }; | |
say $primes_r.elems; # OUTPUT: «1229» | |
</pre> | |
<p>Unlike <span class="code">hyper</span>, <span class="code">race</span> does not preserve the order of elements.</p> | |
<a name="t15.11"></a> <h1 id="_language_control.pod6-gather/take"><a name="263"></a>gather/take</h1> | |
<p><span class="code">gather</span> is a statement or block prefix that returns a <a href="#_type_Seq.pod6">sequence</a> of values. The values come from calls to <a href="#_type_Mu.pod6-routine_take">take</a> in the dynamic scope of the <span class="code">gather</span> block. In the following example, we implement a subroutine to compute the factors of an integer with <span class="code">gather</span> (note that the factors are not generated in a strictly increasing order):</p> | |
<pre class="code">sub factors( Int:D \n ) { | |
my $k = 1; | |
gather { | |
while $k**2 < n { | |
if n %% $k { | |
take $k; | |
take n div $k; | |
} | |
$k++; | |
} | |
take $k if $k**2 == n; | |
} | |
} | |
say factors(36); # OUTPUT: «1, 36, 2, 18, 3, 12, 4, 9, 6»</pre> | |
<p>The <span class="code">gather/take</span> combination can generate values lazily, depending on context. If you want to force lazy evaluation use the <a href="#_type_Iterable.pod6-method_lazy">lazy</a> subroutine or method. Binding to a scalar or sigilless container will also force laziness. For example:</p> | |
<pre class="code">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</pre> | |
<p><span class="code">gather/take</span> is scoped dynamically, so you can call <span class="code">take</span> from subs or methods that are called from within <span class="code">gather</span>:</p> | |
<pre class="code">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)»</pre> | |
<p>If values need to be mutable on the caller side, use <a href="#_type_Mu.pod6-routine_take-rw">take-rw</a>.</p> | |
<p>Note that <span class="code">gather/take</span> also work for hashes. The return value is still a <span class="code">Seq</span> but the assignment to a hash in the following example makes it a hash.</p> | |
<pre class="code">my %h = gather { take "foo" => 1; take "bar" => 2}; | |
say %h; # OUTPUT: «{bar => 2, foo => 1}»</pre> | |
<p><b>Note</b>: <span class="code">gather/take</span> must not be used to collect results from <span class="code">react/whenever</span>. The <span class="code">whenever</span> block is not run from the thread that runs the <span class="code">gather/react</span>, but the thread that runs the <span class="code">emit</span>. On this thread, there is no handler for the control exception thrown by <span class="code">take</span>, causing it to error out.</p> | |
<a name="t15.12"></a> <h1 id="_language_control.pod6-supply/emit"><a name="264"></a>supply/emit</h1> | |
<p>Emits the invocant into the enclosing <a href="#_language_concurrency.pod6-index-entry-supply_(on-demand)">supply</a>:</p> | |
<pre class="code">my $supply = supply { | |
emit $_ for "foo", 42, .5; | |
} | |
$supply.tap: { | |
say "received {.^name} ($_)"; | |
} | |
# OUTPUT: | |
# received Str (foo) | |
# received Int (42) | |
# received Rat (0.5)</pre> | |
<p><a id="i265" name="Other languages switch (given)"></a><span class="indexed"></span> <a id="i266" name="Other languages case statements (given)"></a><span class="indexed"></span></p> | |
<a name="t15.13"></a> <h1 id="_language_control.pod6-given"><a name="267"></a>given</h1> | |
<p>The <span class="code">given</span> statement is Raku's topicalizing keyword in a similar way that <span class="code">switch</span> topicalizes in languages such as C. In other words, <span class="code">given</span> sets <span class="code">$_</span> inside the following block. The keywords for individual cases are <span class="code">when</span> and <span class="code">default</span>. The usual idiom looks like this:</p> | |
<pre class="code">my $var = (Any, 21, any <answer lie>).pick; | |
given $var { | |
when 21 { say $_ * 2 } | |
when 'lie' { .say } | |
default { say 'default' } | |
}</pre> | |
<p>The <span class="code">given</span> statement is often used alone:</p> | |
<pre class="code">given 42 { .say; .Numeric; }</pre> | |
<p>This is a lot more understandable than:</p> | |
<pre class="code">{ .say; .Numeric; }(42)</pre> | |
<a name="t15.13.1"></a> <h2 id="_language_control.pod6-default_and_when"><a name="268"></a>default and when</h2> | |
<p>A block containing a <span class="code">default</span> statement will be left immediately when the sub-block after the <span class="code">default</span> statement is left. It is as though the rest of the statements in the block were skipped.</p> | |
<pre class="code">given 42 { | |
"This says".say; | |
$_ == 42 and ( default { "This says, too".say; 43; } ); | |
"This never says".say; | |
} | |
# The above block evaluates to 43</pre> | |
<p>A <span class="code">when</span> statement will also do this (but a <span class="code">when</span> statement modifier will <i>not</i>.)</p> | |
<p>In addition, <span class="code">when</span> statements <span class="code">smartmatch</span> the topic (<span class="code">$_</span>) against a supplied expression such that it is possible to check against values, regular expressions, and types when specifying a match.</p> | |
<pre class="code">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»</pre> | |
<p>In this form, the <span class="code">given</span>/<span class="code">when</span> construct acts much like a set of <span class="code">if</span>/<span class="code">elsif</span>/<span class="code">else</span> statements. Be careful with the order of the <span class="code">when</span> statements. The following code says <span class="code">"Int"</span> not <span class="code">42</span>.</p> | |
<pre class="code">given 42 { | |
when Int { say "Int" } | |
when 42 { say 42 } | |
default { say "huh?" } | |
} | |
# OUTPUT: «Int»</pre> | |
<p>When a <span class="code">when</span> statement or <span class="code">default</span> statement causes the outer block to return, nesting <span class="code">when</span> or <span class="code">default</span> 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:</p> | |
<pre class="code">given 42 { | |
when Int { | |
when 42 { say 42 } | |
say "Int" | |
} | |
default { say "huh?" } | |
} | |
# OUTPUT: «42»</pre> | |
<p><span class="code">when</span> statements can smartmatch against <a href="#_language_syntax.pod6-Signature_literals">Signatures</a>.</p> | |
<a name="t15.13.2"></a> <h2 id="_language_control.pod6-proceed_and_succeed"><a name="269"></a>proceed and <a name="270"></a>succeed</h2> | |
<p>Both <span class="code">proceed</span> and <span class="code">succeed</span> are meant to be used only from inside <span class="code">when</span> or <span class="code">default</span> blocks.</p> | |
<p>The <span class="code">proceed</span> statement will immediately leave the <span class="code">when</span> or <span class="code">default</span> block, skipping the rest of the statements, and resuming after the block. This prevents the <span class="code">when</span> or <span class="code">default</span> from exiting the outer block.</p> | |
<pre class="code">given * { | |
default { | |
proceed; | |
"This never says".say | |
} | |
} | |
"This says".say; | |
</pre> | |
<p>This is most often used to enter multiple <span class="code">when</span> blocks. <span class="code">proceed</span> will resume matching after a successful match, like so:</p> | |
<pre class="code">given 42 { | |
when Int { say "Int"; proceed } | |
when 42 { say 42 } | |
when 40..* { say "greater than 40" } | |
default { say "huh?" } | |
} | |
# OUTPUT: «Int» | |
# OUTPUT: «42»</pre> | |
<p>Note that the <span class="code">when 40..*</span> match didn't occur. For this to match such cases as well, one would need a <span class="code">proceed</span> in the <span class="code">when 42</span> block.</p> | |
<p>This is not like a <span class="code">C</span> <span class="code">switch</span> statement, because the <span class="code">proceed</span> does not merely enter the directly following block, it attempts to match the <span class="code">given</span> value once more, consider this code:</p> | |
<pre class="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»</pre> | |
<p>...which matches the <span class="code">Int</span>, skips <span class="code">43</span> since the value doesn't match, matches <span class="code">42</span> since this is the next positive match, but doesn't enter the <span class="code">default</span> block since the <span class="code">when 42</span> block doesn't contain a <span class="code">proceed</span>.</p> | |
<p>By contrast, the <span class="code">succeed</span> keyword short-circuits execution and exits the entire <span class="code">given</span> block at that point. It may also take an argument to specify a final value for the block.</p> | |
<pre class="code">given 42 { | |
when Int { | |
say "Int"; | |
succeed "Found"; | |
say "never this!"; | |
} | |
when 42 { say 42 } | |
default { say "dunno?" } | |
} | |
# OUTPUT: «Int»</pre> | |
<p>If you are not inside a when or default block, it is an error to try to use <span class="code">proceed</span> or <span class="code">succeed</span>.Also remember, the <span class="code">when</span> statement modifier form does not cause any blocks to be left, and any <span class="code">succeed</span> or <span class="code">proceed</span> in such a statement applies to the surrounding clause, if there is one:</p> | |
<pre class="code">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; | |
} | |
# OUTPUT: «This saysThis says tooAnd this saysThis also says»</pre> | |
<a name="t15.13.3"></a> <h2 id="_language_control.pod6-given_as_a_statement"><a name="271"></a>given as a statement</h2> | |
<p><span class="code">given</span> can follow a statement to set the topic in the statement it follows.</p> | |
<pre class="code">.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»</pre> | |
<a name="t15.14"></a> <h1 id="_language_control.pod6-loop"><a name="272"></a>loop</h1> | |
<p>The <span class="code">loop</span> statement takes three statements in parentheses separated by <span class="code">;</span> that take the roles of initializer, conditional and incrementer, respectively. The initializer is executed once before the conditional is first tested. In case the initializer involves a variable declaration, the variable is declared as a lexical variable in the loop's <i>outer or containing</i> scope so that it can be used in code following the loop statement. The conditional is executed before each iteration and coerced to <span class="code">Bool</span>; if <span class="code">False</span> the loop is stopped. The incrementer is executed after each iteration, and before the conditional is tested again.</p> | |
<pre class="code">loop (my $i = 0; $i < 10; $i++) { # A typical loop | |
say $i; | |
} | |
my @str = "However Long".comb; # Our very own .char routine: | |
loop (my $l = 0;;) { # Declare $l in outer scope | |
last if !@str[$l++] # and count chars until we hit an | |
} # undefined element (Any) | |
say "The string is {--$l} chars long.";</pre> | |
<p>The infinite loop does not require parentheses.</p> | |
<pre class="code">loop { say 'forever' } | |
</pre> | |
<p>The <span class="code">loop</span> statement may be used to produce values from the result of each run of the attached block if it appears in lists:</p> | |
<pre class="code">(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</pre> | |
<p>Unlike a <span class="code">for</span> loop, one should not rely on whether returned values are produced lazily. It would probably be best to use <span class="code">eager</span> to guarantee that a loop whose return value may be used actually runs:</p> | |
<pre class="code">sub heads-in-a-row { | |
(eager loop (; 2.rand < 1;) { "heads".say }) | |
}</pre> | |
<a name="t15.15"></a> <h1 id="_language_control.pod6-while,_until"><a name="273"></a>while, until</h1> | |
<p>The <span class="code">while</span> statement executes the block as long as its condition is true. So</p> | |
<pre class="code">my $x = 1; | |
while $x < 4 { | |
print $x++; | |
} | |
print "\n"; | |
# OUTPUT: «123»</pre> | |
<p>Similarly, the <span class="code">until</span> statement executes the block as long as the expression is false.</p> | |
<pre class="code">my $x = 1; | |
until $x > 3 { | |
print $x++; | |
} | |
print "\n"; | |
# OUTPUT: «123»</pre> | |
<p>The condition for <span class="code">while</span> or <span class="code">until</span> can be parenthesized, but there must be a space between the keyword and the opening parenthesis of the condition.</p> | |
<p>Both <span class="code">while</span> and <span class="code">until</span> can be used as statement modifiers. E. g.</p> | |
<pre class="code">my $x = 42; | |
$x-- while $x > 12</pre> | |
<p>Also see <span class="code">repeat/while</span> and <span class="code">repeat/until</span> below.</p> | |
<p>All these forms may produce a return value the same way <span class="code">loop</span> does.</p> | |
<a name="t15.16"></a> <h1 id="_language_control.pod6-repeat/while,_repeat/until"><a name="274"></a>repeat/while, repeat/until</h1> | |
<p>Executes the block <i>at least once</i> and, if the condition allows, repeats that execution. This differs from <span class="code">while</span>/<span class="code">until</span> in that the condition is evaluated at the end of the loop, even if it appears at the front.</p> | |
<pre class="code">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»</pre> | |
<p>All these forms may produce a return value the same way <span class="code">loop</span> does.</p> | |
<a name="t15.17"></a> <h1 id="_language_control.pod6-return"><a name="275"></a>return</h1> | |
<p>The sub <span class="code">return</span> will stop execution of a subroutine or method, run all relevant <a href="#_language_phasers.pod6-Block_phasers">phasers</a> and provide the given return value to the caller. The default return value is <span class="code">Nil</span>. If a return <a href="#_type_Signature.pod6-Constraining_return_types">type constraint</a> is provided it will be checked unless the return value is <span class="code">Nil</span>. If the type check fails the exception <a href="#_type_X::TypeCheck::Return.pod6">X::TypeCheck::Return</a> is thrown. If it passes a control exception is raised and can be caught with <a href="#_language_phasers.pod6-CONTROL">CONTROL</a>.</p> | |
<p>Any <span class="code">return</span> in a block is tied to the first <span class="code">Routine</span> in the outer lexical scope of that block, no matter how deeply nested. Please note that a <span class="code">return</span> in the root of a package will fail at runtime. A <span class="code">return</span> in a block that is evaluated lazily (e.g. inside <span class="code">map</span>) may find the outer lexical routine gone by the time the block is executed. In almost any case <span class="code">last</span> is the better alternative. Please check <a href="#_language_functions.pod6-Return_values">the functions documentation</a> for more information on how return values are handled and produced.</p> | |
<a name="t15.18"></a> <h1 id="_language_control.pod6-return-rw"><a name="276"></a>return-rw</h1> | |
<p>The sub <span class="code">return</span> will return values, not containers. Those are immutable and will lead to runtime errors when attempted to be mutated.</p> | |
<pre class="code">sub s(){ my $a = 41; return $a }; | |
say ++s(); | |
CATCH { default { say .^name, ': ', .Str } }; | |
# OUTPUT: «X::Multi::NoMatch.new(dispatcher …</pre> | |
<p>To return a mutable container, use <span class="code">return-rw</span>.</p> | |
<pre class="code">sub s(){ my $a = 41; return-rw $a }; | |
say ++s(); | |
# OUTPUT: «42»</pre> | |
<p>The same rules as for <span class="code">return</span> regarding phasers and control exceptions apply.</p> | |
<a name="t15.19"></a> <h1 id="_language_control.pod6-fail"><a name="277"></a>fail</h1> | |
<p>Leaves the current routine and returns the provided <a href="#_type_Exception.pod6">Exception</a> or <span class="code">Str</span> wrapped inside a <a href="#_type_Failure.pod6">Failure</a>, after all relevant <a href="#_language_phasers.pod6-Block_phasers">phasers</a> are executed. If the caller activated fatal exceptions via the pragma <span class="code">use fatal;</span>, the exception is thrown instead of being returned as a <span class="code">Failure</span>.</p> | |
<pre class="code">sub f { fail "WELP!" }; | |
say f; | |
CATCH { default { say .^name, ': ', .Str } } | |
# OUTPUT: «X::AdHoc: WELP!»</pre> | |
<a name="t15.20"></a> <h1 id="_language_control.pod6-once"><a name="278"></a>once</h1> | |
<p>A block prefix with <span class="code">once</span> will be executed exactly once, even if placed inside a loop or a recursive routine.</p> | |
<pre class="code">my $guard = 3; | |
loop { | |
last if $guard-- <= 0; | |
once { put 'once' }; | |
print 'many' | |
} # OUTPUT: «oncemanymanymany»</pre> | |
<p>This works per "clone" of the containing code object, so:</p> | |
<pre class="code">({ once 42.say } xx 3).map: {$_(), $_()}; # says 42 thrice</pre> | |
<p>Note that this is <b>not</b> 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.</p> | |
<a name="t15.21"></a> <h1 id="_language_control.pod6-quietly"><a name="279"></a>quietly</h1> | |
<p>A <span class="code">quietly</span> block will suppress all warnings generated in it.</p> | |
<pre class="code">quietly { warn 'kaput!' }; | |
warn 'still kaput!'; | |
# OUTPUT: «still kaput! [...]»</pre> | |
<p>Any warning generated from any routine called from within the block will also be suppressed:</p> | |
<pre class="code">sub told-you { warn 'hey...' }; | |
quietly { told-you; warn 'kaput!' }; | |
warn 'Only telling you now!' | |
# OUTPUT: «Only telling you now! [...] »</pre> | |
<a name="t15.22"></a> <h1 id="_language_control.pod6-LABELs">LABELs</h1> | |
<p><span class="code">while</span>, <span class="code">until</span>, <span class="code">loop</span> and <span class="code">for</span> loops can all take a label, which can be used to identify them for <span class="code">next</span>, <span class="code">last</span>, and <span class="code">redo</span>. Nested loops are supported, for instance:</p> | |
<pre class="code">OUTAHERE: while True { | |
for 1,2,3 -> $n { | |
last OUTAHERE if $n == 2; | |
} | |
}</pre> | |
<p>Labels can be used also within nested loops to name each loop, for instance:</p> | |
<pre class="code">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; | |
} | |
</pre> | |
<a name="t15.23"></a> <h1 id="_language_control.pod6-next"><a name="280"></a>next</h1> | |
<p>The <span class="code">next</span> command starts the next iteration of the loop. So the code</p> | |
<pre class="code">my @x = 1, 2, 3, 4, 5; | |
for @x -> $x { | |
next if $x == 3; | |
print $x; | |
} | |
</pre> | |
<p>prints "1245".</p> | |
<p>If the <a href="#_language_phasers.pod6-NEXT"><span class="code">NEXT</span> phaser</a> is present, it runs before the next iteration:</p> | |
<pre class="code">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.» | |
</pre> | |
<p>In a <a href="#_language_concurrency.pod6-index-entry-whenever">whenever</a> block, <span class="code">next</span> immediately exits the block for the current value:</p> | |
<pre class="code">react { | |
whenever Supply.interval(1) { | |
next if .is-prime; | |
say $_; | |
done if $_ == 4; | |
} | |
}</pre> | |
<p>prints "0", "1" and "4" - integers from 0 to 4 with primes skipped.</p> | |
<p>*Since version 6.d, the <span class="code">next</span> command in a loop that collects its last statement values returns <span class="code">Empty</span> for the iterations they run on.*</p> | |
<a name="t15.24"></a> <h1 id="_language_control.pod6-last"><a name="281"></a>last</h1> | |
<p>The <span class="code">last</span> command immediately exits the loop in question.</p> | |
<pre class="code">my @x = 1, 2, 3, 4, 5; | |
for @x -> $x { | |
last if $x == 3; | |
print $x; | |
} | |
</pre> | |
<p>prints "12".</p> | |
<p>If the <a href="#_language_phasers.pod6-LAST"><span class="code">LAST</span> phaser</a> is present, it runs before exiting the loop:</p> | |
<pre class="code">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.» | |
</pre> | |
<p>*Since version 6.d, the <span class="code">last</span> command in a loop that collects its last statement values returns <span class="code">Empty</span> for the iterations they run on.*</p> | |
<a name="t15.25"></a> <h1 id="_language_control.pod6-redo"><a name="282"></a>redo</h1> | |
<p>The <span class="code">redo</span> command restarts the loop block without evaluating the conditional again.</p> | |
<pre class="code">loop { | |
my $x = prompt("Enter a number"); | |
redo unless $x ~~ /\d+/; | |
last; | |
} | |
</pre> | |
</div> | |
<!-- /language/create-cli.pod6 --><div class="pod-body"><a id="_language_create-cli.pod6"></a><a name="t16"></a><h1 class="title">16 Command line interface</h1> <p class="subtitle">Creating your own CLI in Raku</p> <p><a id="i283" name="Programs command line arguments"></a><span class="indexed"></span></p> | |
<a name="t16.1"></a> <h1 id="_language_create-cli.pod6-Command_line_interface_-_an_overview">Command line interface - an overview</h1> | |
<p>The default command line interface of Raku scripts consists of three parts:</p> | |
<a name="t16.1.1"></a> <h2 id="_language_create-cli.pod6-Parsing_the_command_line_parameters_into_a_capture">Parsing the command line parameters into a <a href="#_type_Capture.pod6">capture</a></h2> | |
<p>This looks at the values in <a href="#_language_variables.pod6-index-entry-@*ARGS">@*ARGS</a>, interprets these according to some policy, and creates a <a href="#_type_Capture.pod6">Capture</a> object out of that. An alternative way of parsing may be provided by the developer or installed using a module.</p> | |
<a name="t16.1.2"></a> <h2 id="_language_create-cli.pod6-Calling_a_provided_MAIN_subroutine_using_that_capture">Calling a provided <span class="code">MAIN</span> subroutine using that capture</h2> | |
<p>Standard <a href="#_language_functions.pod6-index-entry-declarator_multi-Multi-dispatch">multi dispatch</a> is used to call the <span class="code">MAIN</span> subroutine with the generated <span class="code">Capture</span> object. This means that your <span class="code">MAIN</span> subroutine may be a <span class="code">multi sub</span>, each candidate of which is responsible for some part of processing the given command line arguments.</p> | |
<a name="t16.1.3"></a> <h2 id="_language_create-cli.pod6-Creating_/_showing_usage_information_if_calling_MAIN_failed">Creating / showing usage information if calling <span class="code">MAIN</span> failed</h2> | |
<p>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 <span class="code">MAIN</span> candidate sub, and any associated Pod information. The result is then shown to the user on STDERR (or on STDOUT if <span class="code">--help</span> was specified). An alternative way of generating the usage information may be provided by the developer or installed using a module.</p> | |
<p><a id="i284" name="Programs MAIN"></a><span class="indexed"></span></p> | |
<a name="t16.2"></a> <h1 id="_language_create-cli.pod6-sub_MAIN">sub MAIN</h1> | |
<p>The sub with the special name <span class="code">MAIN</span> will be executed after all relevant entry phasers (<span class="code">BEGIN</span>, <span class="code">CHECK</span>, <span class="code">INIT</span>, <span class="code">PRE</span>, <span class="code">ENTER</span>) have been run and the <a href="#_language_glossary.pod6-index-entry-Mainline">mainline</a> of the script has been executed. No error will occur if there is no <span class="code">MAIN</span> sub: your script will then just have to do the work, such as argument parsing, in the mainline of the script.</p> | |
<p>Any normal exit from the <span class="code">MAIN</span> sub will result in an exit code of <span class="code">0</span>, indicating success. Any return value of the <span class="code">MAIN</span> sub will be ignored. If an exception is thrown that is not handled inside the <span class="code">MAIN</span> sub, then the exit code will be <span class="code">1</span>. If the dispatch to <span class="code">MAIN</span> failed, a usage message will be displayed on STDERR and the exit code will be <span class="code">2</span>.</p> | |
<p>The command line parameters are present in the <span class="code">@*ARGS</span> dynamic variable and may be altered in the mainline of the script before the <span class="code">MAIN</span> unit is called.</p> | |
<p>The signature of (the candidates of the multi) sub <span class="code">MAIN</span> determines which candidate will actually be called using the standard <a href="#_language_glossary.pod6-index-entry-Multi-Dispatch">multi dispatch</a> semantics.</p> | |
<p>A simple example:</p> | |
<pre class="code"># inside file 'hello.raku' | |
sub MAIN($name) { | |
say "Hello $name, how are you?" | |
}</pre> | |
<p>If you call that script without any parameters, you get the following usage message:</p> | |
<pre class="code">$ raku hello.raku | |
Usage: | |
hello.raku <name> | |
</pre> | |
<p>However, if you give a default value for the parameter, running the script either with or without specifying a name will always work:</p> | |
<pre class="code"># inside file 'hello.raku' | |
sub MAIN($name = 'bashful') { | |
say "Hello $name, how are you?" | |
}</pre> | |
<pre class="code">$ raku hello.raku | |
Hello bashful, how are you? | |
</pre> | |
<pre class="code">$ raku hello.raku Liz | |
Hello Liz, how are you? | |
</pre> | |
<p>Another way to do this is to make <span class="code">sub MAIN</span> a <span class="code">multi sub</span>:</p> | |
<pre class="code"># inside file 'hello.raku' | |
multi sub MAIN() { say "Hello bashful, how are you?" } | |
multi sub MAIN($name) { say "Hello $name, how are you?" }</pre> | |
<p>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.</p> | |
<p>If you want to pass an indeterminate number of parameters to be dealt within <span class="code">sub MAIN</span>, you can use <a href="#_type_Signature_.pod6-Flattened_slurpy">slurpy parameters</a>:</p> | |
<pre class="code"># inside file 'hello-all.raku' | |
sub MAIN(*@all) { @all.map: -> $name { say "Hello, " ~ $name } }</pre> | |
<pre class="code">$ raku hello-all.raku peter paul mary | |
Hello, peter | |
Hello, paul | |
Hello, mary | |
</pre> | |
<p>A more complicated example using a single positional and multiple named parameters, and also showing that <span class="code">where</span> clauses can also be applied to <span class="code">MAIN</span> arguments:</p> | |
<pre class="code"># inside "frobnicate.raku" | |
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'); | |
} | |
</pre> | |
<p>With <span class="code">file.dat</span> present, this will work this way:</p> | |
<pre class="code">$ raku frobnicate.raku | |
24 | |
file.dat | |
Verbosity off | |
</pre> | |
<p>Or this way with <span class="code">--verbose</span>:</p> | |
<pre class="code">$ raku frobnicate.raku --verbose | |
24 | |
file.dat | |
Verbosity on | |
</pre> | |
<p>If the file <span class="code">file.dat</span> 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 <span class="code">MAIN</span> sub:</p> | |
<pre class="code">$ raku frobnicate.raku doesnotexist.dat | |
Usage: | |
frobnicate.raku [--length=<Int>] [--verbose] [<file>] | |
</pre> | |
<p>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:</p> | |
<pre class="code"># inside "frobnicate.raku" | |
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'); | |
} | |
</pre> | |
<p>Which would improve the usage message like this:</p> | |
<pre class="code">$ raku frobnicate.raku doesnotexist.dat | |
Usage: | |
frobnicate.raku [--length=<Int>] [--verbose] [<file>] | |
[<file>] an existing file to frobnicate | |
--length=<Int> length needed for frobnication | |
--verbose required verbosity | |
</pre> | |
<p>From release 2021.03, values to single named arguments can be separated by spaces too. Consider a <span class="code">demo</span> program with the following source:</p> | |
<pre class="code">subset name of Any where Str|True; | |
subset port of Str; | |
multi MAIN( | |
$file, | |
name :$profile, #= Write profile information to a file | |
port :$debug-port, #= Listen for debugger connections on the specified port | |
Bool :v($verbose), #= Display verbose output | |
) {} | |
multi MAIN("--process-files", *@images) {}</pre> | |
<p>This program generates the following usage message:</p> | |
<pre class="code">Usage: | |
demo [--profile[=name]] [--debug-port=<port>] [-v] <file> | |
demo --process-files [<images> ...] | |
--profile[=name] Write profile information to a file | |
--debug-port=<port> Listen for debugger connections on the specified port | |
-v Display verbose output | |
</pre> | |
<p>The following are valid ways to call <span class="code">demo</span>:</p> | |
<pre class="code">demo --profile ~/foo | |
demo --profile=/tmp/bar ~/foo | |
demo --debug-port 4242 ~/foo | |
demo --debug-port=4242 ~/foo | |
demo -v ~/foo | |
demo --process-files *.jpg | |
</pre> | |
<p>These, however, are not valid</p> | |
<pre class="code">demo --profile /tmp/bar ~/foo | |
demo --debug-port ~/foo | |
</pre> | |
<p>The first is invalid because <span class="code">/tmp/bar</span> and <span class="code">~/foo</span> are both parsed as positional arguments, which means <span class="code">demo</span> was called with too many positional arguments. The second is invalid because <span class="code">~/foo</span> is parsed as an argument to <span class="code">--debug-port</span>, and thus <span class="code">demo</span> lacks the required positional argument.</p> | |
<p>Here's how it works; with Raku distinguishing between three types of options:</p> | |
<ul><li><p>Boolean options (like <span class="code">-v</span>), which <i>never</i> take an argument; they are ether present or absent.</p> | |
</li></ul> <ul><li><p>Options with a mandatory argument (like <span class="code">--debug-port</span>), which always take an argument. If you give them an argument with <span class="code">=</span>, they will use that; if not, they'll take the following argument.</p> | |
</li></ul> <ul><li><p>Options with an optional argument (like <span class="code">--profile</span>), which are valid both with and without an argument. You can <i>only</i> give these arguments an option with the <span class="code">=</span> syntax; if there is a space after the option, that means it was called without an argument.</p> | |
</li></ul> <p>And here's the signature that produces each type of argument:</p> | |
<ul><li><p>Boolean options: A <a href="#_type_Bool.pod6"><span class="code">Bool</span></a> type constraint. = Options with a mandatory argument: A type that does not <a href="#_routine_ACCEPTS.pod6"><span class="code"> .ACCEPT</span></a> a <span class="code">Bool</span>.</p> | |
</li></ul> <ul><li><p>Options with an optional argument: A type that <span class="code">.ACCEPTS</span> a <span class="code">True</span> (because passing an option without an argument is equivalent to passing <span class="code">True</span>)</p> | |
</li></ul> <p>As any other subroutine, <span class="code">MAIN</span> can define <a href="#_type_Signature.pod6-index-entry-argument_aliases">aliases</a> for its named parameters.</p> | |
<pre class="code">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'); | |
} | |
</pre> | |
<p>In which case, these aliases will also be listed as alternatives with <span class="code">--help</span>:</p> | |
<pre class="code">Usage: | |
frobnicate.raku [--size|--length=<Int>] [--verbose] [<file>] | |
[<file>] an existing file to frobnicate | |
--size|--length=<Int> length needed for frobnication | |
--verbose required verbosity | |
</pre> | |
<p><span class="code">Enumeration</span>s can be used in signatures with arguments converted automatically to its corresponding <span class="code">enum</span> symbol:</p> | |
<pre class="code">enum Flag ( | |
FLAG_FOO => 0b001, | |
FLAG_BAR => 0b010, | |
FLAG_BAZ => 0b100, | |
); | |
sub MAIN(Flag $flag = FLAG_FOO) { | |
say "Flagging $flag"; | |
} | |
</pre> | |
<p>This will work correctly with</p> | |
<pre class="code">raku MAIN-enum.raku FLAG_BAR | |
</pre> | |
<p>but will die if called with something that is not a <span class="code">Flag</span>.</p> | |
<a name="t16.2.1"></a> <h2 id="_language_create-cli.pod6-%*SUB-MAIN-OPTS"><a name="285"></a><span class="code">%*SUB-MAIN-OPTS</span></h2> | |
<p>It's possible to alter how arguments are processed before they're passed to <span class="code">sub MAIN {}</span> by setting options in the <span class="code">%*SUB-MAIN-OPTS</span> hash. Due to the nature of dynamic variables, it is required to set up the <span class="code">%*SUB-MAIN-OPTS</span> hash and fill it with the appropriate settings. For instance:</p> | |
<pre class="code">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!" | |
}</pre> | |
<p>Available options are:</p> | |
<a name="t16.2.1.1"></a> <h3 id="_language_create-cli.pod6-named-anywhere"><a name="286"></a><span class="code">named-anywhere</span></h3> | |
<p>By default, named arguments passed to the program (i.e., <span class="code">MAIN</span>) cannot appear after any positional argument. However, if <span class="code">%*SUB-MAIN-OPTS<named-anywhere></span> 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:</p> | |
<pre class="code">$ raku example.raku 1 --c=2 3 --d=4 | |
</pre> | |
<a name="t16.2.1.2"></a> <h3 id="_language_create-cli.pod6-bundling"><a name="287"></a><span class="code">bundling</span></h3> | |
<p>When <span class="code">%*SUB-MAIN-OPTS<bundling></span> is set to a true value, single letter named arguments can be bundled together with a single dash. The following two commands are then equivalent:</p> | |
<pre class="code">$ raku example.raku -a -b -c | |
$ raku example.raku -abc | |
</pre> | |
<p>Bundled arguments can be understood as flags, that can neither be negated, nor assigned a value though:</p> | |
<pre class="code">$ raku example.raku -/a # OK | |
$ raku example.raku -a=asdf # OK | |
$ raku example.raku -abc=asdf # Error | |
$ raku example.raku -/abc # Error | |
</pre> | |
<p>This option is only available starting in the 2020.10 release.</p> | |
<a name="t16.2.2"></a> <h2 id="_language_create-cli.pod6-is_hidden-from-USAGE"><a name="288"></a><span class="code">is hidden-from-USAGE</span></h2> | |
<p>Sometimes you want to exclude a <span class="code">MAIN</span> candidate from being shown in any automatically generated usage message. This can be achieved by adding a <span class="code">hidden-from-USAGE</span> trait to the specification of the <span class="code">MAIN</span> candidate you do not want to show. Expanding on an earlier example:</p> | |
<pre class="code"># inside file 'hello.raku' | |
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?" | |
}</pre> | |
<p>So, if you would call this script with just a named variable, you would get the following usage:</p> | |
<pre class="code">$ raku hello.raku --verbose | |
Usage: | |
hello.raku <name> -- the name by which you would like to be called | |
</pre> | |
<p>Without the <span class="code">hidden-from-USAGE</span> trait on the first candidate, it would have looked like this:</p> | |
<pre class="code">$ raku hello.raku --verbose | |
Usage: | |
hello.raku | |
hello.raku <name> -- the name by which you would like to be called | |
</pre> | |
<p>Which, although technically correct, doesn't read as well.</p> | |
<a name="t16.3"></a> <h1 id="_language_create-cli.pod6-Unit-scoped_definition_of_MAIN"><a name="289"></a>Unit-scoped definition of <span class="code">MAIN</span></h1> | |
<p>If the entire program body resides within <span class="code">MAIN</span>, you can use the <span class="code">unit</span> declarator as follows (adapting an earlier example):</p> | |
<pre class="code">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 | |
</pre> | |
<p>Note that this is only appropriate if you can get by with just a single (only) <span class="code">sub MAIN</span>.</p> | |
<a name="t16.3.1"></a> <h2 id="_language_create-cli.pod6-sub_USAGE"><a name="290"></a>sub USAGE<a name="291"></a></h2> | |
<p>If no multi candidate of <span class="code">MAIN</span> is found for the given command line parameters, the sub <span class="code">USAGE</span> is called. If no such method is found, the compiler will output a default usage message.</p> | |
<pre class="code">#|(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 | |
}</pre> | |
<p>The default usage message is available inside <span class="code">sub USAGE</span> via the read-only <span class="code">$*USAGE</span> variable. It will be generated based on available <span class="code">sub MAIN</span> candidates and their parameters. As shown before, you can specify an additional extended description for each candidate using a <span class="code">#|(...)</span> Pod block to set <a href="#_routine_WHY.pod6"><span class="code">WHY</span></a>.</p> | |
<a name="t16.4"></a> <h1 id="_language_create-cli.pod6-Intercepting_CLI_argument_parsing_(2018.10,_v6.d_and_later)">Intercepting CLI argument parsing (2018.10, v6.d and later)</h1> | |
<p>You can replace or augment the default way of argument parsing by supplying a <span class="code">ARGS-TO-CAPTURE</span> subroutine yourself, or by importing one from any of the <a href="#_routine_https:__modules.raku.org_search_?q=getopt.pod6">Getopt</a> modules available in the ecosystem.</p> | |
<a name="t16.4.1"></a> <h2 id="_language_create-cli.pod6-sub_ARGS-TO-CAPTURE"><a name="292"></a>sub ARGS-TO-CAPTURE</h2> | |
<p>The <span class="code">ARGS-TO-CAPTURE</span> subroutine should accept two parameters: a <a href="#_type_Callable.pod6">Callable</a> representing the <span class="code">MAIN</span> 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 <a href="#_type_Capture.pod6">Capture</a> object that will be used to dispatch the <span class="code">MAIN</span> unit. The following is a <b>very</b> contrived example that will create a <span class="code">Capture</span> depending on some keyword that was entered (which can be handy during testing of a command line interface of a script):</p> | |
<pre class="code">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) | |
}</pre> | |
<p>Note that the dynamic variable <a href="#_language_variables.pod6-&*ARGS-TO-CAPTURE"><span class="code">&*ARGS-TO-CAPTURE</span></a> is available to perform the default command line arguments to <span class="code">Capture</span> processing so you don't have to reinvent the whole wheel if you don't want to.</p> | |
<a name="t16.5"></a> <h1 id="_language_create-cli.pod6-Intercepting_usage_message_generation_(2018.10,_v6.d_and_later)">Intercepting usage message generation (2018.10, v6.d and later)</h1> | |
<p>You can replace or augment the default way of usage message generation (after a failed dispatch to MAIN) by supplying a <span class="code">GENERATE-USAGE</span> subroutine yourself, or by importing one from any of the <a href="#_routine_https:__modules.raku.org_search_?q=getopt.pod6">Getopt</a> modules available in the ecosystem.</p> | |
<a name="t16.5.1"></a> <h2 id="_language_create-cli.pod6-sub_RUN-MAIN"><a name="293"></a>sub RUN-MAIN</h2> | |
<p>Defined as:</p> | |
<pre class="code">sub RUN-MAIN(&main, $mainline, :$in-as-argsfiles)</pre> | |
<p>This routine allows complete control over the handling of <span class="code">MAIN</span>. It gets a <span class="code">Callable</span> that is the <span class="code">MAIN</span> that should be executed, the return value of the mainline execution and additional named variables: <span class="code">:in-as-argsfiles</span> which will be <span class="code">True</span> if STDIN should be treated as <span class="code">$*ARGFILES</span>.</p> | |
<p>If <span class="code">RUN-MAIN</span> is not provided, a default one will be run that looks for subroutines of the old interface, such as <span class="code">MAIN_HELPER</span> and <span class="code">USAGE</span>. If found, it will execute following the "old" semantics.</p> | |
<pre class="code">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) ).raku.say | |
} | |
RUN-MAIN( &new-main, Nil ); | |
</pre> | |
<p>This will print the name (first argument) of the generated object.</p> | |
<a name="t16.5.2"></a> <h2 id="_language_create-cli.pod6-sub_GENERATE-USAGE"><a name="294"></a>sub GENERATE-USAGE</h2> | |
<p>The <span class="code">GENERATE-USAGE</span> subroutine should accept a <span class="code">Callable</span> representing the <span class="code">MAIN</span> 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 <span class="code">MAIN</span>. It should return the string of the usage information you want to be shown to the user. An example that will just recreate the <span class="code">Capture</span> that was created from processing the arguments:</p> | |
<pre class="code">sub GENERATE-USAGE(&main, |capture) { | |
capture<foo>:exists | |
?? "You're not allowed to specify a --foo" | |
!! &*GENERATE-USAGE(&main, |capture) | |
}</pre> | |
<p>You can also use multi subroutines to create the same effect:</p> | |
<pre class="code">multi sub GENERATE-USAGE(&main, :$foo!) { | |
"You're not allowed to specify a --foo" | |
} | |
multi sub GENERATE-USAGE(&main, |capture) { | |
&*GENERATE-USAGE(&main, |capture) | |
}</pre> | |
<p>Note that the dynamic variable <a href="#_language_variables.pod6-&*GENERATE-USAGE"><span class="code">&*GENERATE-USAGE</span></a> 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.</p> | |
<a name="t16.6"></a> <h1 id="_language_create-cli.pod6-Intercepting_MAIN_calling_(before_2018.10,_v6.e)">Intercepting MAIN calling (before 2018.10, v6.e)</h1> | |
<p>An older interface enabled one to intercept the calling to <span class="code">MAIN</span> completely. This depended on the existence of a <span class="code">MAIN_HELPER</span> subroutine that would be called if a <span class="code">MAIN</span> subroutine was found in the mainline of a program.</p> | |
<p>This interface was never documented. However, any programs using this undocumented interface will continue to function until <span class="code">v6.e</span>. From v6.d onward, the use of the undocumented API will cause a <span class="code">DEPRECATED</span> message.</p> | |
<p>Ecosystem modules can provide both the new and the old interface for compatibility with older versions of Perl 6 and Raku: if a newer Raku recognizes the new (documented) interface, it will use that. If there is no new interface subroutine available, but the old <span class="code">MAIN_HELPER</span> interface is, then it will use the old interface.</p> | |
<p>If a module developer decides to only offer a module for <span class="code">v6.d</span> or higher, then the support for the old interface can be removed from the module.</p> | |
</div> | |
<!-- /language/enumeration.pod6 --><div class="pod-body"><a id="_language_enumeration.pod6"></a><a name="t17"></a><h1 class="title">17 Enumeration</h1> <p class="subtitle">An example using the enum type</p> <p>The <span class="code">enum</span> type is much more complex in Raku than in some other languages, and the details are found in <a href="#_language_typesystem.pod6-enum">its type description</a>.</p> | |
<p>This short document will give a simple example of its use as is the usual practice in C-like languages.</p> | |
<p>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 (<span class="code">CanWrite</span>), or there is no directory (<span class="code">NoDir</span>) or the directory exists, but you cannot write (<span class="code">NoWrite</span>). The results of the test will determine what actions the program takes next.</p> | |
<pre class="code">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 | |
</pre> | |
</div> | |
<!-- /language/exceptions.pod6 --><div class="pod-body"><a id="_language_exceptions.pod6"></a><a name="t18"></a><h1 class="title">18 Exceptions</h1> <p class="subtitle">Using exceptions in Raku</p> <p>Exceptions in Raku 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.</p> | |
<p>All built-in exceptions inherit from <a href="#_type_Exception.pod6">Exception</a>, which provides some basic behavior, including the storage of a backtrace and an interface for the backtrace printer.</p> | |
<a name="t18.1"></a> <h1 id="_language_exceptions.pod6-Ad_hoc_exceptions"><i>Ad hoc</i> exceptions</h1> | |
<p>Ad hoc exceptions can be used by calling <a href="#_routine_die.pod6">die</a> with a description of the error:</p> | |
<pre class="code">die "oops, something went wrong"; | |
# OUTPUT: «oops, something went wrong in block <unit> at my-script.p6:1»</pre> | |
<p>It is worth noting that <span class="code">die</span> prints the error message to the standard error <span class="code">$*ERR</span>.</p> | |
<a name="t18.2"></a> <h1 id="_language_exceptions.pod6-Typed_exceptions">Typed exceptions</h1> | |
<p>Typed exceptions provide more information about the error stored within an exception object.</p> | |
<p>For example, if while executing <span class="code">.frobnicate</span> on an object, a needed path <span class="code">foo/bar</span> becomes unavailable, then an <a href="#_type_X::IO::DoesNotExist.pod6">X::IO::DoesNotExist</a> exception can be thrown:</p> | |
<pre class="code">method frobnicate($path) { | |
X::IO::DoesNotExist.new(:$path, :trying("frobnicate")).throw | |
unless $path.IO.e; | |
# do the actual frobnication | |
} | |
</pre> | |
<pre class="code">frobnicate("foo/bar"); | |
# OUTPUT: «Failed to find 'foo/bar' while trying to do '.frobnicate' | |
# in block <unit> at my-script.p6:1» | |
</pre> | |
<p>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.</p> | |
<p>Instead of calling the <span class="code">.throw</span> method on the <span class="code">X::IO::DoesNotExist</span> object, one can also use that object as a parameter to <span class="code">die</span>:</p> | |
<pre class="code">die X::IO::DoesNotExist.new(:$path, :trying("frobnicate")); | |
</pre> | |
<a name="t18.3"></a> <h1 id="_language_exceptions.pod6-Catching_exceptions"><a name="295"></a>Catching exceptions</h1> | |
<p>It's possible to handle exceptional circumstances by supplying a <span class="code">CATCH</span> block:</p> | |
<pre class="code">CATCH { | |
when X::IO { $*ERR.say: "some kind of IO exception was caught!" } | |
} | |
X::IO::DoesNotExist.new(:$path, :trying("frobnicate")).throw | |
# OUTPUT: «some kind of IO exception was caught!» | |
</pre> | |
<p>Here, we are saying that if any exception of type <span class="code">X::IO</span> occurs, then the message <span class="code">some kind of IO exception was caught!</span> will be sent to <i>stderr</i>, which is what <span class="code">$*ERR.say</span> does, getting displayed on whatever constitutes the standard error device in that moment, which will probably be the console by default.</p> | |
<p>A <span class="code">CATCH</span> block uses smartmatching similar to how <span class="code">given/when</span> smartmatches on options, thus it's possible to catch and handle various categories of exceptions inside a <span class="code">when</span> block. And it does so because, within the block, <span class="code">$_</span> is set to the exception that has been raised.</p> | |
<p>To handle all exceptions, use a <span class="code">default</span> statement. This example prints out almost the same information as the normal backtrace printer; the <i>dot</i> methods apply to <span class="code">$_</span>, which holds the <span class="code">Exception</span> within the <span class="code">CATCH</span> block.</p> | |
<pre class="code">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}"; | |
} | |
} | |
}</pre> | |
<p>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 <span class="code">CATCH</span> block.</p> | |
<p>Note that the <span class="code">CATCH</span> block semantics apply to the <b>entire</b> lexical scope in which it is defined, <b>regardless</b> of where it is defined inside that lexical scope. It is therefore advised to put any <span class="code">CATCH</span> block at the start of the lexical scope to which they apply so that the casual reader of the code can immediately see that there is something special going on.</p> | |
<a name="t18.3.1"></a> <h2 id="_language_exceptions.pod6-Exception_handlers_and_enclosing_blocks">Exception handlers and enclosing blocks</h2> | |
<p>After a CATCH has handled the exception, the block enclosing the <span class="code">CATCH</span> block is exited.</p> | |
<p>In other words, even when the exception is handled successfully, the <i>rest of the code</i> in the enclosing block will never be executed.</p> | |
<pre class="code">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 ...»</pre> | |
<p>Compare with this:</p> | |
<pre class="code">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!»</pre> | |
<p>See <a href="#_language_exceptions.pod6-Resuming_of_exceptions">Resuming of exceptions</a>, for how to return control back to where the exception originated.</p> | |
<a name="t18.4"></a> <h1 id="_language_exceptions.pod6-try_blocks"><a name="296"></a><span class="code">try</span> blocks</h1> | |
<p>A <span class="code">try</span> block is a normal block which implicitly turns on the <a href="#_language_pragmas.pod6-fatal"><span class="code">use fatal</span> pragma</a> and includes an implicit <span class="code">CATCH</span> block that drops the exception, which means you can use it to contain them. Caught exceptions are stored inside the <span class="code">$!</span> variable, which holds a value of type <span class="code">Exception</span>.</p> | |
<p>A normal block like this one will simply fail:</p> | |
<pre class="code">{ | |
my $x = +"a"; | |
say $x.^name; | |
} # OUTPUT: «Failure» | |
</pre> | |
<p>However, a <span class="code">try</span> block will contain the exception and put it into the <span class="code">$!</span> variable:</p> | |
<pre class="code">try { | |
my $x = +"a"; | |
say $x.^name; | |
} | |
if $! { say "Something failed!" } # OUTPUT: «Something failed!» | |
say $!.^name; # OUTPUT: «X::Str::Numeric» | |
</pre> | |
<p>Any exception that is thrown in such a block will be caught by a <span class="code">CATCH</span> 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.</p> | |
<pre class="code">try { | |
die "Tough luck"; | |
say "Not gonna happen"; | |
} | |
try { | |
fail "FUBAR"; | |
} | |
</pre> | |
<p><a id="i297" name="Tutorial resume (Exceptions)"></a><span class="indexed"></span> In both <span class="code">try</span> blocks above, exceptions will be contained within the block, but the <span class="code">say</span> statement will not be run. We can handle them, though:</p> | |
<pre class="code">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!"; | |
}</pre> | |
<p>Which would output:</p> | |
<pre class="code">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 | |
</pre> | |
<p>Since the <span class="code">CATCH</span> block is handling just the <span class="code">X::AdHoc</span> exception thrown by the <span class="code">die</span> statement, but not the <span class="code">E</span> exception. In the absence of a <span class="code">CATCH</span> block, all exceptions will be contained and dropped, as indicated above. <span class="code">resume</span> will resume execution right after the exception has been thrown; in this case, in the <span class="code">die</span> statement. Please consult the section on <a href="#_language_exceptions.pod6-Resuming_of_exceptions">resuming of exceptions</a> for more information on this.</p> | |
<p>A <span class="code">try</span>-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.</p> | |
<pre class="code">say try { +"99999" } // "oh no"; # OUTPUT: «99999» | |
say try { +"hello" } // "oh no"; # OUTPUT: «oh no» | |
</pre> | |
<p>Try blocks support <span class="code">else</span> blocks indirectly by returning the return value of the expression or <a href="#_type_Nil.pod6">Nil</a> if an exception was thrown.</p> | |
<pre class="code">with try +"♥" { | |
say "this is my number: $_" | |
} else { | |
say "not my number!" | |
} | |
# OUTPUT: «not my number!»</pre> | |
<p><span class="code">try</span> can also be used with a statement instead of a block, that is, as a <a href="#_language_statement-prefixes.pod6-try">statement prefix</a>:</p> | |
<pre class="code">say try "some-filename.txt".IO.slurp // "sane default"; | |
# OUTPUT: «sane default» | |
</pre> | |
<p>What <span class="code">try</span> actually causes is, via the <span class="code">use fatal</span> pragma, an immediate throw of the exceptions that happen within its scope, but by doing so the <span class="code">CATCH</span> block is invoked from the point where the exception is thrown, which defines its scope.</p> | |
<pre class="code">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» | |
</pre> | |
<a name="t18.5"></a> <h1 id="_language_exceptions.pod6-Throwing_exceptions">Throwing exceptions</h1> | |
<p>Exceptions can be thrown explicitly with the <span class="code">.throw</span> method of an <span class="code">Exception</span> object.</p> | |
<p>This example throws an <span class="code">AdHoc</span> exception, catches it and allows the code to continue from the point of the exception by calling the <span class="code">.resume</span> method.</p> | |
<pre class="code">{ | |
X::AdHoc.new(:payload<foo>).throw; | |
"OHAI".say; | |
CATCH { | |
when X::AdHoc { .resume } | |
} | |
} | |
"OBAI".say; | |
# OUTPUT: «OHAIOBAI»</pre> | |
<p>If the <span class="code">CATCH</span> block doesn't match the exception thrown, then the exception's payload is passed on to the backtrace printing mechanism.</p> | |
<pre class="code">{ | |
X::AdHoc.new(:payload<foo>).throw; | |
"OHAI".say; | |
CATCH { } | |
} | |
"OBAI".say; | |
# OUTPUT: «foo | |
# in block <unit> at my-script.p6:1»</pre> | |
<p>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 <span class="code">CATCH</span> block.</p> | |
<pre class="code">{ | |
X::AdHoc.new(:payload<foo>).throw; | |
"OHAI".say; | |
CATCH { | |
when X::AdHoc { } | |
} | |
} | |
"OBAI".say; | |
# OUTPUT: «OBAI»</pre> | |
<p><span class="code">throw</span> can be viewed as the method form of <span class="code">die</span>, just that in this particular case, the sub and method forms of the routine have different names.</p> | |
<a name="t18.6"></a> <h1 id="_language_exceptions.pod6-Resuming_of_exceptions">Resuming of exceptions</h1> | |
<p>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 <span class="code">.resume</span> on the exception object.</p> | |
<pre class="code">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</pre> | |
<p>Resuming will occur right after the statement that has caused the exception, and in the innermost call frame:</p> | |
<pre class="code">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 | |
</pre> | |
<p>In this case, <span class="code">.resume</span> is getting to the <span class="code">return</span> statement that happens right after the <span class="code">die</span> statement. Please note that the assignment to <span class="code">$return</span> is taking no effect, since the <span class="code">CATCH</span> statement is happening <i>inside</i> the call to <span class="code">bad-sub</span>, which, via the <span class="code">return</span> statement, assigns the <span class="code">not returning</span> value to it.</p> | |
<a name="t18.7"></a> <h1 id="_language_exceptions.pod6-Uncaught_exceptions">Uncaught exceptions</h1> | |
<p>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 <span class="code">gist</span> method on the exception object. You can use this to suppress the default behavior of printing a backtrace along with the message:</p> | |
<pre class="code">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</pre> | |
<a name="t18.8"></a> <h1 id="_language_exceptions.pod6-Control_exceptions">Control exceptions</h1> | |
<p>Control exceptions are raised when throwing an Exception which does the <a href="#_type_X::Control.pod6">X::Control</a> role (since Rakudo 2019.03). They are usually thrown by certain <a href="#_language_phasers.pod6-CONTROL">keywords</a> and are handled either automatically or by the appropriate <a href="#_language_phasers.pod6-Loop_phasers">phaser</a>. Any unhandled control exception is converted to a normal exception.</p> | |
<pre class="code">{ return; CATCH { default { $*ERR.say: .^name, ': ', .Str } } } | |
# OUTPUT: «X::ControlFlow::Return: Attempt to return outside of any Routine» | |
# was CX::Return | |
</pre> | |
</div> | |
<!-- /language/experimental.pod6 --><div class="pod-body"><a id="_language_experimental.pod6"></a><a name="t19"></a><h1 class="title">19 Experimental features</h1> <p class="subtitle">Preview of upcoming new language features available for user evaluation</p> <p>During Raku 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 Raku specification. To use these features, one uses the <span class="code">experimental</span> pragma in program source code, for example, like this:</p> | |
<pre class="code">use experimental :macros;</pre> | |
<p>These are the features that, for the time being, are experimental.</p> | |
<a name="t19.0.1"></a> <h2 id="_language_experimental.pod6-pack"><a name="298"></a><b>pack</b></h2> | |
<p>Pack is a feature that allows binary serialization of general data structures, and is inherited from <a href="#_routine_http:__perldoc.perl.org_functions_pack.html.pod6">Perl's pack</a>. The <span class="code">pack</span> order creates a <span class="code">Buf</span> by packing data structures in a certain way given by a <i>packing string</i> with the options shown <a href="#_type_Blob.pod6-method_unpack">in the description of <span class="code">unpack</span></a>. You turn it on by inserting this pragma at the beginning of your program:</p> | |
<pre class="code">use experimental :pack;</pre> | |
<p>For instance, we can pack numbers interpreting them as hexadecimal (<span class="code">H</span>) with the pattern repeating until there are no more elements (<span class="code">*</span>):</p> | |
<pre class="code">use experimental :pack; | |
say pack("H*", "414243").contents;# OUTPUT: «(65 66 67)» | |
</pre> | |
<p>There is a corresponding <span class="code">unpack</span> routine that does exactly the opposite.</p> | |
<pre class="code">use experimental :pack; | |
my $buf=Buf.new(65,66,67); | |
say $buf.unpack("H*"); # OUTPUT: «414243» | |
</pre> | |
<p>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.</p> | |
<p>Please see also documentation for <a href="#_type_Blob.pod6-sub_pack"><span class="code">pack</span></a> and <a href="#_type_Blob.pod6-method_unpack"><span class="code">unpack</span></a> in the <span class="code">Blob</span> page.</p> | |
<a name="t19.0.2"></a> <h2 id="_language_experimental.pod6-macros"><a name="299"></a><b>macros</b></h2> | |
<p><a href="#_routine_https:__en.wikipedia.org_wiki_Macro_(computer_science).pod6">Macros</a> are code-generating routines, that generate code in compile time, before the program is executed. In Raku its use is still experimental and it needs to be turned on via the pragma</p> | |
<pre class="code">use experimental :macros;</pre> | |
<p>Macro processing happens during parsing time. A macro generates an abstract syntax tree, which is grafted into the program syntax tree. <span class="code">quasi</span> is the routine that performs this task.</p> | |
<pre class="code">use experimental :macros; | |
macro does-nothing() { | |
quasi {} | |
}; | |
does-nothing; # OUTPUT: «» | |
</pre> | |
<p><a id="i300" name="Language quasi (macros)"></a><span class="indexed"></span> Macros are a kind of routine, so they can take arguments in exactly the same way, and act also in almost the same way.</p> | |
<pre class="code">use experimental :macros; | |
macro is-mighty( $who ) { | |
quasi { "$who is mighty!"} | |
}; | |
say is-mighty "Freija"; # OUTPUT: « "Freija" is mighty!» | |
</pre> | |
<p><a id="i301" name="Language unquoting (macros)"></a><span class="indexed"></span> <a id="i302" name="Language {{{}}} (macros)"></a><span class="indexed"></span> "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 <span class="code">{{{}}}</span> to get rid of this kind of thing:</p> | |
<pre class="code">use experimental :macros; | |
macro is-mighty( $who ) { | |
quasi { {{{$who}}} ~ " is mighty!"} | |
}; | |
say is-mighty "Freija"; # OUTPUT: «Freija is mighty!» | |
</pre> | |
<p>Since macro expansion happens at parse time, care must be taken when using external variables in them:</p> | |
<pre class="code">use experimental :macros; | |
my $called; | |
macro called() { | |
$called++; | |
quasi { "Called" } | |
}; | |
say called() ~ " $called times"; | |
say called() ~ " $called times"; # OUTPUT: «Called 2 timesCalled 2 times» | |
</pre> | |
<p>Since macros are expanded at parse time, <span class="code">$called</span> will be the result when runtime starts, which is already <span class="code">2</span>, as printed. Initializing <span class="code">$called</span> with 0, however, will make this print <span class="code">Called 0 times</span> since that initialization is run <i>after</i> the parse phase, when the macros are expanded.</p> | |
<p>Macros are terribly useful when complicated, computed initializations need to be done. However, they are still in the <i>experimental</i> 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 <a href="#_routine_https:__perl6advent.wordpress.com_2012_12_23_day-23-macros_.pod6">this article by Masak</a> as well as <a href="#_routine_https:__github.com_masak_007.pod6"><span class="code">007</span></a>, a new macro language, might provide a glimpse into the things to come.</p> | |
<a name="t19.0.3"></a> <h2 id="_language_experimental.pod6-cached"><a name="303"></a><b>cached</b></h2> | |
<p>The following pragma:</p> | |
<pre class="code">use experimental :cached;</pre> | |
<p>turns on the <span class="code">is cached</span> trait, which stores the result of a routine call, returning the same value if called with the same arguments.</p> | |
<p>It can be used when heavy calculations are involved, as in this sample that uses <a href="#_routine_https:__perl6advent.wordpress.com_2018_12_25_calling-numbers-names_.pod6-more-7528">amicable numbers</a>, taken from the 2018 Advent Calendar:</p> | |
<pre class="code">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"; | |
} | |
</pre> | |
<p>This code caches the computation of the <i>aliquot parts</i>, so that when the <span class="code">amic</span> 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.</p> | |
<p>See also <a href="#_routine_https:__docs.raku.org_routine_is%20cached.pod6">the description of the trait</a> for additional information and examples.</p> | |
</div> | |
<!-- /language/faq.pod6 --><div class="pod-body"><a id="_language_faq.pod6"></a><a name="t20"></a><h1 class="title">20 FAQ</h1> <p class="subtitle">Frequently asked questions about Raku™</p> <a name="t20.1"></a> <h1 id="_language_faq.pod6-General">General</h1> | |
<p><a id="i304" name="Reference Raku and Perl 6 (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.1.1"></a> <h2 id="_language_faq.pod6-What's_the_difference_between_Raku,_Rakudo_and_Perl 6?">What's the difference between Raku, Rakudo and Perl 6?</h2> | |
<p>Properly speaking, <a href="#_routine_https:__rakudo.org_.pod6">Rakudo</a> is an implementation of Raku. It's currently the one that's being developed, but there have been other implementations in the past and there will likely be others in the future. Raku is the definition of the language. When talking about the current interpreter, Rakudo and Raku can be used interchangeably. "Perl 6" is the name that was used for "Raku" before October 2019.</p> | |
<a name="t20.1.2"></a> <h2 id="_language_faq.pod6-When_was_Raku_released?">When was Raku released?</h2> | |
<p>The Rakudo 2015.12 implementation version was released on December 25th 2015, which implemented the v6.c Raku specification, released at the same time.</p> | |
<a name="t20.1.3"></a> <h2 id="_language_faq.pod6-Is_there_a_Raku_version_6.0.0?">Is there a Raku version 6.0.0?</h2> | |
<p>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).</p> | |
<p>Running <span class="code">raku -v</span> will display the language version your compiler implements, e.g.:</p> | |
<pre class="code">$ raku -v | |
Welcome to Rakudo™ v2022.04. | |
Implementing the Raku® Programming Language v6.d. | |
Built on MoarVM version 2022.04. | |
</pre> | |
<p><a id="i305" name="Reference v6.d (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.1.4"></a> <h2 id="_language_faq.pod6-When_was_v6.d_released?">When was v6.d released?</h2> | |
<p>The v6.d Specification was released on <a href="#_routine_https:__en.wikipedia.org_wiki_Diwali.pod6">Diwali 2018</a>, 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.</p> | |
<p>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 <span class="code">use v6.d</span> pragma at the top of the file. The rest of about 3100 new commits to the language specification simply clarify previously undefined behavior.</p> | |
<p><a id="i306" name="Reference Rakudo Star DMG binary installer (FAQ)"></a><span class="indexed"></span> <a id="i307" name="Reference Rakudo Star MSI binary installer (FAQ)"></a><span class="indexed"></span> <a id="i308" name="Reference Rakudo Star docker image (FAQ)"></a><span class="indexed"></span> <a id="i309" name="Reference Rakudo Star for Linux (FAQ)"></a><span class="indexed"></span> <a id="i310" name="Reference Rakudo Star for Windows (FAQ)"></a><span class="indexed"></span> <a id="i311" name="Reference Rakudo Star for Mac (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.1.5"></a> <h2 id="_language_faq.pod6-As_a_Raku_user,_what_should_I_install?">As a Raku user, what should I install?</h2> | |
<p>Mac users can use the latest Rakudo Star DMG binary installer at <a href="#_routine_https:__rakudo.org_downloads_star.pod6">https://rakudo.org/downloads/star</a></p> | |
<p>Windows users can use the Rakudo Star MSI binary installer. You will need Windows Git and Strawberry Perl to use zef to install library modules.</p> | |
<p>Linux users probably want to download Rakudo Star and follow the compilation instructions at <a href="#_routine_https:__www.raku.org_downloads_.pod6">https://www.raku.org/downloads/</a>.</p> | |
<p>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.</p> | |
<p>There's an official Rakudo Star docker image at <a href="#_routine_https:__hub.docker.com___rakudo-star_.pod6">https://hub.docker.com/_/rakudo-star/</a></p> | |
<p><a id="i312" name="Reference rakubrew (FAQ)"></a><span class="indexed"></span> <a id="i313" name="Reference rakudobrew (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.1.6"></a> <h2 id="_language_faq.pod6-As_an_advanced_user_I_want_to_track_Rakudo_development.">As an advanced user I want to track Rakudo development.</h2> | |
<p>An option is to clone <a href="#_routine_https:__github.com_rakudo_rakudo.pod6">the repository</a> 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 the Rakudo Raku compiler, you may find the <a href="#_routine_https:__github.com_zoffixznet_z.pod6">Z-Script helper tool</a> useful.</p> | |
<p>To install the last official monthly release, check out the tag visible at <a href="#_routine_https:__raw.githubusercontent.com_rakudo_rakudo_master_VERSION.pod6">https://raw.githubusercontent.com/rakudo/rakudo/master/VERSION</a> or set up <a href="#_routine_https:__github.com_zoffixznet_r.pod6-table-of-contents">a helper command</a>.</p> | |
<p>Some users choose to use <a href="#_routine_https:__rakubrew.org_.pod6">rakubrew</a>, which allows quick installation of multiple versions of Rakudo in parallel.</p> | |
<p>In either case you will probably need to also install <a href="#_routine_https:__modules.raku.org_dist_zef:github.pod6"><span class="code">zef</span></a> and <a href="#_routine_https:__modules.raku.org_dist_p6doc:github.pod6"><span class="code">p6doc</span></a> from the <a href="#_routine_https:__modules.raku.org_.pod6">ecosystem</a>.</p> | |
<a name="t20.1.7"></a> <h2 id="_language_faq.pod6-Where_can_I_find_good_documentation_on_Raku?">Where can I find good documentation on Raku?</h2> | |
<p>See <a href="#_.pod6">the official documentation website</a> (especially its <a href="#_language.html.pod6">"Language" section</a>) as well as the <a href="#_routine_https:__raku.org_resources_.pod6">Resources page</a>. You can also consult this <a href="#_routine_https:__htmlpreview.github.io_?https:__github.com_perl6_mu_blob_master_docs_Perl6_Cheatsheet_cheatsheet.html.pod6">great cheatsheet</a>.</p> | |
<p><a href="#_routine_https:__perl6book.com_.pod6">perl6book.com</a> contains a list of dead tree and electronic books.</p> | |
<p>Be mindful of publication dates when reading third-party articles. Anything published before December, 2015 likely describes a pre-release version of Raku.</p> | |
<p>You can always <a href="#_routine_https:__web.libera.chat_?channel=.pod6-raku">get help from a live human in our help chat</a> or <a href="#_routine_https:__colabti.org_irclogger_irclogger_log_search_raku.pod6">search the chat logs</a> to find previous conversations and discussions.</p> | |
<p><a id="i314" name="Reference Books"></a><span class="indexed"></span></p> | |
<a name="t20.1.8"></a> <h2 id="_language_faq.pod6-Can_I_get_some_books_about_Raku?">Can I get some books about Raku?</h2> | |
<p>Here are some available books, in alphabetical order:</p> | |
<ul><li><p><a href="#_routine_https:__www.learningraku.com_.pod6">Learning Raku</a>, by brian d foy</p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__www.amazon.com_gp_product_B07221XCVL.pod6">Learning to program with Raku: First Steps</a>, by JJ Merelo</p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__www.gitbook.com_book_kyclark_metagenomics_details.pod6">Metagenomics</a>, by Ken Youens-Clark</p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__smile.amazon.com_dp_1484232275_.pod6">Parsing with Perl 6 Regexes and Grammars</a>, by Moritz Lenz</p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__deeptext.media_perl6-at-a-glance_.pod6">Perl 6 at a Glance</a>, by Andrew Shitov</p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__www.apress.com_gp_book_9781484261088.pod6">Raku Fundamentals</a>, by Moritz Lenz</p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__www.packtpub.com_application-development_perl-6-deep-dive.pod6">Perl 6 Deep Dive</a>, by Andrew Shitov</p> | |
</li></ul> <ul><li><p><a href="#_routine_https:__greenteapress.com_wp_think-perl-6_.pod6">Think Perl 6: How to Think Like a Computer Scientist</a>, by Laurent Rosenfeld.</p> | |
</li></ul> <p>A list of books published or in progress is maintained in <a href="#_routine_https:__raku.org_resources_.pod6"><span class="code">raku.org</span></a>.</p> | |
<p><a id="i315" name="Reference Specification (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.1.9"></a> <h2 id="_language_faq.pod6-What_is_the_Raku_specification?">What is the Raku specification?</h2> | |
<p>The specification refers to the official test suite for Raku. It's called <a href="#_routine_https:__github.com_Raku_roast.pod6"><span class="code">roast</span></a> and is hosted on github. Any compiler that passes the tests is deemed to implement that version of the Raku specification.</p> | |
<p>Roast's <span class="code">master</span> 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".</p> | |
<p>So <span class="code">6.c-errata</span> 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.</p> | |
<a name="t20.1.10"></a> <h2 id="_language_faq.pod6-Is_there_a_glossary_of_Raku_related_terms?">Is there a glossary of Raku related terms?</h2> | |
<p>Yes, see <a href="#_language_glossary.pod6">glossary</a>.</p> | |
<a name="t20.1.11"></a> <h2 id="_language_faq.pod6-I'm_a_Perl_programmer._Where_is_a_list_of_differences_between_Perl_and_Raku?">I'm a Perl programmer. Where is a list of differences between Perl and Raku?</h2> | |
<p>There are several <i>Perl to Raku</i> guides in the <a href="#_language.html.pod6">Language section of the documentation</a>, most notable of which is the <a href="#_language_5to6-nutshell.pod6">Overview</a>.</p> | |
<p><a id="i316" name="Reference Ruby Quickstart (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.1.12"></a> <h2 id="_language_faq.pod6-I'm_a_Ruby_programmer_looking_for_quickstart_type_docs?">I'm a Ruby programmer looking for quickstart type docs?</h2> | |
<p>See the <a href="#_language_rb-nutshell.pod6">rb-nutshell</a> guide.</p> | |
<a name="t20.2"></a> <h1 id="_language_faq.pod6-Modules">Modules</h1> | |
<p><a id="i317" name="Reference CPAN (FAQ)"></a><span class="indexed"></span><a id="i318" name="Reference ecosystem"></a><span class="indexed"></span></p> | |
<a name="t20.2.1"></a> <h2 id="_language_faq.pod6-Is_there_a_repository_of_third_party_library_modules_for_Raku?">Is there a repository of third party library modules for Raku?</h2> | |
<p>Yes. As a user, the <a href="#_routine_https:__github.com_ugexe_zef.pod6"><span class="code">zef</span> module installer</a> will automatically install the version of a module with the highest version number. If you want a specific version and/or a version from a specific author, you can also specify that with <span class="code">zef</span>.</p> | |
<p>As a new module author, you can use the <a href="#_routine_https:__raku.land_zef:tony-o_fez.pod6"><span class="code">fez</span> module uploader</a> to upload your module to the Raku ecosystem. There are also a number of helper modules that help you set up a skeleton of a distribution, such as <a href="#_routine_https:__raku.land_cpan:SKAJI_App::Mi6.pod6"><span class="code">App::Mi6</span></a>, which will also help you with uploading once your module is ready for distribution.</p> | |
<p>Historically, you could also upload a Raku module to CPAN by using <a href="#_routine_https:__pause.perl.org_.pod6">PAUSE</a> to upload a module. And before that, there was a way of using Github/Gitlab to make your module available for download. These are now considered to not be the best way for new module authors to start with.</p> | |
<p><a id="i319" name="Reference p6doc (FAQ)"></a><span class="indexed"></span> <a id="i320" name="Other languages perldoc (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.2.2"></a> <h2 id="_language_faq.pod6-Is_there_a_perldoc_(command_line_documentation_viewer)_for_Raku?">Is there a perldoc (command line documentation viewer) for Raku?</h2> | |
<p>Yes, it's called <span class="code">p6doc</span> and is present in the ecosystem under that name. It comes bundled in with Rakudo Star but needs to be manually installed with <span class="code">zef</span> if you are using a Rakudo monthly release.</p> | |
<p><a id="i321" name="Reference Perl modules (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.2.3"></a> <h2 id="_language_faq.pod6-Can_I_use_Perl_modules_from_Raku?">Can I use Perl modules from Raku?</h2> | |
<p>Yes, with <a href="#_routine_https:__github.com_niner_Inline-Perl5_.pod6">Inline::Perl5</a>, which works well with most Perl modules. It can even run Perl Catalyst and DBI.</p> | |
<p><a id="i322" name="Reference C and C++ (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.2.4"></a> <h2 id="_language_faq.pod6-Can_I_use_C_and_C++_from_Raku?">Can I use C and C++ from Raku?</h2> | |
<p><a href="#_language_nativecall.pod6">Nativecall</a> makes this particularly easy.</p> | |
<a name="t20.2.5"></a> <h2 id="_language_faq.pod6-Nativecall_can't_find_libfoo.so_and_I_only_have_libfoo.so.1.2!">Nativecall can't find <span class="code">libfoo.so</span> and I only have <span class="code">libfoo.so.1.2</span>!</h2> | |
<p>In most Linux systems, shared libraries will be installed in such a way that, for a specific <span class="code">libfoo</span>, there will be a <span class="code">libfoo.so.x.y.z</span> real file, and then a set of symlinks <span class="code">libfoo.so</span> and <span class="code">libfoo.so.x</span>. for instance, <span class="code">ls /usr/local/lib/libxxhash.so*</span> returns:</p> | |
<pre class="code">/usr/local/lib/libxxhash.so -> libxxhash.so.0.6.5 | |
/usr/local/lib/libxxhash.so.0 -> libxxhash.so.0.6.5 | |
/usr/local/lib/libxxhash.so.0.6.5 | |
</pre> | |
<p>In general, installing a <span class="code">libfoo-dev</span> or <span class="code">libfoo-devel</span> (depending on the distro) in Linux will install the shared library <i>and</i> set up those symlinks for you. But in some cases, you will only have, as in the question, <span class="code">libfoo.so.1.2</span>.</p> | |
<p>In that case, just use the version of <span class="code">is native</span> that explicitly sets the ABI/API version, as indicated in <a href="#_language_nativecall.pod6-ABI/API_version">the manual</a>:</p> | |
<pre class="code">sub call-foo() is native('foo',v1.2); | |
</pre> | |
<a name="t20.2.6"></a> <h2 id="_language_faq.pod6-Where_have_all_the_traditional_UNIX_library_functions_gone?">Where have all the traditional UNIX library functions gone?</h2> | |
<p>It's fairly easy to use <a href="#_language_nativecall.pod6">NativeCall</a> to access them.</p> | |
<p>An ecosystem module <a href="#_routine_https:__github.com_cspencer_perl6-posix.pod6">POSIX</a> is also available.</p> | |
<p><a id="i323" name="Reference Core standard library (FAQ)"></a><span class="indexed"></span> <a id="i324" name="Reference Rakudo Star distribution and compiler-only release (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.2.7"></a> <h2 id="_language_faq.pod6-Does_Rakudo_have_a_core_standard_library?">Does Rakudo have a core standard library?</h2> | |
<p><a href="#_routine_https:__rakudo.org_downloads_.pod6">Rakudo Star distribution</a> does come with <a href="#_routine_https:__github.com_rakudo_star_blob_master_etc_modules.txt.pod6">many useful modules</a>.</p> | |
<p>Rakudo compiler-only release includes <a href="#_language_modules-core.pod6">only a couple of the most basic modules</a>.</p> | |
<p>Many more modules can be found in the <a href="#_routine_https:__modules.raku.org_.pod6">ecosystem</a>.</p> | |
<a name="t20.2.8"></a> <h2 id="_language_faq.pod6-Is_there_something_like_B::Deparse/How_can_I_get_hold_of_the_AST?">Is there something like <span class="code">B::Deparse</span>/How can I get hold of the AST?</h2> | |
<p>Use <span class="code">--target=optimize</span> command line option to view the AST of your program, e.g., <span class="code">raku --target=optimize -e 'say "hi"'</span></p> | |
<p>The target <span class="code">optimize</span> gives the AST after the static optimizer does its job, while target <span class="code">ast</span> gives the AST before that step. To get the full list of available targets, run <span class="code">raku --stagestats -e ""</span></p> | |
<p><a id="i325" name="Reference Precompile (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.2.9"></a> <h2 id="_language_faq.pod6-What_is_precompilation?">What is precompilation?</h2> | |
<p>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.</p> | |
<p><a id="i326" name="Reference Circular dependencies (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.2.10"></a> <h2 id="_language_faq.pod6-Can_I_have_circular_dependencies_between_modules?">Can I have circular dependencies between modules?</h2> | |
<p>No, you can't have circular dependencies, and you should get a <span class="code">Circular module loading detected</span> error if you have them between your modules.</p> | |
<p>Very likely you can accomplish what you are trying to do using <a href="#_language_objects.pod6-Roles">roles</a>. Instead of <span class="code">A.rakumod</span> depending on <span class="code">B.rakumod</span> and <span class="code">B.rakumod</span> depending on <span class="code">A.rakumod</span>, you can have <span class="code">A-Role.rakumod</span> and <span class="code">B-Role.rakumod</span> and classes in <span class="code">A.rakumod</span> and <span class="code">B.rakumod</span> implementing these roles respectively. Then you can depend on <span class="code">A-Role.rakumod</span> and <span class="code">B-Role.rakumod</span> without the need for the circular dependency.</p> | |
<p>One of the reasons why circular dependencies do not work in Raku 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.</p> | |
<p>Note that Raku 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.</p> | |
<a name="t20.3"></a> <h1 id="_language_faq.pod6-Common_operations">Common operations</h1> | |
<a name="t20.3.1"></a> <h2 id="_language_faq.pod6-String:_How_can_I_parse_and_get_a_number_from_a_string?">String: How can I parse and get a <a href="#_language_numerics.pod6">number</a> from a <a href="#_language_type_Str.pod6">string</a>?</h2> | |
<p>Use the <a href="#_language_operators.pod6-prefix_+">+ prefix</a>:</p> | |
<pre class="code">say "42.123456789123456789"; # OUTPUT: «42.123456789123456789» | |
say +"42.4e-2"; # OUTPUT: «0.424» | |
</pre> | |
<p>This example of <a href="#_language_contexts.pod6">contextualization</a> can numify any string you could enter as a <a href="#_language_syntax.pod6-Number_literals">literal number</a>. <a href="#_routine_val.pod6">val</a> routine converts it to <a href="#_language_glossary.pod6-Allomorph">allomorph</a>. <a href="#_routine_unival.pod6">unival</a> routine converts one unicode codepoint.</p> | |
<a name="t20.3.2"></a> <h2 id="_language_faq.pod6-String:_How_can_I_check_if_a_string_contains_a_substring_and_if_so,_how_can_I_get_indices_of_matches?">String: How can I check if a string contains a substring and if so, how can I get indices of matches?</h2> | |
<p>Use <a href="#_type_Str.pod6-method_contains">.contains</a> or <a href="#_type_Str.pod6-method_indices">.indices</a>:</p> | |
<pre class="code">"az and az and az again".contains("az"); # OUTPUT: «True» | |
"az and az and az again".indices("az"); # OUTPUT: «(0 7 14)» | |
</pre> | |
<a name="t20.3.3"></a> <h2 id="_language_faq.pod6-String:_How_can_I_get_the_hexadecimal_representation_of_a_string?">String: How can I get the hexadecimal representation of a string?</h2> | |
<p>To get a hexadecimal list of each byte of a string (i.e. hex encoder), first convert the string to a <a href="#_type_Blob.pod6">Blob</a> with <a href="#_routine_encode.pod6">.encode</a>.</p> | |
<pre class="code">say "I ❤ 🦋".encode>>.base(16); # OUTPUT: «(49 20 E2 9D A4 20 F0 9F A6 8B)» | |
</pre> | |
<p>Note that <a href="#_routine_gist.pod6">.gist</a> or <a href="#_routine_raku.pod6">.raku</a> methods can be useful for variable introspection:</p> | |
<pre class="code">say "I ❤ 🦋".encode.raku; # OUTPUT: «utf8.new(73,32,226,157,164,32,240,159,166,139)» | |
say "I ❤ 🦋".encode.gist; # OUTPUT: «utf8:0x<49 20 E2 9D A4 20 F0 9F A6 8B>» | |
</pre> | |
<a name="t20.3.4"></a> <h2 id="_language_faq.pod6-String:_How_can_I_remove_from_a_string_some_characters_by_index?">String: How can I remove from a string some characters by index?</h2> | |
<p>Use <a href="#_routine_comb.pod6">.comb</a> to transform it to a <a href="#_type_Seq.pod6">Seq</a>, then the <a href="#_language_operators.pod6-infix_-">(-) infix</a> to remove the unwanted indices:</p> | |
<pre class="code">say '0123456789'.comb[(^* (-) (1..3, 8).flat).keys.sort].join; # OUTPUT: «045679» | |
</pre> | |
<p>If the string is large, <a href="#_routine_comb.pod6">.comb</a> can take time. In which case, <a href="#_routine_substr-rw.pod6">.substr-rw</a> is faster:</p> | |
<pre class="code">multi postcircumfix:<[- ]> (Str:D $str is copy, +@indices) { | |
for @indices.reverse { | |
when Int { $str.substr-rw($_,1) = '' } | |
when Range { $str.substr-rw($_ ) = '' } | |
} | |
return $str; | |
} | |
say '0123456789'[- 1..3, 8 ]; # OUTPUT: «045679» | |
</pre> | |
<a name="t20.3.5"></a> <h2 id="_language_faq.pod6-String:_How_can_I_split_a_string_in_equal_parts?">String: How can I split a string in equal parts?</h2> | |
<p><a href="#_routine_comb.pod6">.comb</a> is accepting an optional <a href="#_type_Int.pod6">Int</a>:</p> | |
<pre class="code">.say for 'abcdefghijklmnopqrstuvwxyz'.comb: 8; # OUTPUT: «abcdefghijklmnopqrstuvwxyz» | |
</pre> | |
<a name="t20.4"></a> <h1 id="_language_faq.pod6-Language_features">Language features</h1> | |
<p><a id="i327" name="Reference Data::Dumper (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.4.1"></a> <h2 id="_language_faq.pod6-How_can_I_dump_Raku_data_structures_(like_Perl_Data::Dumper_and_similar)?">How can I dump Raku data structures (like Perl Data::Dumper and similar)?</h2> | |
<p>Typical options are to use the <a href="#_routine_say.pod6">say</a> routine that uses the <a href="#_routine_gist.pod6">gist</a> method which gives the "gist" of the object being dumped. More detailed output can be obtained by calling the <a href="#_routine_perl.pod6">perl</a> method (soon to be deprecated in favor of <span class="code">$obj.raku</span>, available since the Rakudo 2019.11 release) that typically returns an object's representation in <a href="#_routine_EVAL.pod6">EVAL</a>-able code.</p> | |
<p>If you're using the <a href="#_routine_https:__rakudo.org.pod6">rakudo</a> implementation, you can use the <a href="#_programs_01-debugging.pod6-Dumper_function_(dd)">rakudo-specific <span class="code">dd</span> routine</a> for dumping, whose output is similar to <a href="#_routine_raku.pod6">raku</a>, but with more information.</p> | |
<p>Examples:</p> | |
<pre class="code">my $foo = %( foo => 'bar' ); | |
say $foo.raku; # OUTPUT: «${:foo("bar")}» | |
say $foo; # OUTPUT: «{foo => bar}» | |
# non-standard routine available in rakudo implementation: | |
dd $foo; # OUTPUT: «Hash $foo = ${:foo("bar")}» | |
</pre> | |
<p>There are also <a href="#_routine_https:__modules.raku.org_s_dump.pod6">several ecosystem modules</a> that provide more control over how data structures are dumped, including support for colored output.</p> | |
<a name="t20.4.2"></a> <h2 id="_language_faq.pod6-How_can_I_get_command_line_history_in_the_Raku_prompt_(REPL)?">How can I get command line history in the Raku prompt (REPL)?</h2> | |
<p>Install <a href="#_routine_https:__github.com_hoelzro_p6-linenoise_.pod6">Linenoise</a> from the ecosystem.</p> | |
<p>An alternative for UNIX-like systems is to install <span class="code">rlwrap</span>. This can be done on Debian-ish systems by running:</p> | |
<pre class="code">sudo apt-get install rlwrap | |
</pre> | |
<a name="t20.4.3"></a> <h2 id="_language_faq.pod6-Why_is_the_Rakudo_compiler_so_apologetic?">Why is the Rakudo compiler so apologetic?</h2> | |
<p>If SORRY! is present in the output, the error is a compile time error. Otherwise, it's a runtime error.</p> | |
<p>Example:</p> | |
<pre class="code">sub foo( Int $a, Int $b ) {...} | |
foo(1) # ===SORRY!=== Error while compiling ... | |
</pre> | |
<pre class="code">say 1/0; # Attempt to divide 1 by zero using div | |
</pre> | |
<a name="t20.4.4"></a> <h2 id="_language_faq.pod6-What_is_(Any)?">What is <span class="code">(Any)</span>?</h2> | |
<p><a href="#_type_Any.pod6"><span class="code">Any</span></a> is a top level class most objects inherit from. The <span class="code">Any</span> type object is <a href="#_type_Attribute.pod6-Trait_is_default">the default value</a> on variables and parameters without an explicit type constraint, which means you'll likely see <span class="code">(Any)</span> printed when you output a <a href="#_routine_gist.pod6">gist</a> of a variable without any value by using, for instance, the <a href="#_routine_say.pod6"><span class="code">say</span> routine</a>:</p> | |
<pre class="code">my $foo; | |
say $foo; # OUTPUT: «(Any)» | |
my Int $baz; | |
say $baz; # OUTPUT: «(Int)» | |
my $bar = 70; | |
say $bar; # OUTPUT: «70» | |
</pre> | |
<p>To test whether a variable has any defined values, see <a href="#_language_classtut.pod6-index-entry-.DEFINITE">DEFINITE</a> and <a href="#_routine_defined.pod6">defined</a> routines. Several other constructs exist that test for definiteness, such as <a href="#_syntax_with orwith without.pod6"><span class="code">with</span> , <span class="code">orwith</span> , and <span class="code">without</span></a> statements, <a href="#_routine_$SOLIDUS$SOLIDUS.pod6"><span class="code">//</span></a>, <a href="#_routine_andthen.pod6">andthen</a>, <a href="#_routine_notandthen.pod6">notandthen</a>, and <a href="#_routine_orelse.pod6">orelse</a> operators, as well as <a href="#_type_Signature.pod6-Constraining_argument_definiteness">type constraint smileys</a>.</p> | |
<a name="t20.4.5"></a> <h2 id="_language_faq.pod6-What_is_so?">What is <span class="code">so</span>?</h2> | |
<p><span class="code">so</span> is a loose precedence operator that coerces to <a href="#_type_Bool.pod6">Bool</a>.</p> | |
<p>It has the same semantics as the <span class="code">?</span> prefix operator, just like <span class="code">and</span> is the low-precedence version of <span class="code">&&</span>.</p> | |
<p>Example:</p> | |
<pre class="code">say so 1|2 == 2; # OUTPUT: «True» | |
</pre> | |
<p>In this example, the result of the comparison (which is a <a href="#_type_Junction.pod6">Junction</a>), is converted to Bool before being printed.</p> | |
<a name="t20.4.6"></a> <h2 id="_language_faq.pod6-What_are_those_:D_and_:U_things_in_signatures?">What are those <span class="code">:D</span> and <span class="code">:U</span> things in signatures?</h2> | |
<p>In Raku, classes and other types are objects and pass type checks of their own type.</p> | |
<p>For example, if you declare a variable</p> | |
<pre class="code">my Int $x = 42; | |
</pre> | |
<p>then not only can you assign integers (that is, instances of class Int) to it, but the <span class="code">Int</span> type object itself:</p> | |
<pre class="code">$x = Int | |
</pre> | |
<p>If you want to exclude type objects, you can append the <span class="code">:D</span> type smiley, which stands for "definite":</p> | |
<pre class="code">my Int:D $x = 42; | |
$x = Int; | |
# dies with: | |
# Type check failed in assignment to $x; | |
# expected Int:D but got Int | |
</pre> | |
<p>Likewise, <span class="code">:U</span> constrains to undefined values, that is, type objects.</p> | |
<p>To explicitly allow either type objects or instances, you can use <span class="code">:_</span>.</p> | |
<a name="t20.4.7"></a> <h2 id="_language_faq.pod6-What_is_the_-->_thing_in_the_signature?">What is the <span class="code">--></span> thing in the signature?</h2> | |
<p><a href="#_type_Signature.pod6-Constraining_return_types">--></a> is a return constraint, either a type or a definite value.</p> | |
<p>Example of a type constraint:</p> | |
<pre class="code">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 | |
</pre> | |
<p>Example of a definite return value:</p> | |
<pre class="code">sub discard-random-number( --> 42 ) { rand } | |
say discard-random-number; | |
# OUTPUT: «42» | |
</pre> | |
<p>In this case, the final value is thrown away because the return value is already specified in the signature.</p> | |
<p><a id="i328" name="Reference Junction (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.4.8"></a> <h2 id="_language_faq.pod6-How_can_I_extract_the_values_from_a_Junction?">How can I extract the values from a Junction?</h2> | |
<p>If you want to extract the values (eigenstates) from a <a href="#_type_Junction.pod6">Junction</a>, you are probably doing something wrong and should be using a <a href="#_type_Set.pod6">Set</a> instead.</p> | |
<p>Junctions are meant as matchers, not for doing algebra with them.</p> | |
<p>If you want to do it anyway, you can abuse autothreading for that:</p> | |
<pre class="code">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 | |
</pre> | |
<a name="t20.4.9"></a> <h2 id="_language_faq.pod6-If_Str_is_immutable,_how_does_s///_work?_If_Int_is_immutable,_how_does_$i++_work?">If Str is immutable, how does <span class="code">s///</span> work? If Int is immutable, how does <span class="code">$i++</span> work?</h2> | |
<p>In Raku, values of many basic types are immutable, but the variables holding them are not. The <span class="code">s///</span> operator works on a variable, into which it puts a newly created string object. Likewise, <span class="code">$i++</span> works on the <span class="code">$i</span> variable, not just on the value in it.</p> | |
<p>Knowing this, you would not try to change a literal string (e.g. like <span class="code">'hello' ~~ s/h/H/;</span>), but you might accidentally do something equivalent using <span class="code">map</span> as follows.</p> | |
<pre class="code">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: ... | |
</pre> | |
<p>Instead of modifying the original value in place, use a routine or operator that returns a new value:</p> | |
<pre class="code">my @foo = <hello world>.map: { S/h/H/ }; # ['Hello','world'] | |
my @bar = <hello world>».subst: 'h', 'H'; # ['Hello','world'] | |
</pre> | |
<p>See the documentation on <a href="#_language_containers.pod6">containers</a> for more information.</p> | |
<a name="t20.4.10"></a> <h2 id="_language_faq.pod6-What's_up_with_array_references_and_automatic_dereferencing?_Do_I_need_the_@_sigil?">What's up with array references and automatic dereferencing? Do I need the <span class="code">@</span> sigil?</h2> | |
<p>In Raku, nearly everything is a reference, so talking about taking references doesn't make much sense. Scalar variables can also contain arrays directly:</p> | |
<pre class="code">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» | |
</pre> | |
<p>The big difference is that arrays inside a scalar act as one value in list context, whereas arrays will be happily iterated over.</p> | |
<pre class="code">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» | |
</pre> | |
<p>You can force list context with <span class="code">@( ... )</span> or by calling the <span class="code">.list</span> method on an expression, and item context with <span class="code">$( ... )</span> or by calling the <span class="code">.item</span> method on an expression.</p> | |
<p>See the <a href="#_routine_https:__perl6advent.wordpress.com_2017_12_02_.pod6"><i>Perl 6: Sigils, Variables, and Containers</i></a> article to learn more.</p> | |
<p><a id="i329" name="Reference Sigils (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.4.11"></a> <h2 id="_language_faq.pod6-Why_sigils?_Couldn't_you_do_without_them?">Why sigils? Couldn't you do without them?</h2> | |
<p>There are several reasons:</p> | |
<ul><li><p>they make it easy to interpolate variables into strings</p> | |
</li></ul> <ul><li><p>they form micro-namespaces for different variables and twigils, thus avoiding name clashes</p> | |
</li></ul> <ul><li><p>they allow easy single/plural distinction</p> | |
</li></ul> <ul><li><p>they work like natural languages that use mandatory noun markers, so our brains are built to handle it</p> | |
</li></ul> <ul><li><p>they aren't mandatory, since you can declare sigilless names (if you don't mind the ambiguity)</p> | |
</li></ul> <a name="t20.4.12"></a> <h2 id="_language_faq.pod6-"Type_Str_does_not_support_associative_indexing."">"Type Str does not support associative indexing."</h2> | |
<p>You likely tried to mix string interpolation and key characters, like HTML tags:</p> | |
<pre class="code">my $foo = "abc"; | |
say "$foo<html-tag>"; | |
</pre> | |
<p>Raku thinks <span class="code">$foo</span> is a Hash and <span class="code"><html-tag></span> is a string literal hash key. Use a closure to help it to understand you.</p> | |
<pre class="code">my $foo = "abc"; | |
say "{$foo}<html-tag>"; | |
</pre> | |
<p><a id="i330" name="Reference Coroutine (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.4.13"></a> <h2 id="_language_faq.pod6-Does_Raku_have_coroutines?_What_about_yield?">Does Raku have coroutines? What about <span class="code">yield</span>?</h2> | |
<p>Raku has no <span class="code">yield</span> 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:</p> | |
<pre class="code"># 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² }); | |
</pre> | |
<a name="t20.4.14"></a> <h2 id="_language_faq.pod6-Why_can't_I_initialize_private_attributes_from_the_new_method,_and_how_can_I_fix_this?">Why can't I initialize private attributes from the new method, and how can I fix this?</h2> | |
<p>The <span class="code">say</span> statement in the following code sample</p> | |
<pre class="code">class A { | |
has $!x; | |
method show-x { | |
return $!x; | |
} | |
} | |
say A.new(x => 5).show-x; | |
</pre> | |
<p>does not print 5. Private attributes are <i>private</i>, 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 <span class="code">$!x</span> isn't initialized during object construction by the default constructor.</p> | |
<p>If you still want to initialize private attributes with the default constructor, you can add a <span class="code">submethod BUILD</span> to achieve such task:</p> | |
<pre class="code">class B { | |
has $!x; | |
submethod BUILD(:$!x) { } | |
method show-x { | |
return $!x; | |
} | |
} | |
say B.new(x => 5).show-x; | |
</pre> | |
<p><span class="code">BUILD</span> is called by the default constructor (indirectly, see <a href="#_language_objects.pod6-Object_construction">Object Construction</a> for more details) with all the named arguments that the user passes to the constructor. <span class="code">:$!x</span> is a named parameter with name <span class="code">x</span>, and when called with a named argument of name <span class="code">x</span>, its value is bound to the attribute <span class="code">$!x</span>.</p> | |
<p>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 <span class="code">$.x</span> since the external view is read-only by default, and you can still access it internally with <span class="code">$!x</span>.</p> | |
<a name="t20.4.15"></a> <h2 id="_language_faq.pod6-How_and_why_do_say,_put_and_print_differ?">How and why do <span class="code">say</span>, <span class="code">put</span> and <span class="code">print</span> differ?</h2> | |
<p>The most obvious difference is that <span class="code">say</span> and <span class="code">put</span> append a newline at the end of the output, and <span class="code">print</span> does not.</p> | |
<p>But there's another difference: <span class="code">print</span> and <span class="code">put</span> convert their arguments to a string by calling the <span class="code">Str</span> method on each item passed to them while <span class="code">say</span> uses the <span class="code">gist</span> method. The <span class="code">gist</span> method, which you can also create for your own classes, is intended to create a <span class="code">Str</span> for human interpretation. So it is free to leave out information about the object deemed unimportant to understanding the essence of the object.</p> | |
<p>Or phrased differently, <span class="code">$obj.Str</span> gives a string representation, <span class="code">$obj.gist</span> provides a short summary of that object suitable for fast recognition by a human, and <span class="code">$obj.raku</span> gives a Raku-ish representation from which the object could be re-created.</p> | |
<p>For example, when the <span class="code">Str</span> method is invoked on a type object, also known as an "undefined value", the type is stringified to an empty string and a <span class="code">warn</span>ing is thrown. On the other hand, the <span class="code">gist</span> method returns the name of the type between parentheses (to indicate there's nothing in that value except the type).</p> | |
<pre class="code">my Date $x; # $x now contains the Date type object | |
print $x; # empty string plus warning | |
say $x; # OUTPUT: «(Date)» | |
</pre> | |
<p>If you'd like to show a debugging version of an object, it is probably better to use the <a href="#_programs_01-debugging.pod6-Dumper_function_(dd)">rakudo-specific <span class="code">dd</span> routine</a>. It essentially does a <span class="code">$obj.raku</span> and shows that on STDERR rather than STDOUT, so it won't interfere with any "normal" output of your program.</p> | |
<p>In short, <span class="code">say</span> is optimized for casual human interpretation, <span class="code">dd</span> is optimized for casual debugging output and <span class="code">print</span> and <span class="code">put</span> are more generally suitable for producing output.</p> | |
<p><span class="code">put</span> is thus a hybrid of <span class="code">print</span> and <span class="code">say</span>; like <span class="code">print</span>, it calls the <span class="code">Str</span> method on the object. And like <span class="code">say</span>, it adds a newline at the end of the output.</p> | |
<a name="t20.4.16"></a> <h2 id="_language_faq.pod6-What's_the_difference_between_token_and_rule_?">What's the difference between <span class="code">token</span> and <span class="code">rule</span> ?</h2> | |
<p><span class="code">regex</span>, <span class="code">token</span> and <span class="code">rule</span> introduce regexes, but with slightly different semantics.</p> | |
<p><span class="code">token</span> implies the <span class="code">:ratchet</span> or <span class="code">:r</span> modifier, which prevents the rule from backtracking.</p> | |
<p><span class="code">rule</span> implies both the <span class="code">:ratchet</span> and <span class="code">:sigspace</span> (short <span class="code">:s</span>) modifier, which means a rule doesn't backtrace, and it treats whitespace in the text of the regex as <span class="code"><.ws></span> 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.</p> | |
<p><span class="code">regex</span> declares a plain regex without any implied modifiers.</p> | |
<a name="t20.4.17"></a> <h2 id="_language_faq.pod6-What's_the_difference_between_die_and_fail?">What's the difference between <span class="code">die</span> and <span class="code">fail</span>?</h2> | |
<p><span class="code">die</span> throws an exception.</p> | |
<p><span class="code">fail</span> returns a <span class="code">Failure</span> object. (If the caller has declared <span class="code">use fatal;</span> in the calling lexical scope, <span class="code">fail</span> throws an exception instead of returning it.)</p> | |
<p>A <span class="code">Failure</span> is an "unthrown" or "lazy" exception. It's an object that contains the exception, and throws the exception if you try to use the <span class="code">Failure</span> as an ordinary object or ignore it in sink context.</p> | |
<p>A <span class="code">Failure</span> returns <span class="code">False</span> from a <span class="code">defined</span> check, and you can extract the exception with the <span class="code">exception</span> method.</p> | |
<a name="t20.4.18"></a> <h2 id="_language_faq.pod6-What's_the_difference_between_Pointer_and_OpaquePointer?">What's the difference between <span class="code">Pointer</span> and <span class="code">OpaquePointer</span>?</h2> | |
<p><span class="code">OpaquePointer</span> is deprecated and has been replaced with <span class="code">Pointer</span>.</p> | |
<a name="t20.4.19"></a> <h2 id="_language_faq.pod6-You_can_have_colonpairs_in_identifiers._What's_the_justification?">You can have colonpairs in identifiers. What's the justification?</h2> | |
<p><a href="#_language_syntax.pod6-Identifiers">Identifiers can include colon pairs, which become part of their name</a>. According to <a href="#_routine_https:__github.com_Raku_doc_issues_1753.pod6-issuecomment-362875676">Larry Wall's answer to the issue</a>, <i>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)</i>.</p> | |
<a name="t20.4.20"></a> <h2 id="_language_faq.pod6-How_do_most_people_enter_unicode_characters?">How do most people enter unicode characters?</h2> | |
<p>It depends on the operating system, windowing environment and/or editors. <a href="#_language_unicode_entry.pod6">This page on entering Unicode characters</a> specifies how it is done in the most popular operating systems and editors.</p> | |
<p><a id="i331" name="Reference Raku Implementation (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.5"></a> <h1 id="_language_faq.pod6-Raku_implementation">Raku implementation</h1> | |
<a name="t20.5.1"></a> <h2 id="_language_faq.pod6-What_Raku_implementations_are_available?">What Raku implementations are available?</h2> | |
<p>Currently the best developed is Rakudo (using multiple Virtual Machine backends). Historic implementations include Niecza (.NET) and Pugs (Haskell). Others are listed at <a href="#_routine_https:__www.raku.org_compilers_.pod6">Raku Compilers</a></p> | |
<a name="t20.5.2"></a> <h2 id="_language_faq.pod6-What_language_is_Rakudo_written_in?">What language is Rakudo written in?</h2> | |
<p>A short answer is that Rakudo is written almost entirely in Raku. A more detailed answer is that Rakudo is written in a mixture of Raku and NQP ("Not Quite Perl"). NQP is a lightweight Raku-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 Raku syntax.</p> | |
<p><a id="i332" name="Reference NQP (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.5.3"></a> <h2 id="_language_faq.pod6-What_language_is_NQP_written_in?">What language is NQP written in?</h2> | |
<p>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.</p> | |
<a name="t20.5.4"></a> <h2 id="_language_faq.pod6-Is_Raku_Lisp?">Is Raku Lisp?</h2> | |
<pre class="code">(not (not Nil)) | |
</pre> | |
<a name="t20.5.5"></a> <h2 id="_language_faq.pod6-Can_I_compile_my_script_to_a_standalone_executable?">Can I compile my script to a standalone executable?</h2> | |
<p>Tools like <a href="#_routine_https:__modules.raku.org_dist_App::InstallerMaker::WiX.pod6"><span class="code">App::InstallerMaker::WiX</span></a> 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.</p> | |
<p>If you wish to help out, the <i>Rakudo</i> compiler on <i>MoarVM</i> backend has <a href="#_routine_https:__github.com_MoarVM_MoarVM_issues_875.pod6">https://github.com/MoarVM/MoarVM/issues/875</a> issue opened as a place to discuss this problem.</p> | |
<p><a id="i333" name="Reference Raku Distribution (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.6"></a> <h1 id="_language_faq.pod6-Raku_distribution">Raku distribution</h1> | |
<p><a id="i334" name="Reference Rakudo Star release cycle (FAQ)"></a><span class="indexed"></span></p> | |
<a name="t20.6.1"></a> <h2 id="_language_faq.pod6-When_will_the_next_version_of_Rakudo_Star_be_released?">When will the next version of Rakudo Star be released?</h2> | |
<p>A Rakudo Star release is typically produced quarterly, with release announcements <a href="#_routine_https:__rakudo.org_news.pod6">posted on rakudo.org</a>.</p> | |
<a name="t20.7"></a> <h1 id="_language_faq.pod6-Metaquestions_and_advocacy">Metaquestions and advocacy</h1> | |
<a name="t20.7.1"></a> <h2 id="_language_faq.pod6-Why_was_Raku_originally_called_Perl 6?">Why was Raku originally called Perl 6?</h2> | |
<p>… As opposed to some other name that didn't imply all the things that the higher number might indicate on other languages.</p> | |
<p>The short answer is that it was Larry's choice under <a href="#_routine_https:__perldoc.perl.org_5.12.4_perlhack.html.pod6-DESCRIPTION">Rule 1</a>.</p> | |
<p>The community considers Perl and Raku sister languages - they have a lot in common, address many of the same problem spaces, but Raku is not intended to replace Perl. In fact, both languages interoperate with each other.</p> | |
<a name="t20.7.2"></a> <h2 id="_language_faq.pod6-When_will_Raku_be_ready?_Is_it_ready_now?">When will Raku be ready? Is it ready now?</h2> | |
<p>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, Raku and its compilers may or may not be ready for you.</p> | |
<p>That said, version 6.c (Christmas 2015) is the first official release of Raku as a language, along with a validation suite and a compiler that passes it.</p> | |
<a name="t20.7.3"></a> <h2 id="_language_faq.pod6-Why_should_I_learn_Raku?_What's_so_great_about_it?">Why should I learn Raku? What's so great about it?</h2> | |
<p>Raku 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.</p> | |
<ul><li><p>Raku offers procedural, object-oriented AND functional programming methodologies.</p> | |
</li></ul> <ul><li><p>Easy to use consistent syntax, using invariable sigils for data-structures.</p> | |
</li></ul> <ul><li><p>Full grapheme based Unicode support, including Annex #29.</p> | |
</li></ul> <ul><li><p>Clean, more readable regular expressions; taken to the next level of usability, with a lot more functionality. Named regular expressions improve ease of use.</p> | |
</li></ul> <ul><li><p>Junctions allowing easy checking of multiple possibilities; e.g., <span class="code">$a == 1|3|42</span> (Is <span class="code">$a</span> equal to 1 or 3 or 42?).</p> | |
</li></ul> <ul><li><p>Dynamic variables provide a lexically scoped alternative to global variables.</p> | |
</li></ul> <ul><li><p>Emphasis on composability and lexical scoping to prevent “action at a distance”; e.g., imports are always lexically scoped.</p> | |
</li></ul> <ul><li><p>Easy to understand consistent scoping rules and closures.</p> | |
</li></ul> <ul><li><p>Powerful object orientation, with classes and roles (everything can be seen as an object). Inheritance. Subtyping. Code-reuse.</p> | |
</li></ul> <ul><li><p>Introspection into objects and metaobjects (turtles all the way down).</p> | |
</li></ul> <ul><li><p>MetaObject Protocol allowing for metaprogramming without needing to generate or parse code.</p> | |
</li></ul> <ul><li><p>Subroutine and method signatures for easy unpacking of positional and named parameters.</p> | |
</li></ul> <ul><li><p>Multi-dispatch for identically named subroutines/methods with different signatures, based on arity, types and optional additional code.</p> | |
</li></ul> <ul><li><p>Compile time error reporting on unknown subroutines or impossible dispatch.</p> | |
</li></ul> <ul><li><p>Optional gradual type-checking at no additional runtime cost. With optional type annotations.</p> | |
</li></ul> <ul><li><p>Advanced error reporting based on introspection of the compiler/runtime state. This means more useful, more precise error messages.</p> | |
</li></ul> <ul><li><p>Phasers (like <span class="code">BEGIN</span> / <span class="code">END</span>) allow code to be executed at scope entry / exit, loop first / last / next and many more special contexts.</p> | |
</li></ul> <ul><li><p>High level concurrency model, both for implicit as well as explicit multi-processing, which goes way beyond primitive threads and locks. Raku's concurrency offers a rich set of (composable) tools.</p> | |
</li></ul> <ul><li><p>Multiple-core computers are getting used more and more, and with Raku these can be used thanks to parallelism, both implicit (e.g., with the <span class="code">>></span>. method) and explicit ( <span class="code">start { code }</span> ). This is important, because Moore's Law is ending.</p> | |
</li></ul> <ul><li><p>Structured language support is provided to enable programming for asynchronous execution of code.</p> | |
</li></ul> <ul><li><p>Supplies allow code to be executed when something happens (like a timer, or a signal, or a filesystem event).</p> | |
</li></ul> <ul><li><p><span class="code">react</span> / <span class="code">whenever</span> / <span class="code">supply</span> keywords allows easy construction of interactive, event driven applications.</p> | |
</li></ul> <ul><li><p>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.</p> | |
</li></ul> <ul><li><p>Native data types for faster, closer-to-the-metal, processing.</p> | |
</li></ul> <ul><li><p>Interfacing to external libraries in C and C++ is fairly easy with <a href="#_language_nativecall.pod6">NativeCall</a>.</p> | |
</li></ul> <ul><li><p>Interfacing with Perl (CPAN) and Python modules is fairly easy with <a href="#_routine_https:__modules.raku.org_dist_Inline::Perl5:cpan:NINE.pod6">Inline::Perl5</a> and <a href="#_routine_https:__modules.raku.org_dist_Inline::Python.pod6">Inline::Python</a></p> | |
</li></ul> <ul><li><p>Can have multiple versions of a module installed and loaded simultaneously.</p> | |
</li></ul> <ul><li><p>System administration simplified due to simpler update and upgrade policies.</p> | |
</li></ul> <ul><li><p>Simple numeric computation without precision loss because of <a href="#_routine_https:__docs.raku.org_type_Rat.pod6">Rat</a>s (rational numbers).</p> | |
</li></ul> <ul><li><p>Extensible grammars for parsing data or code (which Raku uses to parse itself).</p> | |
</li></ul> <ul><li><p>Raku is a very mutable language (define your own functions, operators, traits and data-types, which modify the parser for you).</p> | |
</li></ul> <ul><li><p>Large selection of data-types, plus the possibility to create your own types.</p> | |
</li></ul> <ul><li><p>Multi-dimensional shaped or native arrays with proper bounds checking.</p> | |
</li></ul> <ul><li><p>Execute code at any time during parsing of a grammar, or when a certain match occurred.</p> | |
</li></ul> <ul><li><p>Adding a custom operator or adding a trait is as simple as writing a subroutine.</p> | |
</li></ul> <ul><li><p>Automatic generation of hyper-operators on any operator (system or custom added).</p> | |
</li></ul> <ul><li><p>Runs on a variety of back-ends. Currently MoarVM and JVM, JavaScript in development, more may follow.</p> | |
</li></ul> <ul><li><p>Runtime optimization of hot code paths during execution (JIT).</p> | |
</li></ul> <ul><li><p>Runs on small (e.g., Raspberry Pi) and large multi-processor hardware.</p> | |
</li></ul> <ul><li><p>Garbage collection based: no timely destruction, so no reference-counting necessary. Use phasers for timely actions.</p> | |
</li></ul> <ul><li><p>Methods can be mixed into any instantiated object at runtime; e.g., to allow adding out-of-band data.</p> | |
</li></ul> <ul><li><p>Easy command-line interface accessible by <span class="code">MAIN</span> subroutine with multiple dispatch and automated usage message generation.</p> | |
</li></ul> <ul><li><p>Fewer lines of code allow for more compact program creation. Huffman-coding of names allows for better readability.</p> | |
</li></ul> <ul><li><p>Lazy lists defined with a simple iterator interface, which any class can supply by minimally supplying a single method.</p> | |
</li></ul> <ul><li><p>Ability to use hyphens and other non-alphanumeric ASCII characters as well as certain Unicode characters in identifiers. (Using hyphens instead of underscores in test is commonly called "kebab case" among its users. See also "camel case" and "snake case": <a href="#_routine_https:__en.wikipedia.org_wiki_Letter_case.pod6-Special_case_styles">https://en.wikipedia.org/wiki/Letter_case#Special_case_styles</a>.)</p> | |
</li></ul> <ul><li><p>Raku'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.</p> | |
</li></ul> <a name="t20.7.4"></a> <h2 id="_language_faq.pod6-Is_Raku_fast_enough_for_me?">Is Raku fast enough for me?</h2> | |
<p>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 Raku 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.</p> | |
<p>The following crude benchmarks, with all the usual caveats about such things, show that Raku can be faster than Perl for similar tasks if the big weaponry is included, that is, if Raku features are used to its full extent; at the same time, Perl can be faster if only the bare bones are included. Similar situations can be observed when comparing Raku to other languages.</p> | |
<p>Try it on your system. You may be pleasantly surprised!</p> | |
<p>Examples:</p> | |
<pre class="code"># Raku version | |
class Foo { has $.i is rw }; | |
for 1..1_000_000 -> $i { | |
my $obj = Foo.new; | |
$obj.i = $i; | |
} | |
</pre> | |
<pre class="code"># Perl 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 version that offers bare-bones set of features | |
# compared to Moose/Raku'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; | |
</pre> | |
<p>You might want to use this program for comparing performance, too. It works under both languages, as long as <span class="code">perl -Mbigint</span> is used for invocation for Perl.</p> | |
<pre class="code">my ($prev, $current) = (1, 0); | |
for (0..100_000) { | |
($prev, $current) = ($current, $prev + $current); | |
} | |
print $current; | |
</pre> | |
</div> | |
<!-- /language/filename-extensions.pod6 --><div class="pod-body"><a id="_language_filename-extensions.pod6"></a><a name="t21"></a><h1 class="title">21 Filename extensions</h1> <p class="subtitle">The extensions recommended for files with Raku content.</p> <table> | |
<tr><th>File contents</th> <th>Extensions recommended or used at one time</th> <th>Current recommendation</th></tr> | |
<tr><td>Language files:</td> <td></td> <td></td></tr> | |
<tr><td>Raku script</td> <td>.pl, .p6</td> <td>.raku</td></tr> | |
<tr><td>Raku module</td> <td>.pm, .pm6</td> <td>.rakumod</td></tr> | |
<tr><td>Raku documentation</td> <td>.pm, pm6, pod, pod6</td> <td>.rakudoc</td></tr> | |
<tr><td>Test files in raku</td> <td>.t</td> <td>.rakutest</td></tr> | |
<tr><td>Not Quite Perl (NQP)</td> <td></td> <td>.nqp</td></tr> | |
<tr><td>Module specific files:</td> <td></td> <td></td></tr> | |
<tr><td>Cro templates</td> <td></td> <td>.crotmp</td></tr> | |
</table> <a name="t21.1"></a> <h1 id="_language_filename-extensions.pod6-Introduction">Introduction</h1> | |
<p>A filename extension is defined, at least for this page, as the remaining letters after and including the final '.'. A filename without a '.' in the filename does not have a filename extension.</p> | |
<p>Filename extensions can be used to associate behavior with the file content, such as opening a specialized reader or editor, running a program with the file content as input, etc. On some operating systems, this is almost the required behavior. Even when it is not required by the operating system, filename extensions provide a useful mnemonic, or reminder, about the contents of the file.</p> | |
<p>Early filesystems, the part of the operating system handling filenames, constrained filename extensions to three characters after the '.'. This is no longer a constraint.</p> | |
<a name="t21.2"></a> <h1 id="_language_filename-extensions.pod6-History_and_extensions">History and extensions</h1> | |
<p>The Raku language was for many years known as Perl 6, and filename extensions were adopted accordingly. Consequently, there is a best current practice and a previous best practice. The table at the top is an attempt to list all the filename extensions, starting with the earliest on the left.</p> | |
<p>The most recent best practice is shown in the last column.</p> | |
<p>Some modules will become widely used, and will have filename extensions associated with them.</p> | |
<p>A module developer / maintainer may add to the table and create a PR with the change in the same way as making other changes to the documentation.</p> | |
</div> | |
<!-- /language/functions.pod6 --><div class="pod-body"><a id="_language_functions.pod6"></a><a name="t22"></a><h1 class="title">22 Functions</h1> <p class="subtitle">Functions and functional programming in Raku</p> <p>Routines are one of the means Raku has to reuse code. They come in several forms, most notably <a href="#_type_Method.pod6">methods</a>, which belong in classes and roles and are associated with an object; and functions (also called <i>subroutines</i> or <a href="#_type_Sub.pod6">sub</a>s, for short), which can be called independently of objects.</p> | |
<p>Subroutines default to lexical (<span class="code">my</span>) scoping, and calls to them are generally resolved at compile time.</p> | |
<p>Subroutines can have a <a href="#_type_Signature.pod6">signature</a>, also called <i>parameter list</i>, 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.</p> | |
<p>Introspection on subroutines is provided via <a href="#_type_Routine.pod6"><span class="code">Routine</span></a>.</p> | |
<a name="t22.1"></a> <h1 id="_language_functions.pod6-Defining/Creating/Using_functions">Defining/Creating/Using functions</h1> | |
<a name="t22.1.1"></a> <h2 id="_language_functions.pod6-Subroutines"><a name="335"></a>Subroutines</h2> | |
<p>The basic way to create a subroutine is to use the <span class="code">sub</span> declarator followed by an optional <a href="#_language_syntax.pod6-Identifiers">identifier</a>:</p> | |
<pre class="code">sub my-func { say "Look ma, no args!" } | |
my-func;</pre> | |
<p>The sub declarator returns a value of type <a href="#_type_Sub.pod6">Sub</a> that can be stored in any container:</p> | |
<pre class="code">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:<( )>»</pre> | |
<p>The declarator <span class="code">sub</span> will declare a new name in the current scope at compile time. As such, any indirection has to be resolved at compile time:</p> | |
<pre class="code">constant aname = 'foo'; | |
sub ::(aname) { say 'oi‽' }; | |
foo;</pre> | |
<p>This will become more useful once macros are added to Raku.</p> | |
<p>To have the subroutine take arguments, a <a href="#_type_Signature.pod6">signature</a> goes between the subroutine's name and its body, in parentheses:</p> | |
<pre class="code">sub exclaim <b>($phrase)</b> { | |
say $phrase ~ "!!!!" | |
} | |
exclaim "Howdy, World"; | |
</pre> | |
<p>By default, subroutines are <a href="#_syntax_my.pod6">lexically scoped</a>. That is, <span class="code">sub foo {...}</span> is the same as <span class="code">my sub foo {...}</span> and is only defined within the current scope.</p> | |
<pre class="code">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\?» | |
</pre> | |
<p>Subroutines don't have to be named. If unnamed, they're called <i>anonymous</i> subroutines.</p> | |
<pre class="code">say sub ($a, $b) { $a ** 2 + $b ** 2 }(3, 4) # OUTPUT: «25»</pre> | |
<p>But in this case, it's often desirable to use the more succinct <a href="#_type_Block.pod6">block</a> syntax. Subroutines and blocks can be called in place, as in the example above.</p> | |
<pre class="code">say -> $a, $b { $a ** 2 + $b ** 2 }(3, 4) # OUTPUT: «25»</pre> | |
<p>Or even</p> | |
<pre class="code">say { $^a ** 2 + $^b ** 2 }(3, 4) # OUTPUT: «25»</pre> | |
<p><a id="i336" name="Language pointy blocks"></a><span class="indexed"></span></p> | |
<a name="t22.1.2"></a> <h2 id="_language_functions.pod6-Blocks_and_lambdas"><a name="337"></a>Blocks and lambdas</h2> | |
<p>Whenever you see something like <span class="code">{ $_ + 42 }</span>, <span class="code">-> $a, $b { $a ** $b }</span>, or <span class="code">{ $^text.indent($:spaces) }</span>, that's <a href="#_type_Block.pod6">Block</a> syntax; the <span class="code">-></span> is considered also part of the block. Statements such as <span class="code">if</span>, <span class="code">for</span>, <span class="code">while</span> are followed by these kind of blocks.</p> | |
<pre class="code">for 1, 2, 3, 4 -> $a, $b { | |
say $a ~ $b; | |
} | |
# OUTPUT: «1234»</pre> | |
<p>They can also be used on their own as anonymous blocks of code.</p> | |
<pre class="code">say { $^a ** 2 + $^b ** 2}(3, 4) # OUTPUT: «25»</pre> | |
<p>Please note that this implies that, despite the fact that statements such as <span class="code">if</span> do not define a topic variable, they actually can:</p> | |
<pre class="code">my $foo = 33; | |
if $foo ** 33 -> $a { | |
say "$a is not null"; # | |
} # OUTPUT: «129110040087761027839616029934664535539337183380513 is not null» | |
</pre> | |
<p>For block syntax details, see the documentation for the <a href="#_type_Block.pod6">Block</a> type.</p> | |
<a name="t22.1.3"></a> <h2 id="_language_functions.pod6-Signatures">Signatures</h2> | |
<p>The parameters that a function accepts are described in its <i>signature</i>.</p> | |
<pre class="code">sub format <b>(Str $s)</b> { ... } | |
-> <b>$a, $b</b> { ... } | |
</pre> | |
<p>Details about the syntax and use of signatures can be found in the <a href="#_type_Signature.pod6">documentation on the <span class="code">Signature</span> class</a>.</p> | |
<a name="t22.1.3.1"></a> <h3 id="_language_functions.pod6-Automatic_signatures"><a name="338"></a>Automatic signatures</h3> | |
<p>If no signature is provided but either of the two automatic variables <span class="code">@_</span> or <span class="code">%_</span> are used in the function body, a signature with <span class="code">*@_</span> or <span class="code">*%_</span> will be generated. Both automatic variables can be used at the same time.</p> | |
<pre class="code">sub s { say @_, %_ }; | |
say &s.signature # OUTPUT: «(*@_, *%_)»</pre> | |
<a name="t22.1.4"></a> <h2 id="_language_functions.pod6-Arguments"><a name="339"></a>Arguments</h2> | |
<p>Arguments are supplied as a comma separated list. To disambiguate nested calls, use parentheses:</p> | |
<pre class="code">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()</pre> | |
<p>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:</p> | |
<pre class="code">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 | |
f 'hi', :1x, :2y; # Positional and named arguments | |
my \c = <a b c>.Capture; | |
f |c; # Merge the contents of Capture $c as if they were supplied</pre> | |
<p>Arguments passed to a function are conceptually first collected in a <span class="code">Capture</span> container. Details about the syntax and use of these containers can be found in the <a href="#_type_Capture.pod6">documentation on the <span class="code">Capture</span> class</a>.</p> | |
<p>When using named arguments, note that normal list "pair-chaining" allows one to skip commas between named arguments.</p> | |
<pre class="code">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.</pre> | |
<p>If positional arguments are also passed, then either they must be passed within parentheses placed <i>immediately</i> after the function's name or the comma after the last positional argument must be kept when chaining named arguments in abbreviated adverb form. The spaces between chained named arguments and the list of positional arguments is optional.</p> | |
<pre class="code">sub p($x, $y, :$translate, :$rotate) {}; | |
p(1, 1, :translate, :rotate); # normal way | |
p 1, 1, :translate, :rotate; # also normal way | |
p(1, 1) :translate :rotate; # parentheses + chained named arguments | |
p(1, 1) :translate:rotate; | |
p(1, 1):translate:rotate; | |
p 1, 1, :translate :rotate; # dangling comma + chained named arguments | |
p 1, 1, :translate:rotate; | |
p 1, 1,:translate:rotate;</pre> | |
<a name="t22.1.5"></a> <h2 id="_language_functions.pod6-Return_values">Return values</h2> | |
<p>Any <span class="code">Block</span> or <span class="code">Routine</span> will provide the value of its last expression as a return value to the caller. If either <a href="#_language_control.pod6-return">return</a> or <a href="#_language_control.pod6-return-rw">return-rw</a> is called, then its parameter, if any, will become the return value. The default return value is <a href="#_type_Nil.pod6">Nil</a>.</p> | |
<pre class="code">sub a { 42 }; | |
sub b { say a }; | |
sub c { }; | |
b; # OUTPUT: «42» | |
say c; # OUTPUT: «Nil»</pre> | |
<p>Multiple return values are returned as a list or by creating a <a href="#_type_Capture.pod6">Capture</a>. Destructuring can be used to untangle multiple return values.</p> | |
<pre class="code">sub a { 42, 'answer' }; | |
put a.raku; | |
# OUTPUT: «(42, "answer")» | |
my ($n, $s) = a; | |
put [$s, $n]; | |
# OUTPUT: «answer 42» | |
sub b { <a b c>.Capture }; | |
put b.raku; | |
# OUTPUT: «\("a", "b", "c")»</pre> | |
<a name="t22.1.6"></a> <h2 id="_language_functions.pod6-Return_type_constraints">Return type constraints</h2> | |
<p>Raku has many ways to specify a function's return type:</p> | |
<pre class="code">sub foo(--> Int) {}; say &foo.returns; # OUTPUT: «(Int)» | |
</pre> | |
<pre class="code">sub foo() returns Int {}; say &foo.returns; # OUTPUT: «(Int)» | |
</pre> | |
<pre class="code">sub foo() of Int {}; say &foo.returns; # OUTPUT: «(Int)» | |
</pre> | |
<pre class="code">my Int sub foo() {}; say &foo.returns; # OUTPUT: «(Int)» | |
</pre> | |
<p>Attempting to return values of another type will cause a compilation error.</p> | |
<pre class="code">sub foo() returns Int { "a"; }; foo; # Type check fails | |
</pre> | |
<p><span class="code">returns</span> and <span class="code">of</span> are equivalent, and both take only a Type since they are declaring a trait of the <a href="#_type_Callable.pod6">Callable</a>. The last declaration is, in fact, a type declaration, which obviously can take only a type. In the other hand, <span class="code">--></span> can take either undefined or definite values.</p> | |
<p>Note that <span class="code">Nil</span> and <span class="code">Failure</span> are exempt from return type constraints and can be returned from any routine, regardless of its constraint:</p> | |
<pre class="code">sub foo() returns Int { fail }; foo; # Failure returned | |
sub bar() returns Int { return }; bar; # Nil returned | |
</pre> | |
<a name="t22.1.7"></a> <h2 id="_language_functions.pod6-Multi-dispatch"><a name="340"></a>Multi-dispatch</h2> | |
<p>Raku 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 <i>candidate</i> and invokes it.</p> | |
<p>Each candidate is declared with the <span class="code">multi</span> keyword. Dispatch happens depending on the parameter <a href="#_type_Code.pod6-method_arity">arity</a> (number), type and name; and under some circumstances the order of the multi declarations. Consider the following example:</p> | |
<pre class="code"># 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 !» | |
</pre> | |
<p>The first two versions of the <span class="code">happy-birthday</span> 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 <span class="code">multi</span> candidate.</p> | |
<p>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:</p> | |
<pre class="code">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 !» | |
</pre> | |
<p>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.</p> | |
<p>For more information about type constraints see the documentation for the <a href="#_type_Signature.pod6-Type_constraints">Signature</a> class.</p> | |
<pre class="code">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]»</pre> | |
<p>For some signature differences (notably when using a where clause or a subset) the order of definition of the multi methods or subs is used, evaluating each possibility in turn. See <a href="#_routine_language_functions.pod6-multi_resolution_by_order_of_definition">multi resolution by order of definition</a> below for examples.</p> | |
<p><span class="code">multi</span> without any specific routine type always defaults to a <span class="code">sub</span>, but you can use it on methods as well. The candidates are all the multi methods of the object:</p> | |
<pre class="code">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»</pre> | |
<p>Unlike <span class="code">sub</span>, if you use named parameters with multi methods, the parameters must be required parameters to behave as expected.</p> | |
<p>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.</p> | |
<p>Multi-dispatch can also work on parameter traits, with routines with <span class="code">is rw</span> parameters having a higher priority than those that do not:</p> | |
<pre class="code">proto þoo (|) {*} | |
multi sub þoo( $ðar is rw ) { $ðar = 42 } | |
multi sub þoo( $ðar ) { $ðar + 42 } | |
my $bar = 7; | |
say þoo($bar); # OUTPUT: «42» | |
</pre> | |
<a name="t22.1.7.1"></a> <h3 id="_language_functions.pod6-proto"><a name="341"></a>proto</h3> | |
<p><span class="code">proto</span> is a way to formally declare commonalities between <span class="code">multi</span> candidates. It acts as a wrapper that can validate but not modify arguments. Consider this basic example:</p> | |
<pre class="code">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</pre> | |
<pre class="code">congratulate('being a cool number', 42); # Proto match error | |
</pre> | |
<p>The proto insists that all <span class="code">multi congratulate</span> subs conform to the basic signature of two strings, optionally followed by further parameters. The <span class="code">|</span> is an un-named <span class="code">Capture</span> parameter, and allows a <span class="code">multi</span> to take additional arguments. The first two calls succeed, but the third fails (at compile time) because <span class="code">42</span> doesn't match <span class="code">Str</span>.</p> | |
<pre class="code">say &congratulate.signature # OUTPUT: «(Str $reason, Str $name, | is raw)» | |
</pre> | |
<p>You can give the <span class="code">proto</span> a function body, and place the <span class="code">{*}</span> (note there is no whitespace inside the curly braces) where you want the dispatch to be done. This can be useful when you have a "hole" in your routine that gives it different behavior depending on the arguments given:</p> | |
<pre class="code"># attempts to notify someone -- False if unsuccessful | |
proto notify(Str $user, Str $msg) { | |
my \hour = DateTime.now.hour; | |
if 8 < hour < 22 { | |
return {*}; | |
} else { | |
# we can't notify someone when they might be sleeping | |
return False; | |
} | |
}</pre> | |
<p>Since <span class="code">proto</span> is a wrapper for <span class="code">multi</span> candidates, the signatures of the routine's <span class="code">multi</span> candidates do not necessarily have to match that of the <span class="code">proto</span>; arguments of <span class="code">multi</span> candidates may have subtypes of those of the <span class="code">proto</span>, and the return types of the <span class="code">multi</span> candidates may be entirely different from that of the <span class="code">proto</span>. Using differing types like this is especially useful when giving <span class="code">proto</span> a function body:</p> | |
<pre class="code">enum DebugType <LOG WARNING ERROR>; | |
#|[ Prints a message to stderr with a color-coded key. ] | |
proto debug(DebugType:D $type, Str:D $message --> Bool:_) { | |
note sprintf qb/\e[1;%dm[%s]\e[0m %s/, {*}, $type.key, $message | |
} | |
multi debug(LOG;; Str:D --> 32) { } | |
multi debug(WARNING;; Str:D --> 33) { } | |
multi debug(ERROR;; Str:D --> 31) { } | |
</pre> | |
<p><span class="code">{*}</span> always dispatches to candidates with the parameters it's called with. Parameter defaults and type coercions will work but are not passed on.</p> | |
<pre class="code">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 | |
</pre> | |
<pre class="code">mistake-proto('test'); # fails -- not passed on | |
</pre> | |
<p>A longer example using <span class="code">proto</span> for methods shows how to extract common functionality into a proto method.</p> | |
<pre class="code">class NewClass { | |
has $.debug is rw = False; | |
has $.value is rw = 'Initial value'; | |
proto method handle( | ) { | |
note "before value is 「$.value」" if $.debug; | |
{*} | |
note "after value is 「$.value」" if $.debug; | |
} | |
multi method handle(Str $s) { | |
$.value = $s; | |
say 'in string' | |
} | |
multi method handle(Positional $s) { | |
$.value = $s[0]; | |
say 'in positional' | |
} | |
multi method handle( $a, $b ) { | |
$.value = "$a is looking askance at $b"; | |
say 'with more than one value' | |
} | |
} | |
my NewClass $x .= new; | |
$x.handle('hello world'); | |
$x.handle(<hello world>); | |
$x.debug = True; | |
$x.handle('hello world'); | |
$x.handle(<hello world>); | |
$x.handle('Claire', 'John'); | |
# OUTPUT: | |
# in string | |
# in positional | |
# before value is 「hello」 | |
# in string | |
# after value is 「hello world」 | |
# before value is 「hello world」 | |
# in positional | |
# after value is 「hello」 | |
# before value is 「hello」 | |
# with more than one value | |
# after value is 「Claire is looking askance at John」 | |
</pre> | |
<a name="t22.1.7.2"></a> <h3 id="_language_functions.pod6-only"><a name="342"></a>only</h3> | |
<p>The <span class="code">only</span> keyword preceding <span class="code">sub</span> or <span class="code">method</span> indicates that it will be the only function with that name that inhabits a given namespace.</p> | |
<pre class="code">only sub you () {"Can make all the world seem right"};</pre> | |
<p>This will make other declarations in the same namespace, such as</p> | |
<pre class="code">sub you ( $can ) { "Make the darkness bright" }</pre> | |
<p>fail with an exception of type <span class="code">X::Redeclaration</span>. <span class="code">only</span> is the default value for all subs; in the case above, not declaring the first subroutine as <span class="code">only</span> will yield exactly the same error; however, nothing prevents future developers from declaring a proto and preceding the names with <span class="code">multi</span>. Using <span class="code">only</span> before a routine is a <a href="#_routine_https:__en.wikipedia.org_wiki_Defensive_programming.pod6">defensive programming</a> feature that declares the intention of not having routines with the same name declared in the same namespace in the future.</p> | |
<pre class="code">(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> | |
</pre> | |
<p>Anonymous subs cannot be declared <span class="code">only</span>. <span class="code">only sub {}</span> will throw an error of type, surprisingly, <span class="code">X::Anon::Multi</span>.</p> | |
<a name="t22.1.7.3"></a> <h3 id="_language_functions.pod6-multi_resolution_by_order_of_definition">multi resolution by order of definition</h3> | |
<p>When the breakdown by parameter type is not enough to find an unambiguous match, there are some different tie breakers that may be evaluated in order of declaration of the methods or subs: these include where clauses and subsets, named parameters, and signature unpacks.</p> | |
<p>In this code example, two multi subs are distinguished only by where clauses where there's one ambiguous case that might pass either of them, the value 4. In this case, which ever multi sub is defined first wins:</p> | |
<pre class="code">{ | |
multi sub check_range ( Int $n where {$_ > 3} ) { | |
return "over 3"; | |
}; | |
multi sub check_range ( Int $n where {$_ < 5} ) { | |
return "under 5"; | |
}; | |
say check_range(4); # OUTPUT: over 3 | |
} | |
{ | |
multi sub check_range ( Int $n where {$_ < 5} ) { | |
return "under 5"; | |
}; | |
multi sub check_range ( Int $n where {$_ > 3} ) { | |
return "over 3"; | |
}; | |
say check_range(4); # OUTPUT: under 5 | |
} | |
</pre> | |
<p>In the following example, three subsets are used to restrict strings to certain allowed values, where there are overlaps between all three:</p> | |
<pre class="code">subset Monster of Str where { $_ eq any( <godzilla gammera ghidora> ) }; | |
subset Hero of Str where { $_ eq any( <godzilla ultraman inframan> ) }; | |
subset Knockoff of Str where { $_ eq any( <gammera inframan thorndike> ) }; | |
{ | |
multi sub speak (Monster $name) { | |
say "The monster, $name roars!"; | |
} | |
multi sub speak (Hero $name) { | |
say "The hero, $name shouts!"; | |
} | |
multi sub speak (Knockoff $name) { | |
say "The knockoff, $name, slinks away..."; | |
} | |
speak('godzilla'); # OUTPUT: The monster, godzilla roars! | |
speak('gammera'); # OUTPUT: The monster, gammera roars! | |
speak('inframan'); # OUTPUT: The hero, inframan shouts! | |
} | |
</pre> | |
<p>Note that here 'godzilla' is treated as Monster, not as Hero, because the Monster multi comes first; and neither 'gammera' or 'inframan' are treated as Knockoff, because that multi comes last.</p> | |
<p>It should be noted that the order of definition is the order in which Raku sees them, which might not be easy to discern if, for example, the multi subs were imported from different modules. As the organization of a code base becomes more complex, object classes may scale better than using subsets as types, as in this example.</p> | |
<a name="t22.2"></a> <h1 id="_language_functions.pod6-Conventions_and_idioms">Conventions and idioms</h1> | |
<p>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.</p> | |
<a name="t22.2.1"></a> <h2 id="_language_functions.pod6-Slurpy_conventions">Slurpy conventions</h2> | |
<p>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., <a href="#_routine_chrs.pod6">chrs</a>) or where there is a conflict with an established idiom (e.g., <a href="#_routine_pop.pod6">pop</a> being the inverse of <a href="#_routine_push.pod6">push</a>).</p> | |
<p>If you wish to match this look and feel, any <a href="#_type_Iterable.pod6">Iterable</a> argument must be broken out element-by-element using a <span class="code">**@</span> slurpy, with two nuances:</p> | |
<ul><li><p>An <a href="#_type_Iterable.pod6">Iterable</a> inside a <a href="#_language_containers.pod6-Scalar_containers">Scalar container</a> doesn't count.</p> | |
</li></ul> <ul><li><p><a href="#_type_List.pod6">List</a>s created with a <a href="#_routine_,.pod6"><span class="code">,</span></a> at the top level only count as one <a href="#_type_Iterable.pod6">Iterable</a>.</p> | |
</li></ul> <p>This can be achieved by using a slurpy with a <a href="#_type_Signature.pod6-index-entry-trait__is_raw"><span class="code">+</span></a> or <span class="code">+@</span> instead of <span class="code">**@</span>:</p> | |
<pre class="code">sub grab(+@a) { "grab $_".say for @a }</pre> | |
<p>which is shorthand for something very close to:</p> | |
<pre class="code">multi sub grab(**@a) { "grab $_".say for @a } | |
multi sub grab(\a) { | |
a ~~ Iterable and a.VAR !~~ Scalar ?? nextwith(|a) !! nextwith(a,) | |
}</pre> | |
<p>This results in the following behavior, which is known as the <i>"single argument rule"</i> and is important to understand when invoking slurpy functions:</p> | |
<pre class="code">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» | |
</pre> | |
<p>This also makes user-requested flattening feel consistent whether there is one sublist, or many:</p> | |
<pre class="code">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» | |
</pre> | |
<p>It's worth noting that mixing binding and sigilless variables in these cases requires a bit of finesse, because there is no <a href="#_type_Scalar.pod6">Scalar</a> intermediary used during binding.</p> | |
<pre class="code">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» | |
</pre> | |
<p>See the <a href="#_type_List.pod6-routine_list">documentation of the <span class="code">list</span> subroutine</a> for more examples of how to use a routine that adheres to the single argument rule.</p> | |
<a name="t22.3"></a> <h1 id="_language_functions.pod6-Functions_are_first-class_objects">Functions are first-class objects</h1> | |
<p>Functions and other code objects can be passed around as values, just like any other object.</p> | |
<p>There are several ways to get hold of a code object. You can assign it to a variable at the point of declaration:</p> | |
<pre class="code">my $square = sub (Numeric $x) { $x * $x } | |
# and then use it: | |
say $square(6); # OUTPUT: «36»</pre> | |
<p><a id="i343" name="Syntax prefix &"></a><span class="indexed"></span> Or you can reference an existing named function by using the <span class="code">&</span>-sigil in front of it.</p> | |
<pre class="code">sub square($x) { $x * $x }; | |
# get hold of a reference to the function: | |
my $func = &square</pre> | |
<p>This is very useful for <i>higher order functions</i>, that is, functions that take other functions as input. A simple one is <a href="#_type_List.pod6-routine_map">map</a>, which applies a function to each input element:</p> | |
<pre class="code">sub square($x) { $x * $x }; | |
my @squared = map &square, 1..5; | |
say join ', ', @squared; # OUTPUT: «1, 4, 9, 16, 25»</pre> | |
<p>You can use the same for operators, except that in that case the name with which they have been declared, using <span class="code">infix:</span>, must be used:</p> | |
<pre class="code">my $exp := &infix:<**>; say $exp(7,3); # OUTPUT: «343»</pre> | |
<p>This can be done even in cases where operators have been <i>auto-generated</i>, for instance in this case where <span class="code">XX</span> is the metaoperator <span class="code">X</span> applied to the <span class="code">X</span> operator.</p> | |
<pre class="code">my $XX := &infix:<XX>; say $XX( [1,(2,3)] , [(4,5),6] ); | |
# OUTPUT: «(((1 (4 5))) ((1 6)) (((2 3) (4 5))) (((2 3) 6)))»</pre> | |
<p>Baseline is that, in case of operators, you don't really need to worry about the actual way they were defined, just use the <span class="code">&infix< ></span> to grab a pointer to them.</p> | |
<a name="t22.3.1"></a> <h2 id="_language_functions.pod6-Infix_form"><!-- -->Infix form</h2> | |
<p>To call a subroutine with 2 arguments like an infix operator, use a subroutine reference surrounded by <span class="code">[</span> and <span class="code">]</span>.</p> | |
<pre class="code">sub plus { $^a + $^b }; | |
say 21 [&plus] 21; | |
# OUTPUT: «42»</pre> | |
<a name="t22.3.2"></a> <h2 id="_language_functions.pod6-Closures"><a name="344"></a>Closures</h2> | |
<p>All code objects in Raku are <i>closures</i>, which means they can reference lexical variables from an outer scope.</p> | |
<pre class="code">sub generate-sub($x) { | |
my $y = 2 * $x; | |
return sub { say $y }; | |
# ^^^^^^^^^^^^^^ inner sub, uses $y | |
} | |
my $generated = generate-sub(21); | |
$generated(); # OUTPUT: «42»</pre> | |
<p>Here, <span class="code">$y</span> is a lexical variable inside <span class="code">generate-sub</span>, and the inner subroutine that is returned uses it. By the time that inner sub is called, <span class="code">generate-sub</span> has already exited. Yet the inner sub can still use <span class="code">$y</span>, because it <i>closed</i> over the variable.</p> | |
<p>Another closure example is the use of <a href="#_type_List.pod6-routine_map">map</a> to multiply a list of numbers:</p> | |
<pre class="code">my $multiply-by = 5; | |
say join ', ', map { $_ * $multiply-by }, 1..5; # OUTPUT: «5, 10, 15, 20, 25»</pre> | |
<p>Here, the block passed to <span class="code">map</span> references the variable <span class="code">$multiply-by</span> from the outer scope, making the block a closure.</p> | |
<p>Languages without closures cannot easily provide higher-order functions that are as easy to use and powerful as <span class="code">map</span>.</p> | |
<a name="t22.3.3"></a> <h2 id="_language_functions.pod6-Routines">Routines</h2> | |
<p>Routines are code objects that conform to <a href="#_type_Routine.pod6">type <span class="code">Routine</span></a>, most notably <a href="#_type_Sub.pod6"><span class="code">Sub</span></a>, <a href="#_type_Method.pod6"><span class="code">Method</span></a>, <a href="#_type_Regex.pod6"><span class="code">Regex</span></a> and <a href="#_type_Submethod.pod6"><span class="code">Submethod</span></a>.</p> | |
<p>They carry extra functionality in addition to what a <a href="#_type_Block.pod6"><span class="code">Block</span></a> supplies: they can come as <a href="#21-Multi-dispatch">multis</a>, you can <a href="#_type_Routine.pod6-method_wrap">wrap</a> them, and exit early with <span class="code">return</span>:</p> | |
<pre class="code">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»</pre> | |
<p>Here, <span class="code">return</span> doesn't just leave the block inside which it was called, but the whole routine. In general, blocks are transparent to <span class="code">return</span>, they attach to the outermost routine.</p> | |
<p><a id="i345" name="Language use soft (pragma)"></a><span class="indexed"></span> Routines can be inlined and as such provide an obstacle for wrapping. Use the pragma <span class="code">use soft;</span> to prevent inlining to allow wrapping at runtime.</p> | |
<pre class="code">sub testee(Int $i, Str $s){ | |
rand.Rat * $i ~ $s; | |
} | |
sub wrap-to-debug(&c){ | |
say "wrapping {&c.name} with arguments {&c.signature.raku}"; | |
&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.raku}"; | |
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»</pre> | |
Important ones: candidates, wrap, unwrap, assuming, arity, count | |
<a name="t22.4"></a> <h1 id="_language_functions.pod6-Defining_operators">Defining operators</h1> | |
<p>Operators are just subroutines with funny names. The funny names are composed of the category name (<span class="code">infix</span>, <span class="code">prefix</span>, <span class="code">postfix</span>, <span class="code">circumfix</span>, <span class="code">postcircumfix</span>), followed by a colon, and a list of the operator name or names (two components in the case of circumfix and postcircumfix). A expanded explanation of all these operators and what they mean is included <a href="#_language_operators.pod6-Operator_classification">in this table</a>.</p> | |
<p>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 <span class="code">use</span> or <span class="code">import</span> also makes it available.</p> | |
<pre class="code"># 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» | |
</pre> | |
<p>The operator declaration becomes available as soon as possible, so you can recurse into a just-defined operator:</p> | |
<pre class="code">sub postfix:<!>(Int $x where { $x >= 0 }) { | |
$x == 0 ?? 1 !! $x * ($x - 1)! | |
} | |
say 6!; # OUTPUT: «720» | |
</pre> | |
<p>Circumfix and postcircumfix operators are made of two delimiters, one opening and one closing.</p> | |
<pre class="code">sub circumfix:<START END>(*@elems) { | |
"start", @elems, "end" | |
} | |
say START 'a', 'b', 'c' END; # OUTPUT: «(start [a b c] end)» | |
</pre> | |
<p>Postcircumfixes also receive the term after which they are parsed as an argument:</p> | |
<pre class="code">sub postcircumfix:<!! !!>($left, $inside) { | |
"$left -> ( $inside )" | |
} | |
say 42!! 1 !!; # OUTPUT: «42 -> ( 1 )» | |
</pre> | |
<p>Blocks can be assigned directly to operator names. Use a variable declarator and prefix the operator name with a <span class="code">&</span>-sigil.</p> | |
<pre class="code">my &infix:<ieq> = -> |l { [eq] l>>.fc }; | |
say "abc" ieq "Abc"; | |
# OUTPUT: «True»</pre> | |
<a name="t22.4.1"></a> <h2 id="_language_functions.pod6-Precedence"><a name="346"></a>Precedence</h2> | |
<p>Operator precedence in Raku is specified relative to existing operators. The traits <span class="code">is tighter</span>, <span class="code">is equiv</span> and <span class="code">is looser</span> 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.</p> | |
<p>For example, <span class="code">infix:<*></span> has a tighter precedence than <span class="code">infix:<+></span>, and squeezing one in between works like this:</p> | |
<pre class="code">sub infix:<!!>($a, $b) is tighter(&infix:<+>) { | |
2 * ($a + $b) | |
} | |
say 1 + 2 * 3 !! 4; # OUTPUT: «21» | |
</pre> | |
<p>Here, the <span class="code">1 + 2 * 3 !! 4</span> is parsed as <span class="code">1 + ((2 * 3) !! 4)</span>, because the precedence of the new <span class="code">!!</span> operator is between that of <span class="code">+</span> and <span class="code">*</span>.</p> | |
<p>The same effect could have been achieved with:</p> | |
<pre class="code">sub infix:<!!>($a, $b) is looser(&infix:<*>) { ... }</pre> | |
<p>To put a new operator on the same precedence level as an existing operator, use <span class="code">is equiv(&other-operator)</span> instead.</p> | |
<a name="t22.4.2"></a> <h2 id="_language_functions.pod6-Associativity">Associativity</h2> | |
<p>When the same operator appears several times in a row, there are multiple possible interpretations. For example:</p> | |
<pre class="code">1 + 2 + 3</pre> | |
<p>could be parsed as</p> | |
<pre class="code">(1 + 2) + 3 # left associative</pre> | |
<p>or as</p> | |
<pre class="code">1 + (2 + 3) # right associative</pre> | |
<p>For addition of real numbers, the distinction is somewhat moot, because <span class="code">+</span> is <a href="#_routine_https:__en.wikipedia.org_wiki_Associative_property.pod6">mathematically associative</a>.</p> | |
<p>But for other operators it matters a great deal. For example, for the exponentiation/power operator, <span class="code">infix:<**></span>:</p> | |
<pre class="code">say 2 ** (2 ** 3); # OUTPUT: «256» | |
say (2 ** 2) ** 3; # OUTPUT: «64»</pre> | |
<p>Raku has the following possible associativity configurations:</p> | |
<table> | |
<tr><th>Associativity</th> <th>Meaning of $a ! $b ! $c</th></tr> | |
<tr><td>left</td> <td>($a ! $b) ! $c</td></tr> | |
<tr><td>right</td> <td>$a ! ($b ! $c)</td></tr> | |
<tr><td>non</td> <td>ILLEGAL</td></tr> | |
<tr><td>chain</td> <td>($a ! $b) and ($b ! $c)</td></tr> | |
<tr><td>list</td> <td>infix:<!>($a; $b; $c)</td></tr> | |
</table> <p>The <a href="#_language_operators.pod6-Operator_associativity">Operator docs</a> contain additional details about operator associativity.</p> | |
<p><a id="i347" name="Traits is assoc"></a><span class="indexed"></span> You can specify the associativity of an infix operator with the <span class="code">is assoc</span> trait, where <span class="code">left</span> is the default associativity. Specifying the associativity of non-infix operators is planed but not yet implemented.</p> | |
<pre class="code">sub infix:<§>(*@a) is assoc<list> { | |
'(' ~ @a.join('|') ~ ')'; | |
} | |
say 1 § 2 § 3; # OUTPUT: «(1|2|3)» | |
</pre> | |
<a name="t22.5"></a> <h1 id="_language_functions.pod6-Traits">Traits</h1> | |
<p><i>Traits</i> are subroutines that run at compile time and modify the behavior of a type, variable, routine, attribute, or other language object.</p> | |
<p>Examples of traits are:</p> | |
<pre class="code">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 | |
</pre> | |
<p>... and also <span class="code">is tighter</span>, <span class="code">is looser</span>, <span class="code">is equiv</span> and <span class="code">is assoc</span> from the previous section.</p> | |
<p>Traits are subs declared in the form <span class="code">trait_mod<VERB></span>, where <span class="code">VERB</span> stands for the name like <span class="code">is</span>, <span class="code">does</span> or <span class="code">handles</span>. It receives the modified thing as argument, and the name as a named argument. See <a href="#_type_Sub.pod6-Traits">Sub</a> for details.</p> | |
<pre class="code">multi sub trait_mod:<is>(Routine $r, :$doubles!) { | |
$r.wrap({ | |
2 * callsame; | |
}); | |
} | |
sub square($x) is doubles { | |
$x * $x; | |
} | |
say square 3; # OUTPUT: «18» | |
</pre> | |
<p>See <a href="#_type_Routine.pod6">type Routine</a> for the documentation of built-in routine traits.</p> | |
<a name="t22.6"></a> <h1 id="_language_functions.pod6-Re-dispatching">Re-dispatching</h1> | |
<p>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 <span class="code">wrap</span>.</p> | |
<p>Fortunately, we have a series of re-dispatching tools that help us to make it easy.</p> | |
<a name="t22.6.1"></a> <h2 id="_language_functions.pod6-sub_callsame"><a name="348"></a>sub callsame</h2> | |
<p><span class="code">callsame</span> calls the next matching candidate with the same arguments that were used for the current candidate and returns that candidate's return value.</p> | |
<pre class="code">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» | |
</pre> | |
<a name="t22.6.2"></a> <h2 id="_language_functions.pod6-sub_callwith"><a name="349"></a>sub callwith</h2> | |
<p><span class="code">callwith</span> 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.</p> | |
<pre class="code">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» | |
</pre> | |
<p>Here, <span class="code">a 1</span> calls the most specific <span class="code">Int</span> candidate first, and <span class="code">callwith</span> re-dispatches to the less specific <span class="code">Any</span> candidate. Note that although our parameter <span class="code">$x + 1</span> is an <span class="code">Int</span>, still we call the next candidate in the chain.</p> | |
<p>In this case, for example:</p> | |
<pre class="code">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» | |
</pre> | |
<p>the only candidates that take the <span class="code">Pair</span> argument supplied by the user are the two functions defined first. Although a <span class="code">Pair</span> can be easily coerced to a <span class="code">Hash</span>, here is how signatures match:</p> | |
<pre class="code">say :( Pair ) ~~ :( Associative ); # OUTPUT: «True» | |
say :( Pair ) ~~ :( Hash ); # OUTPUT: «False» | |
</pre> | |
<p>The arguments provided by us are a <span class="code">Pair</span>. It does not match a <span class="code">Hash</span>, so the corresponding function is thus not included in the list of candidates, as can be seen by the output of <span class="code">&how-many.cando( \( $little-piggy ));</span>.</p> | |
<a name="t22.6.3"></a> <h2 id="_language_functions.pod6-sub_nextsame"><a name="350"></a>sub nextsame</h2> | |
<p><span class="code">nextsame</span> calls the next matching candidate with the same arguments that were used for the current candidate and <b>never</b> returns.</p> | |
<pre class="code">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» | |
</pre> | |
<a name="t22.6.4"></a> <h2 id="_language_functions.pod6-sub_nextwith"><a name="351"></a>sub nextwith</h2> | |
<p><span class="code">nextwith</span> calls the next matching candidate with arguments provided by users and <b>never</b> returns.</p> | |
<pre class="code">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 nextwith doesn't return"; | |
} | |
a 1; # OUTPUT: «Int 1Any 2» | |
</pre> | |
<a name="t22.6.5"></a> <h2 id="_language_functions.pod6-sub_samewith"><a name="352"></a>sub samewith</h2> | |
<p><span class="code">samewith</span> calls the multi again with arguments provided at the call site and returns the value provided by the call. This can be used for self-recursion.</p> | |
<pre class="code">proto factorial(|) {*} | |
multi factorial(Int $x where * ≤ 1) { 1 } | |
multi factorial(Int $x) { | |
$x * samewith($x-1); | |
} | |
say (factorial 10); # OUTPUT: «36288000» | |
</pre> | |
<a name="t22.6.6"></a> <h2 id="_language_functions.pod6-sub_nextcallee"><a name="353"></a>sub nextcallee</h2> | |
<p>Redispatch may be required to call a block that is not the current scope what provides <span class="code">nextsame</span> and friends with the problem to referring to the wrong scope. Use <span class="code">nextcallee</span> to capture the right candidate and call it at the desired time.</p> | |
<pre class="code">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 | |
</pre> | |
<p>The <span class="code">Int</span> candidate takes the <span class="code">nextcallee</span> and then fires up a <span class="code">Promise</span> to be executed in parallel, after some timeout, and then returns. We can't use <span class="code">nextsame</span> here, because it'd be trying to <span class="code">nextsame</span> the Promise's block instead of our original routine.</p> | |
<a name="t22.6.7"></a> <h2 id="_language_functions.pod6-Wrapped_routines"><a name="354"></a>Wrapped routines</h2> | |
<p>Besides those already mentioned above, re-dispatch is helpful in many more situations. For instance, for dispatching to wrapped routines:</p> | |
<pre class="code"># 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» | |
</pre> | |
<a name="t22.6.8"></a> <h2 id="_language_functions.pod6-Routines_of_parent_class">Routines of parent class</h2> | |
<p>Another use case is to re-dispatch to methods from parent classes.</p> | |
<pre class="code">say Version.new('1.0.2') # OUTPUT: v1.0.2 | |
</pre> | |
<pre class="code">class LoggedVersion is Version { | |
method new(|c) { | |
note "New version object created with arguments " ~ c.raku; | |
nextsame; | |
} | |
} | |
say LoggedVersion.new('1.0.2'); | |
# OUTPUT: | |
# New version object created with arguments \("1.0.2") | |
# v1.0.2 | |
</pre> | |
<a name="t22.7"></a> <h1 id="_language_functions.pod6-Coercion_types">Coercion types</h1> | |
<p>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.</p> | |
<p>In the case the arguments cannot be converted to the stricter type, a <i>Type Check</i> error is thrown.</p> | |
<pre class="code">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' | |
</pre> | |
<p>In the above example, the <a href="#_type_Int.pod6">Int</a> is the target type to which the argument <span class="code">$x</span> will be coerced, and <a href="#_type_Cool.pod6">Cool</a> is the type that the routine accepts as wider input.</p> | |
<p>If the accepted wider input type is <a href="#_type_Any.pod6">Any</a>, it is possible to abbreviate the coercion <span class="code">Int(Any)</span> by omitting the <span class="code">Any</span> type, thus resulting in <span class="code">Int()</span>.</p> | |
<p>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:</p> | |
<pre class="code">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; | |
</pre> | |
<p>In the above code, once a <span class="code">Foo</span> instance is passed as argument to <span class="code">print-bar</span>, the <span class="code">Foo.Bar</span> method is called and the result is placed into <span class="code">$bar</span>.</p> | |
<p>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.</p> | |
Non-parameter coercion types will theoretically be working in 6.2. Updated the reference above to latest version. | |
<p>Coercion also works with return types:</p> | |
<pre class="code">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» | |
</pre> | |
<p>In this case, we are coercing an <span class="code">Int</span> to a <span class="code">Bool</span>, which is then printed (put into a string context) in the <span class="code">for</span> loop that calls the function.</p> | |
<a name="t22.8"></a> <h1 id="_language_functions.pod6-sub_MAIN">sub MAIN</h1> | |
<p>Declaring a <span class="code">sub MAIN</span> is not compulsory in Raku scripts, but you can provide one to create a <a href="#_language_create-cli.pod6">command line interface</a> for your script.</p> | |
</div> | |
<!-- /language/glossary.pod6 --><div class="pod-body"><a id="_language_glossary.pod6"></a><a name="t23"></a><h1 class="title">23 Glossary</h1> <p class="subtitle">Glossary of Raku™ terminology</p> <a name="t23.1"></a> <h1 id="_language_glossary.pod6-Abstract_class"><a name="355"></a>Abstract class</h1> | |
<p>The generic Computer Science term "abstract class" defines the <a href="#22-Interface">interface</a> or <a href="#22-API">API</a> of a class. In Raku, this is implemented using <a href="#22-Roles">roles</a> with <a href="#22-Stub">stubbed</a> methods.</p> | |
<pre class="code">role Canine { | |
method bark { ... } # the ... indicates a stub | |
} | |
class Dog does Canine { | |
method bark { say "woof" } # *MUST* be implemented by class | |
}</pre> | |
<a name="t23.2"></a> <h1 id="_language_glossary.pod6-Advent_calendar"><a name="356"></a>Advent calendar</h1> | |
<p>In the context of Raku, a yearly set of blog posts for each day from the 1st until the 25th of December, to be found at <a href="#_routine_https:__raku-advent.blog.pod6">https://raku-advent.blog</a>.</p> | |
<a name="t23.3"></a> <h1 id="_language_glossary.pod6-Adverb"><a name="357"></a>Adverb</h1> | |
<p>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:</p> | |
<pre class="code">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 | |
</pre> | |
<p>Adverbs are usually expressed with colon pair notation, and for this reason colon pair notation is also known as the adverbial pair form:</p> | |
<pre class="code">:a(4) # Same as "a" => 4</pre> | |
<p>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):</p> | |
<pre class="code">:20seconds # same as seconds => 20</pre> | |
<p>Also see <a href="#22-Colon pair and colon list">#Colon pair and colon list</a>.</p> | |
<a name="t23.4"></a> <h1 id="_language_glossary.pod6-Adverbial_pair"><a name="358"></a>Adverbial pair</h1> | |
<p>A generalized form of <span class="code">pair notation</span>. They all start with the colon, as shown in the following examples:</p> | |
<table> | |
<tr><th>adverbial pair</th> <th>pair notation</th></tr> | |
<tr><td>:foo<bar></td> <td>foo => 'bar'</td></tr> | |
<tr><td>:foo(42)</td> <td>foo => 42</td></tr> | |
<tr><td>:42foo</td> <td>foo => 42</td></tr> | |
<tr><td>:$foo</td> <td>foo => $foo</td></tr> | |
<tr><td>:foo</td> <td>foo => True</td></tr> | |
<tr><td>:!foo</td> <td>foo => False</td></tr> | |
</table> <p>Also see <a href="#22-Adverb">#Adverb</a> and <a href="#22-Colon pair and colon list">#Colon pair and colon list</a>.</p> | |
<a name="t23.5"></a> <h1 id="_language_glossary.pod6-Allomorph"><a name="359"></a>Allomorph</h1> | |
<p>A type that has two related values which may be used depending on the context. For example <a href="#_type_IntStr.pod6">IntStr</a> allomorph <span class="code">is</span> both an <a href="#_type_Int.pod6">Int</a> and a <a href="#_type_Str.pod6">Str</a>, so it will be accepted by anything that expects an <span class="code">Int</span>, a <span class="code">Str</span>, or an <span class="code">IntStr</span>. Keep in mind that certain constructs, such as <a href="#_language_setbagmix.pod6">sets, bags, and mixes</a> care about object identity, and so will not accept an allomorph as equivalent of its components alone.</p> | |
<p>The <i>allomorph</i> types <a href="#_type_IntStr.pod6">IntStr</a>, <a href="#_type_NumStr.pod6">NumStr</a>, <a href="#_type_RatStr.pod6">RatStr</a> and <a href="#_type_ComplexStr.pod6">ComplexStr</a> may be created as a result of parsing a string quoted with angle brackets:</p> | |
<pre class="code">say <42>.^name; # OUTPUT: «IntStr» | |
say <42.1e0>.^name; # OUTPUT: «NumStr» | |
say <42.1>.^name; # OUTPUT: «RatStr»</pre> | |
<p><b>Note</b>: angle brackets can also be used to create literals for which you'd normally need to use some operator (e.g. <span class="code">/</span> for <a href="#_type_Rat.pod6">Rat</a> or <span class="code">+</span> for <a href="#_type_Complex.pod6">Complex</a>). This allows you to use such literals in places where expressions are not allowed, for example, as literals in signatures:</p> | |
<pre class="code"># Wrong, can't use an operator there: | |
multi foo (1/3) { say "It's one third!" } | |
</pre> | |
<pre class="code"># Right, a Rat literal: | |
multi foo (<1/3>) { say "It's one third!" } | |
</pre> | |
<p>If you <i>do</i> want an allomorph and not a literal <a href="#_type_Numeric.pod6">Numeric</a>, then include whitespace around angle brackets:</p> | |
<pre class="code">say <42/1>.^name; # OUTPUT: «Rat» | |
say <42+0i>.^name; # OUTPUT: «Complex» | |
say < 42+0i >.^name; # OUTPUT: «ComplexStr» | |
say < 42/1 >.^name; # OUTPUT: «RatStr»</pre> | |
<p>Please see <a href="#_language_numerics.pod6-Allomorphs">the Numerics page</a> for a more complete description on how to work with these allomorphs.</p> | |
<a name="t23.6"></a> <h1 id="_language_glossary.pod6-Anonymous"><a name="360"></a>Anonymous</h1> | |
<p>A subroutine, method or submethod is called <i>anonymous</i> if it can't be called by name.</p> | |
<pre class="code"># named subroutine | |
sub double($x) { 2 * $x }; | |
# anonymous subroutine, stored in a named scalar | |
my $double = sub ($x) { 2 * $x };</pre> | |
<p>Note that it is still allowed to have a name, but you cannot call it by that name:</p> | |
<pre class="code"># anonymous, but knows its own name | |
my $s = anon sub triple($x) { 3 * $x } | |
say $s.name; # OUTPUT: «triple» | |
</pre> | |
<pre class="code">say triple(42); # OUTPUT: «Undeclared routine: triple» | |
</pre> | |
<a name="t23.7"></a> <h1 id="_language_glossary.pod6-API"><a name="361"></a>API</h1> | |
<p>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.</p> | |
<p>See also <a href="#22-Abstract class">#Abstract class</a>.</p> | |
<a name="t23.8"></a> <h1 id="_language_glossary.pod6-Apocalypse"><a name="362"></a>Apocalypse</h1> | |
<p>A document originally written by <a href="#22-TimToady">#TimToady</a>, 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 <a href="#22-Exegesis">#Exegesis</a> and <a href="#22-Synopsis">#Synopsis</a>.</p> | |
<a name="t23.9"></a> <h1 id="_language_glossary.pod6-Arity"><a name="363"></a>Arity</h1> | |
<p>The number of <a href="#_type_Positional.pod6">positional</a> operands expected by an <a href="#22-Operator">operator</a>, subroutine, method or callable block.</p> | |
<pre class="code">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 | |
</pre> | |
<p>The arity of a <span class="code">Callable</span> is one of the main selectors in <a href="#22-Multi-dispatch">multi-dispatch</a>.</p> | |
<a name="t23.10"></a> <h1 id="_language_glossary.pod6-ASCII_operator"><a name="364"></a>ASCII operator</h1> | |
“Texas” was used in the past but is now discouraged. | |
Remove the link when “Texas” goes completely out of use. | |
<p>The ASCII variant of a non-ASCII Unicode <a href="#22-Operator">operator</a> or <a href="#22-Symbol">symbol</a>. For instance, <span class="code">(elem)</span> corresponds to the <span class="code">∈</span> ("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 <a href="#_language_unicode_ascii.pod6">ASCII variants</a>. Well, maybe just a little...</p> | |
<a name="t23.11"></a> <h1 id="_language_glossary.pod6-Autothreading"><a name="365"></a>Autothreading</h1> | |
<p>Autothreading is what happens if you pass a <a href="#_type_Junction.pod6">Junction</a> to a subroutine that expects a parameter of type <a href="#_type_Any.pod6">Any</a> or a subtype thereof (such as anything <a href="#_type_Cool.pod6">Cool</a>). 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.</p> | |
<pre class="code">sub f($x) { 2 * $x }; | |
say f(1|2|3) == 4; # OUTPUT: «any(False, True, False)»</pre> | |
<p>Here <span class="code">f()</span> is a sub with one parameter, and since it has no explicit type, it is implicitly typed as <span class="code">Any</span>. The <span class="code">Junction</span> argument causes the <span class="code">f(1|2|3)</span> call to be internally executed as <span class="code">f(1)|f(2)|f(3)</span>, and the resulting junction is <span class="code">2|4|6</span>. These are then all compared to <span class="code">4</span>, resulting in a junction <span class="code">False|True|False</span>. This process of separating junction arguments into multiple calls to a function is called <i>autothreading</i>.</p> | |
<p>If you use the resulting junction in a Boolean context, such as with an <span class="code">if</span>, it collapses into a single Boolean which is <span class="code">True</span> if any of the values in the junction are True.</p> | |
<pre class="code">if f(1|2|3) == 4 { # fires because f(2) == 4 is true | |
say 'success'; | |
} | |
</pre> | |
<a name="t23.12"></a> <h1 id="_language_glossary.pod6-Backtracking"><a name="366"></a>Backtracking</h1> | |
<p>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 <a href="#_language_regexes.pod6-Backtracking">Regexp Backtracking section</a>.</p> | |
<a name="t23.13"></a> <h1 id="_language_glossary.pod6-binder"><a name="367"></a>binder</h1> | |
<p>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 <i>binder</i>.</p> | |
<a name="t23.14"></a> <h1 id="_language_glossary.pod6-block"><a name="368"></a>block</h1> | |
<p><a href="#_type_Block.pod6">Blocks</a> are code object with its own lexical scope, which allows them to define variables without interfering with other in the containing block.</p> | |
<a name="t23.15"></a> <h1 id="_language_glossary.pod6-bytecode"><a name="369"></a>bytecode</h1> | |
<p>Although Raku looks like an interpreted language, since it uses the <span class="code">#!</span> form to run its scripts (and they are called <i>scripts</i>), it is actually <a href="#_routine_https:__www.reddit.com_r_perl6_comments_42dkme_perl6_not_being_an_interpreted_language_.pod6">compiled to run in a virtual machine</a> so the compiler (currently Rakudo) generates <a href="#_routine_https:__en.wikipedia.org_wiki_Bytecode.pod6">bytecode</a> that runs either in MoarVM or the Java Virtual Machine, the two VMs currently supported.</p> | |
<a name="t23.16"></a> <h1 id="_language_glossary.pod6-Camelia"><a name="370"></a>Camelia</h1> | |
<p>A butterfly image intended primarily to represent Raku, The Language.</p> | |
<a name="t23.17"></a> <h1 id="_language_glossary.pod6-Colon_pair_and_colon_list"><a name="371"></a>Colon pair and colon list</h1> | |
<p>A colon pair is a shorthand syntax used to create or visually present a <a href="#_type_Pair.pod6">Pair</a> object. The two most common forms are:</p> | |
<pre class="code">: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"))</pre> | |
<p>This is also known as the adverbial pair form.</p> | |
<p><b>Note</b>: when the part after the colon and before the balanced delimiters is not a legal identifier, other semantics apply, not all of which produce <span class="code">Pair</span> objects.</p> | |
<p>Two other common forms are:</p> | |
<pre class="code">:a # Same as :a(True) | |
:!a # Same as :a(False)</pre> | |
<p>A colon list just means that a list that contains only colon pairs, does not need commas, or even spaces:</p> | |
<pre class="code">:a(4):c:!d:c # Same as a => 4, c => True, d => False, c => True</pre> | |
<p>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:</p> | |
<table> | |
<tr><th>variable only</th> <th>same as</th></tr> | |
<tr><td>:$foo</td> <td>foo => $foo</td></tr> | |
<tr><td>:@bar</td> <td>bar => @bar</td></tr> | |
<tr><td>:%mapper</td> <td>mapper => %mapper</td></tr> | |
<tr><td>:&test</td> <td>test => &test</td></tr> | |
</table> <p>See also <a href="#22-Adverb">#Adverb</a>.</p> | |
<a name="t23.18"></a> <h1 id="_language_glossary.pod6-Community"><a name="372"></a>Community</h1> | |
<p>See <a href="#_routine_https:__raku.org_community_.pod6">https://raku.org/community/</a> for information about how to participate in the friendly Raku community.</p> | |
<a name="t23.19"></a> <h1 id="_language_glossary.pod6-Damian_Conway"><a name="373"></a>Damian Conway</h1> | |
<p>Original author of the <a href="#22-Exegesis">#Exegesis</a> (among many other things). See also <a href="#_routine_https:__en.wikipedia.org_wiki_Damian_Conway.pod6">https://en.wikipedia.org/wiki/Damian_Conway</a>.</p> | |
<a name="t23.20"></a> <h1 id="_language_glossary.pod6-decont"><a name="374"></a>decont</h1> | |
<p>Short for "decontainerize", meaning to remove an item <a href="#_language_containers.pod6">from its <span class="code">Scalar</span> container</a>, often to obtain <a href="#_routine_https:__perl6advent.wordpress.com_2017_12_02_.pod6-theoneandonly">a different behavior</a> for items that have it.</p> | |
<a name="t23.21"></a> <h1 id="_language_glossary.pod6-diffy"><a name="375"></a>diffy</h1> | |
<p>See <a href="#22-Operator">operator</a>. It means the type of the operator result is sufficiently different from its arguments that op= makes little sense.</p> | |
<a name="t23.22"></a> <h1 id="_language_glossary.pod6-Exegesis"><a name="376"></a>Exegesis</h1> | |
<p>A document originally written by <a href="#22-TheDamian">#TheDamian</a>, in which he tried to explain the <a href="#22-Apocalypse">Apocalypses</a> to the common (wo)man. Now only kept as an historical document for reference. See also <a href="#22-Synopsis">#Synopsis</a>.</p> | |
<p><a id="i377" name="Reference forward declaration"></a><span class="indexed"></span></p> | |
<a name="t23.23"></a> <h1 id="_language_glossary.pod6-Forward_declarations">Forward declarations</h1> | |
<p>Declare the scope and/or type of a functional entity (class or routine) without actually declaring its code by using the <a href="#_language_operators.pod6-index-entry-..._operators">"stub" operator</a>; code will be declared later on in the same file.</p> | |
<pre class="code">grammar Quux { | |
my regex future {...}; | |
say "foobarbaz" ~~ /<future>/; | |
regex future { f \w** 2 b \w ** 2 } | |
} | |
</pre> | |
<p>In this case, the regex acts as a method; please note that the scope is only declared once.</p> | |
<a name="t23.24"></a> <h1 id="_language_glossary.pod6-fiddly"><a name="378"></a>fiddly</h1> | |
<p>Too complicated to apply a metaop to. See <a href="#22-Operator">operator</a>.</p> | |
<a name="t23.25"></a> <h1 id="_language_glossary.pod6-Handle"><a name="379"></a>Handle</h1> | |
<p>A handle is a data structure used to store information about some input/output operation such as file or socket reading or writing. Raku uses <a href="#_type_IO::Handle.pod6">IO::Handle</a> as a base class for filehandles, and <a href="#_type_IO::Socket.pod6">IO::Socket</a> for sockets.</p> | |
<a name="t23.26"></a> <h1 id="_language_glossary.pod6-Huffmanize"><a name="380"></a>Huffmanize</h1> | |
<p>With reference to <a href="#_routine_https:__en.wikipedia.org_wiki_Huffman_coding.pod6">Huffman coding</a>, "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.</p> | |
<p>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 <a href="#_routine_put.pod6">put</a>. But there's no need to "huffmanize" the rarely-needed atomic operators, which is why you type the lengthier names, such as <a href="#_routine_atomic-inc-fetch.pod6">atomic-inc-fetch</a>. The name <a href="#_routine_put.pod6">put</a> is a bit vague, but because it's commonly used, it's easy to learn what it does. On the other hand, the name <a href="#_routine_atomic-inc-fetch.pod6">atomic-inc-fetch</a> is rarer, and the more descriptive name helps recall its purpose better.</p> | |
<a name="t23.27"></a> <h1 id="_language_glossary.pod6-iffy"><a name="381"></a>iffy</h1> | |
<p>Often used as a Boolean value. See <a href="#22-Operator">operator</a>. Made via the <a href="#_language_modules.pod6-use"><span class="code">use</span> keyword</a>.</p> | |
<a name="t23.28"></a> <h1 id="_language_glossary.pod6-import"><a name="382"></a>import</h1> | |
<p>Include functions from a module in the current namespace.</p> | |
<a name="t23.29"></a> <h1 id="_language_glossary.pod6-Instance"><a name="383"></a>Instance</h1> | |
<p>An <i>instance</i> of a class is also called an <i>object</i> in some other programming languages. It has storage for attributes and is often the return value of a call to a method called <span class="code">new</span>, or a literal.</p> | |
<p>Instances of most types are defined to be <span class="code">True</span> e.g., <span class="code">defined($instance)</span> is <span class="code">True</span>.</p> | |
<pre class="code">my Str $str = "hello"; ## this is with built-in 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.raku;# defined($an_instance) works too.</pre> | |
<p>To put things another way, a class contains the blueprints of methods and attributes, and an instance carries it into the real world.</p> | |
<a name="t23.30"></a> <h1 id="_language_glossary.pod6-Interface"><a name="384"></a>Interface</h1> | |
<p>An interface is an <a href="#22-Abstract class">abstract class</a>.</p> | |
<a name="t23.31"></a> <h1 id="_language_glossary.pod6-Invocant"><a name="385"></a>Invocant</h1> | |
<p>Caller, <i>the one who calls or invokes</i>. The invocant of a method would be the object on which that method is being called, or, in some cases, the class itself. <i>Invocant</i> is used instead of caller because the latter refers to the <i>scope</i>.</p> | |
<a name="t23.32"></a> <h1 id="_language_glossary.pod6-IRC"><a name="386"></a>IRC</h1> | |
<p>Internet Relay Chat. Raku developers and users usually hang out on the <span class="code">#raku</span> channel of <span class="code">irc.libera.chat</span>. This channel is also populated by a host of friendly bots that allow you to interact with Raku and its codebase, as well as send delayed messages and other goodies. Check the full list in <a href="#_routine_https:__raku.org_community_irc.pod6">the community page of raku.org</a>.</p> | |
<a name="t23.33"></a> <h1 id="_language_glossary.pod6-IRC_lingo"><a name="387"></a>IRC lingo</h1> | |
<p>The following terms are often used on the Raku related <a href="#22-IRC">#IRC</a> channels:</p> | |
<a name="t23.33.1"></a> <h2 id="_language_glossary.pod6-ALAP"><a name="388"></a>ALAP</h2> | |
<p>As Late As Possible</p> | |
<a name="t23.33.2"></a> <h2 id="_language_glossary.pod6-autopun"><a name="389"></a>autopun</h2> | |
<p>A self-referencing pun, e.g. "Are you ignorant or apathetic?" - "I don't know, and I don't care."</p> | |
<a name="t23.33.3"></a> <h2 id="_language_glossary.pod6-backlog"><a name="390"></a>backlog</h2> | |
<p>That part of a discussion on an <a href="#22-IRC">#IRC</a> channel that you've missed. If it is not or no longer available in your IRC client, you can go to sites such as <a href="#_routine_http:__colabti.org_irclogger_irclogger_logs_raku.pod6">http://colabti.org/irclogger/irclogger_logs/raku</a> to see what has been logged for you.</p> | |
<a name="t23.33.4"></a> <h2 id="_language_glossary.pod6-Bot"><a name="391"></a>Bot</h2> | |
<p>A program that does automatic tasks on one or more <a href="#22-IRC">#IRC</a> 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 can be found <a href="#_routine_https:__raku.org_community_irc.pod6">on the IRC page of raku.org</a>.</p> | |
<a name="t23.33.5"></a> <h2 id="_language_glossary.pod6-Compilation_unit_or_compunit"><a name="392"></a>Compilation unit or <i>compunit</i></h2> | |
<p>A <a href="#_routine_https:__github.com_rakudo_rakudo_blob_master_docs_module_management.md.pod6">compunit</a>> is a piece of Raku 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 <a href="#_routine_EVAL.pod6">EVAL</a> is also considered a compunit.</p> | |
<a name="t23.33.6"></a> <h2 id="_language_glossary.pod6-DWIM"><a name="393"></a>DWIM</h2> | |
<p><i>Do What I Mean</i>. A programming language designer motto. The opposite of a DWIM is a <a href="#22-WAT">#WAT</a>.</p> | |
<a name="t23.33.7"></a> <h2 id="_language_glossary.pod6-flap"><a name="394"></a>flap</h2> | |
<p>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.</p> | |
<a name="t23.33.8"></a> <h2 id="_language_glossary.pod6-fossil"><a name="395"></a>fossil</h2> | |
<p>Something in a generally current document that is no longer true but which has not yet been fixed by correcting or removing it.</p> | |
<a name="t23.33.9"></a> <h2 id="_language_glossary.pod6-FSVO"><a name="396"></a>FSVO</h2> | |
<p>For Some Value Of...</p> | |
<a name="t23.33.10"></a> <h2 id="_language_glossary.pod6-FTFY"><a name="397"></a>FTFY</h2> | |
<p>Fixed That For You</p> | |
<a name="t23.33.11"></a> <h2 id="_language_glossary.pod6-gradual_typing"><a name="398"></a>gradual typing</h2> | |
<p>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 <a href="#_routine_https:__en.wikipedia.org_wiki_Gradual_typing.pod6">https://en.wikipedia.org/wiki/Gradual_typing</a>.</p> | |
<a name="t23.33.12"></a> <h2 id="_language_glossary.pod6-IIRC"><a name="399"></a>IIRC</h2> | |
<p>If I Read (or Remember) Correctly.</p> | |
<a name="t23.33.13"></a> <h2 id="_language_glossary.pod6-IMHO"><a name="400"></a>IMHO</h2> | |
<p>In My Humble Opinion.</p> | |
<a name="t23.33.14"></a> <h2 id="_language_glossary.pod6-IWBN"><a name="401"></a>IWBN</h2> | |
<p>It Would Be Nice</p> | |
<a name="t23.33.15"></a> <h2 id="_language_glossary.pod6-LHF"><a name="402"></a>LHF</h2> | |
<p>Low Hanging Fruit. Usually used in the context of a (relatively) simple task to be performed by a (relative) newbie.</p> | |
<a name="t23.33.16"></a> <h2 id="_language_glossary.pod6-LGTM"><a name="403"></a>LGTM</h2> | |
<p>Looks Good To Me</p> | |
<a name="t23.33.17"></a> <h2 id="_language_glossary.pod6-LTA"><a name="404"></a>LTA</h2> | |
<p>Less Than Awesome. Usually used in the context of an error message that is rather non-descriptive or unrelated to the actual error.</p> | |
<a name="t23.33.18"></a> <h2 id="_language_glossary.pod6-NST"><a name="405"></a>NST</h2> | |
<p>No Such Thing</p> | |
<a name="t23.33.19"></a> <h2 id="_language_glossary.pod6-Opt"><a name="406"></a>Opt</h2> | |
<p>Short for "optimization", usually in either the context of <a href="#22-Spesh">spesh</a> or JIT.</p> | |
<a name="t23.33.20"></a> <h2 id="_language_glossary.pod6-PB"><a name="407"></a>PB</h2> | |
<p>Short for "problem". As in "that's not the pb".</p> | |
<a name="t23.33.21"></a> <h2 id="_language_glossary.pod6-PR"><a name="408"></a>PR</h2> | |
<p>See <a href="#22-Pull Request">#Pull Request</a>.</p> | |
<a name="t23.33.22"></a> <h2 id="_language_glossary.pod6-P5"><a name="409"></a>P5</h2> | |
<p>Perl 5</p> | |
<a name="t23.33.23"></a> <h2 id="_language_glossary.pod6-P6"><a name="410"></a>P6</h2> | |
<p>Raku (née Perl 6)</p> | |
<a name="t23.33.24"></a> <h2 id="_language_glossary.pod6-RSN"><a name="411"></a>RSN</h2> | |
<p>Real Soon Now.</p> | |
<a name="t23.33.25"></a> <h2 id="_language_glossary.pod6-RT"><a name="412"></a>RT</h2> | |
<p>Request Tracker (<a href="#_routine_https:__rt.perl.org_.pod6">https://rt.perl.org/</a>). The place where all the bugs related to <a href="#22-Rakudo">#Rakudo</a> used to live. Nowadays, the Github issue tracker of the rakudo/rakudo repository is used for that.</p> | |
<a name="t23.33.26"></a> <h2 id="_language_glossary.pod6-TIMTOWTDI"><a name="413"></a>TIMTOWTDI</h2> | |
<p>An alternative form of <a href="#22-TMTOWTDI">#TMTOWTDI</a>, explicitly including the "is" from the contraction "There's".</p> | |
<a name="t23.33.27"></a> <h2 id="_language_glossary.pod6-TMI"><a name="414"></a>TMI</h2> | |
<p>Too Much Information.</p> | |
<a name="t23.33.28"></a> <h2 id="_language_glossary.pod6-TMTOWTDI"><a name="415"></a>TMTOWTDI</h2> | |
<p>"There's More Than One Way To Do It", the Perl motto.</p> | |
<a name="t23.33.29"></a> <h2 id="_language_glossary.pod6-UGT"><a name="416"></a>UGT</h2> | |
<p>"Universal Greeting Time" - i.e., it's always "morning".</p> | |
<a name="t23.33.30"></a> <h2 id="_language_glossary.pod6-WFM"><a name="417"></a>WFM</h2> | |
<p>Works For Me</p> | |
<a name="t23.33.31"></a> <h2 id="_language_glossary.pod6-WIP"><a name="418"></a>WIP</h2> | |
<p>Work In Progress</p> | |
<a name="t23.33.32"></a> <h2 id="_language_glossary.pod6-WP"><a name="419"></a>WP</h2> | |
<p>Wikipedia</p> | |
<a name="t23.33.33"></a> <h2 id="_language_glossary.pod6-WW"><a name="420"></a>WW</h2> | |
<p>Short for <span class="code">wrong window</span>. When on <a href="#22-IRC">#IRC</a>, someone types something in a channel that was intended for another channel, or for a private message.</p> | |
<a name="t23.34"></a> <h1 id="_language_glossary.pod6-Larry_Wall"><a name="421"></a>Larry Wall</h1> | |
<p><a href="#22-Perl">Perl's</a> benevolent dictator for life, among many other things. See also <a href="#_routine_https:__en.wikipedia.org_wiki_Larry_Wall.pod6">https://en.wikipedia.org/wiki/Larry_Wall</a>.</p> | |
<a name="t23.35"></a> <h1 id="_language_glossary.pod6-Lexing"><a name="422"></a>Lexing</h1> | |
<p>Performing <a href="#_routine_https:__en.wikipedia.org_wiki_Lexical_analysis.pod6">lexical analysis</a>, a step which usually precedes parsing.</p> | |
<a name="t23.36"></a> <h1 id="_language_glossary.pod6-Literal"><a name="423"></a>Literal</h1> | |
<p>A <i>literal</i> is a piece of code that directly stands for an (often built-in) object and also refers to the object itself.</p> | |
<pre class="code">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</pre> | |
<p>Different types of literals are described in <a href="#_language_syntax.pod6-Literals">the syntax document</a>.</p> | |
<a name="t23.37"></a> <h1 id="_language_glossary.pod6-LHS"><a name="424"></a>LHS</h1> | |
<p>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 <span class="code">$lhs = "this would be the right-hand side"</span>. 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.</p> | |
<a name="t23.38"></a> <h1 id="_language_glossary.pod6-lvalue"><a name="425"></a>lvalue</h1> | |
<p>An <i>lvalue</i>, or a <i>left value</i>, is anything that can appear on the left-hand side of the assignment operator <span class="code">=</span>. It is anything you can assign to.</p> | |
<p>Typical lvalues are variables, private and <span class="code">is rw</span> attributes, lists of variables and lvalue subroutines.</p> | |
<p>Examples of lvalues:</p> | |
<table> | |
<tr><th>Declaration</th> <th>lvalue</th> <th>Comments</th></tr> | |
<tr><td>my $x;</td> <td>$x</td> <td></td></tr> | |
<tr><td>my ($a, $b);</td> <td>($a, $b)</td> <td></td></tr> | |
<tr><td>has $!attribute;</td> <td>$!attribute</td> <td>Only inside classes</td></tr> | |
<tr><td>has $.attrib is rw;</td> <td>$.attrib</td> <td></td></tr> | |
<tr><td>sub a is rw { $x };</td> <td>a()</td> <td></td></tr> | |
</table> <p>Examples of things that are not lvalues:</p> | |
<table> | |
<tr><td>3</td> <td>literals</td></tr> | |
<tr><td>constant x = 3;</td> <td>constants</td></tr> | |
<tr><td>has $.attrib;</td> <td>attributes; you can only assign to $!attrib</td></tr> | |
<tr><td>sub f { }; f();</td> <td>"normal" subs are not writable</td></tr> | |
<tr><td>sub f($x) { $x = 3 };</td> <td>error - parameters are read-only by default</td></tr> | |
</table> <p>These are typically called <a href="#22-rvalue">rvalues</a>.</p> | |
<a name="t23.39"></a> <h1 id="_language_glossary.pod6-Mainline"><a name="426"></a>Mainline</h1> | |
<p>The <span class="code">mainline</span> is the program text that is not part of any kind of block.</p> | |
<pre class="code">use v6.c; # mainline | |
sub f { | |
# not in mainline, in sub f | |
} | |
f(); # in mainline again | |
</pre> | |
<p>You can also have the mainline of any package-like declarator, such as class, <a href="#_language_modules.pod6">module</a>, <a href="#_language_grammars.pod6">grammar</a>, etc. These are typically run just after the class/module/grammar have been compiled (or when loaded from a precompiled file).</p> | |
<a name="t23.40"></a> <h1 id="_language_glossary.pod6-Mayspec"><a name="427"></a>Mayspec</h1> | |
<p>Stands for "Maybe Specification". Usually refers to existing tests in the <a href="#_routine_https:__github.com_Raku_roast_.pod6">language specification</a>. 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.</p> | |
<a name="t23.41"></a> <h1 id="_language_glossary.pod6-MoarVM"><a name="428"></a>MoarVM</h1> | |
<p>MoarVM is short for Metamodel On A Runtime Virtual Machine. It's a virtual machine designed specifically for <a href="#22-NQP">#NQP</a> and its <a href="#_language_mop.pod6">MOP</a>: <a href="#22-6model">#6model</a>. A document about <a href="#_routine_https:__github.com_MoarVM_MoarVM_blob_master_docs_reveal.md.pod6">the purpose of MoarVM</a>. MoarVM has some similarities with the Hotspot VM so you may peruse its <a href="#_routine_http:__openjdk.java.net_groups_hotspot_docs_HotSpotGlossary.html.pod6">glossary</a> for entries missing from the present one.</p> | |
<a name="t23.42"></a> <h1 id="_language_glossary.pod6-Multi-dispatch"><a name="429"></a>Multi-dispatch</h1> | |
<p>The mechanism used to invoke different routines (<a href="#_type_Method.pod6">methods</a> or <a href="#_type_Sub.pod6">subs</a>) of the same name, selecting the correct one based on the <a href="#_type_Parameter.pod6">parameter</a> prototype and the arguments it was called with.</p> | |
<p>The selection process is primarily based on types and number of arguments (<a href="#22-Arity">arity</a>), where the narrowest, most specific candidate wins, typically without regard to the order of declaration. The <span class="code">is default</span> trait may be used as a tie breaker in this first phase. There is also a secondary phase where some different tie breakers may be evaluated in order of declaration of the methods or subs.</p> | |
<a name="t23.43"></a> <h1 id="_language_glossary.pod6-multi-method"><a name="430"></a>multi-method</h1> | |
<p>A <a href="#_type_Method.pod6">method</a> that has multiple candidates going by the same name and are subject to <a href="#22-Multi-dispatch">Multi-Dispatch</a>.</p> | |
<a name="t23.44"></a> <h1 id="_language_glossary.pod6-Née"><a name="431"></a>Née</h1> | |
<p>"Formerly known as".</p> | |
<a name="t23.45"></a> <h1 id="_language_glossary.pod6-NFG"><a name="432"></a>NFG</h1> | |
<p>Normal Form Grapheme is the way Raku implements graphemes, using a normal form in which strings with the same graphemes can be easily compared in constant time. More on that on <a href="#_routine_https:__6guts.wordpress.com_2015_04_12_this-week-unicode-normalization-many-rts_.pod6">this article in 6guts</a> and an explanation of how NFG works in <a href="#_routine_https:__colabti.org_irclogger_irclogger_log_perl6?date=2018-04-29.pod6-l465">this IRC log</a>.</p> | |
<a name="t23.46"></a> <h1 id="_language_glossary.pod6-Niecza"><a name="433"></a>Niecza</h1> | |
<p>An implementation of Raku targeting the .NET platform. No longer actively maintained.</p> | |
<a name="t23.47"></a> <h1 id="_language_glossary.pod6-Not_Quite_Perl"><a name="434"></a>Not Quite Perl</h1> | |
<p>See <a href="#22-NQP">#NQP</a>.</p> | |
<a name="t23.48"></a> <h1 id="_language_glossary.pod6-NQP"><a name="435"></a>NQP</h1> | |
<p>NQP is a primitive language for writing subroutines and methods using a subset of the Raku 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 <a href="#22-Rakudo">#Rakudo</a>) typically use NQP to compile action methods that convert a parse tree into its equivalent abstract syntax tree representation.</p> | |
<a name="t23.49"></a> <h1 id="_language_glossary.pod6-NYI"><a name="436"></a>NYI</h1> | |
<p>Not Yet Implemented</p> | |
<a name="t23.50"></a> <h1 id="_language_glossary.pod6-opcode"><a name="437"></a>opcode</h1> | |
<p>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 <a href="#_routine_https:__github.com_MoarVM_MoarVM_blob_master_docs_bytecode.markdown.pod6">this document for MoarVM</a>.</p> | |
<a name="t23.51"></a> <h1 id="_language_glossary.pod6-Operator"><a name="438"></a>Operator</h1> | |
<p>An expression is made of operators and operands. More precisely it is made of an operator and operands that can be subexpressions or <a href="#22-value">#value</a>s. Operators are an alternative syntax for a <a href="#22-multi-method">#multi-method</a>. With that syntax, what would be the arguments of the function are named operands instead. Operators are classified into <a href="#_routine_https:__design.raku.org_S02.html.pod6-Grammatical_Categories">categories</a> of categories. A category has a precedence, an arity, and can be <a href="#22-fiddly">#fiddly</a>, <a href="#22-iffy">#iffy</a>, <a href="#22-diffy">#diffy</a>. Raku 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, <span class="code">@a[0]</span> belongs to the postcircumfix category, is broken into the operand <span class="code">@a</span> and the postcircumfix operator <span class="code">[0]</span> where <span class="code">0</span> is the postcircumfixed subexpression.</p> | |
<p>The <span class="code"><O(I<...>)> </span> construction gives information about an operator that completes the information provided by its category. Below <span class="code">%conditional</span> is the category, <span class="code">:reducecheck<ternary> </span>, which specifies calling <span class="code">.ternary</span> to post-process the <a href="#22-Parse_tree">parse subtree</a> and <span class="code">:pasttype<if> </span> specifies the NQP <a href="#22-opcode">#opcode</a> generated in the AST from the parse subtree.</p> | |
<pre class="code"><O('%conditional, :reducecheck<ternary>, :pasttype<if>')></pre> | |
<a name="t23.52"></a> <h1 id="_language_glossary.pod6-Parse_tree"><a name="439"></a>Parse tree</h1> | |
<p>A <a href="#_routine_https:__en.wikipedia.org_wiki_Parse_tree.pod6">parse tree</a> represents the structure of a string or sentence according to a grammar. <a href="#_type_Grammar.pod6">Grammar</a>s in Raku output parse trees when they successfully match a string.</p> | |
<a name="t23.53"></a> <h1 id="_language_glossary.pod6-Parameter"><a name="440"></a>Parameter</h1> | |
<p><a href="#_type_Parameter.pod6">Parameter</a> is a class to define parameters to subroutines, method and a <a href="#_type_Callable.pod6">callable blocks</a>. As opposed to the arguments you specify when calling a subroutine/method/callable block.</p> | |
<pre class="code">sub foo($bar) { say $bar } # $bar is a parameter | |
foo(42); # 42 is an argument</pre> | |
<a name="t23.54"></a> <h1 id="_language_glossary.pod6-Parrot"><a name="441"></a>Parrot</h1> | |
<p>A <a href="#22-Virtual_machine">virtual machine</a> designed to run Raku and other dynamic languages. No longer actively maintained.</p> | |
<a name="t23.55"></a> <h1 id="_language_glossary.pod6-PAST"><a name="442"></a>PAST</h1> | |
<p><a href="#22-Parrot">#Parrot</a> AST.</p> | |
<a name="t23.56"></a> <h1 id="_language_glossary.pod6-Perl"><a name="443"></a>Perl</h1> | |
<p>The Perl programming language.</p> | |
<a name="t23.57"></a> <h1 id="_language_glossary.pod6-Perl 6"><a name="444"></a>Perl 6</h1> | |
<p>The name used for Raku before October 2019.</p> | |
<a name="t23.58"></a> <h1 id="_language_glossary.pod6-PERL"><a name="445"></a>PERL</h1> | |
<p>A way to describe <a href="#22-Perl">Perl</a> as a language, considered to be improper by many in the <a href="#_language_community.pod6">Perl Community</a>.</p> | |
<a name="t23.59"></a> <h1 id="_language_glossary.pod6-POD"><a name="446"></a>POD</h1> | |
<p><b>P</b>lain <b>O</b>l' <b>D</b>ocumentation, a documentation format understood by Raku. See <a href="#_language_pod.pod6">here</a> for further information.</p> | |
<a name="t23.60"></a> <h1 id="_language_glossary.pod6-POV"><a name="447"></a>POV</h1> | |
<p>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 Raku compiler.</p> | |
<a name="t23.61"></a> <h1 id="_language_glossary.pod6-Propspec"><a name="448"></a>Propspec</h1> | |
<p>Stands for "Proposed Specification". Usually refers to existing tests in the <a href="#_routine_https:__github.com_Raku_roast_.pod6">language specification</a> that are proposed for inclusion in the next release.</p> | |
<a name="t23.62"></a> <h1 id="_language_glossary.pod6-Pull_request"><a name="449"></a>Pull request</h1> | |
<p>A feature of <a href="#_routine_https:__github.com.pod6">GitHub</a> and other git hosts like <a href="#_routine_https:__gitlab.com.pod6">GitLab</a> 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 <a href="#22-Repository">repository</a> to hers. PR is its usual acronym.</p> | |
<a name="t23.63"></a> <h1 id="_language_glossary.pod6-property"><a name="450"></a>property</h1> | |
<p>In this context, it either refers to an <a href="#_language_objects.pod6-index-entry-Property">object property</a>, which is the value of an instance variable, or an <a href="#_language_regexes.pod6-Unicode_properties">Unicode property</a> 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.</p> | |
<a name="t23.64"></a> <h1 id="_language_glossary.pod6-pugs"><a name="451"></a>pugs</h1> | |
<p><a href="#_routine_https:__en.wikipedia.org_wiki_Pugs.pod6">pugs</a> was one of the first interpreters/compilers written for Raku. It was written in Haskell by Audrey Tang.</p> | |
<a name="t23.65"></a> <h1 id="_language_glossary.pod6-QAST"><a name="452"></a>QAST</h1> | |
<p>Successor to <a href="#22-PAST">#PAST</a> ('Q' being the next letter after 'P').</p> | |
<a name="t23.66"></a> <h1 id="_language_glossary.pod6-Rakudo"><a name="453"></a>Rakudo</h1> | |
<p>Rakudo is the name of a Raku implementation that runs on <a href="#22-MoarVM">#MoarVM</a> and the JVM. It is an abbreviation of <span class="code">Rakuda-do</span>, which, when translated from Japanese, means "The Way of the Camel". Also, in Japanese, "Rakudo" means "Paradise."</p> | |
<a name="t23.67"></a> <h1 id="_language_glossary.pod6-Reify"><a name="454"></a>Reify</h1> | |
<p>In the English language, <a href="#_routine_https:__www.dictionary.com_browse_reify.pod6">reify means</a> "to convert into or regard as a concrete thing." Its meaning in Raku is very similar, in that conceptual things, like "elements of an infinite list", get <i>reified</i> 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.</p> | |
<a name="t23.68"></a> <h1 id="_language_glossary.pod6-Repository"><a name="455"></a>Repository</h1> | |
<p>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 href="#_routine_https:__github.com_Raku_doc.pod6">a GitHub repository</a>. 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.</p> | |
<p>In Raku context, however, a repository is also a short name for <i>compilation unit repository</i> 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 <span class="code">Compunit::Repository::Installation</span>.</p> | |
<a name="t23.69"></a> <h1 id="_language_glossary.pod6-RHS"><a name="456"></a>RHS</h1> | |
<p>Acronym for Right-Hand Side, usually refers to the right-hand side of assignment expressions such as <span class="code">my $bound := $rhs</span>.</p> | |
<a name="t23.70"></a> <h1 id="_language_glossary.pod6-roast"><a name="457"></a>roast</h1> | |
<p>The Raku <a href="#22-test suite">specification tests</a>, which live here: <a href="#_routine_https:__github.com_Raku_roast_.pod6">https://github.com/Raku/roast/</a>. Originally developed for <a href="#22-pugs">#pugs</a>, it now serves all Raku implementations. Why roast? It's the <b>r</b>epository <b>o</b>f <b>a</b>ll <b>s</b>pec <b>t</b>ests.</p> | |
<a name="t23.71"></a> <h1 id="_language_glossary.pod6-Roles"><a name="458"></a>Roles</h1> | |
<p>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. <a href="#22-Abstract_class">Abstract classes</a> are particular examples of Roles where the actual implementation is deferred to the class that uses that Role.</p> | |
<p>Roles are part of Raku's <a href="#_language_objects.pod6">object system</a>, and are declared using the <a href="#_language_objects.pod6-index-entry-declarator_role-Roles">role</a> keyword and used in class declaration via <a href="#_routine_does.pod6">does</a>.</p> | |
<a name="t23.72"></a> <h1 id="_language_glossary.pod6-rvalue"><a name="459"></a>rvalue</h1> | |
<p>A value that can be used on the right-hand side of an assignment. See also <a href="#22-lvalue">#lvalue</a>.</p> | |
<a name="t23.73"></a> <h1 id="_language_glossary.pod6-SAP"><a name="460"></a>SAP</h1> | |
<p>Stands for "Specification APpendices". The <a href="#_routine_https:__github.com_Raku_roast_tree_master_APPENDICES.pod6">SAP</a> includes optional tests that implementations may choose to follow, but don't necessarily have to.</p> | |
<p>Can be used as a verb. To <i>SAP</i> something is to place it into Specification Appendices.</p> | |
<a name="t23.74"></a> <h1 id="_language_glossary.pod6-Semilist"><a name="461"></a>Semilist</h1> | |
<p>A semilist is a <i>semicolon-separated</i> list like this one: <span class="code">1;3;5</span>, and is actually a list of lists, with each component of the semilist being a slice of a particular dimension. <span class="code">@array[1;3;5]</span> would be equivalent to <span class="code">@array[1][3][5]</span>.</p> | |
<a name="t23.75"></a> <h1 id="_language_glossary.pod6-Sigil"><a name="462"></a>Sigil</h1> | |
<p>In Perl, the sigil is the first character of a variable name. It must be either $, @, %, or & respectively for a <a href="#_type_Scalar.pod6">scalar</a>, <a href="#_type_Array.pod6">array</a>, <a href="#_type_Hash.pod6">hash</a>, or <a href="#_type_Code.pod6">code</a> variable. See also Twigil and role. Also sigiled variables allow short conventions for <a href="#22-Variable_interpolation">variable interpolation</a> in a double quoted string, or even postcircumfix expressions starting with such a variable.</p> | |
<a name="t23.76"></a> <h1 id="_language_glossary.pod6-Sigilless_variable"><a name="463"></a>Sigilless variable</h1> | |
<p><a href="#_language_variables.pod6-index-entry-\_(sigilless_variables)">Sigilless variables</a> 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 <span class="code">\</span>), its value cannot be changed.</p> | |
<a name="t23.77"></a> <h1 id="_language_glossary.pod6-Spesh"><a name="464"></a>Spesh</h1> | |
<p>A functionality of the <a href="#22-MoarVM">#MoarVM</a> platform that uses runtime gathered data to improve commonly used pieces of <a href="#22-bytecode">#bytecode</a>. It is much like a JIT compiler, except that those usually output machine code rather than bytecode.</p> | |
<a name="t23.78"></a> <h1 id="_language_glossary.pod6-STD"><a name="465"></a>STD</h1> | |
<p><span class="code">STD.pm</span> is the "standard" Raku grammar definition (see <a href="#_routine_https:__github.com_perl6_std_.pod6">https://github.com/perl6/std/</a>) that was used to implement Raku. STD.pm is no longer really a "specification" in a proscriptive sense: it's more of a guideline or model for Raku implementations to follow.</p> | |
<a name="t23.79"></a> <h1 id="_language_glossary.pod6-Stub"><a name="466"></a>Stub</h1> | |
<p>Stubs define name and signature of methods whose implementation is deferred to other classes.</p> | |
<pre class="code">role Canine { | |
method bark { ... } # the ... indicates a stub | |
}</pre> | |
<p>Classes with stubs are <a href="#22-Abstract class">Abstract classes</a>.</p> | |
<a name="t23.80"></a> <h1 id="_language_glossary.pod6-Symbol"><a name="467"></a>Symbol</h1> | |
<p>Fancy alternative way to denote a name. Generally used in the context of <a href="#_language_modules.pod6">module</a>s linking, be it in the OS level, or at the Raku <a href="#22-Virtual_machine">#Virtual_machine</a> level for modules generated from languages targeting these VMs. The set of imported or exported symbols is called the symbol table.</p> | |
<a name="t23.81"></a> <h1 id="_language_glossary.pod6-Synopsis"><a name="468"></a>Synopsis</h1> | |
<p>The current human-readable description of the Raku language. Still in development. Much more a community effort than the <a href="#22-Apocalypse">Apocalypses</a> and <a href="#22-Exegesis">Exegeses</a> were. The current state of the language is reflected by <a href="#22-roast">#roast</a>, its <a href="#22-test suite">#test suite</a>, 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.</p> | |
<a name="t23.82"></a> <h1 id="_language_glossary.pod6-Syntax_analysis"><a name="469"></a>Syntax analysis</h1> | |
<p>A syntax or syntactic analysis is equivalent to <a href="#_routine_https:__en.wikipedia.org_wiki_Parsing.pod6">parsing</a> a string to generate its <a href="#22-Parse_tree">parse tree</a>.</p> | |
<a name="t23.83"></a> <h1 id="_language_glossary.pod6-Test_suite"><a name="470"></a>Test suite</h1> | |
<p>The Raku test suite is <a href="#22-roast">#roast</a>.</p> | |
<a name="t23.84"></a> <h1 id="_language_glossary.pod6-TheDamian"><a name="471"></a>TheDamian</h1> | |
<p><a href="#22-IRC">#IRC</a> screen name for <a href="#22-Damian Conway">#Damian Conway</a>, writer of the original <a href="#22-Exegesis">Exegeses</a>.</p> | |
<a name="t23.85"></a> <h1 id="_language_glossary.pod6-TimToady"><a name="472"></a>TimToady</h1> | |
<p><a href="#22-IRC">#IRC</a> screen name for <a href="#22-Larry Wall">#Larry Wall</a>, creator of Perl. The name comes from the pronunciation of <a href="#22-TIMTOWTDI">#TIMTOWTDI</a> as a word.</p> | |
<a name="t23.86"></a> <h1 id="_language_glossary.pod6-token"><a name="473"></a>token</h1> | |
<p>In this context, a <a href="#_syntax_token.pod6"><span class="code">token</span></a> is a regex that does not backtrack. In general, <a href="#_routine_https:__en.wikipedia.org_wiki_Lexical_analysis.pod6">tokens</a> are extracted from the source program while <a href="#22-Lexing">lexing</a>.</p> | |
<a name="t23.87"></a> <h1 id="_language_glossary.pod6-Thunk"><a name="474"></a>Thunk</h1> | |
<p>A piece of code that isn't immediately executed, but doesn't have an independent scope.</p> | |
<a name="t23.88"></a> <h1 id="_language_glossary.pod6-Tight_and_loose_precedence"><a name="475"></a>Tight and loose precedence</h1> | |
<p>In this context, tight or tighter refers to <a href="#_language_functions.pod6-index-entry-is_tighter">precedence rules</a> and is the opposite of <span class="code">looser</span>. Precedence rules for new terms are always expressed in relationship with other terms, so <span class="code">is tighter</span> implies that operands with that operator will be grouped before operands with the looser operator. Operators with <a href="#_language_operators.pod6-Tight_AND_precedence">tight precedence</a> are grouped with priority to others and are generally tighter than most others; loose <a href="#_language_traps.pod6-Loose_Boolean_operators">exactly the opposite</a>, so it is always convenient to be aware of the exact precedence of all operators used in an expression.</p> | |
<a name="t23.89"></a> <h1 id="_language_glossary.pod6-twine"><a name="476"></a>twine</h1> | |
<p>A data structure used to hold a POD string with embedded formatting codes. For example:</p> | |
<pre class="code">=begin pod | |
C<foo> | |
=end pod | |
say $=pod[0].contents[0].contents.raku; | |
</pre> | |
<p>The output will be:</p> | |
<pre class="code">["", Pod::FormattingCode.new(type => "C", meta => [], config => {}, contents => ["foo"]),""] | |
</pre> | |
<p><div class="marginale">The <span class="code">twine</span> is an array with an odd number of elements beginning with a simple string, alternating with formatting code objects and simple strings, and ending with a simple string; the formatting code objects are inter <span class="code">twine</span> d with the strings. The strings may be empty (as shown in the example). A twine with no formatting code will contain one simple string.</div></p> | |
<a name="t23.90"></a> <h1 id="_language_glossary.pod6-Type_objects"><a name="477"></a>Type objects</h1> | |
<p>A <a href="#_language_classtut.pod6-index-entry-type_object">type object</a> 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 <a href="#_type_Mu.pod6">Mu</a>.</p> | |
<a name="t23.91"></a> <h1 id="_language_glossary.pod6-Type_smiley"><a name="478"></a>Type smiley</h1> | |
<p>A <a href="#_type_Signature.pod6-Constraining_argument_definiteness">type smiley</a> is a suffix a type may have that indicates the definiteness of values that can typecheck against it. This may be <span class="code">:D</span> to indicate that only defined values can typecheck (i.e. instances), <span class="code">:U</span> to indicate that only undefined values can typecheck (i.e. type objects), or <span class="code">:_</span> to indicate that both defined and undefined values can typecheck. These resemble emoticons, thus the name.</p> | |
<a name="t23.92"></a> <h1 id="_language_glossary.pod6-value"><a name="479"></a>value</h1> | |
<p>A value is what is actually contained in a container such as a variable. Used in expressions such as <a href="#_language_glossary.pod6-lvalue">lvalue</a>, to indicate that that particular container can be assigned to.</p> | |
<a name="t23.93"></a> <h1 id="_language_glossary.pod6-UB"><a name="480"></a>UB</h1> | |
<p>Stands for "Undefined Behavior". In other words, it is something that is not explicitly specified by the language specification.</p> | |
<a name="t23.94"></a> <h1 id="_language_glossary.pod6-Value_type"><a name="481"></a>Value type</h1> | |
<p>A type is known as a <b>value type</b> 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 <i>called</i> a <b>value</b> (but should not be confused with <a href="#22-lvalue">#lvalue</a>s or <a href="#22-rvalue">#rvalue</a>s).</p> | |
<p>For example, numbers are value types, so a number constructed one place in your program with, for instance, the literal <span class="code">3</span> can't be changed in any way—it simply <i>is</i> 3—and any later use of the literal <span class="code">3</span> can safely be pointed at the same place in memory as the first with no ill consequences.</p> | |
<p>Classes doing the roles <a href="#_type_Numeric.pod6">Numeric</a> and <a href="#_type_Stringy.pod6">Stringy</a> are among a few examples of built-in value types.</p> | |
<p>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 <a href="#_routine_WHICH.pod6"><span class="code">WHICH</span></a> 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).</p> | |
<p>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 <a href="#_routine_clone.pod6"><span class="code">clone</span></a> to return an instance of <span class="code">self</span>, or you want instance construction to be <a href="#_routine_https:__en.wikipedia.org_wiki_Memoization.pod6">memoized</a> so that re-construction of a previously-constructed value always returns the same instance, you currently must override this behavior yourself.</p> | |
<p>(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.)</p> | |
<a name="t23.95"></a> <h1 id="_language_glossary.pod6-Variable"><a name="482"></a>Variable</h1> | |
<p>A variable is a name for a <a href="#_language_containers.pod6">container</a>.</p> | |
<a name="t23.96"></a> <h1 id="_language_glossary.pod6-Variable_interpolation"><a name="483"></a>Variable interpolation</h1> | |
<p>The value of variables is interpolated into strings by simply inserting that variable into the string:</p> | |
<pre class="code">my $polation="polation"; | |
say "inter$polation"; # OUTPUT: «interpolation»</pre> | |
<p>This might need curly braces in case it precedes some alphanumeric characters</p> | |
<pre class="code">my $inter="inter"; | |
say "{$inter}polation"; # OUTPUT: «interpolation»</pre> | |
<p>Interpolation occurs in <a href="#_language_contexts.pod6-String">string context</a>, so a valid stringification method must exist for the class. More general interpolation can be achieved using the <a href="#_language_quoting.pod6-Interpolation:_qq">double q</a> quoting constructs.</p> | |
<a name="t23.97"></a> <h1 id="_language_glossary.pod6-Virtual_machine"><a name="484"></a>Virtual machine</h1> | |
<p>A virtual machine is the Raku compiler entity that executes the <a href="#22-bytecode">bytecode</a>. It can optimize the bytecode or generate machine code Just in Time. Examples are <a href="#22-MoarVM">#MoarVM</a>, <a href="#22-Parrot">#Parrot</a> (who are intended to run Raku) and more generic virtual machines such as JVM and Javascript.</p> | |
<a name="t23.97.1"></a> <h2 id="_language_glossary.pod6-WAT"><a name="485"></a>WAT</h2> | |
<p>The opposite of a <a href="#22-DWIM">#DWIM</a>; counter-intuitive behavior. It is said that to every DWIM there is a corresponding WAT. See also <a href="#_routine_https:__www.destroyallsoftware.com_talks_wat.pod6">https://www.destroyallsoftware.com/talks/wat</a>.</p> | |
<a name="t23.98"></a> <h1 id="_language_glossary.pod6-whitespace"><a name="486"></a>whitespace</h1> | |
<p>A character or group of blank characters, used to separate words. An example is the space character « ».</p> | |
<a name="t23.99"></a> <h1 id="_language_glossary.pod6-6model"><a name="487"></a>6model</h1> | |
<p><span class="code">6model</span> is used in the <a href="#_language_glossary.pod6-MoarVM">MoarVM</a>, and provides primitives used to create an object system. It is described in <a href="#_routine_https:__jnthn.net_papers_2013-yapceu-moarvm.pdf.pod6">this presentation by Jonathan Worthington</a> and implemented <a href="#_routine_https:__github.com_MoarVM_MoarVM_tree_master_src_6model.pod6">here in MoarVM</a>.</p> | |
</div> | |
<!-- /language/grammar_tutorial.pod6 --><div class="pod-body"><a id="_language_grammar_tutorial.pod6"></a><a name="t24"></a><h1 class="title">24 Grammar tutorial</h1> <p class="subtitle">An introduction to grammars</p> <a name="t24.1"></a> <h1 id="_language_grammar_tutorial.pod6-Before_we_start">Before we start</h1> | |
<a name="t24.1.1"></a> <h2 id="_language_grammar_tutorial.pod6-Why_grammars?">Why grammars?</h2> | |
<p>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.</p> | |
<a name="t24.1.2"></a> <h2 id="_language_grammar_tutorial.pod6-When_would_I_use_grammars?">When would I use grammars?</h2> | |
<p>If you have strings to tame or interpret, grammars provide the tools to do the job.</p> | |
<p>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.</p> | |
<a name="t24.1.3"></a> <h2 id="_language_grammar_tutorial.pod6-The_broad_concept_of_grammars">The broad concept of grammars</h2> | |
<p>Regular expressions (<a href="#_language_regexes.pod6">Regexes</a>) 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.</p> | |
<p>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.</p> | |
<a name="t24.2"></a> <h1 id="_language_grammar_tutorial.pod6-Getting_more_technical">Getting more technical</h1> | |
<a name="t24.2.1"></a> <h2 id="_language_grammar_tutorial.pod6-The_conceptual_overview">The conceptual overview</h2> | |
<p>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 <i>grammar</i> keyword instead of <i>class</i>.</p> | |
<pre class="code">grammar G { ... } | |
</pre> | |
<p>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.</p> | |
<pre class="code">my $matchObject = G.parse($string); | |
</pre> | |
<p>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.</p> | |
<p>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 <span class="code">TOP</span> by default.</p> | |
<a name="t24.2.2"></a> <h2 id="_language_grammar_tutorial.pod6-The_technical_overview">The technical overview</h2> | |
<p>As already mentioned, grammars are declared using the <i>grammar</i> keyword and its "methods" are declared with <i>regex</i>, or <i>token</i>, or <i>rule</i>.</p> | |
<ul><li><p>Regex methods are slow but thorough, they will look back in the string and really try.</p> | |
</li></ul> <ul><li><p>Token methods are faster than regex methods and ignore whitespace. Token methods don't backtrack; they give up after the first possible match.</p> | |
</li></ul> <ul><li><p>Rule methods are the same as token methods except whitespace is not ignored.</p> | |
</li></ul> <p>When a method (regex, token or rule) matches in the grammar, the string matched is put into a <a href="#_type_Match.pod6">match object</a> and keyed with the same name as the method.</p> | |
<pre class="code">grammar G { | |
token TOP { <thingy> .* } | |
token thingy { 'clever_text_keyword' } | |
} | |
</pre> | |
<p>If you were to use <span class="code">my $match = G.parse($string)</span> 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 <span class="code"><thingy></span> in your match object. For instance:</p> | |
<pre class="code">grammar G { | |
token TOP { <thingy> .* } | |
token thingy { 'Þor' } | |
} | |
my $match = G.parse("Þor is mighty"); | |
say $match.raku; # OUTPUT: «Match.new(made => Any, pos => 13, orig => "Þor is mighty",...» | |
say $/.raku; # OUTPUT: «Match.new(made => Any, pos => 13, orig => "Þor is mighty",...» | |
say $/<thingy>.raku; | |
# OUTPUT: «Match.new(made => Any, pos => 3, orig => "Þor is mighty", hash => Map.new(()), list => (), from => 0)» | |
</pre> | |
<p>The two first output lines show that <span class="code">$match</span> contains a <span class="code">Match</span> objects with the results of the parsing; but those results are also assigned to the <a href="#_syntax_$$SOLIDUS.pod6">match variable <span class="code">$/</span></a>. Either match object can be keyed, as indicated above, by <span class="code">thingy</span> to return the match for that particular <span class="code">token</span>.</p> | |
<p>The <span class="code">TOP</span> 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 (<span class="code">Nil</span>).</p> | |
<p>As you can see above, in <span class="code">TOP</span>, the <span class="code"><thingy></span> token is mentioned. The <span class="code"><thingy></span> is defined on the next line. That means that <span class="code">'clever_text_keyword'</span> <b>must</b> 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.</p> | |
<a name="t24.3"></a> <h1 id="_language_grammar_tutorial.pod6-Learning_by_example_-_a_REST_contrivance">Learning by example - a REST contrivance</h1> | |
<p>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:</p> | |
<ul><li><p>The first part of the URI will be the "subject", like a part, or a product, or a person.</p> | |
</li></ul> <ul><li><p>The second part of the URI will be the "command", the standard CRUD functions (create, retrieve, update, or delete).</p> | |
</li></ul> <ul><li><p>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.</p> | |
</li></ul> <ul><li><p>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).</p> | |
</li></ul> <p>So, if we have "/product/update/7/notify", we would want our grammar to give us a match object that has a <span class="code">subject</span> of "product", a <span class="code">command</span> of "update", and <span class="code">data</span> of "7/notify".</p> | |
<p>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.</p> | |
<pre class="code">grammar REST { | |
token subject { \w+ } | |
token command { \w+ } | |
token data { .* } | |
} | |
</pre> | |
<p>So far, this REST grammar says we want a subject that will be just <i>word</i> characters, a command that will be just <i>word</i> characters, and data that will be everything else left in the string.</p> | |
<p>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.</p> | |
<pre class="code">grammar REST { | |
token TOP { '/' <subject> '/' <command> '/' <data> } | |
token subject { \w+ } | |
token command { \w+ } | |
token data { .* } | |
} | |
</pre> | |
<p>With this code, we can already get the three parts of our RESTful request:</p> | |
<pre class="code">my $match = REST.parse('/product/update/7/notify'); | |
say $match; | |
# OUTPUT: «「/product/update/7/notify」 | |
# subject => 「product」 | |
# command => 「update」 | |
# data => 「7/notify」» | |
</pre> | |
<p>The data can be accessed directly by using <span class="code">$match<subject></span> or <span class="code">$match<command></span> or <span class="code">$match<data></span> to return the values parsed. They each contain match objects that you can work further with, such as coercing into a string ( <span class="code">$match<command>.Str</span> ).</p> | |
<a name="t24.3.1"></a> <h2 id="_language_grammar_tutorial.pod6-Adding_some_flexibility">Adding some flexibility</h2> | |
<p>So far, the grammar will handle retrieves, deletes and updates. However, a <i>create</i> command doesn't have the third part (the <i>data</i> 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 <i>data</i> position match optional, along with the '/' preceding it. This is accomplished by adding a question mark to the grouped '/' and <i>data</i> components of the TOP token, to indicate their optional nature, just like a normal regex.</p> | |
<p>So, now we have:</p> | |
<pre class="code">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」» | |
</pre> | |
<p>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.</p> | |
<pre class="code">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」» | |
</pre> | |
<p>We're getting some extra junk in the match object now, with those slashes. There are techniques to clean that up that we'll get to later.</p> | |
<a name="t24.3.2"></a> <h2 id="_language_grammar_tutorial.pod6-Inheriting_from_a_grammar">Inheriting from a grammar</h2> | |
<p>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:</p> | |
<pre class="code">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 => 「|」 | |
</pre> | |
<p>This example uses multiple inheritance to compose two different grammars by varying the rules that correspond to <span class="code">quotes</span>. In this case, besides, we are rather using composition than inheritance, so we could use Roles instead of inheritance.</p> | |
<pre class="code">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>? } | |
} | |
</pre> | |
<p>Will output exactly the same as the code above. Symptomatic of the difference between Classes and Roles, a conflict like defining <span class="code">token quote</span> twice using Role composition will result in an error:</p> | |
<pre class="code">grammar Quoted-Quotes does Letters does Quote-Quotes does Quote-Other { ... } | |
# OUTPUT: ... Error while compiling ... Method 'quote' must be resolved ... | |
</pre> | |
<a name="t24.3.3"></a> <h2 id="_language_grammar_tutorial.pod6-Adding_some_constraints">Adding some constraints</h2> | |
<p>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.</p> | |
<p>There are several ways to accomplish this. For example, you could change the command method:</p> | |
<pre class="code">token command { \w+ } | |
# …becomes… | |
token command { 'create'|'retrieve'|'update'|'delete' } | |
</pre> | |
<p>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.</p> | |
<p>There's another technique that provides greater flexibility and improved readability when options grow large: <i>proto-regexes</i>.</p> | |
<p>To utilize these proto-regexes (multimethods, in fact) to limit ourselves to the valid CRUD options, we'll replace <span class="code">token command</span> with the following:</p> | |
<pre class="code">proto token command {*} | |
token command:sym<create> { <sym> } | |
token command:sym<retrieve> { <sym> } | |
token command:sym<update> { <sym> } | |
token command:sym<delete> { <sym> } | |
</pre> | |
<p>The <span class="code">sym</span> keyword is used to create the various proto-regex options. Each option is named (e.g., <span class="code">sym<update></span>), and for that option's use, a special <span class="code"><sym></span> token is auto-generated with the same name.</p> | |
<p>The <span class="code"><sym></span> token, as well as other user-defined tokens, may be used in the proto-regex option block to define the specific <i>match condition</i>. Regex tokens are compiled forms and, once defined, cannot subsequently be modified by adverb actions (e.g., <span class="code">:i</span>). Therefore, as it's auto-generated, the special <span class="code"><sym></span> token is useful only where an exact match of the option name is required.</p> | |
<p>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 <span class="code"><sym></span> 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.</p> | |
<p>Using proto-regex like this gives us a lot of flexibility. For example, instead of returning <span class="code"><sym></span>, 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 <span class="code">token subject</span> method and limit it also to only parsing correctly on valid subjects (like 'part' or 'people', etc.).</p> | |
<a name="t24.3.4"></a> <h2 id="_language_grammar_tutorial.pod6-Putting_our_RESTful_grammar_together">Putting our RESTful grammar together</h2> | |
<p>This is what we have for processing our RESTful URIs, so far:</p> | |
<pre class="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* } | |
} | |
</pre> | |
<p>Let's look at various URIs and see how they work with our grammar.</p> | |
<pre class="code">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» | |
</pre> | |
<p>Note that since <span class="code"><data></span> matches nothing on the second string, <span class="code">$m<data></span> will be <span class="code">Nil</span>, then using it in string context in the <span class="code">say</span> function warns.</p> | |
<p>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.</p> | |
<p>The <i>data</i> 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: <i>actions</i>.</p> | |
<a name="t24.4"></a> <h1 id="_language_grammar_tutorial.pod6-Grammar_actions">Grammar actions</h1> | |
<p>Grammar actions are used within grammar classes to do things with matches. Actions are defined in their own classes, distinct from grammar classes.</p> | |
<p>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.</p> | |
<p>To work with actions, you use a named parameter called <span class="code">actions</span> 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:</p> | |
<pre class="code">my $matchObject = REST.parse($uri, actions => REST-actions.new); | |
# …or if you prefer… | |
my $matchObject = REST.parse($uri, :actions(REST-actions.new)); | |
</pre> | |
<p>If you <i>name your action methods with the same name as your grammar methods</i> (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 <span class="code">$/</span> variable).</p> | |
<p>Let's turn to an example.</p> | |
<a name="t24.4.1"></a> <h2 id="_language_grammar_tutorial.pod6-Grammars_by_example_with_actions">Grammars by example with actions</h2> | |
<p>Here we are back to our grammar.</p> | |
<pre class="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* } | |
} | |
</pre> | |
<p>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 <span class="code">data</span> so our method is also named <span class="code">data</span>.</p> | |
<pre class="code">class REST-actions | |
{ | |
method data($/) { $/.split('/') } | |
} | |
</pre> | |
<p>Now when we pass the URI string through the grammar, the <i>data token match</i> will be passed to the <i>REST-actions' data method</i>. 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").</p> | |
<p>But not really; there's a little more.</p> | |
<a name="t24.4.2"></a> <h2 id="_language_grammar_tutorial.pod6-Keeping_grammars_with_actions_tidy_with_make_and_made">Keeping grammars with actions tidy with <span class="code">make</span> and <span class="code">made</span></h2> | |
<p>If the grammar calls the action above on data, the data method will be called, but nothing will show up in the big <span class="code">TOP</span> grammar match result returned to our program. In order to make the action results show up, we need to call <a href="#_routine_make.pod6">make</a> on that result. The result can be many things, including strings, array or hash structures.</p> | |
<p>You can imagine that the <span class="code">make</span> places the result in a special contained area for a grammar. Everything that we <span class="code">make</span> can be accessed later by <a href="#_routine_made.pod6">made</a>.</p> | |
<p>So instead of the REST-actions class above, we should write:</p> | |
<pre class="code">class REST-actions | |
{ | |
method data($/) { make $/.split('/') } | |
} | |
</pre> | |
<p>When we add <span class="code">make</span> 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 <span class="code">data</span> token of the original grammar. This way, we can work with both if we need to.</p> | |
<p>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 <span class="code">data</span> action that we <span class="code">made</span>:</p> | |
<pre class="code">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» | |
</pre> | |
<p>Here we call <span class="code">made</span> on data, because we want the result of the action that we <span class="code">made</span> (with <span class="code">make</span>) to get the split array. That's lovely! But, wouldn't it be lovelier if we could <span class="code">make</span> a friendlier data structure that contained all of the stuff we want, rather than having to coerce types and remember arrays?</p> | |
<p>Just like Grammar's <span class="code">TOP</span>, which matches the entire string, actions have a TOP method as well. We can <span class="code">make</span> all of the individual match components, like <span class="code">data</span> or <span class="code">subject</span> or <span class="code">command</span>, and then we can place them in a data structure that we will <span class="code">make</span> in TOP. When we return the final match object, we can then access this data structure.</p> | |
<p>To do this, we add the method <span class="code">TOP</span> to the action class and <span class="code">make</span> whatever data structure we like from the component pieces.</p> | |
<p>So, our action class becomes:</p> | |
<pre class="code">class REST-actions | |
{ | |
method TOP ($/) { | |
make { subject => $<subject>.Str, | |
command => $<command>.Str, | |
data => $<data>.made } | |
} | |
method data($/) { make $/.split('/') } | |
} | |
</pre> | |
<p>Here in the <span class="code">TOP</span> method, the <span class="code">subject</span> remains the same as the subject we matched in the grammar. Also, <span class="code">command</span> returns the valid <span class="code"><sym></span> that was matched (create, update, retrieve, or delete). We coerce each into <span class="code">.Str</span>, as well, since we don't need the full match object.</p> | |
<p>We want to make sure to use the <span class="code">made</span> method on the <span class="code">$<data></span> object, since we want to access the split one that we <span class="code">made</span> with <span class="code">make</span> in our action, rather than the proper <span class="code">$<data></span> object.</p> | |
<p>After we <span class="code">make</span> something in the <span class="code">TOP</span> method of a grammar action, we can then access all the custom values by calling the <span class="code">made</span> method on the grammar result object. The code now becomes</p> | |
<pre class="code">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» | |
</pre> | |
<p>If the complete return match object is not needed, you could return only the made data from your action's <span class="code">TOP</span>.</p> | |
<pre class="code">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» | |
</pre> | |
<p>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 <span class="code">TOP</span>... how about we call it <span class="code">subject-id</span> and have it set to element 0 of <span class="code"><data></span>.</p> | |
<pre class="code">class REST-actions | |
{ | |
method TOP ($/) { | |
make { subject => $<subject>.Str, | |
command => $<command>.Str, | |
data => $<data>.made, | |
subject-id => $<data>.made[0] } | |
} | |
method data($/) { make $/.split('/') } | |
} | |
</pre> | |
<p>Now we can do this instead:</p> | |
<pre class="code">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» | |
</pre> | |
<p>Here's the final code:</p> | |
<pre class="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('/') } | |
} | |
</pre> | |
<a name="t24.4.3"></a> <h2 id="_language_grammar_tutorial.pod6-Add_actions_directly">Add actions directly</h2> | |
<p>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:</p> | |
<pre class="code">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» | |
</pre> | |
<p>This example is a reduced portion of a parser. Let's focus more on the feature it shows.</p> | |
<p>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 <span class="code">make</span> really does, which is no more than a sugar of <span class="code">$/.made = ...</span>. And this trick introduces a way to pass messages from within a regex item.</p> | |
<p>Hopefully this has helped introduce you to the grammars in Raku and shown you how grammars and grammar action classes work together. For more information, check out the more advanced <a href="#_language_grammars.pod6">Raku Grammar Guide</a>.</p> | |
<p>For more grammar debugging, see <a href="#_routine_https:__github.com_jnthn_grammar-debugger.pod6">Grammar::Debugger</a>. This provides breakpoints and color-coded MATCH and FAIL output for each of your grammar tokens.</p> | |
</div> | |
<!-- /language/grammars.pod6 --><div class="pod-body"><a id="_language_grammars.pod6"></a><a name="t25"></a><h1 class="title">25 Grammars</h1> <p class="subtitle">Parsing and interpreting text</p> <p>Grammar is a powerful tool used to destructure text and often to return data structures that have been created by interpreting that text.</p> | |
<p>For example, Raku is parsed and executed using a Raku-style grammar.</p> | |
<p>An example that's more practical to the common Raku user is the <a href="#_routine_https:__github.com_moritz_json.pod6">JSON::Tiny module</a>, which can deserialize any valid JSON file; however, the deserializing code is written in less than 100 lines of simple, extensible code.</p> | |
<p>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.</p> | |
<a name="t25.1"></a> <h1 id="_language_grammars.pod6-Named_Regexes"><a name="488"></a>Named Regexes</h1> | |
<p>The main ingredient of grammars is named <a href="#_language_regexes.pod6">regexes</a>. While the syntax of <a href="#_language_regexes.pod6">Raku Regexes</a> is outside the scope of this document, <i>named</i> regexes have a special syntax, similar to subroutine definitions: <div class="marginale">In fact, named regexes can even take extra arguments, using the same syntax as subroutine parameter lists</div></p> | |
<pre class="code">my regex number { \d+ [ \. \d+ ]? } | |
</pre> | |
<p>In this case, we have to specify that the regex is lexically scoped using the <span class="code">my</span> keyword, because named regexes are normally used within grammars.</p> | |
<p>Being named gives us the advantage of being able to easily reuse the regex elsewhere:</p> | |
<pre class="code">say so "32.51" ~~ &number; # OUTPUT: «True» | |
say so "15 + 4.5" ~~ /<number>\s* '+' \s*<number>/ # OUTPUT: «True» | |
</pre> | |
<p><b><span class="code">regex</span></b> isn't the only declarator for named regexes. In fact, it's the least common. Most of the time, the <b><span class="code">token</span></b> or <b><span class="code">rule</span></b> declarators are used. These are both <i>ratcheting</i>, 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:</p> | |
<pre class="code">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 is taken by the .+ | |
</pre> | |
<p>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 <span class="code">|</span> or <span class="code">||</span>, you will retry to match again.</p> | |
<pre class="code">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» | |
</pre> | |
<a name="t25.1.1"></a> <h2 id="_language_grammars.pod6-Rules"><a name="489"></a>Rules</h2> | |
<p>The only difference between the <span class="code">token</span> and <span class="code">rule</span> declarators is that the <span class="code">rule</span> declarator causes <a href="#_language_regexes.pod6-Sigspace"><span class="code">:sigspace</span></a> to go into effect for the Regex:</p> | |
<pre class="code">my token token-match { 'once' 'upon' 'a' 'time' } | |
my rule rule-match { 'once' 'upon' 'a' 'time' } | |
say so 'onceuponatime' ~~ &token-match; # OUTPUT: «True» | |
say so 'once upon a time' ~~ &token-match; # OUTPUT: «False» | |
say so 'onceuponatime' ~~ &rule-match; # OUTPUT: «False» | |
say so 'once upon a time' ~~ &rule-match; # OUTPUT: «True» | |
</pre> | |
<a name="t25.2"></a> <h1 id="_language_grammars.pod6-Creating_grammars"><a name="490"></a>Creating grammars</h1> | |
<p><a href="#_type_Grammar.pod6">Grammar</a> is the superclass that classes automatically get when they are declared with the <span class="code">grammar</span> keyword instead of <span class="code">class</span>. Grammars should only be used to parse text; if you wish to extract complex data, you can add actions within the grammar or use an <a href="#_language_grammars.pod6-Action_objects">action object</a> in conjunction with the grammar.</p> | |
<a name="t25.2.1"></a> <h2 id="_language_grammars.pod6-Proto_regexes"><a name="491"></a>Proto regexes</h2> | |
<p><a href="#_type_Grammar.pod6">Grammar</a>s are composed of rules, tokens and regexes; these are actually methods, since grammars are classes.</p> | |
<p><div class="marginale">They are actually a special kind of class, but for the rest of the section, they behave in the same way as a <i>normal</i> class would</div></p> | |
<p>These methods can share a name and functionality in common, and thus can use <a href="#_syntax_proto.pod6">proto</a>.</p> | |
<p>For instance, if you have a lot of alternations, it may become difficult to produce readable code or subclass your grammar. In the <span class="code">Actions</span> class below, the ternary in <span class="code">method TOP</span> is less than ideal and it becomes even worse the more operations we add:</p> | |
<pre class="code">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»</pre> | |
<p>To make things better, we can use proto regexes that look like <span class="code">:sym<...></span> adverbs on tokens:</p> | |
<pre class="code">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»</pre> | |
<p>In this grammar the alternation has now been replaced with <span class="code"><calc-op></span>, which is essentially the name of a group of values we'll create. We do so by defining a rule prototype with <span class="code">proto rule calc-op</span>. Each of our previous alternations have been replaced by a new <span class="code">rule calc-op</span> definition and the name of the alternation is attached with <span class="code">:sym<></span> adverb.</p> | |
<p>In the class that declares actions, we now got rid of the ternary operator and simply take the <span class="code">.made</span> value from the <span class="code">$<calc-op></span> match object. And the actions for individual alternations now follow the same naming pattern as in the grammar: <span class="code">method calc-op:sym<add></span> and <span class="code">method calc-op:sym<sub></span>.</p> | |
<p>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:</p> | |
<pre class="code">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» | |
</pre> | |
<p>All we had to add are an additional rule and action to the <span class="code">calc-op</span> group and the thing works—all thanks to proto regexes.</p> | |
<a name="t25.2.2"></a> <h2 id="_language_grammars.pod6-Special_tokens">Special tokens</h2> | |
<a name="t25.2.2.1"></a> <h3 id="_language_grammars.pod6-TOP"><a name="492"></a><span class="code">TOP</span></h3> | |
<pre class="code">grammar Foo { | |
token TOP { \d+ } | |
}</pre> | |
<p>The <span class="code">TOP</span> token is the default first token attempted to match when parsing with a grammar. Note that if you're parsing with the <a href="#_type_Grammar.pod6-method_parse"><span class="code">.parse</span></a> method, <span class="code">token TOP</span> is automatically anchored to the start and end of the string. If you don't want to parse the whole string, look up <a href="#_type_Grammar.pod6-method_subparse"><span class="code">.subparse</span></a>.</p> | |
<p>Using <span class="code">rule TOP</span> or <span class="code">regex TOP</span> is also acceptable.</p> | |
<p>A different token can be chosen to be matched first using the <span class="code">:rule</span> named argument to <span class="code">.parse</span>, <span class="code">.subparse</span>, or <span class="code">.parsefile</span>. These are all <span class="code">Grammar</span> methods.</p> | |
<a name="t25.2.2.2"></a> <h3 id="_language_grammars.pod6-ws"><a name="493"></a><span class="code">ws</span></h3> | |
<p>The default <span class="code">ws</span> matches zero or more whitespace characters, as long as that point is not within a word (in code form, that's <span class="code">regex ws { <!ww> \s* }</span>):</p> | |
<pre class="code"># 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」»</pre> | |
<p>Please bear in mind that we're preceding <span class="code">ws</span> 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.</p> | |
<p>When <span class="code">rule</span> is used instead of <span class="code">token</span>, <span class="code">:sigspace</span> is enabled by default and any whitespace after terms and closing parenthesis/brackets are turned into a non-capturing call to <span class="code">ws</span>, written as <span class="code"><.ws></span> where <span class="code">.</span> means non-capturing. That is to say:</p> | |
<pre class="code">rule entry { <key> '=' <value> }</pre> | |
<p>Is the same as:</p> | |
<pre class="code">token entry { <key> <.ws> '=' <.ws> <value> <.ws> }</pre> | |
<p>You can also redefine the default <span class="code">ws</span> token:</p> | |
<pre class="code">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</pre> | |
<p>And even capture it, but you need to use it explicitly. Notice that in the next example we use <span class="code">token</span> instead of <span class="code">rule</span>, as the latter would cause whitespace to be consumed by the implicit non-capturing <span class="code">.ws</span>.</p> | |
<pre class="code">grammar Foo { token TOP {\d <ws> \d} }; | |
my $parsed = Foo.parse: "3 3"; | |
say $parsed<ws>; # OUTPUT: «「 」» | |
</pre> | |
<a name="t25.2.2.3"></a> <h3 id="_language_grammars.pod6-sym"><a name="494"></a><span class="code">sym</span></h3> | |
<p>The <span class="code"><sym></span> token can be used inside proto regexes to match the string value of the <span class="code">:sym</span> adverb for that particular regex:</p> | |
<pre class="code">grammar Foo { | |
token TOP { <letter>+ } | |
proto token letter {*} | |
token letter:sym<R> { <sym> } | |
token letter:sym<a> { <sym> } | |
token letter:sym<k> { <sym> } | |
token letter:sym<u> { <sym> } | |
token letter:sym<*> { . } | |
}.parse("I ♥ Raku", actions => class { | |
method TOP($/) { make $<letter>.grep(*.<sym>).join } | |
}).made.say; # OUTPUT: «Raku»</pre> | |
<p>This comes in handy when you're already differentiating the proto regexes with the strings you're going to match, as using <span class="code"><sym></span> token prevents repetition of those strings.</p> | |
<a name="t25.2.2.4"></a> <h3 id="_language_grammars.pod6-"Always_succeed"_assertion"><a name="495"></a>"Always succeed" assertion</h3> | |
<p>The <span class="code"><?></span> is the <i>always succeed</i> 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 <span class="code">succ</span> token with the always succeed assertion.</p> | |
<p>In the action class, we use calls to the <span class="code">succ</span> method to do set up (in this case, we prepare a new element in <span class="code">@!numbers</span>). In the <span class="code">digit</span> method, we use the Arabic digit as an index into a list of Devanagari digits and add it to the last element of <span class="code">@!numbers</span>. Thanks to <span class="code">succ</span>, the last element will always be the number for the currently parsed <span class="code">digit</span> digits.</p> | |
<pre class="code">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: «(२५५ ४३५ ७७७)»</pre> | |
<a name="t25.2.3"></a> <h2 id="_language_grammars.pod6-Methods_in_grammars">Methods in grammars</h2> | |
<p>It's fine to use methods instead of rules or tokens in a grammar, as long as they return a <a href="#_type_Match.pod6">Match</a>:</p> | |
<pre class="code">grammar DigitMatcher { | |
method TOP (:$full-unicode) { | |
$full-unicode ?? self.num-full !! self.num-basic; | |
} | |
token num-full { \d+ } | |
token num-basic { <[0..9]>+ } | |
}</pre> | |
<p>The grammar above will attempt different matches depending on the argument provided to the subparse methods:</p> | |
<pre class="code">say +DigitMatcher.subparse: '12७१७९०९', args => \(:full-unicode); | |
# OUTPUT: «12717909» | |
say +DigitMatcher.subparse: '12७१७९०९', args => \(:!full-unicode); | |
# OUTPUT: «12» | |
</pre> | |
<a name="t25.2.4"></a> <h2 id="_language_grammars.pod6-Dynamic_variables_in_grammars">Dynamic variables in grammars</h2> | |
<p>Variables can be defined in tokens by prefixing the lines of code defining them with <span class="code">:</span>. 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 <span class="code">$*</span>, <span class="code">@*</span>, <span class="code">&*</span>, <span class="code">%*</span> twigils) in tokens cascades down through <i>all</i> tokens defined thereafter within the one where it's defined, avoiding having to pass them from token to token as arguments.</p> | |
<p>One use for dynamic variables is guards for matches. This example uses guards to explain which regex classes parse whitespace literally:</p> | |
<pre class="code">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" | |
} | |
}</pre> | |
<p>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:</p> | |
<pre class="code">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> | |
</pre> | |
<a name="t25.2.5"></a> <h2 id="_language_grammars.pod6-Attributes_in_grammars">Attributes in grammars</h2> | |
<p>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 <a href="#_type_Match.pod6">Match</a>, not of the grammar itself. Note that mutating an attribute from within a method called in a token will <i>only modify the attribute for that token's own match object</i>! Grammar attributes can be accessed in the match returned after parsing if made public:</p> | |
<pre class="code">grammar HTTPRequest { | |
has Bool $.invalid; | |
token TOP { | |
<type> <.ns> <path> <.ns> 'HTTP/1.1' <.crlf> | |
[ <field> <.crlf> ]+ | |
<.crlf> | |
$<body>=.* | |
} | |
token type { | |
| [ GET | POST | OPTIONS | HEAD | PUT | DELETE | TRACE | CONNECT ] <.accept> | |
| <-[\/]>+ <.error> | |
} | |
token path { | |
| '/' [[\w+]+ % \/] [\.\w+]? <.accept> | |
| '*' <.accept> | |
| \S+ <.error> | |
} | |
token field { | |
| $<name>=\w+ <.ns> ':' <.ns> $<value>=<-crlf>* <.accept> | |
| <-crlf>+ <.error> | |
} | |
method error(--> ::?CLASS:D) { | |
$!invalid = True; | |
self; | |
} | |
method accept(--> ::?CLASS:D) { | |
$!invalid = False; | |
self; | |
} | |
token crlf { # network new line (usually seen as "\r\n") | |
# Several internet protocols (such as HTTP, RF 2616) mandate | |
# the use of ASCII CR+LF (0x0D 0x0A) to terminate lines at | |
# the protocol level (even though, in practice, some applications | |
# tolerate a single LF). | |
# Raku, Raku grammars and strings (Str) adhere to Unicode | |
# conformance. Thus, CR+LF cannot be expressed unambiguously | |
# as \r\n in in Raku grammars or strings (Str), as Unicode | |
# conformance requires \r\n to be interpreted as \n alone. | |
\x[0d] \x[0a] | |
} | |
token ns { # network space | |
# <ws> would consume, e.g., newlines, and \h (and \s) would accept | |
# more codepoints than just ASCII single space and the tab character. | |
[ ' ' | <[\t]> ]* | |
} | |
} | |
my $crlf = "\x[0d]\x[0a]"; | |
my $header = "GOT /index.html HTTP/1.1{$crlf}Host: docs.raku.org{$crlf}{$crlf}body"; | |
my $m = HTTPRequest.parse($header); | |
say "type(\"$m.<type>\")={$m.<type>.invalid}"; | |
# OUTPUT: type("GOT ")=True | |
say "path(\"$m.<path>\")={$m.<path>.invalid}"; | |
# OUTPUT: path("/index.html")=False | |
say "field(\"$m.<field>[0]\")={$m.<field>[0].invalid}"; | |
# OUTPUT: field("Host: docs.raku.org")=False | |
</pre> | |
<p>Notes: <span class="code">$crlf</span> and token <span class="code"><.crlf></span> are required if we want to somehow (within the context of this incomplete example) strictly adhere to HTTP/1.1 (RFC 2616). The reason is that Raku, in contrast to RFC 2616, is Unicode conformant, and \r\n needs to be interpreted as a sole \n, thus preventing the grammar to properly parse a string containing \r\n in the sense expected by the HTTP protocol. Notice how attribute <span class="code">invalid</span> is local to each component (e.g., the value for <span class="code"><type></span> is <span class="code">True</span>, but for <span class="code"><path></span> is <span class="code">False</span>). Notice also how we have a method for <span class="code">accept</span>, the reason being that attribute <span class="code">invalid</span> would be uninitialized (even if present) otherwise.</p> | |
<a name="t25.2.6"></a> <h2 id="_language_grammars.pod6-Passing_arguments_into_grammars">Passing arguments into grammars</h2> | |
<p>To pass arguments into a grammar, you can use the named argument of <span class="code">:args</span> on any of the parsing methods of grammar. The arguments passed should be in a <span class="code">list</span>.</p> | |
<pre class="code">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」» | |
</pre> | |
<p>Once the arguments are passed in, they can be used in a call to a named regex inside the grammar.</p> | |
<pre class="code">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」» | |
</pre> | |
<p>Alternatively, you can initialize dynamic variables and use any arguments that way within the grammar.</p> | |
<pre class="code">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」» | |
</pre> | |
<a name="t25.3"></a> <h1 id="_language_grammars.pod6-Action_objects"><a name="496"></a>Action objects</h1> | |
<p>A successful grammar match gives you a parse tree of <a href="#_type_Match.pod6">Match</a> 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.</p> | |
<p>To avoid the need for diving deep into a match tree, you can supply an <i>actions</i> 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 <a href="#_type_Match.pod6">Match</a> object as a positional argument. If no such method exists, it is skipped.</p> | |
<p>Here is a contrived example of a grammar and actions in action:</p> | |
<pre class="code">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» | |
</pre> | |
<p>An instance of <span class="code">TestActions</span> is passed as named argument <span class="code">actions</span> to the <a href="#_routine_parse.pod6">parse</a> call, and when token <span class="code">TOP</span> has matched successfully, it automatically calls method <span class="code">TOP</span>, passing the match object as an argument.</p> | |
<p>To make it clear that the argument is a match object, the example uses <span class="code">$/</span> as a parameter name to the action method, though that's just a handy convention, nothing intrinsic; <span class="code">$match</span> would have worked too, though using <span class="code">$/</span> does give the advantage of providing <span class="code">$<capture></span> as a shortcut for <span class="code">$/<capture></span>; we use another argument, anyway, in the action for <span class="code">TOP</span>.</p> | |
<p>A slightly more involved example follows:</p> | |
<pre class="code">grammar KeyValuePairs { | |
token TOP { | |
[<pair> \v+]* | |
} | |
token 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 | |
raku=d | |
EOI | |
for @res -> $p { | |
say "Key: $p.key()\tValue: $p.value()"; | |
} | |
</pre> | |
<p>This produces the following output:</p> | |
<pre class="code">Key: second Value: b | |
Key: hits Value: 42 | |
Key: raku Value: d | |
</pre> | |
<p>Rule <span class="code">pair</span>, which parsed a pair separated by an equals sign, aliases the two calls to token <span class="code">identifier</span> to separate capture names so that they are available more easily and intuitively, as they will be in the corresponding Action. The corresponding action method constructs a <a href="#_type_Pair.pod6">Pair</a> object, and uses the <span class="code">.made</span> property of the sub match objects. So it (like the action method <span class="code">TOP</span> too) exploits the fact that action methods for submatches are called before those of the calling/outer regex. So action methods are called in <a href="#_routine_https:__en.wikipedia.org_wiki_Tree_traversal.pod6-Post-order">post-order</a>.</p> | |
<p>The action method <span class="code">TOP</span> simply collects all the objects that were <span class="code">.made</span> by the multiple matches of the <span class="code">pair</span> rule, and returns them in a list. Please note that, in this case, we need to use the method form of <a href="#_routine_make.pod6"><span class="code">make</span></a>, since the routine form can only be used if the argument to the action method is <span class="code">$/</span>. Inversely, if the argument of the method is <span class="code">$/</span>, we can use simply <span class="code">make</span>, which is equivalent to <span class="code">$/.make</span>.</p> | |
<p>Also note that <span class="code">KeyValuePairsActions</span> was passed as a type object to method <span class="code">parse</span>, which was possible because none of the action methods use attributes (which would only be available in an instance).</p> | |
<p>We can extend above example by using inheritance.</p> | |
<pre class="code">use KeyValuePairs; | |
unit grammar ConfigurationSets is KeyValuePairs; | |
token TOP { | |
<configuration-element>+ %% \v | |
} | |
token configuration-element { | |
<pair>+ %% \v | |
} | |
token comment { | |
\s* '#' .+? $$ | |
} | |
token pair { | |
<key=.identifier> '=' <value=.identifier> <comment>? | |
} | |
</pre> | |
<p>We are sub-classing (actually, sub-grammaring) the previous example; we have overridden the definition of <span class="code">pair</span> by adding a <span class="code">comment</span>; the previous <span class="code">TOP</span> rule has been demoted to <span class="code">configuration-element</span>, and there's a new <span class="code">TOP</span> which now considers sets of configuration elements separated by vertical space. We can also reuse actions by subclassing the action class:</p> | |
<pre class="code">use KeyValuePairs; | |
unit class ConfigurationSetsActions is KeyValuePairsActions; | |
method configuration-element($match) { | |
$match.make: $match<pair>».made | |
} | |
method TOP ($match) { | |
my @made-elements = gather for $match<configuration-element> { | |
take $_.made | |
}; | |
$match.make( @made-elements ); | |
} | |
</pre> | |
<p>All existing actions are reused, although obviously new ones have to be written for the new elements in the grammar, including <span class="code">TOP</span>. These can be used together from this script:</p> | |
<pre class="code">use ConfigurationSets; | |
use ConfigurationSetsActions; | |
my $actions = ConfigurationSetsActions; | |
my $sets = ConfigurationSets.parse(q:to/EOI/, :$actions).made; | |
second=b # Just a thing | |
hits=42 | |
raku=d | |
third=c # New one | |
hits=33 | |
EOI | |
for @$sets -> $set { | |
say "Element→ $set"; | |
} | |
</pre> | |
<p>Which will print</p> | |
<pre class="code">Element→ second b hits 42 raku d | |
Element→ third c hits 33 | |
</pre> | |
<p>In other cases, action methods might want to keep state in attributes. Then of course you must pass an instance to method parse.</p> | |
<p>Note that <span class="code">token</span> <span class="code">ws</span> is special: when <span class="code">:sigspace</span> is enabled (and it is when we are using <span class="code">rule</span>), it replaces certain whitespace sequences. This is why the spaces around the equals sign in <span class="code">rule pair</span> work just fine and why the whitespace before closing <span class="code">}</span> does not gobble up the newlines looked for in <span class="code">token TOP</span>.</p> | |
</div> | |
<!-- /language/hashmap.pod6 --><div class="pod-body"><a id="_language_hashmap.pod6"></a><a name="t26"></a><h1 class="title">26 Hashes and maps</h1> <p class="subtitle">Working with associative arrays/dictionaries/hashes</p> <a name="t26.1"></a> <h1 id="_language_hashmap.pod6-The_associative_role_and_associative_classes">The associative role and associative classes</h1> | |
<p>The <a href="#_type_Associative.pod6">Associative</a> role underlies hashes and maps, as well as other classes such as <a href="#_type_MixHash.pod6">MixHash</a>. It defines the two types that will be used in associative classes; by default, you can use anything (literally, since any class that subclasses <a href="#_type_Any.pod6">Any</a> can be used) <a href="#25-Non-string_keys_(object_hash)">as a key</a>, although it will be coerced to a string, and any object as value. You can access these types using the <span class="code">of</span> and <span class="code">keyof</span> methods.</p> | |
<p>By default, any object declared with the <span class="code">%</span> 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.</p> | |
<pre class="code">say (%).^name ; # OUTPUT: «Hash»</pre> | |
<p>Inversely, you cannot use the <span class="code">%</span> sigil if the <span class="code">Associative</span> role is not mixed in, but since this role does not have any associated properties, you will have to redefine the behavior of the <a href="#_language_operators.pod6-postcircumfix_{_}">hash subscript operator</a>. In order to do that, there are several functions you will have to override:</p> | |
<pre class="code">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» | |
</pre> | |
<p>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 <span class="code">Associative</span> to those particular classes, <span class="code">of</span> will return the value type we have used, <span class="code">Cool</span> in this case (we can log lists or strings only). Mixing the <span class="code">Associative</span> role gives it the right to use the <span class="code">%</span> sigil; binding is needed in the definition since <span class="code">%</span>-sigiled variables get by default the <span class="code">Hash</span> type.</p> | |
<p>This log is going to be append-only, which is why we escape the associative array metaphor to use a <span class="code">log</span> 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 <span class="code">AT-KEY</span> multi method, for the latter <span class="code">EXIST-KEY</span>. In the last two statements, we show how the subscript operation invokes <span class="code">AT-KEY</span>, while the <span class="code">:exists</span> adverb invokes <span class="code">EXISTS-KEY</span>.</p> | |
<p>We override <span class="code">DELETE-KEY</span>, <span class="code">ASSIGN-KEY</span> and <span class="code">BIND-KEY</span>, but only to throw an exception. Attempting to assign, delete, or bind a value to a key will result in a <span class="code">Cannot modify an immutable Str (value)</span> exception thrown.</p> | |
<p>Making classes associative provides a very convenient way of using and working with them using hashes; an example can be seen in <a href="#_routine_https:__cro.services_docs_reference_cro-http-client.pod6-Setting_the_request_body">Cro</a>, which uses it extensively for the convenience of using hashes to define structured requests and express its response.</p> | |
<a name="t26.2"></a> <h1 id="_language_hashmap.pod6-Mutable_hashes_and_immutable_maps">Mutable hashes and immutable maps</h1> | |
<p>A <a href="#_type_Hash.pod6"><span class="code">Hash</span></a> is a mutable mapping from keys to values (called <i>dictionary</i>, <i>hash table</i> or <i>map</i> in other programming languages). The values are all scalar containers, which means you can assign to them. <a href="#_type_Map.pod6"><span class="code">Map</span></a>s are, on the other hand, immutable. Once a key has been paired with a value, this pairing cannot be changed.</p> | |
<p>Maps and hashes are usually stored in variables with the percent <span class="code">%</span> sigil, which is used to indicate they are Associative.</p> | |
<p>Hash and map elements are accessed by key via the <span class="code">{ }</span> postcircumfix operator:</p> | |
<pre class="code">say %*ENV{'HOME', 'PATH'}.raku; | |
# OUTPUT: «("/home/camelia", "/usr/bin:/sbin:/bin")»</pre> | |
<p>The general <a href="#_language_subscripts.pod6">Subscript</a> rules apply providing shortcuts for lists of literal strings, with and without interpolation.</p> | |
<pre class="code">my %h = oranges => 'round', bananas => 'bendy'; | |
say %h<oranges bananas>; | |
# OUTPUT: «(round bendy)» | |
my $fruit = 'bananas'; | |
say %h«oranges "$fruit"»; | |
# OUTPUT: «(round bendy)»</pre> | |
<p>You can add new pairs simply by assigning to an unused key:</p> | |
<pre class="code">my %h; | |
%h{'new key'} = 'new value';</pre> | |
<a name="t26.3"></a> <h1 id="_language_hashmap.pod6-Hash_assignment">Hash assignment</h1> | |
<p>Assigning a list of elements to a hash variable first empties the variable, and then iterates the elements of the right-hand side (which must contain an even number of elements). Note that hash keys are always coerced to be strings even if they are unquoted, but keys with spaces in their names must be quoted. For example, using the common <a href="#_type_Pair.pod6">Pair</a> syntax:</p> | |
<pre class="code">my %h = 1 => 'a', b => 2, '1 2' => 3; | |
say %h.keys.sort.raku; # OUTPUT: «("1", "1 2", "b").Seq» | |
say %h.values.sort.raku # OUTPUT: «(2, 3, "a").Seq»</pre> | |
<p>The stringification of the keys can lead to surprising results. For example, the Raku module <span class="code">CSV::Parser</span> in one mode returns a CSV data line as a hash of <span class="code">{UInt => 'value'}</span> pairs which can look like this fragment of a 20-field line:</p> | |
<pre class="code">my %csv = '2' => 'a', '10' => 'b'; | |
say %csv.keys.sort.raku; # OUTPUT: «("10", "2").Seq»</pre> | |
<p>The sort result is not what one would normally want. We can use the power of Raku to coerce the string values into integers for the sort. There are several ways that can be done but this method may present the least "line noise" to novices or non-Raku viewers:</p> | |
<pre class="code">say %csv.keys.map(+*).sort.raku; # OUTPUT: «(2, 10).Seq» | |
</pre> | |
<p>In a hash constructor list the <span class="code">Pair</span> syntax doesn't have to be used, or it may be intermixed with ordinary list values as long as the list has an even number of elements in total as well as between <span class="code">Pair</span>s. If an element is a <span class="code">Pair</span> type (e.g., 'a => 1'), 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 <a href="#_type_Str.pod6">Str</a> and used as a hash key, while the next element of the list is taken as the corresponding value.</p> | |
<pre class="code">my %h = 'a', 'b', c => 'd', 'e', 'f';</pre> | |
<p>Same as</p> | |
<pre class="code">my %h = a => 'b', c => 'd', e => 'f';</pre> | |
<p>or</p> | |
<pre class="code">my %h = <a b c d e f>;</pre> | |
<p>or even</p> | |
<pre class="code">my %h = %( a => 'b', c => 'd', e => 'f' );</pre> | |
<p>If you have an odd number of elements using most constructors you will see an error:</p> | |
<pre class="code">my %h = <a b c>; # OUTPUT: «hash initializer expected...»</pre> | |
<p>There are two other valid ways of constructing a hash, but the user should be wary:</p> | |
<pre class="code">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</pre> | |
<p>or</p> | |
<pre class="code">my $h = { a => 'b', c => 'd', e => 'f'};</pre> | |
<p>Please note that curly braces are used only in the case that we are not assigning it to a <span class="code">%</span>-sigiled variable; in case we use it for a <span class="code">%</span>-sigiled variable we will get an <span class="code">Potential difficulties: Useless use of hash composer on right side of hash assignment; did you mean := instead?</span> error. As this error indicates, however, we can use curly braces as long as we use also binding:</p> | |
<pre class="code">my %h := { a => 'b', c => 'd', e => 'f'}; | |
say %h; # OUTPUT: «{a => b, c => d, e => f}»</pre> | |
<p>Nested hashes can also be defined using the same syntax:</p> | |
<pre class="code">my %h = e => f => 'g'; | |
say %h<e><f>; # OUTPUT: «g»</pre> | |
<p>However, what you are defining here is a key pointing to a <a href="#_type_Pair.pod6">Pair</a>, which is fine if that is what you want and your nested hash has a single key. But <span class="code">%h<e></span> will point to a <span class="code">Pair</span> which will have these consequences:</p> | |
<pre class="code">my %h = e => f => 'g'; | |
%h<e><q> = 'k'; | |
# OUTPUT: «PairCannot modify an immutable Str (Nil) in block <unit>» | |
</pre> | |
<p>This, however, will effectively define a nested hash:</p> | |
<pre class="code">my %h = e => { f => 'g' }; | |
say %h<e>.^name; # OUTPUT: «Hash» | |
say %h<e><f>; # OUTPUT: «g»</pre> | |
<p>If a <a href="#_type_Pair.pod6">Pair</a> is encountered where a value is expected, it is used as a hash value:</p> | |
<pre class="code">my %h = 'a', 'b' => 'c'; | |
say %h<a>.^name; # OUTPUT: «Pair» | |
say %h<a>.key; # OUTPUT: «b»</pre> | |
<p>If the same key appears more than once, the value associated with its last occurrence is stored in the hash:</p> | |
<pre class="code">my %h = a => 1, a => 2; | |
say %h<a>; # OUTPUT: «2»</pre> | |
<p>To assign a hash to a variable which does not have the <span class="code">%</span> sigil, you may use the <span class="code">%()</span> hash constructor:</p> | |
<pre class="code">my $h = %( a => 1, b => 2 ); | |
say $h.^name; # OUTPUT: «Hash» | |
say $h<a>; # OUTPUT: «1»</pre> | |
<p>If one or more values reference the topic variable, <span class="code">$_</span>, the right-hand side of the assignment will be interpreted as a <a href="#_type_Block.pod6">Block</a>, not a Hash:</p> | |
<pre class="code">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; | |
</pre> | |
<p>This would have been avoided if you had used the <span class="code">%()</span> hash constructor. Only use curly braces for creating Blocks.</p> | |
<p><a id="i497" name="Language hash slice"></a><span class="indexed"></span></p> | |
<a name="t26.3.1"></a> <h2 id="_language_hashmap.pod6-Hash_slices">Hash slices</h2> | |
<p>You can assign to multiple keys at the same time with a slice.</p> | |
<pre class="code">my %h; %h<a b c> = 2 xx *; %h.raku.say; # OUTPUT: «{:a(2), :b(2), :c(2)}» | |
my %h; %h<a b c> = ^3; %h.raku.say; # OUTPUT: «{:a(0), :b(1), :c(2)}»</pre> | |
<a name="t26.3.2"></a> <h2 id="_language_hashmap.pod6-Non-string_keys_(object_hash)"><a name="498"></a>Non-string keys (object hash)</h2> | |
<p>By default keys in <span class="code">{ }</span> are forced to strings. To compose a hash with non-string keys, use a colon prefix:</p> | |
<pre class="code">my $when = :{ (now) => "Instant", (DateTime.now) => "DateTime" };</pre> | |
<p>Note that with objects as keys, you often cannot use the <span class="code"><...></span> construct for key lookup, as it creates only strings and <a href="#_language_glossary.pod6-index-entry-Allomorph">allomorphs</a>. Use the <span class="code">{...}</span> instead:</p> | |
<pre class="code">:{ 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»</pre> | |
<p><i>Note</i>: Rakudo implementation currently erroneously applies <a href="#_routine_{ }.pod6-(Operators)_term_{_}">the same rules</a> for <span class="code">:{ }</span> as it does for <span class="code">{ }</span> and can construct a <a href="#_type_Block.pod6">Block</a> in certain circumstances. To avoid that, you can instantiate a parameterized Hash directly. Parameterization of <span class="code">%</span>-sigiled variables is also supported:</p> | |
<pre class="code">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</pre> | |
<p>Now if you want to define a hash to preserve the objects you are using as keys <i>as the <b>exact</b> objects you are providing to the hash to use as keys</i>, then object hashes are what you are looking for.</p> | |
<pre class="code">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; | |
} | |
</pre> | |
<p>This example uses an object hash that only accepts keys of type <a href="#_type_Instant.pod6">Instant</a> to implement a rudimentary, yet type-safe, logging mechanism. We utilize a named <a href="#_language_variables.pod6-The_state_declarator">state</a> variable for keeping track of the previous <span class="code">Instant</span> so that we can provide an interval.</p> | |
<p>The whole point of object hashes is to keep keys as objects-in-themselves. Currently object hashes utilize the <a href="#_routine_WHICH.pod6">WHICH</a> method of an object, which returns a unique identifier for every mutable object. This is the keystone upon which the object identity operator (<a href="#_routine_===.pod6">===</a>) rests. Order and containers really matter here as the order of <span class="code">.keys</span> is undefined and one anonymous list is never <a href="#_routine_===.pod6">===</a> to another.</p> | |
<pre class="code">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: «True» | |
say ($first-instant, $second-instant) === %intervals.keys.sort; # OUTPUT: «False» | |
say $first-instant === %intervals.keys.sort[0]; # OUTPUT: «True» | |
</pre> | |
<p>Since <span class="code">Instant</span> defines its own comparison methods, in our example a sort according to <a href="#_routine_cmp.pod6">cmp</a> will always provide the earliest instant object as the first element in the <a href="#_type_List.pod6">List</a> it returns.</p> | |
<p>If you would like to accept any object whatsoever in your hash, you can use <a href="#_type_Any.pod6">Any</a>!</p> | |
<pre class="code">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";</pre> | |
<p>There is a more concise syntax which uses binding.</p> | |
<pre class="code">my %h := :{ (now) => "Instant", (DateTime.now) => "DateTime" };</pre> | |
<p>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.</p> | |
<p>Since 6.d was released, <a href="#_type_Junction.pod6"><span class="code">Junction</span> s</a> can also be used as hash keys. The result will also be a <span class="code">Junction</span> of the same type used as key.</p> | |
<pre class="code">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)»</pre> | |
<p>If a Junction of any kind is used to define a key, it will have the same effect of defining elements of the <span class="code">Junction</span> as separate keys:</p> | |
<pre class="code">my %hash = %( "a"|"b" => 1, c => 2 ); | |
say %hash{"b"|"c"}; # OUTPUT: «any(1, 2)» | |
</pre> | |
<a name="t26.3.3"></a> <h2 id="_language_hashmap.pod6-Constraint_value_types">Constraint value types</h2> | |
<p>Place a type object in-between the declarator and the name to constrain the type of all values of a <span class="code">Hash</span>.</p> | |
<pre class="code">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")</pre> | |
<p>You can do the same by a more readable syntax.</p> | |
<pre class="code">my %h of Int; # the same as my Int %h</pre> | |
<p>If you want to constraint the type of all keys of a <span class="code">Hash</span>, add <span class="code">{Type}</span> following the name of variable.</p> | |
<pre class="code">my %h{Int};</pre> | |
<p>Even put these two constraints together.</p> | |
<pre class="code">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")</pre> | |
<a name="t26.4"></a> <h1 id="_language_hashmap.pod6-Looping_over_hash_keys_and_values">Looping over hash keys and values</h1> | |
<p>A common idiom for processing the elements in a hash is to loop over the keys and values, for instance,</p> | |
<pre class="code">my %vowels = 'a' => 1, 'e' => 2, 'i' => 3, 'o' => 4, 'u' => 5; | |
for %vowels.kv -> $vowel, $index { | |
"$vowel: $index".say; | |
}</pre> | |
<p>gives output similar to this:</p> | |
<pre class="code">a: 1 | |
e: 2 | |
o: 4 | |
u: 5 | |
i: 3 | |
</pre> | |
<p>where we have used the <span class="code">kv</span> method to extract the keys and their respective values from the hash, so that we can pass these values into the loop.</p> | |
<p>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</p> | |
<pre class="code">my %vowels = 'a' => 1, 'e' => 2, 'i' => 3, 'o' => 4, 'u' => 5; | |
for %vowels.sort(*.key)>>.kv -> ($vowel, $index) { | |
"$vowel: $index".say; | |
}</pre> | |
<p>which prints</p> | |
<pre class="code">a: 1 | |
e: 2 | |
i: 3 | |
o: 4 | |
u: 5 | |
</pre> | |
<p>in alphabetical order as desired. To achieve this result, we sorted the hash of vowels by key (<span class="code">%vowels.sort(*.key)</span>) which we then ask for its keys and values by applying the <span class="code">.kv</span> method to each element via the unary <span class="code">>></span> hyperoperator resulting in a <a href="#_type_List.pod6">List</a> of key/value lists. To extract the key/value the variables thus need to be wrapped in parentheses.</p> | |
<p>An alternative solution is to flatten the resulting list. Then the key/value pairs can be accessed in the same way as with plain <span class="code">.kv</span>:</p> | |
<pre class="code">my %vowels = 'a' => 1, 'e' => 2, 'i' => 3, 'o' => 4, 'u' => 5; | |
for %vowels.sort(*.key)>>.kv.flat -> $vowel, $index { | |
"$vowel: $index".say; | |
}</pre> | |
<p>You can also loop over a <span class="code">Hash</span> using <a href="#_type_Signature.pod6-Destructuring_arguments">destructuring</a>.</p> | |
<a name="t26.4.1"></a> <h2 id="_language_hashmap.pod6-In_place_editing_of_values">In place editing of values</h2> | |
<p>There may be times when you would like to modify the values of a hash while iterating over them.</p> | |
<pre class="code">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»</pre> | |
<p>This is traditionally accomplished by sending both the key and the value as follows.</p> | |
<pre class="code">my %answers = illuminatus => 23, hitchhikers => 42; | |
for %answers.kv -> $k,$v { %answers{$k} = $v + 10 };</pre> | |
<p>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.</p> | |
<pre class="code">my %answers = illuminatus => 23, hitchhikers => 42; | |
for %answers.values -> $v is rw { $v += 10 };</pre> | |
<p>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:</p> | |
<pre class="code">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; » | |
</pre> | |
<p>replace key 'b' with 'bb' but retain 'b's value as the new key's value:</p> | |
<pre class="code">for %h.keys -> $k { | |
if $k eq 'b' { | |
%h<bb> = %h{$k}:delete; | |
} | |
} | |
for %h.keys.sort -> $k { | |
print "$k => {%h{$k}}; "; | |
} | |
say ''; # OUTPUT: «a => 1; bb => 2; » | |
</pre> | |
</div> | |
<!-- /language/haskell-to-p6.pod6 --><div class="pod-body"><a id="_language_haskell-to-p6.pod6"></a><a name="t27"></a><h1 class="title">27 Haskell to Raku - nutshell</h1> <p class="subtitle">Learning Raku from Haskell, in a nutshell: what do I already know?</p> <p>Haskell and Raku are <i>very</i> 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 Raku. The Haskell user may find that they need not abandon all of their Haskelly thoughts while scripting in Raku.</p> | |
<p>Note that this should not be mistaken for a beginner tutorial or overview of Raku; it is intended as a technical reference for Raku learners with a strong Haskell background.</p> | |
<a name="t27.1"></a> <h1 id="_language_haskell-to-p6.pod6-Types">Types</h1> | |
<a name="t27.1.1"></a> <h2 id="_language_haskell-to-p6.pod6-Types_vs_values">Types vs values</h2> | |
<p>In Haskell, you have type level programming and then value level programming.</p> | |
<pre class="code">plusTwo :: Integer -> Integer -- Types | |
plusTwo x = x + 2 -- Values | |
</pre> | |
<p>You do not mix types and values in Haskell like the below</p> | |
<pre class="code">plusTwo 2 -- This is valid | |
plusTwo Integer -- This is not valid | |
</pre> | |
<p>In Raku, types (AKA type objects) live on the same level as values</p> | |
<pre class="code">sub plus-two(Int $x --> Int) { $x + 2 } | |
plus-two(2); # This is valid | |
plus-two(Int); # This is valid | |
</pre> | |
<p>I will illustrate this unique aspect of Raku with one more example:</p> | |
<pre class="code">multi sub is-string(Str $ --> True) {} | |
multi sub is-string(Any $ --> False) {} | |
is-string('hello'); #True | |
is-string(4); #False | |
</pre> | |
<a name="t27.1.2"></a> <h2 id="_language_haskell-to-p6.pod6-Maybe">Maybe</h2> | |
<p>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:</p> | |
<pre class="code">parseInt :: String -> Maybe Integer | |
case parseInt myString of | |
Just x -> x | |
Nothing -> 0 | |
</pre> | |
<p>In Raku, 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.</p> | |
<pre class="code">sub parse-int(Str $s --> Int) { ... } | |
my $string = {...}; | |
given parse-int($string) { | |
when Int:D { $_ } | |
when Int:U { 0 } | |
} | |
</pre> | |
<p>So in Raku we have type constraints that indicate the definedness of a type. These are</p> | |
<pre class="code">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. | |
</pre> | |
<p>If we wanted to be explicit in the above example (probably a good idea), we could add the <span class="code">:_</span> 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.</p> | |
<pre class="code">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 | |
</pre> | |
<p>The <span class="code">with</span> operator that you see above is like <span class="code">if</span>, except it explicitly tests for definedness and then passes the result to the following block. Similarly, <span class="code">without</span> tests that the object is undefined and also passes the result to the following block.</p> | |
<p>For more natural control flow with undefined and defined types, Raku introduces <span class="code">andthen</span> and <span class="code">orelse</span>.</p> | |
<pre class="code">sub parse-int(Str $s --> Int:_) { ... } | |
my $string = {...}; | |
my $result = parse-int($string) orelse 0; | |
sub hello() { say 'hi' } | |
hello() andthen say 'bye'; | |
</pre> | |
TODO: include a better example for andthen that makes sense. Maybe using promise objects? | |
<p>So in practice, Raku does not have the concept of a null type, but rather of defined or undefined types.</p> | |
<a name="t27.1.3"></a> <h2 id="_language_haskell-to-p6.pod6-Data_definitions">Data definitions</h2> | |
<p>Raku 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.</p> | |
<p>Here is a Haskell code example:</p> | |
<pre class="code">data Point = Point x y | |
moveUp :: Point -> Point | |
moveUp (Point x y) = Point x (y + 1) | |
</pre> | |
<p>And an equivalent Raku example:</p> | |
<pre class="code">class Point { has $.x; has $.y; } | |
sub move-up(Point $p --> Point) { | |
Point.new(x => $p.x, y => $p.y + 1) | |
} | |
</pre> | |
<p>The code I illustrated above is an example of a <a href="#_routine_https:__wiki.haskell.org_Algebraic_data_type.pod6">Product Type</a>. If instead you'd like to write a Sum Type, there is not an exact equivalent in Raku. The closest thing would be an <a href="#_language_typesystem.pod6-enum">Enum</a>.</p> | |
<pre class="code">data Animal = Dog | Cat | Bird | Horse | |
testAnimal :: Animal -> String | |
testAnimal Dog = "Woof" | |
testAnimal Horse = "Neigh" | |
</pre> | |
<p>Although it does not fit the same exact use cases, it can be used in putting constraints on types.</p> | |
<pre class="code">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; | |
</pre> | |
<a name="t27.1.4"></a> <h2 id="_language_haskell-to-p6.pod6-Type_aliases_and_subsets">Type aliases and subsets</h2> | |
<p>In Haskell, you can alias an existing type to simply increase clarity of intent and re-use existing types.</p> | |
<pre class="code">type Name = String | |
fullName :: Name -> Name -> Name | |
fullName first last = first ++ last | |
</pre> | |
<p>The equivalent in Raku is the following.</p> | |
<pre class="code">my constant Name = Str; | |
sub full-name ( Name \first, Name \last --> Name ) { first ~ last } | |
</pre> | |
<p>It should be noted that in Raku, one can also create a subset of an existing type.</p> | |
<pre class="code">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 | |
</pre> | |
<a name="t27.1.5"></a> <h2 id="_language_haskell-to-p6.pod6-Typeclasses">Typeclasses</h2> | |
<p>TODO</p> | |
explain how Raku roles compare to Haskell typeclasses | |
<a name="t27.2"></a> <h1 id="_language_haskell-to-p6.pod6-Functions">Functions</h1> | |
<a name="t27.2.1"></a> <h2 id="_language_haskell-to-p6.pod6-Definitions_and_signatures">Definitions and signatures</h2> | |
<p>Matching</p> | |
<p>Haskell makes heavy use of pattern matching in function definitions.</p> | |
<pre class="code">greeting :: String -> String | |
greeting "" = "Hello, World!" | |
greeting "bub" = "Hey bub." | |
greeting name = "Hello, " ++ name ++ "!" | |
</pre> | |
<p>Raku does this as well! You just use the <span class="code">multi</span> keyword to signify that it is a multiple dispatch function.</p> | |
<pre class="code">proto greeting ( Str --> Str ) {*} | |
multi greeting ( "" --> "Hello, World!" ) {} | |
multi greeting ( "bub" --> "Hey bub." ) {} | |
multi greeting ( \name ) { "Hello, " ~ name ~ "!" } | |
</pre> | |
<p>The <span class="code">proto</span> 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.</p> | |
<pre class="code">proto greeting ( Str \name --> Str ) {*} | |
say &greeting.signature; # (Str \name --> Str) | |
</pre> | |
<p>An interesting thing to note in the Raku code above is that passing values like <span class="code">'bub'</span> as a function parameter is just syntax sugar for a <span class="code">where</span> guard.</p> | |
<p>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.</p> | |
<pre class="code">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.'} | |
</pre> | |
<p><span class="code">$_</span> is known as the topic variable. It assumes the form of whatever is appropriate. The smartmatch operator <span class="code">~~</span> 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).</p> | |
<p>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.</p> | |
<pre class="code">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 ){…} | |
</pre> | |
<p>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.</p> | |
<p>When using <span class="code">where</span>, note that the order of definition is important, just like in Haskell.</p> | |
<pre class="code">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 | |
</pre> | |
<p>Deconstruction</p> | |
<p>TODO</p> | |
<a name="t27.2.2"></a> <h2 id="_language_haskell-to-p6.pod6-Currying">Currying</h2> | |
<p>TODO</p> | |
<p>.assuming vs currying</p> | |
<p>method chaining vs currying</p> | |
<a name="t27.2.3"></a> <h2 id="_language_haskell-to-p6.pod6-Composing">Composing</h2> | |
<p>TODO</p> | |
<p>show function composition operator. Maybe explain a more native Raku way to do this though.</p> | |
<a name="t27.3"></a> <h1 id="_language_haskell-to-p6.pod6-Case_/_matching">Case / matching</h1> | |
<p>Haskell makes heavy use of case matching like the below:</p> | |
<pre class="code">case number of | |
2 -> "two" | |
4 -> "four" | |
8 -> "eight" | |
_ -> "don't care" | |
</pre> | |
<p>In Raku you can achieve this same thing with the given/when structure:</p> | |
<pre class="code">my $number = {...}; | |
given $number { | |
when 2 { "two" } | |
when 4 { "four" } | |
when 8 { "eight" } | |
default { "don't care" } | |
} | |
</pre> | |
<p>Note that the order of the <span class="code">when</span>'s is also significant, just like with the <span class="code">where</span>'s in the guard section of this page.</p> | |
<a name="t27.4"></a> <h1 id="_language_haskell-to-p6.pod6-Lists">Lists</h1> | |
<p>TODO</p> | |
<p>explain differences between Raku Arrays, Sequences, and Lists. Explain data shapes in regards to the <span class="code">@</span> sigil. Explain how you can convert an Array to a flattened list of objects with <span class="code">|@</span></p> | |
<p>data shapes become quite intuitive, but it takes a bit of practice.</p> | |
<a name="t27.4.1"></a> <h2 id="_language_haskell-to-p6.pod6-List_comprehensions">List comprehensions</h2> | |
<p>There are no explicit list comprehensions in Raku. But you can achieve list comprehensions a couple of different ways.</p> | |
<p>Here is a trivial example in Haskell:</p> | |
<pre class="code">evens = [ x | x <- [0..100], even x ] | |
</pre> | |
<p>And now in Raku:</p> | |
<pre class="code"># 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 }; | |
</pre> | |
<p>Since <span class="code">for</span> is always eager it is generally better to use <span class="code">map</span> or <span class="code">grep</span> which will inherit the laziness or eagerness of its list argument.</p> | |
<pre class="code">my @evens = map { $_ if $_ %% 2 }, 0..100; | |
my @evens = grep { $_ %% 2 }, 0..100; | |
# using a Whatever lambda | |
my @evens = grep * %% 2, 0..100; | |
</pre> | |
<p>Here is the creation of tuples in Haskell:</p> | |
<pre class="code">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)] | |
</pre> | |
<p>And in Raku:</p> | |
<pre class="code">my @tuples = 1,2 X 1..4; | |
# [(1,1), (1,2), (1,3), (1,4), (2,1), (2,2), (2,3), (2,4)] | |
</pre> | |
<p>See this design document for more information on what kinds of list comprehensions are possible in: <a href="#_routine_https:__design.raku.org_S04.html.pod6-The_do-once_loop">https://design.raku.org/S04.html#The_do-once_loop</a>.</p> | |
<p>As you can see, when you get into some more advanced Haskell list comprehensions, Raku does not translate exactly the same, but it's possible to do the same things, nonetheless.</p> | |
<a name="t27.4.2"></a> <h2 id="_language_haskell-to-p6.pod6-Fold">Fold</h2> | |
<p>Fold in Haskell is called Reduce in Raku.</p> | |
<pre class="code">mySum = foldl (+) 0 numList | |
</pre> | |
<pre class="code">my @numbers = {...}; | |
reduce { $^a + $^b }, 0, |@numbers; | |
@numbers.reduce: {$^a + $^b} | |
</pre> | |
<p>However, in Raku, if you want to use an infix operator (+ - / % etc) there is a nice little helper called the Reduction metaoperator.</p> | |
<pre class="code">my @numbers = {...}; | |
[+] @numbers # This is the same | |
[+] 0, |@numbers # as this | |
</pre> | |
<p>It inserts the operator in between all values in the list and produces a result, just like Fold.</p> | |
<p>In Haskell you, you have foldl and foldr. In Raku, this difference is determined by the associativity attached to the operator/subroutine.</p> | |
<pre class="code">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 | |
</pre> | |
<a name="t27.4.3"></a> <h2 id="_language_haskell-to-p6.pod6-takeWhile"><span class="code">takeWhile</span></h2> | |
<p>The <span class="code">takeWhile</span> function in Haskell runs over a list returning all elements until a condition is met:</p> | |
<pre class="code">fibs = 0 : 1 : zipWith (+) fibs (tail fibs) | |
takeWhile (<20) fibs -- Returns [0,1,1,2,3,5,8,13] | |
</pre> | |
<p>There's no single equivalent function in Raku; several alternatives have been proposed in the <a href="#_routine_https:__github.com_Raku_doc_issues_3932.pod6">issue that originated this text</a>. This would be one of the alternatives:</p> | |
<pre class="code">[1, 2, 3, 40, 50, 60, 7, 8, 9] ...^ !(* < 10) | |
</pre> | |
<p>Although it's not a single function, it's essentially a specific way of using the <a href="#_language_operators.pod6-infix_...">sequence operator</a> using the caret for excluding the last term, and using a condition for ending the sequence. This specific example would be equivalent to</p> | |
<pre class="code">takeWhile (<10) [1, 2, 3, 40, 50, 60, 7, 8, 9] | |
</pre> | |
<a name="t27.4.4"></a> <h2 id="_language_haskell-to-p6.pod6-Map">Map</h2> | |
<p>TODO</p> | |
<a name="t27.4.5"></a> <h2 id="_language_haskell-to-p6.pod6-Ranges">Ranges</h2> | |
<p>Haskell and Raku both allow you to specify ranges of values.</p> | |
<pre class="code">myRange1 = 10..100 | |
myRange2 = 1.. -- Infinite | |
myRange3 = 'a'..'h' -- Letters work too | |
</pre> | |
<pre class="code">my $range1 = 10..100; | |
my $range2 = 1..*; # Infinite | |
my $range3 = 'a'..'h'; # Letters work too | |
</pre> | |
<a name="t27.4.6"></a> <h2 id="_language_haskell-to-p6.pod6-Laziness_vs_eagerness">Laziness vs eagerness</h2> | |
<p>In the examples above, you have the concept of laziness displayed very plainly. Raku 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.</p> | |
<pre class="code">(1 .. 100).is-lazy; # False | |
(1 .. Inf).is-lazy; # True | |
</pre> | |
<p>These are the "sane defaults" that Raku takes pride in. But they are still defaults and can be changed into one or the other.</p> | |
<pre class="code">(1 .. 100).lazy.is-lazy; # True | |
(1 .. 100).lazy.eager.is-lazy; # False | |
</pre> | |
<a name="t27.5"></a> <h1 id="_language_haskell-to-p6.pod6-Contexts_(let-in_/_where)">Contexts (let-in / where)</h1> | |
<p>TODO</p> | |
<p>explain how <span class="code">given/when</span> and <span class="code">with/without</span> and <span class="code">for loops</span> open lexical scopes with the argument as the context.</p> | |
<p>compare it to let/in and where constructs maybe?</p> | |
<a name="t27.6"></a> <h1 id="_language_haskell-to-p6.pod6-Parsers">Parsers</h1> | |
<a name="t27.6.1"></a> <h2 id="_language_haskell-to-p6.pod6-Parser_combinators_vs_grammars">Parser combinators vs grammars</h2> | |
<p>TODO</p> | |
<a name="t27.7"></a> <h1 id="_language_haskell-to-p6.pod6-Tail_Call_Optimization_or_Tail_Call_Elimination">Tail Call Optimization or Tail Call Elimination</h1> | |
<p>Haskell and many other functional programming languages use tail call optimization, also sometimes called tail call elimination, to remove the stack overhead of some types of recursive function calls.</p> | |
<p>There is nothing in the Raku language specification forbidding the implementation of this class of optimization, but no current implementation has it.</p> | |
<p>Please note that many Haskell looping constructs use recursive function calls. Haskell programs would encounter stack overflow errors more often without tail call optimization. The standard Raku looping constructs are not built on recursive function calls, which makes the feature less important.</p> | |
### 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 Raku 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. | |
</div> | |
<!-- /language/intro.pod6 --><div class="pod-body"><a id="_language_intro.pod6"></a><a name="t28"></a><h1 class="title">28 Brief introduction</h1> <p class="subtitle">Using Raku™ official documentation</p> <p>Documenting a large language like Raku 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.</p> | |
<p>Note the recent name change to Raku from Perl 6 has resulted in some objects having changed names and their former names, while still available, are deprecated and their use is not recommended in new code. Those items are shown in the following table:</p> | |
<table> | |
<caption>Raku object names versus deprecated Perl 6 names</caption>><tr><th>Raku</th> <th>Perl 6</th> <th>Notes</th></tr> | |
<tr><td>raku</td> <td>perl</td> <td>routine</td></tr> | |
<tr><td>*RAKULIB</td> <td>PERL6LIB</td> <td>environment variable for module paths (*NYI)</td></tr> | |
<tr><td>.raku</td> <td>.p6</td> <td>file extension for Raku scripts</td></tr> | |
<tr><td>.rakumod</td> <td>.pm6</td> <td>file extension for Raku modules</td></tr> | |
</table> <p>For a quick hands-on introduction, there is a short <a href="#_language_101-basics.pod6"><span class="code">annotated programming example</span></a>.</p> | |
<p>For programmers with experience in other languages, there are a number of <b>Migration</b> guides that compare and contrast the features of Raku with other languages.</p> | |
<p>A number of <b>Tutorials</b> cover several areas in which Raku is particularly innovative. The section headers should help navigate the remaining documents.</p> | |
<p>There are a number of <a href="#_routine_https:__raku.org_resources.pod6"><span class="code">useful resources</span></a> listed elsewhere on the raku.org site. These include articles, books, slide presentations, and videos.</p> | |
<p>It has been found that newcomers to Raku often ask questions that indicate assumptions carried over from other programming paradigms. It is suggested that the following sections in the <span class="code">Fundamental topics</span> section should be reviewed first.</p> | |
<ul><li><p><a href="#_type_Signature.pod6"><span class="code">Signatures</span></a> - each routine, which includes subroutines and methods, has a signature. Understanding the information given in the signature of a <span class="code">sub</span> or <span class="code">method</span> provides a quick way to grasp the operation and effect of the routine.</p> | |
</li></ul> <ul><li><p><a href="#_language_containers.pod6"><span class="code">Containers</span></a> - 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, Raku 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.</p> | |
</li></ul> <ul><li><p><a href="#_language_classtut.pod6"><span class="code">Classes and Roles</span></a> - Raku is fundamentally based on objects, which are described in terms of classes and roles. Raku, unlike some languages, does not <b>impose</b> object-oriented programming practices, and useful programs can be written as if Raku was purely procedural in nature. However, complex software, such as the Rakudo compiler of Raku, is made much simpler by writing in object-oriented idioms, which is why the Raku 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.</p> | |
</li></ul> <ul><li><p><a href="#_language_traps.pod6"><span class="code">Traps to Avoid</span></a> - 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.</p> | |
</li></ul></div> | |
<!-- /language/io-guide.pod6 --><div class="pod-body"><a id="_language_io-guide.pod6"></a><a name="t29"></a><h1 class="title">29 Input/Output the definitive guide</h1> <p class="subtitle">Correctly use Raku IO</p> <a name="t29.1"></a> <h1 id="_language_io-guide.pod6-The_basics">The basics</h1> | |
<p>The vast majority of common IO work is done by the <a href="#_type_IO::Path.pod6">IO::Path</a> 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.</p> | |
<p>Behind the scenes, <a href="#_type_IO::Path.pod6">IO::Path</a> works with <a href="#_type_IO::Handle.pod6">IO::Handle</a>, a class which you can use directly if you need a bit more control than what <a href="#_type_IO::Path.pod6">IO::Path</a> provides. When working with other processes, e.g. via <a href="#_type_Proc.pod6">Proc</a> or <a href="#_type_Proc::Async.pod6">Proc::Async</a> types, you'll also be dealing with a <i>subclass</i> of <a href="#_type_IO::Handle.pod6">IO::Handle</a>: the <a href="#_type_IO::Pipe.pod6">IO::Pipe</a>.</p> | |
<p>Lastly, you have the <a href="#_type_IO::CatHandle.pod6">IO::CatHandle</a>, as well as <a href="#_type_IO::Spec.pod6">IO::Spec</a> 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.</p> | |
<p>Along with all these classes, Raku provides several subroutines that let you indirectly work with these classes. These come in handy if you like functional programming style or in Raku one liners.</p> | |
<p>While <a href="#_type_IO::Socket.pod6">IO::Socket</a> and its subclasses also have to do with Input and Output, this guide does not cover them.</p> | |
<a name="t29.2"></a> <h1 id="_language_io-guide.pod6-Navigating_paths">Navigating paths</h1> | |
<a name="t29.2.1"></a> <h2 id="_language_io-guide.pod6-What's_an_IO::Path_anyway?">What's an IO::Path anyway?</h2> | |
<p>To represent paths as either files or directories, use <a href="#_type_IO::Path.pod6">IO::Path</a> type. The simplest way to obtain an object of that type is to coerce a <a href="#_type_Str.pod6">Str</a> by calling the <a href="#_routine_IO.pod6"><span class="code">.IO</span></a> method on it:</p> | |
<pre class="code">say 'my-file.txt'.IO; # OUTPUT: «"my-file.txt".IO»</pre> | |
<p>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 <a href="#_routine_raku.pod6"><span class="code">.raku</span></a> method:</p> | |
<pre class="code">say 'my-file.txt'.IO.raku; | |
# OUTPUT: «IO::Path.new("my-file.txt", :SPEC(IO::Spec::Unix), :CWD("/home/camelia"))»</pre> | |
<p>The two extra attributes—<span class="code">SPEC</span> and <span class="code">CWD</span>—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.</p> | |
<p>This means that regardless of how you made one, an <a href="#_type_IO::Path.pod6">IO::Path</a> object technically always refers to an absolute path. This is why its <a href="#_routine_absolute.pod6"><span class="code">.absolute</span></a> and <a href="#_routine_relative.pod6"><span class="code">.relative</span></a> methods return <a href="#_type_Str.pod6">Str</a> objects and they are the correct way to stringify a path.</p> | |
<p>However, don't be in a rush to stringify anything. Pass paths around as <a href="#_type_IO::Path.pod6">IO::Path</a> objects. All the routines that operate on paths can handle them, so there's no need to convert them.</p> | |
<a name="t29.2.2"></a> <h2 id="_language_io-guide.pod6-Path_parts">Path parts</h2> | |
<p>Given a local file name, it's very easy to get its components. For example, we have a file, "financial.data", in some directory, "/usr/local/data". Use Raku to analyze its path:</p> | |
<pre class="code">my $fname = "financial.data"; | |
# Stringify the full path name | |
my $f = $fname.IO.absolute; | |
say $f; | |
# OUTPUT: «/usr/local/data/financial.data» | |
# Stringify the path's parts: | |
say $f.IO.dirname; # OUTPUT: «/usr/local/data» | |
say $f.IO.basename; # OUTPUT: «financial.data» | |
# And the basename's parts: | |
# Use a method for the extension: | |
say $f.IO.extension; # OUTPUT: «data» | |
# Remove the extension by redefining it: | |
say ($f.IO.extension("")).IO.basename; # OUTPUT: «financial» | |
</pre> | |
<a name="t29.2.3"></a> <h2 id="_language_io-guide.pod6-Working_with_files">Working with files</h2> | |
<a name="t29.2.3.1"></a> <h3 id="_language_io-guide.pod6-Writing_into_files">Writing into files</h3> | |
<a name="t29.2.3.1.1"></a> <h4 id="_language_io-guide.pod6-Writing_new_content">Writing new content</h4> | |
<p>Let's make some files and write and read data from them! The <a href="#_routine_spurt.pod6"><span class="code">spurt</span></a> and <a href="#_routine_slurp.pod6"><span class="code">slurp</span></a> 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.</p> | |
<pre class="code">"my-file.txt".IO.spurt: "I ♥ Raku!"; | |
</pre> | |
<p>The code above creates a file named <span class="code">my-file.txt</span> in the current directory and then writes text <span class="code">I ♥ Raku!</span> into it. If Raku 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.</p> | |
<p>However, that is all the code you need. The string will be encoded in <span class="code">utf-8</span> encoding by default and the errors are handled via the <a href="#_type_Failure.pod6">Failure</a> mechanism: these are exceptions you can handle using regular conditionals. In this case, we're letting all potential <a href="#_type_Failure.pod6">Failures</a> get sunk after the call and so any <a href="#_type_Exception.pod6">Exceptions</a> they contain will be thrown.</p> | |
<a name="t29.2.3.1.2"></a> <h4 id="_language_io-guide.pod6-Appending_content">Appending content</h4> | |
<p>If you wanted to add more content to the file we created in the previous section, you could note the <a href="#_routine_spurt.pod6"><span class="code">spurt</span> documentation</a> mentions <span class="code">:append</span> as one of its argument options. However, for finer control, let's get ourselves an <a href="#_type_IO::Handle.pod6">IO::Handle</a> to work with:</p> | |
<pre class="code">my $fh = 'my-file.txt'.IO.open: :a; | |
$fh.print: "I count: "; | |
$fh.print: "$_ " for ^10; | |
$fh.close; | |
</pre> | |
<p>The <a href="#_routine_open.pod6"><span class="code">.open</span></a> method call opens our <a href="#_type_IO::Path.pod6">IO::Path</a> and returns an <a href="#_type_IO::Handle.pod6">IO::Handle</a>. We passed <span class="code">:a</span> as argument, to indicate we want to open the file for writing in append mode.</p> | |
<p>In the next two lines of code, we use the usual <a href="#_routine_print.pod6"><span class="code">.print</span></a> method on that <a href="#_type_IO::Handle.pod6">IO::Handle</a> to print a line with 11 pieces of text (the <span class="code">'I count: '</span> string and 10 numbers). Note that, once again, <a href="#_type_Failure.pod6">Failure</a> mechanism takes care of all the error checking for us. If the <a href="#_routine_open.pod6"><span class="code">.open</span></a> fails, it returns a <a href="#_type_Failure.pod6">Failure</a>, which will throw when we attempt to call method the <a href="#_routine_print.pod6"><span class="code">.print</span></a> on it.</p> | |
<p>Finally, we close the <a href="#_type_IO::Handle.pod6">IO::Handle</a> by calling the <a href="#_routine_close.pod6"><span class="code">.close</span></a> method on it. It is <i>important that you do it</i>, 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 <a href="#_routine_open.pod6"><span class="code">.open</span></a> call will fail. Note that unlike some other languages, Raku does not use reference counting, so the filehandles <b>are NOT closed</b> 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 <i>before</i> the open handles get a chance to get garbage collected.</p> | |
<a name="t29.2.3.2"></a> <h3 id="_language_io-guide.pod6-Reading_from_files">Reading from files</h3> | |
<a name="t29.2.3.2.1"></a> <h4 id="_language_io-guide.pod6-Using_IO::Path">Using IO::Path</h4> | |
<p>We've seen in previous sections that writing stuff to files is a single-line of code in Raku. Reading from them, is similarly easy:</p> | |
<pre class="code">say 'my-file.txt'.IO.slurp; # OUTPUT: «I ♥ Raku!» | |
say 'my-file.txt'.IO.slurp: :bin; # OUTPUT: «Buf[uint8]:0x<49 20 E2 99 A5 20 52 61 6B 75 21>» | |
</pre> | |
<p>The <a href="#_routine_slurp.pod6"><span class="code">.slurp</span></a> method reads entire contents of the file and returns them as a single <a href="#_type_Str.pod6">Str</a> object, or as a <a href="#_type_Buf.pod6">Buf</a> object, if binary mode was requested, by specifying <span class="code">:bin</span> named argument.</p> | |
<p>Since <a href="#_routine_slurp.pod6">slurping</a> loads the entire file into memory, it's not ideal for working with huge files.</p> | |
<p>The <a href="#_type_IO::Path.pod6">IO::Path</a> type offers two other handy methods: <a href="#_type_IO::Path.pod6-method_words"><span class="code">.words</span></a> and <a href="#_type_IO::Path.pod6-method_lines"><span class="code">.lines</span></a> that lazily read the file in smaller chunks and return <a href="#_type_Seq.pod6">Seq</a> objects that (by default) don't keep already-consumed values around.</p> | |
<p>Here's an example that finds lines in a text file that mention Raku and prints them out. Despite the file itself being too large to fit into available <a href="#_routine_https:__en.wikipedia.org_wiki_Random-access_memory.pod6">RAM</a>, the program will not have any issues running, as the contents are processed in small chunks:</p> | |
<pre class="code">.say for '500-PetaByte-File.txt'.IO.lines.grep: *.contains: 'Raku'; | |
</pre> | |
<p>Here's another example that prints the first 100 words from a file, without loading it entirely:</p> | |
<pre class="code">.say for '500-PetaByte-File.txt'.IO.words: 100 | |
</pre> | |
<p>Note that we did this by passing a limit argument to <a href="#_type_IO::Path.pod6-method_words"><span class="code">.words</span></a> instead of, say, using <a href="#_language_operators.pod6-index-entry-array_indexing_operator-array_subscript_operator-array_indexing_operator">a list indexing operation</a>. The reason for that is there's still a filehandle in use under the hood, and until you fully consume the returned <a href="#_type_Seq.pod6">Seq</a>, the handle will remain open. If nothing references the <a href="#_type_Seq.pod6">Seq</a>, 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 <a href="#_type_Seq.pod6">Seq</a> from <a href="#_type_IO::Path.pod6">IO::Path</a>'s <a href="#_type_IO::Path.pod6-method_words"><span class="code">.words</span></a> and <a href="#_type_IO::Path.pod6-method_lines"><span class="code">.lines</span></a> methods is <a href="#_language_glossary.pod6-index-entry-Reify">fully reified</a>; and the limit argument is there to help you with that.</p> | |
<a name="t29.2.3.2.2"></a> <h4 id="_language_io-guide.pod6-Using_IO::Handle">Using IO::Handle</h4> | |
<p>You can read from files using the <a href="#_type_IO::Handle.pod6">IO::Handle</a> type; this gives you a finer control over the process.</p> | |
<pre class="code">given 'some-file.txt'.IO.open { | |
say .readchars: 8; # OUTPUT: «I ♥ Raku» | |
.seek: 1, SeekFromCurrent; | |
say .readchars: 15; # OUTPUT: «I ♥ Programming» | |
.close | |
} | |
</pre> | |
<p>The <a href="#_type_IO::Handle.pod6">IO::Handle</a> gives you <a href="#_type_IO::Handle.pod6-method_read">.read</a>, <a href="#_type_IO::Handle.pod6-method_readchars">.readchars</a>, <a href="#_type_IO::Handle.pod6-routine_get">.get</a>, <a href="#_type_IO::Handle.pod6-routine_getc">.getc</a>, <a href="#_type_IO::Handle.pod6-routine_words">.words</a>, <a href="#_type_IO::Handle.pod6-routine_lines">.lines</a>, <a href="#_type_IO::Handle.pod6-method_slurp">.slurp</a>, <a href="#_type_IO::Handle.pod6-method_comb">.comb</a>, <a href="#_type_IO::Handle.pod6-method_split">.split</a>, and <a href="#_type_IO::Handle.pod6-method_Supply">.Supply</a> 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.</p> | |
<p>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 <span class="code">:close</span> argument, you can also use the <a href="#_language_phasers.pod6-index-entry-Phasers__will_trait"><span class="code">will leave</span> trait</a>, or the <span class="code">does auto-close</span> trait provided by the <a href="#_routine_https:__modules.raku.org_dist_Trait::IO.pod6"><span class="code">Trait::IO</span></a> module.</p> | |
<a name="t29.3"></a> <h1 id="_language_io-guide.pod6-The_wrong_way_to_do_things">The wrong way to do things</h1> | |
<p>This section describes how NOT to do Raku IO.</p> | |
<a name="t29.3.1"></a> <h2 id="_language_io-guide.pod6-Leave_$*SPEC_alone">Leave $*SPEC alone</h2> | |
<p>You may have heard of <a href="#_language_variables.pod6-Dynamic_variables"><span class="code">$*SPEC</span></a> 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.</p> | |
<p>However, unless you're writing your own IO framework, you almost never need to use <a href="#_language_variables.pod6-Dynamic_variables"><span class="code">$*SPEC</span></a> directly. <a href="#_language_variables.pod6-Dynamic_variables"><span class="code">$*SPEC</span></a> 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)!</p> | |
<p>The <a href="#_type_IO::Path.pod6"><span class="code">IO::Path</span></a> type is the workhorse of Raku 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 <a href="#_language_variables.pod6-Dynamic_variables"><span class="code">$*SPEC</span></a> stuff.</p> | |
<p>Tip: you can join path parts with <span class="code">/</span> and feed them to <a href="#_type_IO::Path.pod6"><span class="code">IO::Path</span></a>'s routines; they'll still do The Right Thing™ with them, regardless of the operating system.</p> | |
<pre class="code"># WRONG!! TOO MUCH WORK! | |
my $fh = open $*SPEC.catpath: '', 'foo/bar', $file; | |
my $data = $fh.slurp; | |
$fh.close; | |
</pre> | |
<pre class="code"># RIGHT! Use IO::Path to do all the dirty work | |
my $data = 'foo/bar'.IO.add($file).slurp; | |
</pre> | |
<p>However, it's fine to use it for things not otherwise provided by <a href="#_type_IO::Path.pod6">IO::Path</a>. For example, the <a href="#_routine_devnull.pod6"><span class="code">.devnull</span> method</a>:</p> | |
<pre class="code">{ | |
temp $*OUT = open :w, $*SPEC.devnull; | |
say "In space no one can hear you scream!"; | |
} | |
say "Hello"; | |
</pre> | |
<a name="t29.3.2"></a> <h2 id="_language_io-guide.pod6-Stringifying_IO::Path">Stringifying IO::Path</h2> | |
<p>Don't use the <span class="code">.Str</span> method to stringify <a href="#_type_IO::Path.pod6"><span class="code">IO::Path</span></a> objects, unless you just want to display them somewhere for information purposes or something. The <span class="code">.Str</span> method returns whatever basic path string the <a href="#_type_IO::Path.pod6"><span class="code">IO::Path</span></a> was instantiated with. It doesn't consider the value of the <a href="#_type_IO::Path.pod6-attribute_CWD"><span class="code">$.CWD</span> attribute</a>. For example, this code is broken:</p> | |
<pre class="code">my $path = 'foo'.IO; | |
chdir 'bar'; | |
# WRONG!! .Str DOES NOT USE $.CWD! | |
run <tar -cvvf archive.tar>, $path.Str; | |
</pre> | |
<p>The <a href="#_routine_chdir.pod6"><span class="code">chdir</span></a> call changed the value of the current directory, but the <span class="code">$path</span> we created is relative to the directory before that change.</p> | |
<p>However, the <a href="#_type_IO::Path.pod6"><span class="code">IO::Path</span></a> object <i>does</i> know what directory it's relative to. We just need to use <a href="#_routine_absolute.pod6"><span class="code">.absolute</span></a> or <a href="#_routine_relative.pod6"><span class="code">.relative</span></a> to stringify the object. Both routines return a <a href="#_type_Str.pod6"><span class="code">Str</span></a> object; they only differ in whether the result is an absolute or relative path. So, we can fix our code like this:</p> | |
<pre class="code">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; | |
</pre> | |
<a name="t29.3.3"></a> <h2 id="_language_io-guide.pod6-Be_mindful_of_$*CWD">Be mindful of $*CWD</h2> | |
<p>While usually out of view, every <a href="#_type_IO::Path.pod6"><span class="code">IO::Path</span></a> object, by default, uses the current value of <a href="#_language_variables.pod6-Dynamic_variables"><span class="code">$*CWD</span></a> to set its <a href="#_type_IO::Path.pod6-attribute_CWD"><span class="code">$.CWD</span> attribute</a>. This means there are two things to pay attention to.</p> | |
<a name="t29.3.3.1"></a> <h3 id="_language_io-guide.pod6-temp_the_$*CWD">temp the $*CWD</h3> | |
<p>This code is a mistake:</p> | |
<pre class="code"># WRONG!! | |
my $*CWD = "foo".IO; | |
</pre> | |
<p>The <span class="code">my $*CWD</span> made <a href="#_language_variables.pod6-Dynamic_variables"><span class="code">$*CWD</span></a> undefined. The <a href="#_routine_IO.pod6"><span class="code">.IO</span></a> coercer then goes ahead and sets the <a href="#_type_IO::Path.pod6-attribute_CWD"><span class="code">$.CWD</span> attribute</a> of the path it's creating to the stringified version of the undefined <span class="code">$*CWD</span>; an empty string.</p> | |
<p>The correct way to perform this operation is use <a href="#_routine_temp.pod6"><span class="code">temp</span></a> instead of <span class="code">my</span>. It'll localize the effect of changes to <a href="#_language_variables.pod6-Dynamic_variables"><span class="code">$*CWD</span></a>, just like <span class="code">my</span> would, but it won't make it undefined, so the <a href="#_routine_IO.pod6"><span class="code">.IO</span></a> coercer will still get the correct old value:</p> | |
<pre class="code">temp $*CWD = "foo".IO; | |
</pre> | |
<p>Better yet, if you want to perform some code in a localized <a href="#_language_variables.pod6-Dynamic_variables"><span class="code">$*CWD</span></a>, use the <a href="#_routine_indir.pod6"><span class="code">indir</span> routine</a> for that purpose.</p> | |
</div> | |
<!-- /language/io.pod6 --><div class="pod-body"><a id="_language_io.pod6"></a><a name="t30"></a><h1 class="title">30 Input/Output</h1> <p class="subtitle">File-related operations</p> <p>Here we present a quick overview of the file-related input/output operations. Details can be found in the documentation for the <a href="#_type_IO.pod6">IO</a> role, as well as the <a href="#_type_IO::Handle.pod6">IO::Handle</a> and <a href="#_type_IO::Path.pod6">IO::Path</a> types.</p> | |
<a name="t30.1"></a> <h1 id="_language_io.pod6-Reading_from_files">Reading from files</h1> | |
<p>One way to read the contents of a file is to open the file via the <span class="code">open</span> function with the <span class="code">:r</span> (read) file mode option and slurp in the contents:</p> | |
<pre class="code">my $fh = open "testfile", :r; | |
my $contents = $fh.slurp; | |
$fh.close; | |
</pre> | |
<p>Here we explicitly close the filehandle using the <span class="code">close</span> method on the <span class="code">IO::Handle</span> 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:</p> | |
<pre class="code">my $contents = "testfile".IO.slurp; | |
# or in procedural form: | |
$contents = slurp "testfile" | |
</pre> | |
<p>By adding the <span class="code">IO</span> 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 <span class="code">slurp</span> takes care of opening and closing the file for you.</p> | |
<a name="t30.1.1"></a> <h2 id="_language_io.pod6-Line_by_line">Line by line</h2> | |
<p>We also have the option to read a file line-by-line. The new line separator (i.e., <span class="code">$*IN.nl-in</span>) will be excluded.</p> | |
<pre class="code">for 'huge-csv'.IO.lines -> $line { | |
# Do something with $line | |
} | |
# or if you'll be processing later | |
my @lines = 'huge-csv'.IO.lines; | |
</pre> | |
<a name="t30.2"></a> <h1 id="_language_io.pod6-Writing_to_files">Writing to files</h1> | |
<p>To write data to a file, again we have the choice of the traditional method of calling the <span class="code">open</span> function – this time with the <span class="code">:w</span> (write) option – and printing the data to the file:</p> | |
<pre class="code">my $fh = open "testfile", :w; | |
$fh.print("data and stuff\n"); | |
$fh.close; | |
</pre> | |
<p>Or equivalently with <span class="code">say</span>, thus the explicit newline is no longer necessary:</p> | |
<pre class="code">my $fh = open "testfile", :w; | |
$fh.say("data and stuff"); | |
$fh.close; | |
</pre> | |
<p>We can simplify this by using <span class="code">spurt</span> to open the file in write mode, writing the data to the file and closing it again for us:</p> | |
<pre class="code">spurt "testfile", "data and stuff\n"; | |
</pre> | |
<p>By default all (text) files are written as UTF-8, however if necessary, an explicit encoding can be specified via the <span class="code">:enc</span> option:</p> | |
<pre class="code">spurt "testfile", "latin1 text: äöüß", enc => "latin1"; | |
</pre> | |
<p>To write formatted strings to a file, use the <a href="#_routine_printf.pod6">printf</a> function of <a href="#_type_IO::Handle.pod6">IO::Handle</a>.</p> | |
<pre class="code">my $fh = open "testfile", :w; | |
$fh.printf("formatted data %04d\n", 42); | |
$fh.close; | |
</pre> | |
<p>To append to a file, specify the <span class="code">:a</span> option when opening the filehandle explicitly,</p> | |
<pre class="code">my $fh = open "testfile", :a; | |
$fh.print("more data\n"); | |
$fh.close; | |
</pre> | |
<p>or equivalently with <span class="code">say</span>, thus the explicit newline is no longer necessary,</p> | |
<pre class="code">my $fh = open "testfile", :a; | |
$fh.say("more data"); | |
$fh.close; | |
</pre> | |
<p>or even simpler with the <span class="code">:append</span> option in the call to <span class="code">spurt</span>:</p> | |
<pre class="code">spurt "testfile", "more data\n", :append; | |
</pre> | |
<p>To explicitly write binary data to a file, open it with the <span class="code">:bin</span> option. The input/output operations then will take place using the <span class="code">Buf</span> type instead of the <span class="code">Str</span> type.</p> | |
<a name="t30.3"></a> <h1 id="_language_io.pod6-Copying,_renaming,_and_removing_files">Copying, renaming, and removing files</h1> | |
<p>Routines <span class="code">copy</span>, <span class="code">rename</span>, <span class="code">move</span>, and <span class="code">unlink</span> are available to avoid low-level system commands. See details at <a href="#_routine_copy.pod6">copy</a>, <a href="#_routine_rename.pod6">rename</a>, <a href="#_routine_move.pod6">move</a>, and <a href="#_routine_unlink.pod6">unlink</a>. Some examples:</p> | |
<pre class="code">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 | |
unlink $filea; | |
$fileb.IO.unlink; | |
</pre> | |
<p>The two <span class="code">unlink</span> sentences remove their argument if it exists, unless the user does not have the correct permissions to do so; in that case, it raises an exception.</p> | |
<a name="t30.4"></a> <h1 id="_language_io.pod6-Checking_files_and_directories">Checking files and directories</h1> | |
<p>Use the <span class="code">e</span> method on an <span class="code">IO::Handle</span> object to test whether the file or directory exists.</p> | |
<pre class="code">if "nonexistent_file".IO.e { | |
say "file exists"; | |
} | |
else { | |
say "file doesn't exist"; | |
} | |
</pre> | |
<p>It is also possible to use the colon pair syntax to achieve the same thing:</p> | |
<pre class="code">if "path/to/file".IO ~~ :e { | |
say 'file exists'; | |
} | |
</pre> | |
<pre class="code">my $file = "path/to/file"; | |
if $file.IO ~~ :e { | |
say 'file exists'; | |
} | |
</pre> | |
<p>Similarly to the file existence check, one can also check to see if a path is a directory. For instance, assuming that the file <span class="code">testfile</span> and the directory <span class="code">lib</span> exist, we would obtain from the existence test method <span class="code">e</span> the same result, namely that both exist:</p> | |
<pre class="code">say "testfile".IO.e; # OUTPUT: «True» | |
say "lib".IO.e; # OUTPUT: «True» | |
</pre> | |
<p>However, since only one of them is a directory, the directory test method <span class="code">d</span> will give a different result:</p> | |
<pre class="code">say "testfile".IO.d; # OUTPUT: «False» | |
say "lib".IO.d; # OUTPUT: «True» | |
</pre> | |
<p>Naturally the tables are turned if we check to see if the path is a file via the file test method <span class="code">f</span>:</p> | |
<pre class="code">say "testfile".IO.f; # OUTPUT: «True» | |
say "lib".IO.f; # OUTPUT: «False» | |
</pre> | |
<p>There are other methods that can be used to query a file or directory, some useful ones are:</p> | |
<pre class="code">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 | |
</pre> | |
<p>See more methods and details at <a href="#_type_IO::Path.pod6">IO::Path</a>.</p> | |
<a name="t30.5"></a> <h1 id="_language_io.pod6-Getting_a_directory_listing">Getting a directory listing</h1> | |
<p>To list the contents of the current directory, use the <span class="code">dir</span> function. It returns a list of <a href="#_type_IO::Path.pod6">IO::Path</a> objects.</p> | |
<pre class="code">say dir; # OUTPUT: «"/path/to/testfile".IO "/path/to/lib".IO»</pre> | |
<p>To list the files and directories in a given directory, simply pass a path as an argument to <span class="code">dir</span>:</p> | |
<pre class="code">say dir "/etc/"; # OUTPUT: «"/etc/ld.so.conf".IO "/etc/shadow".IO ....»</pre> | |
<a name="t30.6"></a> <h1 id="_language_io.pod6-Creating_and_removing_directories">Creating and removing directories</h1> | |
<p>To create a new directory, simply call the <span class="code">mkdir</span> function with the directory name as its argument:</p> | |
<pre class="code">mkdir "newdir"; | |
</pre> | |
<p>The function returns the name of the created directory on success and <span class="code">Nil</span> on failure. Thus the standard Perl idiom works as expected:</p> | |
<pre class="code">mkdir "newdir" or die "$!"; | |
</pre> | |
<p>Use <span class="code">rmdir</span> to remove <i>empty</i> directories:</p> | |
<pre class="code">rmdir "newdir" or die "$!"; | |
</pre> | |
</div> | |
<!-- /language/ipc.pod6 --><div class="pod-body"><a id="_language_ipc.pod6"></a><a name="t31"></a><h1 class="title">31 Inter-process communication</h1> <p class="subtitle">Programs running other programs and communicating with them</p> <p><a id="i499" name="Language IPC"></a><span class="indexed"></span></p> | |
<a name="t31.1"></a> <h1 id="_language_ipc.pod6-Running_programs"><a name="500"></a>Running programs</h1> | |
<p>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 Raku is as easy as:</p> | |
<pre class="code">run 'git', 'status';</pre> | |
<p>This line runs the program named "git" and passes "git" and "status" to its command-line. It will find the program using the <span class="code">%*ENV<PATH> </span> setting.</p> | |
<p>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 metacharacters are interpreted by the shell, including pipes, redirects, environment variable substitutions and so on.</p> | |
<pre class="code">shell 'ls -lR | gzip -9 > ls-lR.gz';</pre> | |
<p>Caution should be taken when using <span class="code">shell</span> with user input.</p> | |
<a name="t31.2"></a> <h1 id="_language_ipc.pod6-The_Proc_object">The <span class="code">Proc</span> object</h1> | |
<p>Both <span class="code">run</span> and <span class="code">shell</span> return a <a href="#_type_Proc.pod6">Proc</a> 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.</p> | |
<pre class="code">my $git = run 'git', 'log', '--oneline', :out; | |
for $git.out.lines -> $line { | |
my ($sha, $subject) = $line.split: ' ', 2; | |
say "$subject [$sha]"; | |
} | |
$git.out.close();</pre> | |
<p>If the program fails (exits with a non-zero exit code), it will throw an exception when the returned <a href="#_type_Proc.pod6">Proc</a> object is sunk. You can save it into a variable, even anonymous one, to prevent the sinking:</p> | |
<pre class="code">$ = run '/bin/false'; # does not sink the Proc and so does not throw</pre> | |
<p>You can tell the <span class="code">Proc</span> object to capture output as a filehandle by passing the <span class="code">:out</span> and <span class="code">:err</span> flags. You may also pass input via the <span class="code">:in</span> flag.</p> | |
<pre class="code">my $echo = run 'echo', 'Hello, world', :out; | |
my $cat = run 'cat', '-n', :in($echo.out), :out; | |
say $cat.out.get; | |
$cat.out.close();</pre> | |
<p>You may also use <span class="code">Proc</span> to capture the PID, send signals to the application, and check the exitcode.</p> | |
<pre class="code">my $crontab = run 'crontab', '-l'; | |
if $crontab.exitcode == 0 { | |
say 'crontab -l ran ok'; | |
} | |
else { | |
say 'something went wrong'; | |
}</pre> | |
<a name="t31.3"></a> <h1 id="_language_ipc.pod6-The_Proc::Async_object">The <span class="code">Proc::Async</span> object</h1> | |
<p>When you need more control over the communication with and from another process, you will want to make use of <a href="#_type_Proc::Async.pod6">Proc::Async</a>. This class provides support for asynchronous communication with a program, as well as the ability to send signals to that program.</p> | |
<pre class="code"># 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; | |
</pre> | |
<p>The small program above uses the "tail" program to print out the contents of the log named <span class="code">system.log</span> for 10 seconds and then tells the program to stop with a QUIT signal.</p> | |
<p>Whereas <span class="code">Proc</span> provides access to output using <span class="code">IO::Handle</span>s, <span class="code">Proc::Async</span> provides access using asynchronous supplies (see <a href="#_type_Supply.pod6">Supply</a>).</p> | |
<p>If you want to run a program and do some work while you wait for the original program to finish, the <span class="code">start</span> routine returns a <a href="#_type_Promise.pod6">Promise</a>, which is kept when the program quits.</p> | |
<p>Use the <span class="code">write</span> method to pass data into the program.</p> | |
</div> | |
<!-- /language/iterating.pod6 --><div class="pod-body"><a id="_language_iterating.pod6"></a><a name="t32"></a><h1 class="title">32 Iterating</h1> <p class="subtitle">Functionalities available for visiting all items in a complex data structure</p> <a name="t32.1"></a> <h1 id="_language_iterating.pod6-The_Iterator_and_Iterable_roles">The <span class="code">Iterator</span> and <span class="code">Iterable</span> roles</h1> | |
<p>Raku 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 <a href="#_type_Iterator.pod6">Iterator</a> and <a href="#_type_Iterable.pod6">Iterable</a> roles.</p> | |
<p>The <span class="code">Iterable</span> role is relatively simple. It provides a stub for the <span class="code">iterator</span> method, which is the one actually used by statements such as <span class="code">for</span>. <span class="code">for</span> will call <span class="code">.iterator</span> on the variable it precedes, and then run a block once for every item. Other methods, such as array assignment, will make the <span class="code">Iterable</span> class behave in the same way.</p> | |
<pre class="code">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.raku; | |
# OUTPUT: «[("A", "C", "G"), ("T", "A", "C"), ("G", "T", "T")]» | |
say @longer-chain».join("").join("|"); # OUTPUT: «ACG|TAC|GTT» | |
</pre> | |
<p>In this example, which is an extension of the <a href="#_type_Iterable.pod6">example in <span class="code">Iterable</span> that shows how <span class="code">for</span> calls <span class="code">.iterator</span></a>, the <span class="code">iterator</span> method will be called in the appropriate context only when the created object is assigned to a <a href="#_type_Positional.pod6">Positional</a> variable, <span class="code">@longer-chain</span>; this variable is an <a href="#_type_Array.pod6">Array</a> and we operate on it as such in the last example.</p> | |
<p>The (maybe a bit confusingly named) <span class="code">Iterator</span> role is a bit more complex than <span class="code">Iterable</span>. First, it provides a constant, <span class="code">IterationEnd</span>. Then, it also provides a series of <a href="#_type_Iterator.pod6-Methods">methods</a> such as <span class="code">.pull-one</span>, 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 <span class="code">pull-one</span>, of which only a stub is provided by the role. While <span class="code">Iterable</span> provides the high-level interface loops will be working with, <span class="code">Iterator</span> provides the lower-level functions that will be called in every iteration of the loop. Let's extend the previous example with this role.</p> | |
<pre class="code">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)» | |
</pre> | |
<p>We declare a <span class="code">DNA</span> class which does the two roles, <span class="code">Iterator</span> and <span class="code">Iterable</span>; 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.</p> | |
<p>Let us look at the <span class="code">pull-one</span> 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 <span class="code">$.index</span> attribute will hold that state across invocations; <span class="code">pull-one</span> will check if the end of the chain has been reached and will return the <span class="code">IterationEnd</span> constant provided by the role. Implementing this low-level interface, in fact, simplifies the implementation of the <span class="code">Iterable</span> interface. Now the iterator will be the object itself, since we can call <span class="code">pull-one</span> on it to access every member in turn; <span class="code">.iterator</span> will thus return just <span class="code">self</span>; this is possible since the object will be, at the same time, <span class="code">Iterable</span> and <span class="code">Iterator</span>.</p> | |
<p>This need not always be the case, and in most cases <span class="code">.iterator</span> 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.</p> | |
<a name="t32.2"></a> <h1 id="_language_iterating.pod6-How_to_iterate:_contextualizing_and_topic_variables">How to iterate: contextualizing and topic variables</h1> | |
<p><span class="code">for</span> and other loops place the item produced in every iteration into the <a href="#_language_variables.pod6-index-entry-topic_variable">topic variable <span class="code">$_</span></a>, 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 <a href="#_syntax_$CIRCUMFLEX_ACCENT.pod6-(Traps_to_avoid)_twigil_^"><span class="code">^</span> twigil</a>.</p> | |
<p>Implicit iteration occurs when using the <a href="#_language_operators.pod6-index-entry-..._operators">sequence operator</a>.</p> | |
<pre class="code">say 1,1,1, { $^a²+2*$^b+$^c } … * > 300; # OUTPUT: «(1 1 1 4 7 16 46 127 475)</pre> | |
<p>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.</p> | |
<p>This can be done more systematically through the use of the <a href="#_syntax_gather take.pod6"><span class="code">gather/take</span> blocks</a>, which are a different kind of iterating construct that instead of running in sink context, returns an item every iteration. This <a href="#_routine_https:__perl6advent.wordpress.com_2009_12_23_day-23-lazy-fruits-from-the-gather-of-eden_.pod6">Advent Calendar tutorial</a> 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 <span class="code">take</span> and creates a list out of them.</p> | |
<a name="t32.3"></a> <h1 id="_language_iterating.pod6-Classic_loops_and_why_we_do_not_like_them"><span class="code">Classic</span> loops and why we do not like them</h1> | |
<p>Classic <span class="code">for</span> loops, with a loop variable being incremented, can be done in Raku through the <a href="#_language_control.pod6-loop"><span class="code">loop</span> keyword</a>. Other <a href="#_language_control.pod6-repeat/while,_repeat/until">repeat</a> and <a href="#_language_control.pod6-while,_until">while</a> loops are also possible.</p> | |
<p>However, in general, they are discouraged. Raku is a functional and concurrent language; when coding in Raku, 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 <a href="#_routine_hyper.pod6"><span class="code">hyper</span></a> or <a href="#_routine_race.pod6"><span class="code">race</span></a> auto-threading methods.</p> | |
<p>If you feel more comfortable with your good old loops, the language allows you to use them. However, it is considered better practice in Raku to try and use, whenever possible, functional and concurrent iterating constructs.</p> | |
<p><i>Note:</i> Since version 6.d loops can produce a list of values from the values of last statements.</p> | |
</div> | |
<!-- /language/js-nutshell.pod6 --><div class="pod-body"><a id="_language_js-nutshell.pod6"></a><a name="t33"></a><h1 class="title">33 JavaScript (Node.js) to Raku - nutshell</h1> <p class="subtitle">Learning Raku from Node.js, in a nutshell</p> <p>This page attempts to provide a way for users experienced in Node.js to learn Raku. Features shared between the two languages will be explained here, as well as major differences in syntax and features.</p> | |
<p>This is not a tutorial for learning Raku; this is a reference for users who are already at an intermediate to advanced skill level with Node.js.</p> | |
<a name="t33.1"></a> <h1 id="_language_js-nutshell.pod6-Basic_syntax">Basic syntax</h1> | |
<a name="t33.1.1"></a> <h2 id="_language_js-nutshell.pod6-"Hello,_world!"">"Hello, world!"</h2> | |
<p>Let's start with the typical first program when learning new languages. In Node.js, a hello world program would be written like this:</p> | |
<pre class="code">console.log('Hello, world!'); | |
</pre> | |
<p>Here are a couple ways to write this in the same way in Raku:</p> | |
<pre class="code">say('Hello, world!'); | |
say 'Hello, world!'; | |
</pre> | |
<p>Parentheses are optional for function calls in Raku. While semicolons are, for the most part, optional in Node.js, they are mandatory for expressions in Raku.</p> | |
<p>Now that we've greeted the world, let's greet our good friend, Joe. We'll start with Node.js again:</p> | |
<pre class="code">let name = 'Joe'; | |
console.log('What\'s up,' + name + '?'); | |
console.log(`What's up, ${name}?`); | |
console.log("What's up, ", name, "?"); | |
</pre> | |
<p>Since he didn't hear us, let's greet him again, this time in Raku:</p> | |
<pre class="code">my $name = 'Joe'; | |
say 'What\'s up, ' ~ $name ~ '?'; | |
say "What's up, $name?"; | |
say "What's up, ", $name, "?"; | |
</pre> | |
<p>Here, there are only a couple differences: most variables in Raku have what are called sigils, which are what the <span class="code">$</span> in front of its name is, and string concatenation uses the <span class="code">~</span> operator instead of <span class="code">+</span>. What the two languages share in common here is support for string interpolation.</p> | |
<p>Now that the basic examples are out of the way, let's explain the similarities between the two languages in greater detail.</p> | |
<a name="t33.1.2"></a> <h2 id="_language_js-nutshell.pod6-Variables">Variables</h2> | |
<p>Variables in Node.js can be defined like this;</p> | |
<pre class="code">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 Raku dynamic variables exists. | |
global.foo = 1; // Globally scoped | |
foo = 1; // Ditto, but implicit; forbidden in strict mode | |
</pre> | |
<p>In Raku there is no equivalent to <span class="code">var</span>. An important note to make is that there is no variable hoisting in Raku; 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.</p> | |
<p>In addition to regular variables, in Raku 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 Raku:</p> | |
<pre class="code">my $foo = 1; # Lexically scoped | |
our $foo = 1; # Package scoped | |
</pre> | |
<pre class="code">my constant foo = 1; # Lexically scoped; constant | |
</pre> | |
<pre class="code">constant foo = 1; # Package scoped; constant | |
</pre> | |
<pre class="code">my $*foo = 1; # Dynamic variable; lexically scoped | |
our $*foo = 1; # Dynamic variable; package scoped | |
</pre> | |
<p>GLOBAL::<$foo> := 1; # Globally scoped</p> | |
<p>Use <span class="code">my</span> where you'd use <span class="code">let</span>, <span class="code">our</span> for variables you'd define in the outermost scope needed, and <span class="code">constant</span> where you'd use <span class="code">const</span>.</p> | |
<p>You may have noticed the <span class="code">$</span> and <span class="code">$*</span> 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 <a href="#_language_variables.pod6">variables</a> for more information on sigils, twigils, and containers.</p> | |
<p>Variables in Node.js can have the same name as others from outer scopes without conflicting (though linters will usually complain about it depending on how they're configured):</p> | |
<pre class="code">let foo = 1; | |
function logDupe() { | |
let foo = 2; | |
console.log(foo); | |
} | |
logDupe(2); // OUTPUT: 2 | |
console.log(foo); // OUTPUT: 1 | |
</pre> | |
<p>Raku also allows this:</p> | |
<pre class="code">my $foo = 1; | |
sub log-dupe { | |
my $foo = 2; | |
say $foo; | |
} | |
log-dupe; # OUTPUT: 2 | |
say $foo; # OUTPUT: 1 | |
</pre> | |
<a name="t33.1.3"></a> <h2 id="_language_js-nutshell.pod6-Operators">Operators</h2> | |
<a name="t33.1.3.1"></a> <h3 id="_language_js-nutshell.pod6-Assignment">Assignment</h3> | |
<p>The <span class="code">=</span> operator works the same across both languages.</p> | |
<p>The <span class="code">:=</span> operator in Raku 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 <span class="code">=</span> or mutated with <span class="code">++</span>, <span class="code">--</span>, etc. but they can be bound to another value again:</p> | |
<pre class="code">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: {} | |
</pre> | |
<a name="t33.1.3.2"></a> <h3 id="_language_js-nutshell.pod6-Equality">Equality</h3> | |
<p>Node.js has two equality operators: <span class="code">==</span> and <span class="code">===</span>.</p> | |
<p><span class="code">==</span> 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:</p> | |
<pre class="code">console.log(1 == 1); // OUTPUT: true | |
console.log('1' == 1); // OUTPUT: true | |
console.log([] == 0); // OUTPUT: true | |
</pre> | |
<p>Similarly, in Raku, both operands are cast to Numeric before comparison if they don't share the same type:</p> | |
<pre class="code">say 1 == 1; # OUTPUT: True | |
say '1' == 1; # OUTPUT: True | |
say [1,2,3] == 3; # OUTPUT: True, since the array has three elements | |
</pre> | |
<p>The inverse of <span class="code">==</span> is <span class="code">!=</span>.</p> | |
<p>Raku has another operator similar to <span class="code">==</span>: <span class="code">eq</span>. Instead of casting operands to Numeric if they're different types, <span class="code">eq</span> will cast them to strings:</p> | |
<pre class="code">say '1' eq '1'; # OUTPUT: True | |
say 1 eq '1'; # OUTPUT: True | |
</pre> | |
<p>The inverse of <span class="code">eq</span> is <span class="code">ne</span> or <span class="code">!eq</span>.</p> | |
<p><span class="code">===</span> is the strict equality operator. This returns true if both operands are the same value. When comparing objects, this will <i>only</i> return true if they are the exact same object:</p> | |
<pre class="code">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; | |
</pre> | |
<p>In Raku, the operator behaves the same, with one exception: two objects that have the same value, but different containers, will return false:</p> | |
<pre class="code">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 | |
</pre> | |
<p>In the last case it's the same object, but containers are different, which is why it returns False.</p> | |
<p>The inverse of <span class="code">===</span> is <span class="code">!==</span>.</p> | |
<p>This is where Raku's other equality operators are useful. If the values have different containers, the <span class="code">eqv</span> 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:</p> | |
<pre class="code">say {a => 1} eqv {a => 1}; # OUTPUT: True | |
my \hash = {}; | |
my %hash := hash; | |
say hash eqv %hash; # OUTPUT: True | |
</pre> | |
<p>In the case you need to check if two variables have the same container and value, use the <span class="code">=:=</span> operator.</p> | |
<pre class="code">my @arr = [1,2,3]; | |
my @arr2 := @arr; # Bound variables keep the container of the other variable | |
say @arr =:= @arr2; # OUTPUT: True | |
</pre> | |
<a name="t33.1.3.3"></a> <h3 id="_language_js-nutshell.pod6-Smartmatching">Smartmatching</h3> | |
<p>Raku has one last operator for comparing values, but it is not exactly an equality operator. This is <span class="code">~~</span>, the smartmatch operator. This has several uses: it can be used like <span class="code">instanceof</span> in Node.js, to match a regex, and to check if a value is a key in a hash, bag, set, or map:</p> | |
<pre class="code">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 | |
</pre> | |
<p>While we are talking about <span class="code">instanceof</span>, the equivalent to the <span class="code">constructor</span> property on Node.js objects in Raku is the <span class="code">WHAT</span> attribute:</p> | |
<pre class="code">console.log('foo'.constructor); // OUTPUT: String | |
</pre> | |
<pre class="code">say 'foo'.WHAT; # OUTPUT: Str | |
</pre> | |
<a name="t33.1.3.4"></a> <h3 id="_language_js-nutshell.pod6-Numeric">Numeric</h3> | |
<p>Node.js has <span class="code">+</span>, <span class="code">-</span>, <span class="code">/</span>, <span class="code">*</span>, <span class="code">%</span>, and (in ES6) <span class="code">**</span> 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:</p> | |
<pre class="code">console.log(1 + 2); // OUTPUT: 3 | |
console.log([] + {}); // OUTPUT: [object Object] | |
console.log({} + []); // OUTPUT: 0 | |
</pre> | |
<p>In Raku, again, they are converted to a Numeric type, as before:</p> | |
<pre class="code">say 1 + 2; # OUTPUT: 3 | |
say [] + {}; # OUTPUT: 0 | |
say {} + [1,2,3]; # OUTPUT: 3 | |
</pre> | |
<p>In addition, Raku has <span class="code">div</span> and <span class="code">%%</span>. <span class="code">div</span> behaves like <span class="code">int</span> division in C, while <span class="code">%%</span> checks if one number is cleanly divisible by another or not:</p> | |
<pre class="code">say 4 div 3; # OUTPUT: 1 | |
say 4 %% 3; # OUTPUT: False | |
say 6 %% 3; # OUTPUT: True | |
</pre> | |
<a name="t33.1.3.5"></a> <h3 id="_language_js-nutshell.pod6-Bitwise">Bitwise</h3> | |
<p>Node.js has <span class="code">&</span>, <span class="code">|</span>, <span class="code">^</span>, <span class="code">~</span>, <span class="code"><<</span>, <span class="code">>></span>, <span class="code">>>></span>, and <span class="code">~</span> for bitwise operators:</p> | |
<pre class="code">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 | |
</pre> | |
<p>In Raku, there is no equivalent to <span class="code">>>></span>. All bitwise operators are prefixed with <span class="code">+</span>, however bitwise negation uses <span class="code">+^</span> instead of <span class="code">~</span>:</p> | |
<pre class="code">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 | |
</pre> | |
<a name="t33.1.3.6"></a> <h3 id="_language_js-nutshell.pod6-Checking_for_definedness">Checking for definedness</h3> | |
<p>Javascript includes a nullish coalescing operator, <span class="code">??</span>, which progresses only if null or undefined:</p> | |
<pre class="code">undefined || null || 0 || 1 ; // => 1 | |
undefined ?? null ?? 0 ?? 1 ; // => 0 | |
</pre> | |
<p>This is very similar to Raku <a href="#_routine_$SOLIDUS$SOLIDUS.pod6"><span class="code">//</span></a> operator:</p> | |
<pre class="code">Any || Nil || 0 || 1 ; # => 1 | |
Any // Nil // 0 // 1 ; # => 0 | |
</pre> | |
<a name="t33.1.3.7"></a> <h3 id="_language_js-nutshell.pod6-Custom_operators_and_operator_overloading">Custom operators and operator overloading</h3> | |
<p>Node.js does not allow operator overloading without having to use a Makefile or build Node.js with a custom version of V8. Raku allows custom operators and operator overloading natively! Since all operators are subroutines, you can define your own like so:</p> | |
<pre class="code">multi sub infix:<||=>($a, $b) is equiv(&infix:<+=>) { $a || $b } | |
my $foo = 0; | |
$foo ||= 1; | |
say $foo; # OUTPUT: 1 | |
</pre> | |
<p>Operators can be defined as <span class="code">prefix</span>, <span class="code">infix</span>, or <span class="code">postfix</span>. The <span class="code">is tighter</span>, <span class="code">is equiv</span>, and <span class="code">is looser</span> traits optionally define the operator's precedence. In this case, <span class="code">||=</span> has the same precedence as <span class="code">+=</span>.</p> | |
<p>Note how <span class="code">multi</span> 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 <a href="#32-Functions">Functions</a> section. For now, all we need to know is that it allows us to override any native operator we want:</p> | |
<pre class="code"># 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 | |
</pre> | |
<a name="t33.1.4"></a> <h2 id="_language_js-nutshell.pod6-Control_flow">Control flow</h2> | |
<a name="t33.1.4.1"></a> <h3 id="_language_js-nutshell.pod6-if/else">if/else</h3> | |
<p>You should be familiar with how <span class="code">if</span>/<span class="code">else</span> looks in JavaScript:</p> | |
<pre class="code">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}.`); | |
} | |
</pre> | |
<p>In Raku, <span class="code">if</span>/<span class="code">else</span> works largely the same, with a few key differences. One, parentheses are not required. Two, <span class="code">else if</span> is written as <span class="code">elsif</span>. Three, the if clause may be written <i>after</i> a statement:</p> | |
<pre class="code">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."; | |
} | |
</pre> | |
<p>Alternatively, though less efficient, this could be written to use <span class="code">if</span> after statements:</p> | |
<pre class="code">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; | |
</pre> | |
<p>Raku also has <span class="code">when</span>, which is like <span class="code">if</span>, but if the condition given is true, no code past the <span class="code">when</span> block within the block it's in is executed:</p> | |
<pre class="code">{ | |
when True { | |
say 'In when block!'; # OUTPUT: In when block! | |
} | |
say 'This will never be output!'; | |
} | |
</pre> | |
<p>Additionally, Raku has <span class="code">with</span>, <span class="code">orwith</span>, and <span class="code">without</span>, which are like <span class="code">if</span>, <span class="code">else if</span>, and <span class="code">else</span> respectively, but instead of checking whether their condition is true, they check if it's defined.</p> | |
<a name="t33.1.4.2"></a> <h3 id="_language_js-nutshell.pod6-switch">switch</h3> | |
<p>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. <span class="code">case</span> statements define each value to compare to. <span class="code">default</span>, if included, acts as a fallback for when the given value matches no cases. After matching a case, <span class="code">break</span> is typically used to prevent the code from the cases that follow the one matched from being executed, though rarely this is intentionally omitted.</p> | |
<pre class="code">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; | |
} | |
} | |
</pre> | |
<p>In Raku, <span class="code">given</span> can be used like switch statements. There is no equivalent to <span class="code">break</span> since <span class="code">when</span> blocks are most commonly used like <span class="code">case</span> statements. One major difference between <span class="code">switch</span> and <span class="code">given</span> is that a value passed to a <span class="code">switch</span> statement will only match cases that are exactly equal to the value; <span class="code">given</span> values are smartmatched (<span class="code">~~</span>) against the <span class="code">when</span> values.</p> | |
<pre class="code">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 { $_ } | |
}; | |
} | |
</pre> | |
<p>If there are multiple <span class="code">when</span> blocks that match the value passed to <span class="code">given</span> and you wish to run more than one of them, use <span class="code">proceed</span>. <span class="code">succeed</span> may be used to exit both the <span class="code">when</span> block it's in and the given block, preventing any following statements from being executed:</p> | |
<pre class="code">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 | |
</pre> | |
<a name="t33.1.4.3"></a> <h3 id="_language_js-nutshell.pod6-for,_while,_and_do/while">for, while, and do/while</h3> | |
<p>There are three different types of for loops in JavaScript:</p> | |
<pre class="code">// 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. | |
</pre> | |
<p>Raku <span class="code">for</span> loops most closely resemble <span class="code">for..of</span> loops, since they work on anything as long as it's iterable. C-style loops are possible to write using <span class="code">loop</span>, but this is discouraged since they're better written as <span class="code">for</span> loops using ranges. Like <span class="code">if</span> statements, <span class="code">for</span> may follow a statement, with the current iteration being accessible using the <span class="code">$_</span> variable (known as "it"). Methods on <span class="code">$_</span> may be called without specifying the variable:</p> | |
<pre class="code">my Str %letters{Str}; | |
%letters{$_} = .uc for 'a'..'z'; | |
.say for %letters.values; | |
# OUTPUT: | |
# A | |
# B | |
# C | |
# etc. | |
</pre> | |
<p><span class="code">while</span> loops work identically between JavaScript and Raku. Raku also has <span class="code">until</span> loops, where instead of iterating until the given condition is false, they iterate until the condition is true.</p> | |
<p><span class="code">do/while</span> loops are known as <span class="code">repeat/while</span> loops in Raku. Likewise with <span class="code">while</span>, <span class="code">repeat/until</span> loops also exist and loop until the given condition is false.</p> | |
<p>To write infinite loops in Raku, use <span class="code">loop</span> rather than <span class="code">for</span> or <span class="code">while</span>.</p> | |
<p>In JavaScript, <span class="code">continue</span> is used to skip to the next iteration in a loop, and <span class="code">break</span> is used to exit a loop early:</p> | |
<pre class="code">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 } | |
</pre> | |
<p>In Raku, these are known as <span class="code">next</span> and <span class="code">last</span> respectively. There is also <span class="code">redo</span>, which repeats the current iteration without evaluating the loop's condition again.</p> | |
<p><span class="code">next</span>/<span class="code">redo</span>/<span class="code">last</span> 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:</p> | |
<pre class="code">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) | |
</pre> | |
<a name="t33.1.4.4"></a> <h3 id="_language_js-nutshell.pod6-do">do</h3> | |
<p><span class="code">do</span> is not currently a feature in JavaScript, however a proposal has been made to <a href="#_routine_https:__github.com_tc39_proposal-do-expressions.pod6">add it to ECMAScript</a>. <span class="code">do</span> expressions evaluate a block and return the result:</p> | |
<pre class="code">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 | |
</pre> | |
<a name="t33.1.5"></a> <h2 id="_language_js-nutshell.pod6-Types">Types</h2> | |
<a name="t33.1.5.1"></a> <h3 id="_language_js-nutshell.pod6-Creating_types">Creating types</h3> | |
<p>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:</p> | |
<pre class="code">type ID = string | number; | |
</pre> | |
<p>In Raku, classes, roles, subsets, and enums are considered types. Creating classes and roles will be discussed in <a href="#32-Object-oriented_programming">the OOP section of this article</a>. Creating an ID subset can be done like so:</p> | |
<pre class="code">subset ID where Str | Int; | |
</pre> | |
<p>See the documentation on <a href="#_language_typesystem.pod6-subset">subset</a> and <a href="#_type_Junction.pod6">Junction</a> for more information.</p> | |
<p>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):</p> | |
<pre class="code">enum Direction ( | |
UP = '↑', | |
DOWN = '↓', | |
LEFT = '←', | |
RIGHT = '→' | |
); | |
</pre> | |
<p>Enums in Raku may have any type as their keys' values. Enum keys (and optionally, values) can be defined by writing <span class="code">enum</span>, followed by the name of the enum, then the list of keys (and optionally, values), which can be done using <a href="#_language_quoting.pod6-Word_quoting:_<_>">< ></a>, <a href="#_language_quoting.pod6-Word_quoting_with_interpolation_and_quote_protection:_«_»">« »</a>, or <a href="#_language_operators.pod6-term_(_)">( )</a>. <span class="code">( )</span> must be used if you want to define values for the enum's keys. Here is the Direction enum as written in Raku:</p> | |
<pre class="code">enum Direction ( | |
UP => '↑', | |
DOWN => '↓', | |
LEFT => '←', | |
RIGHT => '→' | |
); | |
</pre> | |
<p>See the documentation on <a href="#_language_typesystem.pod6-enum">enum</a> for more information.</p> | |
<a name="t33.1.5.2"></a> <h3 id="_language_js-nutshell.pod6-Using_types">Using types</h3> | |
<p>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:</p> | |
<pre class="code">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; | |
}; | |
</pre> | |
<p>In Raku, variables can be typed by placing the type between the declarator (<span class="code">my</span>, <span class="code">our</span>, 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:</p> | |
<pre class="code">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; | |
}; | |
</pre> | |
<a name="t33.1.5.3"></a> <h3 id="_language_js-nutshell.pod6-Comparing_JavaScript_and_Raku_types">Comparing JavaScript and Raku types</h3> | |
<p>Here is a table of some JavaScript types and their equivalents in Raku:</p> | |
<table> | |
<tr><th>JavaScript</th> <th>Raku</th></tr> | |
<tr><td>Object</td> <td>Mu, Any, Hash</td></tr> | |
<tr><td>Array</td> <td>List, Array, Seq</td></tr> | |
<tr><td>String</td> <td>Str</td></tr> | |
<tr><td>Number</td> <td>Int, Num, Rat</td></tr> | |
<tr><td>Boolean</td> <td>Bool</td></tr> | |
<tr><td>Map</td> <td>Map, Hash</td></tr> | |
<tr><td>Set</td> <td>Set, SetHash</td></tr> | |
</table> <p><span class="code">Object</span> is both a superclass of all types in JavaScript and a way to create a hash. In Raku, <a href="#_type_Mu.pod6">Mu</a> is a superclass of all types, though usually you want to use <a href="#_type_Any.pod6">Any</a> instead, which is a subclass of <span class="code">Mu</span> but also a superclass of nearly every type, with <a href="#_type_Junction.pod6">Junction</a> being an exception. When using <span class="code">Object</span> as a hash, <a href="#_type_Hash.pod6">Hash</a> is what you want to use. One key difference between <span class="code">Object</span> and <span class="code">Hash</span> is that <span class="code">Object</span> preserves the order of its keys; <span class="code">Hash</span> does not by default.</p> | |
<p>There are three types equivalent to <span class="code">Array</span>. <a href="#_type_Array.pod6">Array</a> is most similar to <span class="code">Array</span>, since it acts as a mutable array. <a href="#_type_List.pod6">List</a> is similar to <span class="code">Array</span>, but is immutable. <a href="#_type_Seq.pod6">Seq</a> is used to create lazy arrays.</p> | |
<p><span class="code">String</span> and <a href="#_type_Str.pod6">Str</a> are for the most part used identically.</p> | |
<p>There are several different types in Raku equivalent to <span class="code">Number</span>, but the three you'll most commonly see are <a href="#_type_Int.pod6">Int</a>, <a href="#_type_Num.pod6">Num</a>, and <a href="#_type_Rat.pod6">Rat</a>. <span class="code">Int</span> represents an integer. <span class="code">Num</span> represents a floating-point number, making it the most similar to <span class="code">Number</span>. <span class="code">Rat</span> represents a fraction of two numbers, and is used when <span class="code">Num</span> cannot provide precise enough values.</p> | |
<p><span class="code">Boolean</span> and <a href="#_type_Bool.pod6">Bool</a> are for the most part used identically.</p> | |
<p><span class="code">Map</span> has both a mutable and an immutable equivalent in Raku. <a href="#_type_Map.pod6">Map</a> is the immutable one, and <a href="#_type_Hash.pod6">Hash</a> is the mutable one. Don't get them mixed up! Like <span class="code">Map</span> in JavaScript, <span class="code">Map</span> and <span class="code">Hash</span> can have any type of key or value, not just strings for keys.</p> | |
<p>Like <span class="code">Map</span>, <span class="code">Set</span> also has both a mutable and an immutable equivalent in Raku. <a href="#_type_Set.pod6">Set</a> is the immutable one, and <a href="#_type_SetHash.pod6">SetHash</a> is the mutable one.</p> | |
<a name="t33.1.6"></a> <h2 id="_language_js-nutshell.pod6-Functions">Functions</h2> | |
TODO | |
<p># TBD</p> | |
<a name="t33.2"></a> <h1 id="_language_js-nutshell.pod6-Object-oriented_programming">Object-oriented programming</h1> | |
TODO | |
<p># TBD</p> | |
<a name="t33.3"></a> <h1 id="_language_js-nutshell.pod6-Asynchronous_programming">Asynchronous programming</h1> | |
TODO | |
<p># TBD</p> | |
<a name="t33.4"></a> <h1 id="_language_js-nutshell.pod6-The_networking_API">The networking API</h1> | |
<a name="t33.4.1"></a> <h2 id="_language_js-nutshell.pod6-Net">Net</h2> | |
<p>In Raku, there are two APIs for dealing with networking: <span class="code">IO::Socket::INET</span> (for synchronous networking), and <span class="code">IO::Socket::Async</span> (for asynchronous networking).</p> | |
<p><span class="code">IO::Socket::INET</span> 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:</p> | |
<pre class="code">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; | |
</pre> | |
<p>By default, <span class="code">IO::Socket::INET</span> connections are IPv4 only. To use IPv6 instead, pass <span class="code">:family(PF_INET6)</span> when constructing a server or a client.</p> | |
<p>In contrast, <span class="code">IO::Socket::Async</span> 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 <span class="code">Supply.tap</span> is multithreaded; if this is undesirable, use <span class="code">Supply.act</span> instead:</p> | |
<pre class="code">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!'; | |
</pre> | |
<p>The equivalent code in Node.js looks like this:</p> | |
<pre class="code">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!"); | |
}); | |
</pre> | |
<a name="t33.4.2"></a> <h2 id="_language_js-nutshell.pod6-HTTP/HTTPS">HTTP/HTTPS</h2> | |
<p>Raku doesn't natively support HTTP/HTTPS. However, CPAN packages such as <a href="#_routine_https:__cro.services_.pod6">Cro</a> help fill the gap.</p> | |
<a name="t33.4.3"></a> <h2 id="_language_js-nutshell.pod6-DNS">DNS</h2> | |
<p>Raku does not currently support the majority of the features that Node.js's DNS module implements. <span class="code">IO::Socket::INET</span> and <span class="code">IO::Socket::Async</span> 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 <a href="#_routine_https:__github.com_tbrowder_Net-DNS-BIND-Manage-Perl6_.pod6">Net::DNS::BIND::Manage</a>, that aim to improve DNS support.</p> | |
<a name="t33.4.4"></a> <h2 id="_language_js-nutshell.pod6-Punycode">Punycode</h2> | |
<p>Punycode support is available through the <a href="#_routine_https:__github.com_Kaiepi_p6-Net-LibIDN.pod6">Net::LibIDN</a>, <a href="#_routine_https:__github.com_Kaiepi_p6-Net-LibIDN2.pod6">Net::LibIDN2</a>, and <a href="#_routine_https:__github.com_FROGGS_p6-IDNA-Punycode.pod6">IDNA::Punycode</a> modules on CPAN.</p> | |
<a name="t33.5"></a> <h1 id="_language_js-nutshell.pod6-The_filesystem_API">The filesystem API</h1> | |
TODO | |
<p># TBD</p> | |
<a name="t33.6"></a> <h1 id="_language_js-nutshell.pod6-Modules_and_packages">Modules and packages</h1> | |
TODO | |
<p># TBD</p> | |
</div> | |
<!-- /language/list.pod6 --><div class="pod-body"><a id="_language_list.pod6"></a><a name="t34"></a><h1 class="title">34 Lists, sequences, and arrays</h1> <p class="subtitle">Positional data constructs</p> <p>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 Raku to design, but through persistence and patience, Raku has arrived with an elegant system for handling them.</p> | |
<a name="t34.1"></a> <h1 id="_language_list.pod6-Literal_lists">Literal lists</h1> | |
<p>Literal <a href="#_type_List.pod6"><span class="code">List</span> s</a> are created with commas and semicolons, <b>not</b> with parentheses, so:</p> | |
<pre class="code">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</pre> | |
<p>There is one exception, empty lists are created with just a pair of parentheses:</p> | |
<pre class="code">(); # This is an empty List | |
</pre> | |
<pre class="code">(,); # This is a syntax error | |
</pre> | |
<p>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.</p> | |
<p>Parentheses can be used to mark the beginning and end of a <span class="code">List</span>, so:</p> | |
<pre class="code">(1, 2), (1, 2); # This is a list of two lists.</pre> | |
<p><span class="code">List</span>s of <span class="code">List</span>s 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.</p> | |
<pre class="code">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»</pre> | |
<p>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:</p> | |
<pre class="code">say('foo';); # a list with one element and the empty list | |
# OUTPUT: «(foo)()» | |
say(('foo';)); # no list, just the string "foo" | |
# OUTPUT: «foo»</pre> | |
<p>Because the semicolon doubles as a <a href="#_language_control.pod6-Statements">statement terminator</a> 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:</p> | |
<pre class="code">say so (42) eqv $(my $a = 42; $a;); | |
# OUTPUT: «True» | |
say so (42,42) eqv (my $a = 42; $a;); | |
# OUTPUT: «True»</pre> | |
<p>Individual elements can be pulled out of a list using a subscript. The first element of a list is at index number zero:</p> | |
<pre class="code">say (1, 2)[0]; # says 1 | |
say (1, 2)[1]; # says 2 | |
say (1, 2)[2]; # says Nil | |
</pre> | |
<pre class="code">say (1, 2)[-1]; # Error | |
</pre> | |
<pre class="code">say ((<a b>,<c d>),(<e f>,<g h>))[1;0;1]; # says "f" | |
</pre> | |
<a name="t34.2"></a> <h1 id="_language_list.pod6-The_@_sigil">The @ sigil</h1> | |
<p>Variables in Raku whose names bear the <span class="code">@</span> sigil are expected to contain some sort of list-like object. Other variables may also contain these objects, but <span class="code">@</span>-sigiled variables always do, and are expected to act the part.</p> | |
<p>By default, when you assign a <span class="code">List</span> to an <span class="code">@</span>-sigiled variable, you create an <span class="code">Array</span>. Those are described below. If instead you want to refer directly to a <span class="code">List</span> object using an <span class="code">@</span>-sigiled variable, you can use binding with <span class="code">:=</span> instead.</p> | |
<pre class="code">my @a := 1, 2, 3;</pre> | |
<p>One of the ways <span class="code">@</span>-sigiled variables act like lists is by always supporting <a href="#_language_subscripts.pod6">positional subscripting</a>. Anything bound to a <span class="code">@</span>-sigiled value must support the <a href="#_type_Positional.pod6">Positional</a> role which guarantees that this is going to fail:</p> | |
<pre class="code">my @a := 1; # Type check failed in binding; expected Positional but got Int</pre> | |
<a name="t34.3"></a> <h1 id="_language_list.pod6-Reset_a_list_container">Reset a list container</h1> | |
<p>To remove all elements from a Positional container assign <a href="#_type_Slip.pod6-constant_Empty"><span class="code">Empty</span></a>, the empty list <span class="code">()</span> or a <span class="code">Slip</span> of the empty list to the container.</p> | |
<pre class="code">my @a = 1, 2, 3; | |
@a = (); | |
@a = Empty; | |
@a = |();</pre> | |
<a name="t34.4"></a> <h1 id="_language_list.pod6-Iteration">Iteration</h1> | |
<p>All lists may be iterated, which means taking each element from the list in order and stopping after the last element:</p> | |
<pre class="code">for 1, 2, 3 { .say } # OUTPUT: «123»</pre> | |
<a name="t34.4.1"></a> <h2 id="_language_list.pod6-Single_Argument_Rule"><a name="501"></a>Single Argument Rule</h2> | |
<p>It is the rule by which the set of parameters passed to an iterator such as <span class="code">for</span> is treated as a single argument, instead of several arguments; that is <span class="code">some-iterator( a, b, c, ...)</span> will always be treated as <span class="code">some-iterator( list-or-array(a, b, c))</span>. In this example</p> | |
<pre class="code">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 | |
</pre> | |
<p>Since what <span class="code">for</span> receives is a single argument, it will be treated as a list of elements to iterate over. The rule of thumb is that <a href="#_routine_https:__perl6advent.wordpress.com_2015_12_14_day-15-2015-the-year-of-the-great-list-refactor_.pod6">if there's a comma, anything preceding it is an element</a> and the list thus created becomes the <i>single element</i>. That happens in the case of the two arrays separated by a comma which is the third element in the <span class="code">Array</span> we are iterating in this example. In general, quoting the article linked above, the single argument rule <i>... makes for behavior as the programmer would expect</i>.</p> | |
<p>This rule is equivalent to saying that arguments to iterators will not flatten, will not de-containerize, and will behave as if a single argument has been handled to them, whatever the shape that argument has.</p> | |
<pre class="code">my @a = 1,2; .say for @a, |@a; # OUTPUT: «[1 2]12» | |
my @a = 1,2; .say for $[@a, |@a ]; # OUTPUT: «[[1 2] 1 2]» | |
</pre> | |
<p>In the second case, the single argument is a single element, since we have itemized the array. There's an exception to the single argument rule <a href="#_routine_https:__design.raku.org_S07.html.pod6-The_single_argument_rule">mentioned in the Synopsis</a>: list or arrays with a single element will be flattened:</p> | |
<pre class="code">my @a = 1,2; .say for [[@a ]]; # OUTPUT: «12» | |
</pre> | |
<p>The result may be a bit surprising in the case of using a trailing comma:</p> | |
<pre class="code">my @a = 1,2; .say for @a,; # OUTPUT: «[1 2]» | |
</pre> | |
<p>But the <a href="#_routine_,.pod6">comma operator</a> is actually building a higher-order <span class="code">List</span> with a single element, which is also a <span class="code">List</span>. So not so surprising. Since it's got a single element, any higher-order list will be also flattened as above:</p> | |
<pre class="code">my @a = 1,2; .say for [@a,]; # OUTPUT: «[1 2]» | |
</pre> | |
<a name="t34.5"></a> <h1 id="_language_list.pod6-Testing_for_elements">Testing for elements</h1> | |
<p>To test for elements in a <span class="code">List</span> or <span class="code">Array</span>, you can use the <a href="#_language_setbagmix.pod6-infix_(elem),_infix_∈">"is element of"</a> <a href="#_type_Set.pod6"><span class="code">Set</span></a> operator.</p> | |
<pre class="code">my @a = <foo bar buzz>; | |
say 'bar' (elem) @a; # OUTPUT: «True» | |
say 'bar' ∈ @a; # same, using unicode version of operator</pre> | |
<p>This is the equivalent of:</p> | |
<pre class="code">'bar' (elem) @a.Set; # convert the array to a Set first | |
</pre> | |
<p>except that, if possible, it won't actually do the conversion.</p> | |
<p>It basically compares the value with each element in the array using the <a href="#_routine_===.pod6">===</a> infix operator. If you want to use another way to compare values, you probably should use <a href="#_routine_first.pod6-(List)_routine_first">first</a>.</p> | |
<a name="t34.5.1"></a> <h2 id="_language_list.pod6-Sequences">Sequences</h2> | |
<p>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 <a href="#_type_Seq.pod6">Seq</a>. As it so happens, loops return <span class="code">Seq</span>s.</p> | |
<pre class="code">(loop { 42.say })[2] # OUTPUT: «424242»</pre> | |
<p>So, it is fine to have infinite lists in Raku, 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 – Raku will try to return <span class="code">Inf</span> if it knows a sequence is infinite, but it cannot always know.</p> | |
<p>These lists can be built using the <a href="#_language_operators.pod6-infix_...">...</a> operator, which builds lazy lists using a variety of generating expressions.</p> | |
<p>Although the <span class="code">Seq</span> class does provide some positional subscripting, it does not provide the full interface of <span class="code">Positional</span>, so an <span class="code">@</span>-sigiled variable may <b>not</b> be bound to a <span class="code">Seq</span>, and trying to do so will yield an error.</p> | |
<pre class="code">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))»</pre> | |
<p>This is because the <span class="code">Seq</span> 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:</p> | |
<pre class="code">for 'filename'.IO.lines -> $line { | |
do-something-with($line); | |
} | |
</pre> | |
<p>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.</p> | |
<p>On the other hand, you may want to keep old values around in some cases. It is possible to hide a <span class="code">Seq</span> inside a <span class="code">List</span>, which will still be lazy, but will remember old values. This is done by calling the <span class="code">.list</span> method. Since this <span class="code">List</span> fully supports <span class="code">Positional</span>, you may bind it directly to an <span class="code">@</span>-sigiled variable.</p> | |
<pre class="code">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</pre> | |
<p>You may also use the <span class="code">.cache</span> method instead of <span class="code">.list</span>, depending on how you want the references handled. See the <a href="#_type_Seq.pod6">page on <span class="code">Seq</span></a> for details.</p> | |
<a name="t34.5.2"></a> <h2 id="_language_list.pod6-Using_.iterator">Using <span class="code">.iterator</span></h2> | |
<p>All lists mix in the <a href="#_type_Iterator.pod6">Iterator</a> role, and as such have an <span class="code">.iterator</span> method they can use for a finer control over a list. We can use it like this, for instance:</p> | |
<pre class="code">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; | |
</pre> | |
<p>Instead of using the iterator implicitly as we do in <span class="code">for</span> loops, we explicitly assign it to the <span class="code">$odd-iterator</span> variable to work over the odd elements of the sequence only. That way, we can skip even elements using <span class="code">.skip-one</span>. We do have to test explicitly for termination, which we do in the <span class="code">until</span> expression. When there's nothing left to iterate, <span class="code">$odd</span> will have the value <span class="code">IterationEnd</span>. Please check the <a href="#_type_Iterator.pod6">documentation on <span class="code">Iterator</span> s</a> for the methods and functions that are available.</p> | |
<a name="t34.5.3"></a> <h2 id="_language_list.pod6-Slips">Slips</h2> | |
<p>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 <a href="#_type_Slip.pod6">Slip</a>.</p> | |
<pre class="code">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»</pre> | |
<p>Another way to make a <span class="code">Slip</span> is with the <span class="code">|</span> 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 <a href="#_type_Scalar.pod6">Scalars</a>.</p> | |
<pre class="code">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: «True»</pre> | |
<a name="t34.6"></a> <h1 id="_language_list.pod6-Lazy_lists"><a name="502"></a>Lazy lists</h1> | |
<p><span class="code">List</span>s, <span class="code">Seq</span>s, <span class="code">Array</span>s and any other class that implements the <a href="#_type_Iterator.pod6">Iterator</a> 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 <a href="#_language_control.pod6-gather/take">gather/take</a> or the <a href="#_language_operators.pod6-infix_...">sequence operator</a>. You can also write a class that implements the role <a href="#_type_Iterator.pod6">Iterator</a> and returns <span class="code">True</span> on a call to <a href="#_routine_is-lazy.pod6">is-lazy</a>. Please note that some methods like <span class="code">elems</span> cannot be called on a lazy List and will result in a thrown <a href="#_type_Exception.pod6">Exception</a>.</p> | |
<pre class="code"># 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) | |
</pre> | |
<p>In the example above, <span class="code">@lazy-array</span> is an <span class="code">Array</span> which, through construction, is made <span class="code">lazy</span>. Calling <span class="code">is-lazy</span> on it actually calls the method mixed in by the role <span class="code">Iterator</span>, which, since it originates in a lazy list, is itself lazy.</p> | |
<p>A common use case for lazy <span class="code">Seq</span>s 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.</p> | |
<pre class="code">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)» | |
</pre> | |
<p>You can easily assign lazy objects to other objects, conserving their laziness:</p> | |
<pre class="code">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»</pre> | |
<a name="t34.7"></a> <h1 id="_language_list.pod6-Immutability">Immutability</h1> | |
<p>The lists we have talked about so far (<span class="code">List</span>, <span class="code">Seq</span> and <span class="code">Slip</span>) are all immutable. This means you cannot remove elements from them, or re-bind existing elements:</p> | |
<pre class="code">(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 | |
</pre> | |
<p>However, if any of the elements is wrapped in a <a href="#_type_Scalar.pod6"><span class="code">Scalar</span></a> you can still change the value which that <span class="code">Scalar</span> points to:</p> | |
<pre class="code">my $a = 2; | |
(1, $a, 3)[1] = 42; | |
$a.say; # OUTPUT: «42»</pre> | |
<p>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.</p> | |
<a name="t34.8"></a> <h1 id="_language_list.pod6-List_contexts">List contexts</h1> | |
<p>So far we have mostly dealt with lists in neutral contexts. Lists are actually very context sensitive on a syntactical level.</p> | |
<a name="t34.8.1"></a> <h2 id="_language_list.pod6-List_assignment_context">List assignment context</h2> | |
<p>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 < |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment