@@ -14,8 +14,8 @@ Synopsis 3: Perl 6 Operators
14
14
15
15
Created: 8 Mar 2004
16
16
17
- Last Modified: 2 May 2013
18
- Version: 262
17
+ Last Modified: 7 May 2013
18
+ Version: 263
19
19
20
20
=head1 Overview
21
21
@@ -4144,18 +4144,68 @@ A unary hyper operator (either prefix or postfix) has only one
4144
4144
hyper marker, located on its argument side, while an infix operator
4145
4145
always has one on each side to indicate there are two arguments.
4146
4146
4147
- Unary hyper operators always produce a hash or array of exactly the
4148
- same I<declared> shape as the single argument. If the item is not
4149
- declared with a shape, only the top dimension is mapped, equivalent
4150
- to a normal C<.map> method. (To map deeper dimensions than provided
4151
- for by hypers, use the either C<.duckmap> or C<.deepmap> method,
4152
- depending on whether you want to give the item mapping or the
4153
- substructure first shot at each node.)
4154
-
4155
- When infix operators are presented with
4156
- two lists or arrays of identical shape, a result of that same shape is
4157
- produced. Otherwise the result depends on how you write the hyper
4158
- markers.
4147
+ The meaning of a unary hyper operator depends on whether the operator
4148
+ is considered to be a structural dereferencing operator. Most operators
4149
+ are not structural.
4150
+
4151
+ Non-structural unary hyper operators produce a hash or array of exactly the
4152
+ same shape as the single argument. The hyper will descend into nested
4153
+ lists and hashes to distribute over the lower-level values just as they
4154
+ distribute over the top-level values that are leaves in the tree. Non-structural
4155
+ unary hypers do not care whether the nesting is achieved by declaration
4156
+ in the case of shaped arrays, or by mere incorporation of sublists and subhashes
4157
+ dynamically. In any case the operator is applied only to the leaves of the
4158
+ structure.
4159
+
4160
+ There are a few operators that are deemed to be structural, however,
4161
+ and will produce counterintuitive results if treated as ordinary
4162
+ operators. These include the dereferencing operators such as
4163
+ subscripts, as well as various methods that assume they are already
4164
+ working something Positional or Associative that serves as a parental node
4165
+ in the tree that a normal hyperop would want to descend into.
4166
+
4167
+ These operations are marked by declaring them with the C<is nodal>
4168
+ property, which is available by inspection to the hyper controller
4169
+ when it examines the function it was passed. (Hypers are just one
4170
+ form of higher-order programming, after all, and functions are also
4171
+ objects with properties.) So this declaration is to be placed on
4172
+ the top-level declaration of the operator, a proto declaration when
4173
+ there are multiple candidates, or the candidate itself when there is
4174
+ only one candidate. If the C<is nodal> trait is declared, the hyper
4175
+ controller will consider it to be structural.
4176
+
4177
+ [Conjecture: we might revise this be a C<does Nodal> role instead of
4178
+ a trait, if the implementors decide that makes more sense.]
4179
+
4180
+ For structural hypers, we never implicitly follow references to
4181
+ substructures, since the operator itself wants to deal with the
4182
+ structure. So these operators distribute only over the top level
4183
+ of the structure.
4184
+
4185
+ For arrays or hashes declared with a shape (see S09), this top level
4186
+ may be multidimensional; unary hypers consider shaped arrays to really
4187
+ be one-dimensional (and indeed, for compactly stored multidimensional
4188
+ arrays, multidimensional subscripts can just be calculations into an
4189
+ underlying linear representation, which can be optimized to run on
4190
+ a GPU, so this makes implementational sense).
4191
+
4192
+ If the item is not declared with a shape, only the top dimension
4193
+ is mapped, equivalent to a normal C<.map> method. (To map deeper
4194
+ dimensions than provided for by hypers, use the either C<.duckmap>
4195
+ or C<.deepmap> method, depending on whether you want to give the item
4196
+ mapping or the substructure first shot at each node.)
4197
+
4198
+ In contrast to unary operators that allows for (a few) structural
4199
+ operators, infix operators are never considered structural, so the
4200
+ hyper infix controller will always consider the dynamic shape as
4201
+ potentially traversable in addition to any static shape. That is,
4202
+ it is allowed to follow references from any parent node to dynamically
4203
+ nested structures. (Whether it actually follows a particular reference
4204
+ depends on the relative shapes of the two arguments.)
4205
+
4206
+ When infix operators are presented with two lists or arrays of
4207
+ identical shape, a result of that same shape is produced. Otherwise
4208
+ the result depends on how you write the hyper markers.
4159
4209
4160
4210
For an infix operator, if either argument is insufficiently
4161
4211
dimensioned, Perl "upgrades" it, but only if you point the "sharp" end
@@ -4287,49 +4337,6 @@ which means something like:
4287
4337
my $type = $node.WHAT;
4288
4338
$node.?foo // $type($node.map: { .».foo })
4289
4339
4290
- When processing recursive structures, there is an ambiguity when a node
4291
- could be processed either directly by the operator or recursively
4292
- by iterating a contained structure. For unary hypers, we use a
4293
- policy called "duck mapping", which says that when a node responds
4294
- directly to the operator supplied, it is considered a leaf node,
4295
- and any Iterable components of the node are ignored. If and only if
4296
- a node does not respond to the operator, it is examined to see if is
4297
- Iterable, and recursion occurs. (For this meaning of "responds to",
4298
- we ignore any multi candidates defined in Cool, or the negation
4299
- above would not work, since Array responds to negation via Cool.
4300
- [Conjecture: there's a C<use strict :multi> pragma that can enable
4301
- these dispatch semantics in a lexical scope.])
4302
-
4303
- A declaratively shaped array or hash with multiple dimensions is
4304
- considered a single level of tree node for this purpose. You must
4305
- use subscripting if you wish to isolate a 1-dimensional slice of such
4306
- a shaped object.
4307
-
4308
- The main upshot of this duck mapping policy is that it is possible
4309
- to use array or hash operators that make sense on a node of the tree,
4310
- and the requested operator will take precedence over recursion. For
4311
- example, if you have an array of hashes, you can subscript into
4312
- each of the hashes in parallel without caring whether the value
4313
- produced is iterable:
4314
-
4315
- @AoHoA».<foo>; # a list of all the 'foo' Arrays
4316
-
4317
- This would not be possible if recursion took precedence over subscripting.
4318
- Since duck mapping stops recursing whenever the operator is applicable,
4319
- duck mapping can be considered to have a shallow bias. If you wish to have
4320
- a deep mapping where the recursion takes precedence over the operator,
4321
- so that all the leaves are found first, and then the operator applied,
4322
- you need to use the C<.deepmap> method instead:
4323
-
4324
- $node.deepmap: *.foo;
4325
-
4326
- which means something like:
4327
-
4328
- my $type = $node.WHAT;
4329
- $node ~~ Iterable ?? $type($node.map({ .deepmap: *.foo })) !! $node.?foo
4330
-
4331
- [Conjecture: we could allow C<««> and C<»»> hypers which did deep mapping.]
4332
-
4333
4340
You are not allowed to define your own hyper operators, because they
4334
4341
are supposed to have consistent semantics derivable entirely from
4335
4342
the modified scalar operator. If you're looking for a mathematical
0 commit comments