@@ -80,6 +80,19 @@ is equivalent to
80
80
method attr() is rw { $!attr }
81
81
}
82
82
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
+
83
96
= head2 Binding
84
97
85
98
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
116
129
semantics in Perl 6. The most basic one is L < List|/type/List >
117
130
It is created by the comma operator.
118
131
119
- say (1, 2, 3).WHAT ; # ( List)
132
+ say (1, 2, 3).^name ; # List
120
133
121
134
A list is immutable, which means you cannot change the number of elements
122
135
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).
154
167
155
168
Nevertheless, it's easy to observe how different they are:
156
169
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
159
172
160
173
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.
162
176
163
177
To place a non-C < Array > into an array variable, binding works:
164
178
@@ -182,7 +196,8 @@ at run time).
182
196
183
197
The answer is that binding to array elements is recognized at the syntax
184
198
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.
186
201
187
202
Note that, while supported, one should generally avoid directly binding
188
203
uncontainerized things into array elements. Doing so may produce
@@ -200,135 +215,46 @@ a thing happening accidentally.
200
215
201
216
= head2 Flattening, items and containers
202
217
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.
213
220
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
216
225
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:
218
228
219
229
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
296
232
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 > :
298
235
299
- say $x.list.perl; # (("a", "D"), ("b", "E"), ("c", "F")).list
300
236
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
304
239
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
306
242
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:
311
244
312
- = head3 What flattens, what doesn't?
245
+ sub f(*@x) { @x.elems };
246
+ say f $@a, 4, 5; # 3
313
247
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:
317
249
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
323
252
324
- And a few that don't flatten:
253
+ Methods generally don't care whether their invocant is in a scalar, so
325
254
326
- = item Indexing with [$idx]
327
- = item .elems
328
- = item .tree
255
+ my $x = (1, 2, 3);
256
+ $x.map(*.say); # 3 iterations
329
257
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.
333
259
334
260
= end pod
0 commit comments