1NiceSlice(3) User Contributed Perl Documentation NiceSlice(3)
2
3
4
6 PDL::NiceSlice - toward a nicer slicing syntax for PDL
7
9 use PDL::NiceSlice;
10
11 $a(1:4) .= 2; # concise syntax for ranges
12 print $b((0),1:$end); # use variables in the slice expression
13 $a->xchg(0,1)->(($pos-1)) .= 0; # default method syntax
14
15 $idx = long 1, 7, 3, 0; # a piddle of indices
16 $a(-3:2:2,$idx) += 3; # mix explicit indexing and ranges
17 $a->clump(1,2)->(0:30); # 'default method' syntax
18 $a(myfunc(0,$var),1:4)++; # when using functions in slice expressions
19 # use parentheses around args!
20
21 $b = $a(*3); # Add dummy dimension of order 3
22
23 # modifiers are specified in a ;-separated trailing block
24 $a($a!=3;?)++; # short for $a->where($a!=3)++
25 $a(0:1114;_) .= 0; # short for $a->flat->(0:1114)
26 $b = $a(0:-1:3;|); # short for $a(0:-1:3)->sever
27 $n = sequence 3,1,4,1;
28 $b = $n(;-); # drop all dimensions of size 1 (AKA squeeze)
29 $b = $n(0,0;-|); # squeeze *and* sever
30 $c = $a(0,3,0;-); # more compact way of saying $a((0),(3),(0))
31
32 # Use with perldl versions < v1.31 (or include these lines in .perldlrc)
33 perldl> use PDL::NiceSlice;
34 # next one is required, see below
35 perldl> $PERLDL::PREPROCESS = \&PDL::NiceSlice::perldlpp;
36 perldl> $a(4:5) .= xvals(2);
37
39 Slicing is a basic, extremely common operation, and PDL's slice method
40 would be cumbersome to use in many cases. "PDL::NiceSlice" rectifies
41 that by incorporating new slicing syntax directly into the language via
42 a perl source filter (see the perlfilter man page). NiceSlice adds no
43 new functionality, only convenient syntax.
44
45 NiceSlice is loaded automatically in the perldl shell, but (to avoid
46 conflicts with other modules) must be loaded automatically in
47 standalone perl/PDL scripts (see below). If you prefer not to use a
48 prefilter on your standalone scripts, you can use the slice method in
49 those scripts, rather than the more compact NiceSlice constructs.
50
52 The new slicing syntax can be switched on and off in scripts and perl
53 modules by using or unloading "PDL::NiceSlice".
54
55 Note: this will not work in the perldl shell < v1.31. Because the
56 perldl shell uses evals, and NiceSlice is a perl source filter, you
57 have to set a special variable to use it within perldl. See below how
58 to enable the new slicing syntax within older perldl.
59
60 But now back to scripts and modules. Everything after "use
61 PDL::NiceSlice" will be translated and you can use the new slicing
62 syntax. Source filtering will continue until the end of the file is
63 encountered. You can stop sourcefiltering before the end of the file
64 by issuing a "no PDL::NiceSlice" statement.
65
66 Here is an example:
67
68 use PDL::NiceSlice;
69
70 # this code will be translated
71 # and you can use the new slicing syntax
72
73 no PDL::NiceSlice;
74
75 # this code won't
76 # and the new slicing syntax will raise errors!
77
78 See also Filter::Simple and example in this distribution for further
79 examples.
80
81 NOTE: Unlike "normal" modules you need to include a "use
82 PDL::NiceSlice" call in each and every file that contains code that
83 uses the new slicing syntax. Imagine the following situation: a file
84 test0.pl
85
86 # start test0.pl
87 use PDL;
88 use PDL::NiceSlice;
89
90 $a = sequence 10;
91 print $a(0:4),"\n";
92
93 require 'test1.pl';
94 # end test0.pl
95
96 that "require"s a second file test1.pl
97
98 # begin test1.pl
99 $aa = sequence 11;
100 print $aa(0:7),"\n";
101 1;
102 # end test1.pl
103
104 Following conventional perl wisdom everything should be alright since
105 we "use"d "PDL" and "PDL::NiceSlice" already from within test0.pl and
106 by the time test1.pl is "require"d things should be defined and
107 imported, etc. A quick test run will, however, produce something like
108 the following:
109
110 perl test0.pl
111 [0 1 2 3 4]
112 syntax error at test1.pl line 3, near "0:"
113 Compilation failed in require at test0.pl line 7.
114
115 This can be fixed by adding the line
116
117 use PDL::NiceSlice;
118
119 "before" the code in test1.pl that uses the new slicing syntax (to play
120 safe just include the line near the top of the file), e.g.
121
122 # begin corrected test1.pl
123 use PDL::NiceSlice;
124 $aa = sequence 11;
125 print $aa(0:7),"\n";
126 1;
127 # end test1.pl
128
129 Now things proceed more smoothly
130
131 perl test0.pl
132 [0 1 2 3 4]
133 [0 1 2 3 4 5 6 7]
134
135 Note that we don't need to issue "use PDL" again. "PDL::NiceSlice" is
136 a somewhat funny module in that respect. It is a consequence of the way
137 source filtering works in Perl (see also the IMPLEMENTATION section
138 below).
139
140 Usage with perldl
141 NOTE: This information only applies to versions of perldl earlier than
142 1.31 . From v1.31 onwards niceslicing is enabled by default, i.e. it
143 should just work. See perldl for details.
144
145 For pre v1.31 "perldl"s you need to add the following two lines to your
146 .perldlrc file:
147
148 use PDL::NiceSlice;
149 $PERLDL::PREPROCESS = \&PDL::NiceSlice::perldlpp;
150
151 A more complete tool box of commands for experimentation is in the file
152 local.perldlrc in the "PDL::NiceSlice" source directory. Just include
153 the code in that file in your usual ~/.perldlrc and you can switch
154 source filtering with PDL::NiceSlice on and off by typing "trans" and
155 "notrans", respectively. To see what and how your commands are
156 translated switch reporting on:
157
158 perldl> report 1;
159
160 Similarly, switch reporting off as needed
161
162 perldl> report 0;
163
164 Note that these commands will only work if you included the contents of
165 local.perldlrc in your perldl startup file. In "perldl" v1.31 and
166 later these commands are available by default.
167
168 evals and "PDL::NiceSlice"
169 Due to "PDL::NiceSlice" being a source filter it won't work in the
170 usual way within evals. The following will not do what you want:
171
172 $a = sequence 10;
173 eval << 'EOE';
174
175 use PDL::NiceSlice;
176 $b = $a(0:5);
177
178 EOE
179 print $b;
180
181 Instead say:
182
183 use PDL::NiceSlice;
184 $a = sequence 10;
185 eval << 'EOE';
186
187 $b = $a(0:5);
188
189 EOE
190 print $b;
191
192 Source filters must be executed at compile time to be effective. And
193 "PDL::NiceFilter" is just a source filter (although it is not
194 necessarily obvious for the casual user).
195
197 Using "PDL::NiceSlice" slicing piddles becomes so much easier since,
198 first of all, you don't need to make explicit method calls. No
199
200 $pdl->slice(....);
201
202 calls, etc. Instead, "PDL::NiceSlice" introduces two ways in which to
203 slice piddles without too much typing:
204
205 · using parentheses directly following a scalar variable name, for
206 example
207
208 $c = $b(0:-3:4,(0));
209
210 · using the so called default method invocation in which the piddle
211 object is treated as if it were a reference to a subroutine (see also
212 perlref). Take this example that slices a piddle that is part of a
213 perl list @b:
214
215 $c = $b[0]->(0:-3:4,(0));
216
217 The format of the argument list is the same for both types of
218 invocation and will be explained in more detail below.
219
220 Parentheses following a scalar variable name
221 An arglist in parentheses following directly after a scalar variable
222 name that is not preceded by "&" will be resolved as a slicing command,
223 e.g.
224
225 $a(1:4) .= 2; # only use this syntax on piddles
226 $sum += $a(,(1));
227
228 However, if the variable name is immediately preceded by a "&", for
229 example
230
231 &$a(4,5);
232
233 it will not be interpreted as a slicing expression. Rather, to avoid
234 interfering with the current subref syntax, it will be treated as an
235 invocation of the code reference $a with argumentlist "(4,5)".
236
237 The $a(ARGS) syntax collides in a minor way with the perl syntax. In
238 particular, ``foreach $avar(LIST)'' appears like a PDL slicing call.
239 NiceSlice avoids translating the ``for $avar(LIST)'' and ``foreach
240 $avar(LIST)'' constructs for this reason. Since you can't use just any
241 old lvalue expression in the 'foreach' 'for' constructs -- only a real
242 perl scalar will do -- there's no functionality lost. If later
243 versions of perl accept ``foreach <lvalue-expr> (LIST)'', then you can
244 use the code ref syntax, below, to get what you want.
245
246 The default method syntax
247 The second syntax that will be recognized is what I called the default
248 method syntax. It is the method arrow "->" directly followed by an open
249 parenthesis, e.g.
250
251 $a->xchg(0,1)->(($pos)) .= 0;
252
253 Note that this conflicts with the use of normal code references, since
254 you can write in plain Perl
255
256 $sub = sub { print join ',', @_ };
257 $sub->(1,'a');
258
259 NOTE: Once "use PDL::NiceSlice" is in effect (you can always switch it
260 off with a line "no PDL::NiceSlice;" anywhere in the script) the source
261 filter will incorrectly replace the above call to $sub with an
262 invocation of the slicing method. This is one of the pitfalls of using
263 a source filter that doesn't know anything about the runtime type of a
264 variable (cf. the Implementation section).
265
266 This shouldn't be a major problem in practice; a simple workaround is
267 to use the "&"-way of calling subrefs, e.g.:
268
269 $sub = sub { print join ',', @_ };
270 &$sub(1,'a');
271
272 When to use which syntax?
273 Why are there two different ways to invoke slicing? The first syntax
274 "$a(args)" doesn't work with chained method calls. E.g.
275
276 $a->xchg(0,1)(0);
277
278 won't work. It can only be used directly following a valid perl
279 variable name. Instead, use the default method syntax in such cases:
280
281 $a->xchg(0,1)->(0);
282
283 Similarly, if you have a list of piddles @pdls:
284
285 $b = $pdls[5]->(0:-1);
286
287 The argument list
288 The argument list is a comma separated list. Each argument specifies
289 how the corresponding dimension in the piddle is sliced. In contrast to
290 usage of the slice method the arguments should not be quoted. Rather
291 freely mix literals (1,3,etc), perl variables and function invocations,
292 e.g.
293
294 $a($pos-1:$end,myfunc(1,3)) .= 5;
295
296 There can even be other slicing commands in the arglist:
297
298 $a(0:-1:$pdl($step)) *= 2;
299
300 NOTE: If you use function calls in the arglist make sure that you use
301 parentheses around their argument lists. Otherwise the source filter
302 will get confused since it splits the argument list on commas that are
303 not protected by parentheses. Take the following example:
304
305 sub myfunc { return 5*$_[0]+$_[1] }
306 $a = sequence 10;
307 $sl = $a(0:myfunc 1, 2);
308 print $sl;
309 PDL barfed: Error in slice:Too many dims in slice
310 Caught at file /usr/local/bin/perldl, line 232, pkg main
311
312 The simple fix is
313
314 $sl = $a(0:myfunc(1, 2));
315 print $sl;
316 [0 1 2 3 4 5 6 7]
317
318 Note that using prototypes in the definition of myfunc does not help.
319 At this stage the source filter is simply not intelligent enough to
320 make use of this information. So beware of this subtlety.
321
322 Another pitfall to be aware of: currently, you can't use the
323 conditional operator in slice expressions (i.e., "?:", since the parser
324 confuses them with ranges). For example, the following will cause an
325 error:
326
327 $a = sequence 10;
328 $b = rand > 0.5 ? 0 : 1; # this one is ok
329 print $a($b ? 1 : 2); # error !
330 syntax error at (eval 59) line 3, near "1,
331
332 For the moment, just try to stay clear of the conditional operator in
333 slice expressions (or provide us with a patch to the parser to resolve
334 this issue ;).
335
336 Modifiers
337 Following a suggestion originally put forward by Karl Glazebrook the
338 latest versions of "PDL::NiceSlice" implement modifiers in slice
339 expressions. Modifiers are convenient shorthands for common variations
340 on PDL slicing. The general syntax is
341
342 $pdl(<slice>;<modifier>)
343
344 Four modifiers are currently implemented:
345
346 · "_" : flatten the piddle before applying the slice expression. Here
347 is an example
348
349 $b = sequence 3, 3;
350 print $b(0:-2;_); # same as $b->flat->(0:-2)
351 [0 1 2 3 4 5 6 7]
352
353 which is quite different from the same slice expression without the
354 modifier
355
356 print $b(0:-2);
357 [
358 [0 1]
359 [3 4]
360 [6 7]
361 ]
362
363 · "|" : sever the link to the piddle, e.g.
364
365 $a = sequence 10;
366 $b = $a(0:2;|)++; # same as $a(0:2)->sever++
367 print $b;
368 [1 2 3]
369 print $a; # check if $a has been modified
370 [0 1 2 3 4 5 6 7 8 9]
371
372 · "?" : short hand to indicate that this is really a where expression
373
374 As expressions like
375
376 $a->where($a>5)
377
378 are used very often you can write that shorter as
379
380 $a($a>5;?)
381
382 With the "?"-modifier the expression preceding the modifier is not
383 really a slice expression (e.g. ranges are not allowed) but rather
384 an expression as required by the where method. For example, the
385 following code will raise an error:
386
387 $a = sequence 10;
388 print $a(0:3;?);
389 syntax error at (eval 70) line 3, near "0:"
390
391 That's about all there is to know about this one.
392
393 · "-" : squeeze out any singleton dimensions. In less technical
394 terms: reduce the number of dimensions (potentially) by deleting
395 all dims of size 1. It is equivalent to doing a reshape(-1). That
396 can be very handy if you want to simplify the results of slicing
397 operations:
398
399 $a = ones 3, 4, 5;
400 $b = $a(1,0;-); # easier to type than $a((1),(0))
401 print $b->info;
402 PDL: Double D [5]
403
404 It also provides a unique opportunity to have smileys in your code!
405 Yes, PDL gives new meaning to smileys.
406
407 Combining modifiers
408 Several modifiers can be used in the same expression, e.g.
409
410 $c = $a(0;-|); # squeeze and sever
411
412 Other combinations are just as useful, e.g. ";_|" to flatten and sever.
413 The sequence in which modifiers are specified is not important.
414
415 A notable exception is the "where" modifier ("?") which must not be
416 combined with other flags (let me know if you see a good reason to
417 relax this rule).
418
419 Repeating any modifier will raise an error:
420
421 $c = $a(-1:1;|-|); # will cause error
422 NiceSlice error: modifier | used twice or more
423
424 Modifiers are still a new and experimental feature of "PDL::NiceSlice".
425 I am not sure how many of you are actively using them. Please do so and
426 experiment with the syntax. I think modifiers are very useful and make
427 life a lot easier. Feedback is welcome as usual. The modifier syntax
428 will likely be further tuned in the future but we will attempt to
429 ensure backwards compatibility whenever possible.
430
431 Argument formats
432 In slice expressions you can use ranges and secondly, piddles as 1D
433 index lists (although compare the description of the "?"-modifier above
434 for an exception).
435
436 · ranges
437
438 You can access ranges using the usual ":" separated format:
439
440 $a($start:$stop:$step) *= 4;
441
442 Note that you can omit the trailing step which then defaults to 1.
443 Double colons ("::") are not allowed to avoid clashes with Perl's
444 namespace syntax. So if you want to use steps different from the
445 default you have to also at least specify the stop position.
446 Examples:
447
448 $a(::2); # this won't work (in the way you probably intended)
449 $a(:-1:2); # this will select every 2nd element in the 1st dim
450
451 Just as with slice negative indices count from the end of the
452 dimension backwards with "-1" being the last element. If the start
453 index is larger than the stop index the resulting piddle will have
454 the elements in reverse order between these limits:
455
456 print $a(-2:0:2);
457 [8 6 4 2 0]
458
459 A single index just selects the given index in the slice
460
461 print $a(5);
462 [5]
463
464 Note, however, that the corresponding dimension is not removed from
465 the resulting piddle but rather reduced to size 1:
466
467 print $a(5)->info
468 PDL: Double D [1]
469
470 If you want to get completely rid of that dimension enclose the index
471 in parentheses (again similar to the slice syntax):
472
473 print $a((5));
474 5
475
476 In this particular example a 0D piddle results. Note that this syntax
477 is only allowed with a single index. All these will be errors:
478
479 print $a((0,4)); # will work but not in the intended way
480 print $a((0:4)); # compile time error
481
482 An empty argument selects the whole dimension, in this example all of
483 the first dimension:
484
485 print $a(,(0));
486
487 Alternative ways to select a whole dimension are
488
489 $a = sequence 5, 5;
490 print $a(:,(0));
491 print $a(0:-1,(0));
492 print $a(:-1,(0));
493 print $a(0:,(0));
494
495 Arguments for trailing dimensions can be omitted. In that case these
496 dimensions will be fully kept in the sliced piddle:
497
498 $a = random 3,4,5;
499 print $a->info;
500 PDL: Double D [3,4,5]
501 print $a((0))->info;
502 PDL: Double D [4,5]
503 print $a((0),:,:)->info; # a more explicit way
504 PDL: Double D [4,5]
505 print $a((0),,)->info; # similar
506 PDL: Double D [4,5]
507
508 · dummy dimensions
509
510 As in slice, you can insert a dummy dimension by preceding a single
511 index argument with '*'. A lone '*' inserts a dummy dimension of
512 order 1; a '*' followed by a number inserts a dummy dimension of that
513 order.
514
515 · piddle index lists
516
517 The second way to select indices from a dimension is via 1D piddles
518 of indices. A simple example:
519
520 $a = random 10;
521 $idx = long 3,4,7,0;
522 $b = $a($idx);
523
524 This way of selecting indices was previously only possible using dice
525 ("PDL::NiceSlice" attempts to unify the "slice" and "dice"
526 interfaces). Note that the indexing piddles must be 1D or 0D. Higher
527 dimensional piddles as indices will raise an error:
528
529 $a = sequence 5, 5;
530 $idx2 = ones 2,2;
531 $sum = $a($idx2)->sum;
532 piddle must be <= 1D at /home/XXXX/.perldlrc line 93
533
534 Note that using index piddles is not as efficient as using ranges.
535 If you can represent the indices you want to select using a range use
536 that rather than an equivalent index piddle. In particular, memory
537 requirements are increased with index piddles (and execution time may
538 be longer). That said, if an index piddle is the way to go use it!
539
540 As you might have expected ranges and index piddles can be freely mixed
541 in slicing expressions:
542
543 $a = random 5, 5;
544 $b = $a(-1:2,pdl(3,0,1));
545
546 piddles as indices in ranges
547 You can use piddles to specify indices in ranges. No need to turn them
548 into proper perl scalars with the new slicing syntax. However, make
549 sure they contain not more than one element! Otherwise a runtime error
550 will be triggered. First a couple of examples that illustrate proper
551 usage:
552
553 $a = sequence 5, 5;
554 $rg = pdl(1,-1,3);
555 print $a($rg(0):$rg(1):$rg(2),2);
556 [
557 [11 14]
558 ]
559 print $a($rg+1,:$rg(0));
560 [
561 [2 0 4]
562 [7 5 9]
563 ]
564
565 The next one raises an error
566
567 print $a($rg+1,:$rg(0:1));
568 multielement piddle where only one allowed at XXX/Core.pm line 1170.
569
570 The problem is caused by using the 2-element piddle "$rg(0:1)" as the
571 stop index in the second argument ":$rg(0:1)" that is interpreted as a
572 range by "PDL::NiceSlice". You can use multielement piddles as index
573 piddles as described above but not in ranges. And "PDL::NiceSlice"
574 treats any expression with unprotected ":"'s as a range. Unprotected
575 means as usual "not occurring between matched parentheses".
576
578 "PDL::NiceSlice" exploits the ability of Perl to use source filtering
579 (see also perlfilter). A source filter basically filters (or rewrites)
580 your perl code before it is seen by the compiler. "PDL::NiceSlice"
581 searches through your Perl source code and when it finds the new
582 slicing syntax it rewrites the argument list appropriately and splices
583 a call to the "nslice" method using the modified arg list into your
584 perl code. You can see how this works in the perldl shell by switching
585 on reporting (see above how to do that).
586
587 The "nslice" method is an extended version of mslice that knows how to
588 deal with index piddles (and therefore combines slicing and dicing).
589 Full documentation of "nslice" will be in the next PDL release.
590
592 Conditional operator
593 The conditional operator can't be used in slice expressions (see
594 above).
595
596 The "DATA" file handle
597 Note: To avoid clobbering the "DATA" filehandle "PDL::NiceSlice"
598 switches itself off when encountering the "__END__" or "__DATA__"
599 tokens. This should not be a problem for you unless you use
600 "SelfLoader" to load PDL code including the new slicing from that
601 section. It is even desirable when working with Inline::Pdlpp, see
602 below.
603
604 Possible interaction with Inline::Pdlpp
605 There is currently an undesired interaction between "PDL::NiceSlice"
606 and the new Inline::Pdlpp module (currently only in PDL CVS). Since PP
607 code generally contains expressions of the type "$var()" (to access
608 piddles, etc) "PDL::NiceSlice" recognizes those incorrectly as slice
609 expressions and does its substitutions. This is not a problem if you
610 use the "DATA" section for your Pdlpp code -- the recommended place for
611 Inline code anyway. In that case "PDL::NiceSlice" will have switched
612 itself off before encountering any Pdlpp code (see above):
613
614 # use with Inline modules
615 use PDL;
616 use PDL::NiceSlice;
617 use Inline Pdlpp;
618
619 $a = sequence(10);
620 print $a(0:5);
621
622 __END__
623
624 __Pdlpp__
625
626 ... inline stuff
627
628 Otherwise switch "PDL::NiceSlice" explicitly off around the
629 Inline::Pdlpp code:
630
631 use PDL::NiceSlice;
632
633 $a = sequence 10;
634 $a(0:3)++;
635 $a->inc;
636
637 no PDL::NiceSlice; # switch off before Pdlpp code
638 use Inline Pdlpp => "Pdlpp source code";
639
640 The cleaner solution is to always stick with the "DATA" way of
641 including your "Inline" code as in the first example. That way you keep
642 your nice Perl code at the top and all the ugly Pdlpp stuff etc at the
643 bottom.
644
645 Bug reports
646 Feedback and bug reports are welcome. Please include an example that
647 demonstrates the problem. Log bug reports in the PDL bug database at
648
649 http://sourceforge.net/bugs/?group_id=612
650
651 or send them to the pdl-porters mailing list
652 <pdl-porters@jach.hawaii.edu>.
653
655 Copyright (c) 2001, 2002 Christian Soeller. All Rights Reserved. This
656 module is free software. It may be used, redistributed and/or modified
657 under the same terms as PDL itself (see http://pdl.perl.org).
658
659
660
661perl v5.12.3 2009-10-17 NiceSlice(3)