smol projects

a lot about lists in raku

12.11.2023 4 min read

Lists in Raku are a hard topic to understand. They are positional constructs, sure… but how do you instantiate one (spoiler: there are lots of ways to do it)? How do they differ from arrays?

constructing a list

We can construct a list using the .List method:

my $list = (1, 2, 3).List;

We really don’t have to, though:

my $list = (1, 2, 3);

The important thing here seems to be the parentheses.

However, if we’re not assigning it to a variable, we don’t need the parentheses at all:

say $_ for 1, 2, 3;

If we’d rather use the positional sigil, we can, provided we use the binding operator:

my @list := (1, 2, 3);

Calling .WHAT on each of these in Raku will provide the same answer:

$list.WHAT; # (List)
@list.WHAT; # (List)

a gotcha

However, Raku will not treat these values equally!

say $_ for $list; # (1, 2, 3)
say $_ for @list; # 1\n2\n3

A way to look at it is this: because one has a scalar sigil, it is treated as such and will be iterated over once. The other is treated as a positional. If we wanted Raku to treat it as a positional, we have to call .list on the List:

say $_ for $list.list;

See: Items, flattening and sigils

lists cannot be typed?

We can type an array by specifying the type of values it contains beforehand:

my Int @nums = [1, 2, 3];
# alternatively
my @nums = Array[Int](1, 2, 3);
# last one, promise
my @nums = Array[Int].new(1, 2, 3);

Doing this with lists will fail:

List[Int](1, 2, 3); # ===SORRY!=== Error while compiling:
# List cannot be parameterized

lists are immutable

my @list = (1, 2, "a");
@list.push(4); # [1 2 a 4]
my $list = (1, 2, "a");
$list.push(4) # Cannot call 'push' on an immutable 'List'

See: Immutability

other ways to construct a list…

We can use angled brackets:

my $fruits = <pear banana apple>; # (pear banana apple)

We can use angled brackets with comma-separated values:

my $fruits = <pear, banana, apple>; # (pear, banana, apple)

In practice, there doesn’t seem to be a difference.

my $first-fruits = <pear banana apple>;
my $second-fruits = <pear, banana, apple>;
$first-fruits.elems.say; # 3
$second-fruits.elems.say; # 3

another gotcha

However, things start getting weird when you try doing angled bracket syntax with numbers!

my $nums = <1 2 3>;
$nums.elems # 3
$nums[0].WHAT; # (IntStr)
my $nums = <1, 2, 3>; 
$nums[0].WHAT; # Str

The first time round, we get an IntStr… the second time round, we get a Str!

Personally, I’d only use angle bracket syntax with words, and avoid using them for anything else unless my intention is to create IntStr types, which are an Allomorph.

a slight detour: allomorph

See: class Allomorph

A “dual value number and string”. What does this mean? Well, my understanding is that an allomorph accepts methods that are defined on String AND Number.

"42" + "42" # 84
42 ~ 42 # 4242
"some string" + "another string" # Cannot convert string to number...

E.g. when a user inputs a number into the CLI, but really, it gets converted into a string - it’s both a string AND a number. It seems that allomorphs are good at handling input data where you do not yet know the type.


“…represent anything that can produce a sequence of values”.

I don’t know too much about this, but it seems you create sequences from lists / arrays when you use built-ins like map or grep (you can probably create them in other ways too, but I don’t know how).

Practically speaking… sometimes, you’ll get an error when you try to iterate over sequences more than once, because they’ve been consumed already. But, I can’t seem to reproduce the error on demand - I only know that I’ve seen it before. When that happens, you’ll need to .cache the sequence so you can work with it multiple times.

There is something about laziness, and eagerness, but sometimes sequences lie about being lazy - or something.

Sorry about this section. This whole topic is hard to grok.

Proof that I’m not lying: Getting the last element of a lazy seq in raku

See: class Seq


Idk what these are, and I’ve never used them.


Well… I really wish I could say this was everything there is to say about lists. I really, really, wanted to get down to the bottom of it, once and for all. But the topic is immensely huge. The language is immensely huge. I might post updates to this as I find out more, but, I doubt it - some of these topics are just downright confusing. But, I hope this brings light to some of the unexpected parts.

Built with Astro and Tailwind 🚀