Is there some model to use to understand containers, references, raw, rw, \ in Raku?
When you write this:
my $a = 'b';
$a = 'c';
say $a;
What happens is something that is sort-of like this:
my $a := Scalar.new( value => 'b' );
$a.set-value('c');
say $a.get-value();
Basically a new Scalar object is created and $a
is a pointer to it.
Of course it isn't quite that simple as you can't even call .new
on a Scalar and have it do anything.
There is also a lot more information stored inside of the Scalar object. For example the type information and any default.
Really what you think about $
variables is all contained inside of the Scalar object.
Normally this container tries to be completely transparent.
You can however get at the Scalar object with the .VAR
method/macro.
my Int $a is default(42) = 3;
my $var = $a.VAR;
say $var.name; # $a
say $var.of; # (Int)
say $var.default; # 42
say $var.self; # 3
There are other ways that this transparency gets more translucent than transparent.
sub foo ( \v ){ # the \ is so it isn't seen as a Type name
say v.VAR.name
v = 22;
}
foo $a; # $a
say $a; # 22
That is because the Scalar gets passed to the subroutine, not the value inside of the Scalar. The Scalar is always passed to the function call, it's just that the function often decides to do something other than allowing you raw access to the original Scalar.
In the following, the value inside of the passed Scalar is copied to a new Scalar that doesn't allow modification.
sub bar ( $v ){
# $v = 3; # ERROR
}
bar $a
If you had declared $v
as is rw
or is raw
, $v
would actually be a pointer to the Scalar container you passed in just like \v
above. (\v
is very similar to is raw
.)
Ok, I'll try to give you a mental model:
- there is no real assignment in Raku, only binding (like NQP)
- everything in Raku is an object.
- objects can have attributes, that can bind to other objects.
- Raku adds syntactic sugar to write assignments, but really that's just binding an object to an attribute of a Container object.
So what does this mean for:
# bind a container object to the name '$a' in the lexpad
my $a;
# bind an Int object to the value attribute of that container
$a = 42;
Normally, you don't need to know if something is inside a container or not, as most decontainerization is done for you behind the scenes. For instance, if you return a variable from a subroutine, it is automatically removed from its container. Except if the subroutine is marked as is raw
.
Does that help with creating a model?
I like the advent calendar article on this topic https://perl6advent.wordpress.com/2017/12/02/perl-6-sigils-variables-and-containers/ , not sure if that is what you are looking for, but it helped me to getter a better feel of what’s going on...