Is there a way to detect whether something is immutable?

Viewed 183

In Raku a scalar might be immutable or it might be an actual variable:

 my $a := 6;  # constant
 my $b  = 6;  # variable

Is there a programmatic way to check whether a scalar is immutable without just trying to change it and seeing if it works?

2 Answers

First, a slight terminological correction (not to be nitpicky, but just because this area is a bit tricky and being precise with our terms can help).

It's not really right to say that my $a := 6 is a constant; that expression binds $a to the value 6, which prevents you from assigning a different value to $a (with the = operator). However, you can still rebind a new value to $a (with the := operator). This means that $a can still, in a sense, be mutated – or, at least, can be made to point to something new. For a truly constant $a, you should use either constant $a or change $a to a sigil-less variable (my \a = 6).

Now to the actual answer to your question: To determine whether $a is bound or assigned to a value, you can use $a.VAR.WHAT. If $a is assigned a value, this will return the type of container, (Scalar); if it is bound, then it will return the type of the bound value.

As far as I know, there isn't a way to tell the difference between an $a bound to a value and one that's a constant, though I would love to be wrong about that.

The code below illustrates what I just said:

my $a = 1;
say $a.VAR.WHAT; # OUTPUT: «(Scalar)»
$a = 2;
say $a;          # OUTPUT: «2»

my $b := 1;
say $b.VAR.WHAT;# OUTPUT: «(Int)»
$b := 2;
say $b;          # OUTPUT: «2»

constant $c = 1;
say $c.VAR.WHAT; # OUTPUT: «(Int)»
# $c := 2; ILLEGAL 
say $c;          # OUTPUT: «1»

Another way, using multiple dispatch:

my $a := 6;  # constant
my $b  = 6;  # variable

multi sub mutable($ is rw) { True }
multi sub mutable($) { False }

say mutable($a); # False
say mutable($b); # True
say mutable(42); # False

Related