Containers, Binding and Itemization

13.1 Assignment vs Binding

my $a = 1;
my $b = $a;          # assignment: copies the value into $b's container
$b = 2;
say $a;              # 1

my $c := $a;         # binding: $c is now the SAME container as $a
$c = 5;
say $a;              # 5
say $a =:= $c;       # True (container identity)

my $readonly := 42;  # bound to a value, not a container
# $readonly = 1;     # error: Cannot assign to an immutable value

my @arr := (1, 2, 3);   # @arr is the List itself (immutable)
my \sigilless = 10;     # sigilless: binding

13.2 Scalar Containers and Itemization

Rule of thumb: @ and % variables iterate their contents. $ variables are treated as a single item. Use | (slip) to flatten into argument lists or outer lists.

my @nested = [1, 2], [3, 4];
say @nested.elems;           # 2
for @nested -> $item { say $item }        # [1 2] then [3 4]
my @flat = flat @nested;
say @flat;                   # [1 2 3 4]
my $aref = [1, 2, 3];        # an Array in a Scalar container (itemized)
for $aref { .say }           # ONE iteration: prints [1 2 3]
for @$aref { .say }          # three iterations (decontainerize with @ or .list)
for $aref.list { .say }
say (1, (2, 3)).elems;       # 2
say (1, $(2, 3)).flat;       # (1 (2 3)): $( ) itemizes, preventing flattening
say (1, |(2, 3)).elems;      # 3: | slips (flattens) into the outer list
my $x = (1, 2);
say $x.VAR.WHAT;             # (Scalar)
say $x<>.WHAT;               # (List) (<> decontainerizes)

13.3 Proxy and is rw

sub first-elem(@a) is rw { @a[0] }     # return the container, not the value
my @list = 1, 2, 3;
first-elem(@list) = 99;
say @list;                             # [99 2 3]

my $celsius = 0;
my $fahrenheit := Proxy.new(
    FETCH => method ()     { $celsius * 9 / 5 + 32 },
    STORE => method ($new) { $celsius = ($new - 32) * 5 / 9 },
);
$fahrenheit = 212;
say $celsius;                          # 100