Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 237 lines (164 sloc) 7.966 kB
3ea163c [spec/S08] started writing the introduction;
ruoso authored
1
2 =encoding utf8
3
4 =head1 TITLE
5
6 Synopsis 8: Capture and Parcel
7
8 =head1 AUTHORS
9
10 Daniel Ruoso <daniel@ruoso.com>
11
12 =head1 VERSION
13
14 Created: 20 Sep 2009
15
736a666 [Spec] random whackage on List, Seq, Parcel, Capture, Iterator, Nil etc.
lwall authored
16 Last Modified: 23 Jan 2010
17 Version: 2
3ea163c [spec/S08] started writing the introduction;
ruoso authored
18
19 =head1 Introduction
20
21 Unlike most programming languages, the data structure that is used to
22 send the parameters into a routine invocation (be it a method or a
23 sub) is exposed to the language as a built-in type like any
f6c7d85 [S08] use POD markup where appropriate
moritz authored
24 other. This represents a very important aspect of the Perl 6 runtime
3ea163c [spec/S08] started writing the introduction;
ruoso authored
25 requirements.
26
27 Additionally to the fact that this data structure is visible in the
28 language type system, it is not assumed that the capture is a native
29 type, which means that the internal representation of the data is
30 subject to change. The only thing the runtime can assume is the API
31 described here.
32
33 Of course the runtime can cheat whenever it knows the capture is
34 implemented by its own internal data structure for optimization
35 purposes, but it should allow the use of foreign types when invoking a
f6c7d85 [S08] use POD markup where appropriate
moritz authored
36 routine, as long as the object says true to C<.^does(Capture)>.
3ea163c [spec/S08] started writing the introduction;
ruoso authored
37
38 Captures and Parcels are also the basis for the multidimensionality of
f6c7d85 [S08] use POD markup where appropriate
moritz authored
39 lists in Perl 6. Unlike Perl 5, no flattening happens unless it's
736a666 [Spec] random whackage on List, Seq, Parcel, Capture, Iterator, Nil etc.
lwall authored
40 explicitly required by the user, which is done by enforcing the list
41 context. If you use the item context the dimensionality should be
3ea163c [spec/S08] started writing the introduction;
ruoso authored
42 preserved.
43
736a666 [Spec] random whackage on List, Seq, Parcel, Capture, Iterator, Nil etc.
lwall authored
44 In addition to the list and item context, there's also a special
3ea163c [spec/S08] started writing the introduction;
ruoso authored
45 context, which is, in a simplified way, called "Capture context", but
46 it actually means "deferred context", in a way that the Capture or
47 Parcel is kept as-is while they are manipulated in the code. This is
51f0b5b [S08] small fixes by mberends++
ruoso authored
48 useful to avoid unwanted flattening as well as avoiding the DWIMmy
3ea163c [spec/S08] started writing the introduction;
ruoso authored
49 features that might change the capture's behavior.
50
f6c7d85 [S08] use POD markup where appropriate
moritz authored
51 This is the main point of why Capture and Parcel replace Perl 5
3ea163c [spec/S08] started writing the introduction;
ruoso authored
52 references, they allow you to send data untouched from one place to
f6c7d85 [S08] use POD markup where appropriate
moritz authored
53 another. The second reason is that as in Perl 6 everything is an
3ea163c [spec/S08] started writing the introduction;
ruoso authored
54 object, there isn't really "pass-by-value" anymore, you're always
55 sending a reference, Captures and Parcels simply carry other objects
56 without enforcing any context on them.
57
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
58 =head1 Capture or Parcel
59
f6c7d85 [S08] use POD markup where appropriate
moritz authored
60 While a C<Capture> is the object that holds the parameters sent to a
61 routine (positional and named), a C<Parcel> is a more fundamental data
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
62 structure that doesn't really differentiate named arguments from
63 positional arguments (but it still lets you access the named ones by
64 their name).
65
66 The basic underlying concept is that a Parcel behaves much like a
67 list, but it doesn't enforce any context, in a way that no flattening
f6c7d85 [S08] use POD markup where appropriate
moritz authored
68 or coercion is done. When you use the C<Positional> API on a Parcel, it
5cdc66e [S08] another typo by mberends++, s/list/array/ as pointed by PerlJam…
ruoso authored
69 will include all the listed items, whether they look like named
51f0b5b [S08] small fixes by mberends++
ruoso authored
70 arguments or positional arguments. For example:
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
71
72 1, 2, :a<b>
73
74 The Parcel represented here has 3 positional items and allows you to
f6c7d85 [S08] use POD markup where appropriate
moritz authored
75 access the element 'a' through the C<Associative> interface. A Parcel
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
76 might be statically converted to a Capture if it's clear to the parser
77 that it's being used as the arguments to a routine call.
78
79 A Capture, on the other hand, is not required to keep the positional
51f0b5b [S08] small fixes by mberends++
ruoso authored
80 information for the named arguments, for example:
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
81
82 foo(1,:a<b>,2)
83
84 In the call to the routine foo, there are only two positional
85 arguments and one named argument, and you won't be able to find "b"
f6c7d85 [S08] use POD markup where appropriate
moritz authored
86 from the C<Positional> interface, but only from the Associative.
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
87
88 The differentiation from Parcel and Capture is important to keep the
89 regular use of inline declarations consistent, let's say you do the
90 following:
91
bc0c9eb [S08] enforce correct precedence, as pointed out by pmichaud++
ruoso authored
92 my $a = (0, :a<b>, 2);
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
93 say $a[2];
94
95 If we had Capture and Parcel as the same data structure, you wouldn't
f6c7d85 [S08] use POD markup where appropriate
moritz authored
96 get C<2> as the result of the above code, because there are only two
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
97 positional arguments, not three. Using the same example:
98
99 sub foo($p1, $p2, :$a) {...}
100 foo(|$a);
101
102 In that case, the Parcel is converted into a Capture, and therefore
f6c7d85 [S08] use POD markup where appropriate
moritz authored
103 the pair C<< :a<b> >> is no longer visible as a positional argument,
104 only as named.
678c922 [spec/S08] section that differentiates Parcel from Capture
ruoso authored
105
106 Note that once you convert a Parcel into a Capture, you won't be able
107 to get the original Parcel again, because a Capture doesn't hold the
108 information about the position of named arguments.
109
1edc972 [S08] adding two more sections
ruoso authored
110 =head1 Multidimensionality
111
112 Probably the most important task of Parcels and Captures is to
f6c7d85 [S08] use POD markup where appropriate
moritz authored
113 implement the multidimensionality of lists in Perl 6, this means that
1edc972 [S08] adding two more sections
ruoso authored
114 the barrier used to detect the dimensionality of the data structures
115 by the operators is whatever the item inside it implements Parcel or
116 Capture. For instance:
117
92a5290 [S08] enforce correct precedence, as pointed out by pmichaud++
ruoso authored
118 my $a = (1, (2, (3, 4)));
1edc972 [S08] adding two more sections
ruoso authored
119 say $a[1];
120
f6c7d85 [S08] use POD markup where appropriate
moritz authored
121 In that case, you'll get C<2, (3, 4)> (or whatever is implemented in
235def3 [S08]: Some notes where online discussions are at odds with the spec.
pmichaud authored
122 the .Str method of that specific Parcel).
123
124 [Update: The above (and much of what follows below) doesn't conform
125 to the latest discussion on parcels; parcels flatten under item assignment.
126 See L<http://irclog.perlgeek.de/perl6/2009-09-23#i_1532822>.]
127
128 But, you should be able to:
1edc972 [S08] adding two more sections
ruoso authored
129
130 say $a[1;0];
131
f6c7d85 [S08] use POD markup where appropriate
moritz authored
132 Which is going to return C<2>, which is almost the same as:
1edc972 [S08] adding two more sections
ruoso authored
133
134 say $a[1][0];
135
136 But the first provides a more convenient and optimizeable way of
f6c7d85 [S08] use POD markup where appropriate
moritz authored
137 asking for it. If you want to get the value C<4> from that data
1edc972 [S08] adding two more sections
ruoso authored
138 structure you need to:
139
140 say $a[1;1;1];
141
5cdc66e [S08] another typo by mberends++, s/list/array/ as pointed by PerlJam…
ruoso authored
142 Note that if you assign that parcel to an array, it will be flattened,
143 so:
1edc972 [S08] adding two more sections
ruoso authored
144
145 my @a = 1, (2, (3, 4));
146 say @a[3];
147
f6c7d85 [S08] use POD markup where appropriate
moritz authored
148 Would print C<4>, at the same time that trying to ask for
1edc972 [S08] adding two more sections
ruoso authored
149 multidimensionality information from that list would result in a
150 failure:
151
152 say @a[1;1;1];
153
f6c7d85 [S08] use POD markup where appropriate
moritz authored
154 As the element 1 of the array C<@a> is not a Capture or a Parcel, it is
155 not possible for the C<.[]> operator to traverse it.
1edc972 [S08] adding two more sections
ruoso authored
156
157 [Conjecture: It is still not clear if the multidimensional access
f6c7d85 [S08] use POD markup where appropriate
moritz authored
158 should be able to get into regular arrays, i.e.: C<[1,[2,[3,[4]]]] ]>
1edc972 [S08] adding two more sections
ruoso authored
159
160 It is important to realize that it's not the parens that are creating
f6c7d85 [S08] use POD markup where appropriate
moritz authored
161 the Parcel, but the C<< infix:<,> >>. The parens are only required in
162 order to define a sub-parcel.
1edc972 [S08] adding two more sections
ruoso authored
163
164 On the other hand, if you bind a parcel to a variable, it doesn't
165 really matter which sigil it uses:
166
bc0c9eb [S08] enforce correct precedence, as pointed out by pmichaud++
ruoso authored
167 my @a := (1, (2, (3, 4)));
1edc972 [S08] adding two more sections
ruoso authored
168 say @a[1;1;1]; # "4"
169 say @a[3]; # failure
170
171 Captures and Parcels are seen the same way regarding
172 multidimensionality, for instance:
173
92a5290 [S08] enforce correct precedence, as pointed out by pmichaud++
ruoso authored
174 my $a = ((map { $_ * 2 }, 1..5),(map { $_ / 2 }, 1..5));
1edc972 [S08] adding two more sections
ruoso authored
175 say $a[0;0]; # 2
176 say $a[1;0]; # 0.5
177
178 The same way, if each map closure returns more than one item inside
179 its capture:
180
92a5290 [S08] enforce correct precedence, as pointed out by pmichaud++
ruoso authored
181 my $a = ((map { $_ * 2, $_ / 2 }, 1..5),(map { $_ / 2, $_ * 2 }, 1..5));
1edc972 [S08] adding two more sections
ruoso authored
182 say $a[0;0;0]; # 2
183 say $a[0;0;1]; # 0.5
184 say $a[1;0;0]; # 0.5
185 say $a[1;0;0]; # 2
186
187 The flattening process will traverse into Parcels and Captures, so:
188
189 1, (2, (3, 4))
190
191 will result in:
192
193 1, 2, 3, 4
194
195 after flattening, while:
196
197 1, [2, [3, 4]]
198
199 Would remain as-is.
200
201 =head1 Context deferral
202
203 Also known as "Capture Context", defines how you can defer the context
204 coercion for a given value. That is a fundamental feature because
205 something as simple as assigning to a scalar might imply context
206 coercion that would get you a modified value.
207
208 Both the Parcel and the Capture are able to preserve the values as-is,
209 in a way that you can later apply any context and have the same result
51f0b5b [S08] small fixes by mberends++
ruoso authored
210 as if the context was applied immediately.
1edc972 [S08] adding two more sections
ruoso authored
211
f6c7d85 [S08] use POD markup where appropriate
moritz authored
212 Context deferral is actually the reason why Perl 6 no longer supports
1edc972 [S08] adding two more sections
ruoso authored
213 the "wantarray" operator, nor does it provide any substitute. The way
214 you should implement wantarray-like behavior is by properly overriding
215 the coercion for each context. The Contextual::Return module is an
f6c7d85 [S08] use POD markup where appropriate
moritz authored
216 implementation of that concept in Perl 5.
1edc972 [S08] adding two more sections
ruoso authored
217
218 In order to use the context deferral in your code, you need to use the
219 "capture sigil", which can be presented in two forms:
220
bc0c9eb [S08] enforce correct precedence, as pointed out by pmichaud++
ruoso authored
221 my ¢a = (1, (2, (3, 4)));
1edc972 [S08] adding two more sections
ruoso authored
222
223 or
224
bc0c9eb [S08] enforce correct precedence, as pointed out by pmichaud++
ruoso authored
225 my @%a = (1, (2, (3, 4)));
1edc972 [S08] adding two more sections
ruoso authored
226
227 The latter is provided as an alternative for situations where you want
228 to preserve the code in 7-bits only.
229
235def3 [S08]: Some notes where online discussions are at odds with the spec.
pmichaud authored
230 [Update: C<@%a> might not work out as a capture sigil --
231 See L<http://irclog.perlgeek.de/perl6/2009-09-21#i_1523801>.]
232
3ea163c [spec/S08] started writing the introduction;
ruoso authored
233 =head1 Additions
234
235 Please post errors and feedback to perl6-language. If you are making
236 a general laundry list, please separate messages by topic.
Something went wrong with that request. Please try again.