This code:
constant %what = { doesn't => 'change' };
%what = { will => "change" }
Should say something along the lines of "Cannot modify an immutable hash". However, it says:
Potential difficulties:
Useless use of hash composer on right side of hash assignment; did you mean := instead?
Positionals have pretty much the same problem, but the error is different. In this case it's about cannot modify an immutable, but an Str:
constant @what = <does not change>;
@what = <does change> # Cannot modify an immutable Str (does)
A Scalar works as expected. Is this a case of LTA error message, or is some container magic at work here that I'm missing?
This code:
constant %what = { doesn't => 'change' };
%what = { will => "change" }
Should say something along the lines of "Cannot modify an immutable hash".
Who says so? I mean this rhetorically, not rudely. I get why you think so but it's important to be careful with use of the word "should" because it implies some authority says so, eg the specification, or a design document, or someone's common sense, or whatever.
Per the current spec, and Rakudo implementation, what constant foo ...
does is permanently (constantly) bind foo
to some particular "value".
If that "value" is a container, then foo
constantly refers to that container. (Yes, a container can be a "value", for some definition of "value" that is appropriate here.)
So your code above has changed the elements contained within that container, and that is, per spec, perfectly cromulent:
say %what; # {will => change}
In the meantime, the warning message legitimately mentions useless use of a hash constructor, plus it notes:
did you mean := instead?
If you try that:
constant %what = { doesn't => 'change' };
%what := { will => "change" }
You get:
Cannot use bind operator with this left-hand side
Because, as already established, %what
is a compile time constant permanently bound to a hash created and initialized at compile time and that aspect -- the permanent binding of %what
to that particular hash -- can't be changed during this program run.
Positional
s have pretty much the same problem, but the error is different. In this case it's about cannot modify an immutable, but anStr
:
constant @what = <does not change>;
@what = <does change> # Cannot modify an immutable Str (does)
That's a bit different. A constant
declaration binds, regardless of whether you write =
or :=
. So the constant declarations are equivalent to:
constant %what := { doesn't => 'change' }
constant @what := <does not change>;
The first line binds %what
to { doesn't => 'change' }
which is a mutable Hash
.
The second line binds @what
to <does not change>
which is an immutable List
.
You could instead write:
constant @what = [<does not change>];
@what = <does change>;
say @what; # [does change]
A
Scalar
works as expected.
Not quite.
A scalar (lowercase, the generic term) does:
constant $scalar = 42;
$scalar = 99; # Cannot assign to an immutable value
Remembering that constant
always binds, the above code parallels:
my $scalar := 42;
$scalar = 99; # Cannot assign to an immutable value
But a Scalar
works the same as the other containers in this context:
constant $scalar = $ = 42;
$scalar = 99; # OK
(Don't write code like that unless you want to annoy people.)
Is this a case of LTA error message, or is some container magic at work?
That's a good question, and one I'm not going to try answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With