Possible Bugs
Every behaviour the chapters mark as a possible bug, with the evidence that makes it look unintended and the smallest program that shows it.
Some corners in this book carry the tag Bug?. It marks a behaviour of Rakudo that looks unintended: something a program can run into, and could come to depend on, although there is a reason to think it is not meant to work that way. This appendix collects all of them in chapter order, so that they can be scanned in one place, kept out of programs that are meant to last, and reported to Rakudo's developers or examined further.
The tag asks a question; it does not answer it. Whether a behaviour is a bug is for Rakudo's developers to decide, and some of these may prove to be intended, or be documented another way later. What the book records is what happens and what makes it look unintended. A corner keeps the tag only with evidence of one of these kinds:
- the documentation: docs.raku.org says something else. The entry names the page by its file in the documentation's repository, Raku/doc, such as
doc/Type/Str.rakudoc, and says what the page states; - Roast: a test in the language's test suite asserts something else. The entry names the test file in the Raku/roast repository;
- a hang: a call does not return, on input it accepts;
- an internal leak: an object or a message from inside the compiler or the virtual machine reaches the program, such as
NQPMu,VMNull, "cannot unbox", or an error about a call the program never made; - a crash on valid input: a call dies on arguments it accepts, for example because its result fails the method's own declared return type;
- a related form: Rakudo itself does something else for a closely related call, such as the same method on another type, the same operator with a slightly different operand, or the one-argument form of a call.
Every behaviour below was reproduced on Rakudo v2026.08 when this book was built: the examples are run like all the others, and the outputs are the ones it printed. A later Rakudo may behave differently, and the build that checks the book against it will show which entries have changed.
Each entry's heading says what happens. The entry opens with the chapter it comes from, then says in a sentence or two what Rakudo does, and a line beginning Evidence: names the kind of evidence and, for the documentation or Roast, the file and what it says. The example is the smallest program that shows the behaviour, often shorter than the chapter's. A program that never returns is shown without output and marked not run; one that needs threads, timers or processes is marked run it locally. The link at the end leads to the full corner, which explains the behaviour in its context and shows more of it. Where two corners describe one behaviour, the entry links both, so the 72 tagged corners make 69 entries. The index of all corners can also filter the book by this tag.
A.1 Braces inside qx{…} run a command of their own
From Quotes and Interpolation. With brace delimiters, Rakudo 2026.08 runs the text between a pair of inner braces in a qx as a shell command of its own, before the outer command, and puts that command's output, trailing newline included, in place of the braces. With any other delimiters the braces stay as text.
Evidence: the documentation and a related form. doc/Language/quoting.rakudoc says that delimiters can be nested and that qx does not interpolate; in the other quoting forms, qq{…} included, nested braces are text.
say qx[echo '{echo inner}'].raku; say qx{echo '{echo inner}'}.raku;run it locally
"\{echo inner}\n"
"\{inner\n}\n"A.2 7 mod 2.5 is -0.5, and an Int's polymod follows it
From Numbers. Rakudo 2026.08 accepts a Rat divisor for mod and div. It truncates the divisor to an Int for the quotient and uses the full value for the remainder, so 7 mod 2.5 is 7 - 3 * 2.5: -0.5, a Rat with the opposite sign to the divisor. An Int's polymod uses mod and div and gives negative remainders as well, while the same number written as a Rat, 10.0, uses %.
Evidence: the documentation and a related form. doc/Language/operators.rakudoc declares infix:<mod>(Int:D $a, Int:D $b --> Int:D), with an Int result; % gives 2 for the same operands, and polymod answers differently for 10 and 10.0.
-0.5 2 (-2.5 5) (0 4)
The editor’s engine, Raku++, prints something else here
-0.5 2 (0 5) (0 4)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.3 Inf ** -1 is an underflow, not zero
From Numbers. Rakudo 2026.08 returns a Failure of X::Numeric::Underflow for any negative power of Inf: the power operator counts the zero result as an underflow from a non-zero base.
Evidence: a related form. IEEE 754 makes infinity to a negative power zero, and Rakudo agrees that 1 / Inf is 0e0; the same power operator gives a plain 0 for the mirror case, a fraction raised to Inf.
0e0 X::Numeric::Underflow 0
A.4 A negative base to a negative power puts the sign on the denominator
From Numbers. (-2) ** -3 in Rakudo 2026.08 is a Rat whose denominator carries the sign, <1/-8>. It is not equal to -0.125, it prints as -1.875, and any arithmetic on it normalises it to <-1/8>.
Evidence: the documentation. doc/Type/Rational.rakudoc (method norm) says that since 6.d a Rational is normalised when it is created, with a positive denominator.
<1/-8> False -1.875
The editor’s engine, Raku++, prints something else here
-0.125 True -0.125
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.5 [lcm] () dies of an ambiguous call
From Numbers. lcm has two candidates that accept no arguments, and Rakudo 2026.08 cannot choose between them, so reducing an empty list with lcm dies. [gcd] () returns a Failure of X::NoZeroArgMeaning, like the other numeric operators without an identity.
Evidence: the documentation and an internal leak. doc/Language/operators.rakudoc (section Identity) says that infix operators can in general be applied to no element without an error; the message points into two files of Rakudo's own setting.
X::NoZeroArgMeaning
Ambiguous call to 'infix:<lcm>(...)'; these signatures all match: () from SETTING::src/core.c/Numeric.rakumod line 265 () from SETTING::src/core.c/Int.rakumod line 421 in block <unit> at example.raku line 2
The editor’s engine, Raku++, prints something else here
X::NoZeroArgMeaning 1
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.6 A left shift by a negative count past -63 wraps around
From Numbers. A negative count reverses the direction of a shift. For an Int that fits in 64 bits, Rakudo 2026.08 takes a negative count for +< modulo 64: +< -64 shifts nothing and +< -65 shifts right by one place, where a right shift by 64 or 65 places gives 0.
Evidence: Roast. S03-operators/numeric-shift.t asserts that $a +< -$b equals $a +> $b.
1024 0 512 0
The editor’s engine, Raku++, prints something else here
0 0 0 0
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.7 1e-300.narrow is 0
From Numbers. For a Num, Rakudo 2026.08 decides whether it is whole with the approximate comparison =~=, which compares absolutely when one side is zero. Every Num below 1e-15 is then taken for 0, and a Num close to a large integer for that integer.
Evidence: the documentation. doc/Type/Numeric.rakudoc says that narrow converts a number to the narrowest type that can hold it "without loss of precision"; 0 keeps nothing of 1e-300.
4.5e0 1e-14 0
The editor’s engine, Raku++, prints something else here
4.5e0 1e-14 1e-300
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.8 <42>.lines returns an allomorph whose number is 0
From Strings. On an allomorph, lines in Rakudo 2026.08 returns allomorphs of the same type, holding the text of each line and the number 0, so the line is eq "42" and == 0 at once. The same text as a Str gives Strs.
Evidence: related forms. doc/Type/Allomorph.rakudoc describes chomp, comb, lc and the allomorph's other string methods as calling the Str method on its Str value, and they return plain Strs; the number that lines gives disagrees with its text.
(IntStr.new(0, "42"),).Seq True "42"
The editor’s engine, Raku++, prints something else here
("42",).Seq
False
"42"Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.9 rindex dies on a position at the end
From Strings. Given the position at the end of the string, rindex in Rakudo 2026.08 throws an untyped exception whose message calls the offset out of a range that contains it. An empty needle is spared, and for the other search methods a position past the end is no error.
Evidence: the documentation. doc/Type/Str.rakudoc says that rindex returns the last position of the needle "not after $pos", which here is the last occurrence.
2
index start offset (3) out of range (0..3) in block <unit> at example.raku line 2
The editor’s engine, Raku++, prints something else here
2 2
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.10 rindex with a needle list and a position never returns
From Strings. rindex searches a list of needles when it is given no position. Given a position as well, the call in Rakudo 2026.08 does not return, and runs until it is killed.
Evidence: a hang.
say "abc".rindex(<a b>, 1);not run
A.11 comb with a string and a limit finds overlapping matches
From Strings. Given a limit, comb with a string needle in Rakudo 2026.08 moves on by one character after each match instead of by the length of the needle, so the matches overlap; a negative limit gives all the overlapping ones. Without a limit, or with *, the matches stay apart.
Evidence: the documentation. doc/Type/Str.rakudoc says that comb returns "non-overlapping matches limited to at most $limit matches".
(aa aa) (aa aa aa)
The editor’s engine, Raku++, prints something else here
(aa aa) (aa aa)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.12 lines(:!count) dies
From Strings. :count, which the documentation calls deprecated, makes lines return the number of lines. :!count asks for the ordinary call, and Rakudo 2026.08 computes the lines, then dies: the method's declared return type is an integer, and the Seq of lines fails that check.
Evidence: a crash on valid input: the method fails its own declared return type.
(nothing)Type check failed for return value; expected Int:D but got Seq (("a", "b").Seq)
in block <unit> at example.raku line 1
The editor’s engine, Raku++, prints something else here
(a b)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.13 split with a string needle dies on a fractional limit
From Strings. With a string needle, a limit that is not an Int, even 2.0, makes split die in Rakudo 2026.08. With a regex needle the same limit is taken as an integer.
Evidence: an internal leak. The message comes from the virtual machine, which cannot unbox the limit to a native integer, and names the internal representation P6opaque.
("a", "b2c").SeqThis type cannot unbox to a native integer: P6opaque, Rat in block <unit> at example.raku line 2
The editor’s engine, Raku++, prints something else here
("a", "b2c").Seq
("a", "b;c").SeqMeasured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.14 split(:v) gives a string for a regex in a list of needles
From Strings. A regex needle on its own makes split(:v) return each delimiter as a Match object. In a list of needles, Rakudo 2026.08 returns a Str for every delimiter, regex or not.
Evidence: the documentation. doc/Type/Str.rakudoc (routine split) says that with :v a regex delimiter comes back as its Match object, and that each element of a list is a delimiter according to its type.
(Str Match Str) (Str Str Str)
The editor’s engine, Raku++, prints something else here
(Str Match Str) (Str Match Str)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.15 A zero-width regex in a list of needles never returns
From Strings. A single regex that matches the empty string makes split cut between the characters. Alone in a list of needles, the same regex in Rakudo 2026.08 matches at one place again and again, and the call does not return.
Evidence: a hang.
say "abc".split([/<?>/]);not run
A.16 An empty needle with :g misses both ends
From Strings. An empty string needle matches at position 0, so subst without :g puts the replacement at the start. With :g, Rakudo 2026.08 matches an empty needle only between characters, never at the start or the end; the regex /<?>/, which also matches the empty string, finds the ends too.
Evidence: the documentation and a related form. doc/Type/Str.rakudoc (method subst) says that :g "tries to match as often as possible", and the same needle without :g matches at the start.
-abc a-b-c -a-b-c-
The editor’s engine, Raku++, prints something else here
abc abc -a-b-c-
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.17 subst with :as(Str) dies under :g, :nth or :x
From Strings. subst accepts :as(Str) and ignores it for a single replacement. With any adverb that makes several matches, Rakudo 2026.08 dies, with a message about a method from that the program never calls: subst asks each match for its position, and a string has none.
Evidence: a crash on valid input, and a related form: the single replacement accepts the same adverb.
axcb
No such method 'from' for string 'b'. Did you mean 'trim'? in block <unit> at example.raku line 2
The editor’s engine, Raku++, prints something else here
axcb axcx
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.18 subst-mutate accepts :ov and :ex, which subst refuses
From Strings. subst refuses :ov and :ex with X::Str::Subst::Adverb. Its in-place form, subst-mutate, lets them through in Rakudo 2026.08: :ov replaces overlapping matches one after another in the same text, and :ex dies with a message about a substring length of -3, which the program never gave.
Evidence: a related form: subst refuses the same adverbs.
xax X::Str::Subst::Adverb
The editor’s engine, Raku++, prints something else here
xax X::Syntax::Regex::Adverb
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.19 .match with a negative :c matches before the start
From Strings. Given :c(-1), Rakudo 2026.08 starts the match at -1, outside the string, and takes its text from the other end. A bare :c, with no position, always starts at 1.
Evidence: the documentation and related forms. doc/Type/Str.rakudoc (method match) says that a bare :c starts at $/.to when $/ is set, and at 0 otherwise; index and substr refuse a negative position as out of range.
Match.new(:orig("abc"), :from(-1), :pos(0))
1The editor’s engine, Raku++, prints something else here
Nil 3
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
The first match ends at 3, where the documentation starts a bare :c.
A.20 encode with an undefined or numeric encoding never returns
From Strings and Blobs and Bufs. An unknown encoding name is refused with X::Encoding::Unknown. An undefined encoding, the Str type object or a variable that was never set, is not refused, nor is a number: in Rakudo 2026.08 encode does not return. Each of these calls runs until it is killed.
Evidence: a hang.
my $encoding; say "abc".encode($encoding); say "a".encode(42).raku;not run
The full corners: an undefined encoding and a number.
A.21 splice without a size removes only what a lazy array has computed
From Lists, Arrays, Seqs and Slips. On a lazy array, splice without a size in Rakudo 2026.08 removes only the elements computed so far, leaves the lazy rest in place, and reports no error. push and pop, which also need the end of the array, refuse a lazy array with X::Cannot::Lazy.
Evidence: the documentation. doc/Type/Array.rakudoc (routine splice) says that when the number of elements is omitted, all the elements from the start index on are deleted.
[] (1, 2, 3).Seq
The editor’s engine, Raku++, prints something else here
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, …
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.22 reverse of a fractional range counts down from its end
From Ranges. For a range that is not of Ints or of single characters, reverse in Rakudo 2026.08 starts at the end point, or one below it when the end is excluded, and counts down by one while it stays at or above the start. The result is not the elements reversed, and can hold values the range never yields.
Evidence: the documentation. doc/Type/Range.rakudoc (method reverse) describes the result as all the elements that the Range represents, reversed.
(1.1, 2.1, 3.1) (4, 3, 2).Seq
The editor’s engine, Raku++, prints something else here
(1.1, 2.1, 3.1) (3.1, 2.1, 1.1).Seq
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.23 first(:end, :kv) on a Range counts its index from the end
From Ranges. With :end, a Range answers :k with the position counted from the front, but with :kv Rakudo 2026.08 pairs the value with the position counted from the end. The same call on an Array counts from the front.
Evidence: the documentation and Roast. doc/Type/List.rakudoc (routine first) says that the index is always counted from the beginning of the list, whether or not :end is given, and S32-list/first-end-kv.t asserts that for lists and arrays.
8 (1, 9) (8, 9)
The editor’s engine, Raku++, prints something else here
8 (8, 9) (8, 9)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.24 A none junction as the endpoint makes the sequence endless
From The Sequence Operator. 1 ... none(1, 2) is a lazy sequence that never stops in Rakudo 2026.08. Before it looks at the endpoint, the operator tests whether the endpoint is infinite by comparing it with Inf, and the junction answers that test too: neither 1 nor 2 is Inf. The same condition in a block stops at 3.
Evidence: the documentation and a related form. doc/Language/operators.rakudoc (infix ...) says that an endpoint other than * is smartmatched against each generated element, and names junctions among the possible endpoints.
(1, 2, 3, 4, 5).Seq (1, 2, 3).Seq
The editor’s engine, Raku++, prints something else here
(1, 2, 3).Seq (1, 2, 3).Seq
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.25 A geometric sequence of negative numbers misses its endpoint
From The Sequence Operator. With negative seeds and a ratio above 1 the values fall, but Rakudo 2026.08 stops before the first value above the endpoint, and the first seed already is: -1, -2, -4 ... -16 is empty, although -16 is on its path. An endpoint above every value is never passed, and that sequence never ends.
Evidence: related forms. The arithmetic sequence -1, -3 ... -9 stops at its endpoint, and so does the geometric sequence with the signs flipped, like the documentation's own example 1, 2, 4 ... 32.
(1, 2, 4, 8, 16).Seq ().Seq (-1, -3, -5, -7, -9).Seq
A.26 The endpoint is tested once per call of the generator
From The Sequence Operator. When the generator returns a Slip, Rakudo 2026.08 tests the endpoint once for the whole call rather than once for each element. A code endpoint sees only the last values, and any other endpoint is smartmatched against the Slip itself, which as a number is its length.
Evidence: the documentation. doc/Language/operators.rakudoc (infix ...) says that the endpoint is smartmatched against each generated element.
(1, 2, 3, 2, 3, 2).Seq (1, 5, 6).Seq
The editor’s engine, Raku++, prints something else here
(1, 2, 3).Seq (1, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, …
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
The 3 never ends the first sequence, although every Slip holds a 3; the 2 ends the second after a Slip of two elements that holds no 2.
A.27 ...^ keeps the end of a string sequence of equal lengths
From The Sequence Operator. For strings of the same length and more than one character, Rakudo 2026.08 ignores the final caret of ...^ and includes the endpoint. For single characters it is left out.
Evidence: the documentation. doc/Language/operators.rakudoc says that the variants with a final caret produce sequences that do not contain the final element.
("a", "b").Seq
("aa", "ab").SeqThe editor’s engine, Raku++, prints something else here
("a", "b").Seq
("aa",).SeqMeasured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.28 A chain always ends with its last endpoint
From The Sequence Operator. At the end of a chain of sequence operators, Rakudo 2026.08 emits the last endpoint whether the sequence reached it or not, as if it started a further segment: 1 ... 5 ... 7.5 ends with 7 and then 7.5. In a chain, ^...^ keeps the last element.
Evidence: the documentation and a related form. doc/Language/operators.rakudoc says that a final caret leaves out the final element, and the unchained 1 ... 7.5 stops at 7.
(1, 2, 3, 4, 5, 6, 7).Seq (1, 2, 3, 4, 5, 6, 7, 7.5).Seq (2, 3, 4, 5, 4, 3, 2, 1).Seq
The editor’s engine, Raku++, prints something else here
(1, 2, 3, 4, 5, 6, 7).Seq (1, 2, 3, 4, 5, 6, 7, 7.5).Seq (2, 3, 4, 5, 4, 3, 2).Seq
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.29 .Bag of a Mix truncates the Mix itself
From Sets, Bags and Mixes. In Rakudo 2026.08, .Bag and .BagHash of a Mix or a MixHash also rewrite the source: every weight of 1 or more becomes its .Int. A total computed before is remembered, so afterwards the Mix no longer adds up.
Evidence: the documentation. doc/Type/Mix.rakudoc calls a Mix an immutable collection and describes .Bag as a coercion to a Bag.
Bag(a(2)) Mix(a(2) b(0.5))
The editor’s engine, Raku++, prints something else here
Bag(a(2)) Mix(a(2.7) b(0.5))
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.30 my %h is Set; without a value is unusable
From Sets, Bags and Mixes. Declared without an initializer, the variable in Rakudo 2026.08 holds an object that claims to be a Set but throws from .elems, .gist and .raku; being immutable, it cannot be assigned afterwards either. is Bag behaves the same. An initializer, even an empty list, gives a working Set.
Evidence: the documentation and an internal leak. doc/Language/syntax.rakudoc lists my %set is Set;, with no value, as the declaration of a Set variable; the error is about a Scalar, the container underneath.
This type (Scalar) does not support elems 0
The editor’s engine, Raku++, prints something else here
Nil 0
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.31 ∩ of two Hashes ignores false values
From Sets, Bags and Mixes. When both operands of ∩ are plain Hashes, Rakudo 2026.08 compares only their keys, so a key whose value is false is an element of the result. Every other set operator, and ∩ with any other operand, leaves such a key out.
Evidence: the documentation. doc/Type/Set.rakudoc says that set operators act as if they called .Set on their operands, and that .Set of a Hash skips the keys whose values are false.
Set(a b) Set(a)
The editor’s engine, Raku++, prints something else here
Set(a) Set(a)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.32 A Junction operand makes four set operators hang
From Sets, Bags and Mixes. The set operators that build a collection do not autothread over a Junction. In Rakudo 2026.08 ∪, ∩, ⊎ and ⊍ with a Junction on either side never return, and ∖ and ⊖ die with a message that names the virtual machine's representation of the object.
Evidence: a hang, and an internal leak in the message of the other two operators.
Cannot iterate object with P6opaque representation (Junction)
The editor’s engine, Raku++, prints something else here
Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
Each of these lines runs until it is killed:
say set(1) (|) any(2, 3); say any(2, 3) (&) set(1); say set(1) (+) any(2, 3); say set(1) (.) any(2, 3);not run
A.33 .bytes of a Blob[int] counts one byte per element
From Blobs and Bufs. Blob[int] and Blob[uint] store 64 bits per element, as the hex dump shows, but Rakudo 2026.08 counts one byte for each; a buf64 of the same two values counts 16.
Evidence: the documentation. doc/Type/Blob.rakudoc says that .bytes returns the number of bytes used by the elements, and shows 24 for three elements of a blob64.
16 2 Blob[int]:0x<0000000000000001 0000000000000002>
The editor’s engine, Raku++, prints something else here
16 2 Blob[int8]:0x<01 02>
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.34 allocate with an empty pattern never returns
From Blobs and Bufs. The pattern given to allocate is repeated until the buffer is full. Given an empty list, Rakudo 2026.08 never returns, and runs until it is killed.
Evidence: a hang.
say Blob.allocate(3, ()).raku;not run
A.35 A bad value among several grows the Buf, then throws
From Blobs and Bufs. Given several values, push and append in Rakudo 2026.08 throw at a bad one only after the buffer has grown by one slot for each value before it and one for the bad value itself, which holds 0. A single bad value returns a Failure and leaves the buffer as it was.
Evidence: related forms: the one-argument call, and splice with a bad element in its list, leave the buffer unchanged.
Buf.new(7,7,1,0) Failure Buf.new(7,7,1,0)
The editor’s engine, Raku++, prints something else here
Buf.new(7,7)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.36 A failed splice still changes the Buf
From Blobs and Bufs. An offset past the end with a nonzero size, a negative offset and a negative size make splice return a Failure of X::OutOfRange, and in Rakudo 2026.08 they change the buffer as well. An infinite list as the replacement is not refused as lazy, and the call never returns.
Evidence: a related form and a hang. A bad replacement value makes splice return a Failure and leaves the buffer alone.
X::OutOfRange Buf.new(1,2,3,0,0)
The editor’s engine, Raku++, prints something else here
(nothing on standard output; standard error says:)
No such method 'exception' for invocant of type 'Buf'
(X::Method::NotFound)
in block <unit> at example.raku line 3
3 | say $f.exception.^name;Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
The call with the infinite list runs until it is killed:
my $b = Buf.new(1, 2, 3); say $b.splice(0, 2, 1..*).raku;not run
A.37 subbuf with a string start and a length never returns
From Blobs and Bufs. A string start alone, a string length and a fractional start have no candidate and throw X::Multi::NoMatch at once. A string start followed by an integer length is not refused, and in Rakudo 2026.08 the call never returns.
Evidence: a hang.
say Blob.new(1, 2).subbuf("1", 1).raku;not run
A.38 ~& and ~| die on signed buffers of unequal length
From Blobs and Bufs. Between two signed buffers of different lengths, and for ~& with a signed left operand and an unsigned right one of another length, Rakudo 2026.08 dies. Unsigned buffers of unequal length are padded, and ~^ works with any.
Evidence: an internal leak. The message comes from the virtual machine and names its array type, MVMArray.
MVMArray: bindpos I8 expected int register Blob[uint8].new(1,0)
The editor’s engine, Raku++, prints something else here
Nil Blob[uint8].new(1,0)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.39 write-ubits clears the bits after the run in its last byte
From Blobs and Bufs. When the run ends inside a byte, Rakudo 2026.08 also changes the bits of that byte to the right of the run: only the first of them survives, and the rest become zeros. A run that ends on a byte boundary leaves every other bit alone.
Evidence: the documentation. doc/Type/Buf.rakudoc describes write-ubits as writing a value to the given number of bits from the given bit offset.
Buf[uint8].new(8) Buf[uint8].new(240)
The editor’s engine, Raku++, prints something else here
Buf[uint8].new(15) Buf[uint8].new(240)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
With the four low bits kept, the first result would be 15.
A.40 .multi is 0 on a proto, and a plain sub's .dispatcher is an NQPMu
From Signatures and Introspection. A candidate answers .multi with True, but in Rakudo 2026.08 a proto and a plain sub answer the number 0. .dispatcher of a plain sub is the compiler's internal NQPMu, which is not a Raku object and has no .raku.
Evidence: the documentation and an internal leak. doc/Type/Routine.rakudoc declares .multi to return a Bool:D and shows a proto answering False.
0 NQPMu
The editor’s engine, Raku++, prints something else here
Bool::True Mu
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.41 .prec("prec") fails its own return type
From Signatures and Introspection. Given a key, an operator's .prec computes that one property, a string, and in Rakudo 2026.08 dies with X::TypeCheck::Return, because the method is declared to return Hash:D. Subscripting the Hash that .prec returns without a key works.
Evidence: a crash on valid input: the method fails its own declared return type.
t= Type check failed for return value; expected Hash:D but got Str
The editor’s engine, Raku++, prints something else here
(nothing on standard output; standard error says:)
No such method 'prec' for invocant of type 'Sub'
(X::Method::NotFound)
in block <unit> at example.raku line 1
1 | say &infix:<+>.prec<prec>;Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.42 A method's signature prints $::, which does not parse back
From Signatures and Introspection. The invocant marker is one colon, as in method m($self: $x). In Rakudo 2026.08 a method's signature prints it as two, $::, and the printed signature does not compile.
Evidence: the documentation. The printed signatures in doc/Type/Routine.rakudoc have one colon, as in (Cool $: Str $matcher, $limit = Inf, *%_); EVAL of the printed text throws.
:(C $:: $x, *%_) X::Syntax::Signature::InvocantMarker
The editor’s engine, Raku++, prints something else here
:($x, *%_) Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.43 Int:D() prints as Int:D(Any):D, which does not compile
From Signatures and Introspection. A definite coercion type in a signature prints, in Rakudo 2026.08, with a second :D after the coercion, and the printed text does not compile.
Evidence: the documentation. doc/Type/Mu.rakudoc says that .raku conventionally returns a representation of the object that EVAL can use to reconstruct it.
:(Int:D(Any):D $x) X::MultipleTypeSmiley
The editor’s engine, Raku++, prints something else here
:(Int(Any):D $x) Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.44 A signature built with Signature.new cannot bind anything
From Signatures and Introspection. Smartmatching a Capture against a signature built at run time with Signature.new throws in Rakudo 2026.08, even for an empty signature and an empty Capture.
Evidence: the documentation and an internal leak. doc/Type/Signature.rakudoc (method ACCEPTS) says that smartmatching a Capture against a signature answers whether the Capture can be bound to it; the message comes from the virtual machine and names p6invokeunder and an MVMCode.
p6invokeunder first argument has to be a concrete MVMCode, got a concrete P6opaque (type ContainerDescriptor)
The editor’s engine, Raku++, prints something else here
Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.45 Parameter.new dies on +@a and doubles a bare name
From Signatures and Introspection. In Rakudo 2026.08 Parameter.new accepts a name without a sigil and prints it twice, and dies on the single-argument slurpy +@a with an out-of-range substr from inside the constructor.
Evidence: the documentation and an internal leak. doc/Type/Parameter.rakudoc says that the name is written as in a Signature, and lists the +, * and ** prefixes among the marks it may carry.
xx Start argument to substr out of range. Is: -1, should be in 0..2; use *-1 if you want to index relative to the end
The editor’s engine, Raku++, prints something else here
x Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.46 A WhateverCode's .file is a null string
From Signatures and Introspection. A sub answers .file with the name of its source file. A WhateverCode in Rakudo 2026.08 answers with a Str object that holds no string at all: it is defined, but using it as a string dies.
Evidence: an internal leak: an error from the virtual machine about a null string.
True concatenate requires a concrete string, but got null
The editor’s engine, Raku++, prints something else here
True SETTING::src/core.c/ Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.47 A ForeignCode's gist is not its name
From Signatures and Introspection. ForeignCode is code that belongs to the virtual machine rather than to Raku, such as some of the methods every routine has. In Rakudo 2026.08 its .gist is ForeignCode.new, and its .Str the default form with an address.
Evidence: the documentation. doc/Type/ForeignCode.rakudoc says that .gist and .Str return the name of the code, by calling .name.
<anon> ForeignCode.new
The editor’s engine, Raku++, prints something else here
Any (Any)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.48 Rethrowing a caught return, take or emit loses its value
From Exceptions and Failures. When a CONTROL block rethrows a CX::Return, CX::Take or CX::Emit, the construct in Rakudo 2026.08 receives the control exception itself instead of the value: the routine returns the CX::Return object, gather collects CX::Take objects, and a supply emits the CX::Emit.
Evidence: the documentation and a related form. doc/Type/Exception.rakudoc describes .rethrow as throwing the exception again, and a rethrown CX::Next does go on to the next iteration.
CX::Return.new
The editor’s engine, Raku++, prints something else here
5
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.49 A bare succeed yields an internal null that cannot be printed
From Exceptions and Failures. With an argument, succeed makes it the value of the when or given block, and an empty when yields Nil. A bare succeed in Rakudo 2026.08 yields VMNull, the virtual machine's internal null, which is not a Raku object and has no methods, not even the .gist that say calls.
Evidence: an internal leak.
(nothing)No such method 'gist' for invocant of type 'VMNull'. Found 'gist' on type 'Mu' in block <unit> at example.raku line 2
The editor’s engine, Raku++, prints something else here
(Any)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.50 In a loop, LEAVE runs before NEXT
From Exceptions and Failures. When a loop body is about to go round again, Rakudo 2026.08 runs its LEAVE phaser first and NEXT after it.
Evidence: the documentation and Roast. doc/Language/phasers.rakudoc says that NEXT runs before LEAVE, and S04-phasers/next.t asserts that order, with a #?rakudo todo on the test.
LEAVE 1 NEXT 1 LEAVE 2 NEXT 2
A.51 .match with :x(Nil) dies of an arity error
From Regexes and Grammars. A count that is neither a number nor a Range, a numeric string included, makes .match return a Failure of X::Str::Match::x. Nil is neither, but in Rakudo 2026.08 :x(Nil) dies, with an arity error about a call made inside .match.
Evidence: the documentation and an internal leak. doc/Type/Str.rakudoc (method match) says that a value of :x other than a Numeric or a Range makes .match return a Failure containing X::Str::Match::x.
X::Str::Match::x Too many positionals passed; expected 3 arguments but got 4
The editor’s engine, Raku++, prints something else here
(nothing on standard output; standard error says:)
in Str.match, got invalid value of type Str for :x, must be Int or Range
(X::Str::Match::x)
in block <unit> at example.raku line 1
1 | say "aaaa".match(/a/, :x("2")).exception.^name;Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.52 :nth(2), :x(1) answers an empty list
From Regexes and Grammars. With a single :nth number and :x(1), .match in Rakudo 2026.08 returns an empty List, although the match exists. A list of one number, :nth((2,)), returns that match.
Evidence: the documentation and a related form. doc/Type/Str.rakudoc (method match) describes :x as the number of matches to return.
(b) ()
The editor’s engine, Raku++, prints something else here
(b)
Match.new(:orig("abcd"), :from(1), :pos(2))Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.53 .actions of a parse without actions is not a Raku object
From Regexes and Grammars. Without an actions object, .actions of a parse result in Rakudo 2026.08 is an object of the compiler's own NQPMu type, which has no .gist, so printing it dies.
Evidence: the documentation and an internal leak. doc/Type/Match.rakudoc says that .actions returns Mu when no actions object was set.
NQPMu
Method NQPMu.gist not found in block <unit> at example.raku line 3
The editor’s engine, Raku++, prints something else here
Any (Any)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.54 A Date range compares by text, so a formatter cuts it short
From Dates and Times. A range decides where its iteration stops with cmp, and cmp compares Dates as text. With a formatter on the start, Rakudo 2026.08 stops as soon as the formatted text sorts after the end: below, the days print as their numbers, "3" sorts after "2019-05-09", and a range of nine days has two elements.
Evidence: the documentation. doc/Type/Date.rakudoc offers $date .. $date.last-date-in-month as the remaining dates of a month; a formatter changes where such a range stops.
(1 2)
The editor’s engine, Raku++, prints something else here
(1 2 3 4 5 6 7 8 9)
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.55 A date-only string with a bad month dies with an internal error
From Dates and Times. DateTime.new given a full timestamp with month 13, or a date-only string with day 32, throws X::Temporal::OutOfRange. Given a date-only string with month 13, Rakudo 2026.08 dies with an X::AdHoc about unboxing a type object.
Evidence: an internal leak, and related forms: the two neighbouring forms name the field that is out of range.
X::Temporal::OutOfRange Cannot unbox a type object (Nil) to int.
The editor’s engine, Raku++, prints something else here
X::Temporal::OutOfRange Month out of range. Is: 13, should be in 1..12
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.56 Rounding the second can print one that does not exist, or die
From Dates and Times. A DateTime prints its second with six decimals, rounded half up. In Rakudo 2026.08 a second just below 60 prints as 60.000000, a leap second that DateTime.new refuses at that time, and a second from 0.9999995 up to 1 makes .Str die on a value the constructor accepted.
Evidence: related forms and an internal leak. The constructor refuses the second of 60 that .Str prints, while 10.9999996 is carried to 11.000000; the message of the other case is about a negative repeat count.
2000-01-01T00:00:60.000000Z Repeat count (-1) cannot be negative
The editor’s engine, Raku++, prints something else here
2000-01-01T00:00:60.000000Z 2000-01-01T00:00:01.000000Z Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.57 A DateTime's identity is its printed text
From Dates and Times. The identity of a DateTime, which ===, unique and sets use, is made from its .Str in Rakudo 2026.08. Two DateTimes for the same moment in different zones are == and eqv but not ===, and two whose formatter prints the same text are === whatever moments they hold.
Evidence: the documentation. doc/Language/operators.rakudoc says that for value types === behaves like eqv.
True False
The editor’s engine, Raku++, prints something else here
False False
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.58 DateTimes compare by moment, except with cmp, leg and sort
From Dates and Times. ==, < and <=> compare the moments of two DateTimes. In Rakudo 2026.08 cmp and leg compare their texts, and so do sort, min and max, which use cmp: moments in different zones can sort in the reverse of their order in time.
Evidence: the documentation. doc/Type/DateTime.rakudoc says that cmp on two DateTimes compares the equivalent instants.
True More
$early is 03:00 UTC and $late 07:00 UTC.
A.59 read($n) on a binary pipe returns a whole chunk, whatever $n is
From Processes. On a pipe opened with :bin, read in Rakudo 2026.08 returns everything that has arrived in one piece, whatever the count; the next read finds nothing left. On a text pipe the count is kept.
Evidence: the documentation. doc/Type/IO/Handle.rakudoc says that read returns up to the given number of bytes.
my $p = run "printf", "abcdef", :out, :bin; say $p.out.read(2).raku;run it locally
Buf[uint8].new(97,98,99,100,101,102)
A.60 Asking a new Proc for its status fixes the status at 1
From Processes. On a Proc.new that has not spawned anything, Rakudo 2026.08 answers .exitcode with 1, and the answer sticks: a spawn afterwards runs the program, but the Proc keeps reporting 1. A Proc that spawns a second time keeps the status of its first program.
Evidence: the documentation. doc/Type/Proc.rakudoc says that .exitcode is -1 for a process that has not exited yet.
my $p = Proc.new; say $p.exitcode; $p.spawn("true"); say $p.exitcode;run it locally
1 1
A.62 await on a Channel takes a Nil value for no value
From Promises, Locks and Awaiting. A Nil sent into a channel is a value like any other, and .receive returns it. await in Rakudo 2026.08 consumes the Nil and goes on waiting: with a later value it returns that one, and with none it never returns.
Evidence: the documentation and a hang. doc/Type/Channel.rakudoc says that await calls .receive on the Channel.
my $c = Channel.new; $c.send(Nil); say $c.receive.raku; $c.send(Nil); $c.send(1); say await $c;run it locally
Nil 1
A.63 sleep-timer NaN fails its own return type check
From Promises, Locks and Awaiting. sleep NaN returns at once. sleep-timer NaN in Rakudo 2026.08 throws X::TypeCheck::Return: the value it returns is not a Duration but a Rat of 0/0 with an internal role mixed in.
Evidence: the documentation and a crash on valid input. doc/Type/independent-routines.rakudoc gives sleep-timer the signature (Real() $seconds = Inf --> Duration:D) and says it is implemented like sleep; NaN is a Real.
try sleep-timer NaN; say $!.message;run it locally
Type check failed for return value; expected Duration:D but got Rat+{Duration::add-tai} (<0/0>)A.64 A Semaphore's permit count wraps at 32 bits
From Promises, Locks and Awaiting. Rakudo 2026.08 keeps the number of permits of a Semaphore in 32 bits. Counts from 2**31 to 2**32 - 1 are refused; from 2**32 on, the count is accepted silently and only its low 32 bits are kept, so 2**32 + 1 gives one permit.
Evidence: a related form and the documentation. The smaller count 2**31 is refused outright, and doc/Type/Semaphore.rakudoc describes the count as the number of acquires that pass before one blocks.
True False Failed to initialize Semaphore: invalid argument
The editor’s engine, Raku++, prints something else here
True True Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.65 A LAST run by last cannot emit
From Supplies. A LAST phaser in a whenever can emit when its source finishes. When last is what runs it, in Rakudo 2026.08 the phaser no longer runs inside the supply: emit dies with "emit without supply or react", although the code sits in a supply block, and the supply quits. A tap without a quit handler hears nothing at all.
Evidence: Roast and a related form. S17-supply/syntax.t asserts that a LAST in a whenever can emit, and that last runs the LAST block; the same phaser emits when the source finishes by itself.
got 1 got 2 quit: emit without supply or react
The editor’s engine, Raku++, prints something else here
got 1 got 2 got from LAST
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.66 After a quit from .map, later values and a done still arrive
From Supplies. .map turns an exception in its code into a quit. When the source is synchronous, as from-list is, Rakudo 2026.08 goes on mapping and delivering the later values, and the done arrives after the quit; .grep does the same. The consumers that turn a supply into a value then lose the exception: the late done ends .list normally, before the failing value, await returns the last value it saw, and .wait throws a type check failure instead of the exception of the quit.
Evidence: related forms and the documentation. Over a live source nothing follows the quit, and .do over the same synchronous source stops at its quit. doc/Type/Supply.rakudoc says that .list throws once the list reaches the quit, and that .wait throws the exception passed to quit.
got 10 quit: cannot map 2 got 30 done (10) Type check failed in binding; expected Exception but got Any (Any)
The editor’s engine, Raku++, prints something else here
got 10 quit: cannot map 2
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
The full corners: the late values and .list and await.
A.67 batch(:emit-timed) never emits
From Supplies. Without :emit-timed, a batch with :seconds is emitted when a value arrives in a later slice of time, or at the done. With :emit-timed, Rakudo 2026.08 emits nothing at all, not even the done.
Evidence: the documentation. doc/Type/Supply.rakudoc (method batch) says that with :emit-timed a timer emits whatever is in the batch every given number of seconds, and that the remaining values come in a final batch when the supply is done.
my $sup = Supplier.new; my @got; $sup.Supply.batch(:seconds(0.1), :emit-timed) .tap(-> $b { @got.push($b) }, done => { @got.push("done") }); $sup.emit(1); sleep 0.2; $sup.done; say @got.raku;run it locally
[]
A.68 elems with an interval below one second divides by zero
From Supplies. Given an interval below one second, the Supply method .elems in Rakudo 2026.08 makes the first value die with X::Numeric::DivideByZero, a division the caller never wrote.
Evidence: the documentation and a crash on valid input. doc/Type/Supply.rakudoc describes the argument of .elems as an interval in seconds, and batch takes its :seconds to the millisecond.
X::Numeric::DivideByZero
The editor’s engine, Raku++, prints something else here
(2) Nil
Measured with Raku++ 4.0.1-245-ge1e6e3a1-modified (2026-09-28) arm64-darwin. The book shows the reference compiler’s output; the editor runs Raku++ compiled to WebAssembly.
A.69 stable emits a waiting value after the done
From Supplies. .stable($seconds) passes a value on only when no newer value follows within the time. In Rakudo 2026.08 the done is passed on at once, and a value still waiting is emitted after it, when a react or a .list has stopped listening.
Evidence: related forms: delayed and throttle, which also hold values back for a time, deliver what they hold before the done.
my $sup = Supplier.new; my @got; $sup.Supply.stable(0.1).tap(-> $v { @got.push($v) }, done => { @got.push("done") }); $sup.emit(1); $sup.done; sleep 0.2; say @got;run it locally
[done 1]