Skip to content

Commit 3118235

Browse files
committed
documentation on containers, assignment and binding
1 parent c57c8d0 commit 3118235

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

lib/containers.pod

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
=begin pod
2+
3+
=head1 Perl 6 Containers: a low-level approach
4+
5+
This article started as a conversion on IRC explaining the difference between
6+
the C<Array> and the C<List> type in Perl 6. It explains the levels of
7+
indirection involved in dealing with variables and container elements.
8+
9+
=head2 What is a variable?
10+
11+
Some people like to say "everything is an object", but in fact a variable is
12+
not a user-exposed object in Perl 6.
13+
14+
When the compiler encounters a variable declaration like C<my $x>, it
15+
registers it in some internal symbol table. This internal symbol table is used
16+
to detect undeclared variables, and to tie the code generation for the
17+
variable to the correct scope.
18+
19+
At run time, a variable appears as an entry in a I<lexical pad>, short
20+
I<lexpad>. This is a per-scope data structure that stores a pointer for each
21+
variable.
22+
23+
In the case of C<my $x>, the lexpad entry for the variable C<$x> is a pointer
24+
to an object of type C<Scalar>, usually just called I<the container>.
25+
26+
=head2 Scalar containers
27+
28+
Although objects of type C<Scalar> are everywhere in Perl 6, you usually never
29+
see them directly as objects, because most operations I<decontainerize>, which
30+
means they act on the C<Scalar> container's contents instead of the container
31+
itself.
32+
33+
In a code like
34+
35+
my $x = 42;
36+
say $x;
37+
38+
the assignment C<$x = 42> stores a pointer to the C<Int> object 42 in the
39+
scalar container to which the lexpad entry for C<$x> points.
40+
41+
The assignment operator asks the container on the left to store the value on
42+
its right. What exactly that means is up to the container type. For C<Scalar>
43+
it means "replace the previously stored value with the new one".
44+
45+
Note that subroutine signatures allow passing around of containers:
46+
47+
sub f($a is rw) {
48+
$a = 23;
49+
}
50+
my $x = 42;
51+
f($x);
52+
say $x; # 23
53+
54+
Inside the subroutine, the lexpad entry for C<$a> points to the same
55+
container that C<$x> points to outside the subroutine. Which is why assignment
56+
to C<$a> also modifies the contents of C<$x>.
57+
58+
=head2 Binding
59+
60+
Next to assignment, Perl 6 also supports I<binding> with the C<:=> operator.
61+
When binding a value or a
62+
container to a variable, the lexpad entry of the variable is modified (and not
63+
just the container it points to). If you write
64+
65+
my $x := 42;
66+
67+
then the lexpad entry for C<$x> directly points to the C<Int> 42. Which means
68+
that you cannot assign to it anymore:
69+
70+
$ perl6 -e 'my $x := 42; $x = 23'
71+
Cannot modify an immutable value
72+
in block at -e:1
73+
74+
You can also bind variables to other variables:
75+
76+
my $a = 0;
77+
my $b = 0;
78+
$a := $b;
79+
$b = 42;
80+
say $a; # 42
81+
82+
Here after the initial binding, the lexpad entries for C<$a> and C<$b> both
83+
point to the same scalar container, so assigning to one variable also changes
84+
the contents of the other.
85+
86+
You've seen this situation before: it is exactly what happened with the
87+
signature parameter marked as C<is rw>.
88+
89+
=head2 Scalar Containers and Listy Things
90+
91+
There are a number of positional container types with slightly different
92+
semantics in Perl 6. The most basic one is I<Parcel>, short for I<Parenthesis
93+
cell>. It is created by the comma operator, and often delimited by round
94+
parenthesis -- hence the name.
95+
96+
say (1, 2, 3).WHAT; # (Parcel)
97+
98+
A parcel is immutable, which means you cannot change the number of elements in
99+
a parcel. But if one of the elements happens to be a scalar container, you can
100+
still assign to it:
101+
102+
my $x = 42;
103+
($x, 1, 2)[0] = 23;
104+
say $x; # 23
105+
($x, 1, 2)[1] = 23; # Error: Cannot modify an immutable value
106+
107+
So the parcel doesn't care about whether its elements are values or
108+
containers, they just store and retrieve whatever was given to them.
109+
110+
A C<List> has the same attitude of indifference towards containers. But it
111+
allows modifying the length (for example with C<push>, C<pop>, C<shift> and
112+
C<unshift>), and it is also lazy.
113+
114+
An C<Array> is just like a list, except that it forces all its elements to be
115+
containers. Thus you can say
116+
117+
my @a = 1, 2, 3;
118+
@a[0] = 42;
119+
say @a; # 42 2 3
120+
121+
and C<@a> actually stores three scalar containers. C<@a[0]> returns one of
122+
them, and the assignment operator replaces the integer value stored in that
123+
container with the new one, C<42>.
124+
125+
=head2 Assigning and Binding to Array Variables
126+
127+
Assigning to a scalar variable and to an array variable both do basically the
128+
same thing: discard the old value(s), and enter some new value(s).
129+
130+
Still it's easy to observe how different they are:
131+
132+
my $x = 42; say $x.WHAT; # (Int)
133+
my @a = 42; say @a.WHAT; # (Array)
134+
135+
This is because the C<Scalar> container type hides itself well, but C<Array>
136+
makes no such effort.
137+
138+
To place a non-C<Array> into an array variable, binding works:
139+
140+
my @a := (1, 2, 3);
141+
say @a.WHAT; # (Capture)
142+
143+
=head2 Binding to Array Elements
144+
145+
As a curious side note, Perl 6 supports binding to array elements:
146+
147+
my @a = (1, 2, 3);
148+
@a[0] := my $x;
149+
$x = 42;
150+
say @a; # 42 2 3
151+
152+
If you've read and understood the previous explanations, it is now time to
153+
wonder how this can possibly work. After all binding to a variable requires a
154+
lexpad entry for that variable, and while there is one for an array, there
155+
aren't lexpad entries for each array element (you cannot expand the lexpad at
156+
run time).
157+
158+
The answer is that binding to array elements is recognized at the syntax
159+
level, and instead of emitting code for a normal binding operation, a special
160+
method on the array is called that knows how to do the binding itself.
161+
162+
=end pod

0 commit comments

Comments
 (0)