Skip to content

Commit c40a1aa

Browse files
committed
Rework containers.pod
closes #139
1 parent c91af90 commit c40a1aa

File tree

1 file changed

+46
-120
lines changed

1 file changed

+46
-120
lines changed

lib/Language/containers.pod

Lines changed: 46 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ is equivalent to
8080
method attr() is rw { $!attr }
8181
}
8282
83+
Scalar containers are transparent to type checks and most kinds of read-only
84+
accesses. A C<.VAR> makes them visible:
85+
86+
my $x = 42;
87+
say $x.^name; # Int
88+
say $x.VAR.^name; # Scalar
89+
90+
And C<is rw> on a parameter requires the presence of a writable Scalar
91+
container:
92+
93+
sub f($x is rw) { say $x };
94+
f 42; # Parameter '$x' expected a writable container, but got Int value
95+
8396
=head2 Binding
8497
8598
Next to assignment, Perl 6 also supports I<binding> with the C<:=> operator.
@@ -116,7 +129,7 @@ There are a number of positional container types with slightly different
116129
semantics in Perl 6. The most basic one is L<List|/type/List>
117130
It is created by the comma operator.
118131
119-
say (1, 2, 3).WHAT; # (List)
132+
say (1, 2, 3).^name; # List
120133
121134
A list is immutable, which means you cannot change the number of elements
122135
in a list. But if one of the elements happens to be a scalar container,
@@ -154,11 +167,12 @@ the same thing: discard the old value(s), and enter some new value(s).
154167
155168
Nevertheless, it's easy to observe how different they are:
156169
157-
my $x = 42; say $x.WHAT; # (Int)
158-
my @a = 42; say @a.WHAT; # (Array)
170+
my $x = 42; say $x.^name; # Int
171+
my @a = 42; say @a.^name; # Array
159172
160173
This is because the C<Scalar> container type hides itself well, but C<Array>
161-
makes no such effort.
174+
makes no such effort. Also assignment to an array variable is coercive, so
175+
you can assign a non-array value to an array variable.
162176
163177
To place a non-C<Array> into an array variable, binding works:
164178
@@ -182,7 +196,8 @@ at run time).
182196
183197
The answer is that binding to array elements is recognized at the syntax
184198
level and instead of emitting code for a normal binding operation, a special
185-
method on the array is called that knows how to do the binding itself.
199+
method (called C<BIND-KEY>) is called on the array. This method handles binding
200+
to array elements.
186201
187202
Note that, while supported, one should generally avoid directly binding
188203
uncontainerized things into array elements. Doing so may produce
@@ -200,135 +215,46 @@ a thing happening accidentally.
200215
201216
=head2 Flattening, items and containers
202217
203-
The C<%> and C<@> sigils in Perl 6 generally indicate flattening. Hence
204-
flattening list context iterates over them as if there were no container
205-
boundary:
206-
207-
my @a = 1, 2, 3;
208-
my @b = @a, 4, 5;
209-
say @b.elems; # 5
210-
say @b.join: '|'; # 1|2|3|4|5
211-
212-
Here C<@a> is flattened out in the second line.
218+
The C<%> and C<@> sigils in Perl 6 generally indicate multiple values
219+
to an iteration construct, whereas the C<$> sigil indicates only one value.
213220
214-
Item containers prevent flattening, thus allowing the programmer to write
215-
nested data structures.
221+
my @a = 1, 2 3;
222+
for @a { }; # 3 iterations
223+
my $a = (1, 2, 3);
224+
for $a { }; # 1 iteration
216225
217-
The following examples all do the same and do not flatten:
226+
Contrary to earlier versions of Perl 6, and to Perl 5, C<@>-sigiled variables
227+
do not flatten in list context:
218228
219229
my @a = 1, 2, 3;
220-
my @b = @a.item, 4, 5;
221-
@b = $(@a), 4, 5;
222-
@b = $@a, 4, 5;
223-
@b = [1, 2, 3], 4, 5;
224-
225-
my $item = @a;
226-
@b = $item, 4, 5;
227-
228-
say @b.perl; # Array.new([1, 2, 3], 4, 5);
229-
230-
C<[...]> creates an itemized array, and C<Array.new(...)> a non-itemized
231-
array.
232-
233-
There is a slight exception though: if you call a method on an itemized
234-
container, it will generally behave as if it weren't itemized. So C<[1, 2,
235-
3].join(',')> produces C<"1,2,3"> as a result, as one might hope.
236-
237-
This also means that calling the C<.list> method flattens out an itemized
238-
container:
239-
240-
my $item = [1, 2, 3];
241-
my @b = $item.list, 4, 5; # 5 elems
242-
@b = @($item), 4, 5; # a shortcut
243-
@b = @$item, 4, 5; # another shortcut
244-
245-
Other methods on lists also return flat lists, so for example
246-
247-
my $item = [1, 2, 3];
248-
my @b = $item.sort, 4, 5; # 5 elems
249-
250-
sorts the elements of C<$item> and then returns a list that is flattened out
251-
in the array assignment.
252-
253-
Note that C<.list> de-itemizes only the invocant; it does not recursively
254-
flatten the whole data structure. For example in
255-
256-
my @a = [1, [2, 3, 4]].list;
257-
say @a.elems; # 2
258-
259-
the C<.list> only de-itemizes the outer brackets, the inner ones create an
260-
array that is stored in the second element of the Array and is not touched
261-
by C<.list>.
262-
263-
=head3 Non-flattening contexts
264-
265-
In the examples above, it was always assignment to an array variable that
266-
flattened out non-itemized arrays. However, sometimes you want to preserve
267-
the structure.
268-
269-
The most common case (and one of the reasons for the whole flattening vs.
270-
non-flattening distinction to exist) is to have some list-like operator that
271-
could conceivably return either a flat list, or a list of lists. Consider
272-
the zip operator C<Z>, which takes an element from each list like a zipper:
273-
274-
my @left = <a b c>;
275-
my @right = 1, 2, 3;
276-
277-
my @flat = @left Z @right;
278-
my @tree = (@left Z @right).tree;
279-
280-
The expression C<@left Z @right> returns C<(('a', 1), ('b', 2), ('c', 3))>.
281-
In a flattening context like array assignment, that flattens out into a list
282-
of 6 elements, C<('a', 1, 'b', 2, 'c', 3)>. But if you want to preserve the
283-
structure, you can append C<.tree>, and it returns the array
284-
285-
['a', 1], ['b', 2], ['c', 3]
286-
287-
On the other hand, assigning (or binding) to a scalar preserves the
288-
structure without itemizing any inner arrays or lists:
289-
290-
my $x = (<a b c> Z <D E F>);
291-
say $x.perl; # (("a", "D"), ("b", "E"), ("c", "F")).list.item
292-
293-
Again C<.tree> can turn the inner parcels into "hard", itemized arrays:
294-
295-
say $x.tree.perl; # (["a", "D"], ["b", "E"], ["c", "F"]).list
230+
my @b = @a, 4, 5;
231+
say @b.elems; # 3
296232
297-
What happens when you call C<$x.list>?
233+
There are operations that flatten out sublists that are not inside a scalar
234+
container: slurpy parameters (C<*@a>) and explicit calls to C<flat>:
298235
299-
say $x.list.perl; # (("a", "D"), ("b", "E"), ("c", "F")).list
300236
301-
It just returned the same object without the outer C<.item> container, but
302-
didn't look inside the list. If that's what you want, there is another
303-
utility method called C<flat>:
237+
my @a = 1, 2, 3;
238+
say (flat @a, 4, 5).elems; # 5
304239
305-
say $x.flat.perl # ("a", "D", "b", "E", "c", "F").list
240+
sub f(*@x) { @x.elems };
241+
say f @a, 4, 5; # 5
306242
307-
To reiterate the previous point: C<.list> only removes the itemization (or
308-
scalar container) of the invocant, whereas C<.flat> walks the elements of
309-
the invocant and removes their itemization (note that both methods don't
310-
modify the invocant object; they just return a modified copy).
243+
As hinted above, scalar containers prevent that flattening:
311244
312-
=head3 What flattens, what doesn't?
245+
sub f(*@x) { @x.elems };
246+
say f $@a, 4, 5; # 3
313247
314-
In general, operations that have to iterate the list usually flatten the
315-
list. Other operations don't. Here is a list of a few operations that
316-
flatten:
248+
The C<@> character can also be used as a prefix to remove a scalar container:
317249
318-
=item .map, .grep, .first
319-
=item Iteration with "for"
320-
=item .join
321-
=item assignment to an array variable
322-
=item assignment to a hash variable
250+
my $x = (1, 2, 3);
251+
.say for @$x; # 3 iterations
323252
324-
And a few that don't flatten:
253+
Methods generally don't care whether their invocant is in a scalar, so
325254
326-
=item Indexing with [$idx]
327-
=item .elems
328-
=item .tree
255+
my $x = (1, 2, 3);
256+
$x.map(*.say); # 3 iterations
329257
330-
The first two cannot flatten, otherwise it would be very hard to get access
331-
to the structure that's actually stored in the list and the whole
332-
point of C<.tree> is not to flatten.
258+
maps over a list of three elements, not of one.
333259
334260
=end pod

0 commit comments

Comments
 (0)