1Sub::HandlesVia::HandleUrsLeirbrCaornyt:r:iAbrurtaeydS(u3Pb)e:r:lHaDnodcluemseVnitaa:t:iHoanndlerLibrary::Array(3)
2
3
4
6 Sub::HandlesVia::HandlerLibrary::Array - library of array-related
7 methods
8
10 package My::Class {
11 use Moo;
12 use Sub::HandlesVia;
13 use Types::Standard 'ArrayRef';
14 has attr => (
15 is => 'rwp',
16 isa => ArrayRef,
17 handles_via => 'Array',
18 handles => {
19 'my_accessor' => 'accessor',
20 'my_all' => 'all',
21 'my_all_true' => 'all_true',
22 'my_any' => 'any',
23 'my_apply' => 'apply',
24 'my_clear' => 'clear',
25 'my_count' => 'count',
26 'my_delete' => 'delete',
27 'my_elements' => 'elements',
28 'my_first' => 'first',
29 'my_first_index' => 'first_index',
30 'my_flatten' => 'flatten',
31 'my_flatten_deep' => 'flatten_deep',
32 'my_for_each' => 'for_each',
33 'my_for_each_pair' => 'for_each_pair',
34 'my_get' => 'get',
35 'my_grep' => 'grep',
36 'my_head' => 'head',
37 'my_insert' => 'insert',
38 'my_is_empty' => 'is_empty',
39 'my_join' => 'join',
40 'my_map' => 'map',
41 'my_max' => 'max',
42 'my_maxstr' => 'maxstr',
43 'my_min' => 'min',
44 'my_minstr' => 'minstr',
45 'my_natatime' => 'natatime',
46 'my_not_all_true' => 'not_all_true',
47 'my_pairfirst' => 'pairfirst',
48 'my_pairgrep' => 'pairgrep',
49 'my_pairkeys' => 'pairkeys',
50 'my_pairmap' => 'pairmap',
51 'my_pairs' => 'pairs',
52 'my_pairvalues' => 'pairvalues',
53 'my_pick_random' => 'pick_random',
54 'my_pop' => 'pop',
55 'my_print' => 'print',
56 'my_product' => 'product',
57 'my_push' => 'push',
58 'my_reduce' => 'reduce',
59 'my_reductions' => 'reductions',
60 'my_reset' => 'reset',
61 'my_reverse' => 'reverse',
62 'my_sample' => 'sample',
63 'my_set' => 'set',
64 'my_shallow_clone' => 'shallow_clone',
65 'my_shift' => 'shift',
66 'my_shuffle' => 'shuffle',
67 'my_shuffle_in_place' => 'shuffle_in_place',
68 'my_sort' => 'sort',
69 'my_sort_in_place' => 'sort_in_place',
70 'my_splice' => 'splice',
71 'my_sum' => 'sum',
72 'my_tail' => 'tail',
73 'my_uniq' => 'uniq',
74 'my_uniq_in_place' => 'uniq_in_place',
75 'my_uniqnum' => 'uniqnum',
76 'my_uniqnum_in_place' => 'uniqnum_in_place',
77 'my_uniqstr' => 'uniqstr',
78 'my_uniqstr_in_place' => 'uniqstr_in_place',
79 'my_unshift' => 'unshift',
80 },
81 );
82 }
83
85 This is a library of methods for Sub::HandlesVia.
86
88 "accessor( $index, $value? )"
89 Arguments: Int, Optional[Any].
90
91 Acts like "get" if given just an index, or "set" if given an index and
92 value.
93
94 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
95 $object->my_accessor( 1, 'quux' );
96 say Dumper( $object->attr ); ## ==> [ 'foo', 'quux', 'baz' ]
97 say $object->my_accessor( 2 ); ## ==> 'baz'
98
99 "all()"
100 All elements in the array, in list context.
101
102 my $object = My::Class->new( attr => [ 'foo', 'bar' ] );
103 my @list = $object->my_all;
104 say Dumper( \@list ); ## ==> [ 'foo', 'bar' ]
105
106 "all_true( $coderef )"
107 Arguments: CodeRef.
108
109 Like "List::Util::all()".
110
111 "any( $coderef )"
112 Arguments: CodeRef.
113
114 Like "List::Util::any()".
115
116 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
117 my $truth = $object->my_any( sub { /a/ } );
118 say $truth; ## ==> true
119
120 "apply( $coderef )"
121 Arguments: CodeRef.
122
123 Executes the coderef (which should modify $_) against each element of
124 the array; returns the resulting array in list context.
125
126 "clear()"
127 Empties the array.
128
129 my $object = My::Class->new( attr => [ 'foo' ] );
130 $object->my_clear;
131 say Dumper( $object->attr ); ## ==> []
132
133 "count()"
134 The number of elements in the referenced array.
135
136 my $object = My::Class->new( attr => [ 'foo', 'bar' ] );
137 say $object->my_count; ## ==> 2
138
139 "delete( $index )"
140 Arguments: Int.
141
142 Removes the indexed element from the array and returns it. Elements
143 after it will be "moved up".
144
145 "elements()"
146 All elements in the array, in list context. (Essentially the same as
147 "all".)
148
149 my $object = My::Class->new( attr => [ 'foo', 'bar' ] );
150 my @list = $object->my_elements;
151 say Dumper( \@list ); ## ==> [ 'foo', 'bar' ]
152
153 "first( $coderef )"
154 Arguments: CodeRef.
155
156 Like "List::Util::first()".
157
158 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
159 my $found = $object->my_first( sub { /a/ } );
160 say $found; ## ==> 'bar'
161
162 "first_index( $coderef )"
163 Arguments: CodeRef.
164
165 Like "List::MoreUtils::first_index()".
166
167 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
168 my $found = $object->my_first_index( sub { /z$/ } );
169 say $found; ## ==> 2
170
171 "flatten()"
172 All elements in the array, in list context. (Essentially the same as
173 "all".)
174
175 my $object = My::Class->new( attr => [ 'foo', 'bar' ] );
176 my @list = $object->my_flatten;
177 say Dumper( \@list ); ## ==> [ 'foo', 'bar' ]
178
179 "flatten_deep( $depth? )"
180 Arguments: Optional[Int].
181
182 Flattens the arrayref into a list, including any nested arrayrefs. (Has
183 the potential to loop infinitely.)
184
185 my $object = My::Class->new( attr => [ 'foo', [ 'bar', [ 'baz' ] ] ] );
186 say Dumper( [ $object->my_flatten_deep ] ); ## ==> [ 'foo', 'bar', 'baz' ]
187
188 my $object2 = My::Class->new( attr => [ 'foo', [ 'bar', [ 'baz' ] ] ] );
189 say Dumper( [ $object->my_flatten_deep(1) ] ); ## ==> [ 'foo', 'bar', [ 'baz' ] ]
190
191 "for_each( $coderef )"
192 Arguments: CodeRef.
193
194 Chainable method which executes the coderef on each element of the
195 array. The coderef will be passed two values: the element and its
196 index.
197
198 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
199 $object->my_for_each( sub { say "Item $_[1] is $_[0]." } );
200
201 "for_each_pair( $coderef )"
202 Arguments: CodeRef.
203
204 Chainable method which executes the coderef on each pair of elements in
205 the array. The coderef will be passed the two elements.
206
207 "get( $index )"
208 Arguments: Int.
209
210 Returns a single element from the array by index.
211
212 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
213 say $object->my_get( 0 ); ## ==> 'foo'
214 say $object->my_get( 1 ); ## ==> 'bar'
215 say $object->my_get( -1 ); ## ==> 'baz'
216
217 "grep( $coderef )"
218 Arguments: CodeRef.
219
220 Like "grep" from perlfunc.
221
222 "head( $count )"
223 Arguments: Int.
224
225 Returns the first $count elements of the array in list context.
226
227 "insert( $index, $value )"
228 Arguments: Int, Any.
229
230 Inserts a value into the array with the given index. Elements after it
231 will be "moved down".
232
233 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
234 $object->my_insert( 1, 'quux' );
235 say Dumper( $object->attr ); ## ==> [ 'foo', 'quux', 'bar', 'baz' ]
236
237 "is_empty()"
238 Boolean indicating if the referenced array is empty.
239
240 my $object = My::Class->new( attr => [ 'foo', 'bar' ] );
241 say $object->my_is_empty; ## ==> false
242 $object->_set_attr( [] );
243 say $object->my_is_empty; ## ==> true
244
245 "join( $with? )"
246 Arguments: Optional[Str].
247
248 Returns a string joining all the elements in the array; if $with is
249 omitted, defaults to a comma.
250
251 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
252 say $object->my_join; ## ==> 'foo,bar,baz'
253 say $object->my_join( '|' ); ## ==> 'foo|bar|baz'
254
255 "map( $coderef )"
256 Arguments: CodeRef.
257
258 Like "map" from perlfunc.
259
260 "max()"
261 Like "List::Util::max()".
262
263 "maxstr()"
264 Like "List::Util::maxstr()".
265
266 "min()"
267 Like "List::Util::min()".
268
269 "minstr()"
270 Like "List::Util::minstr()".
271
272 "natatime( $n, $callback? )"
273 Arguments: Int, Optional[CodeRef].
274
275 Given just a number, returns an iterator which reads that many elements
276 from the array at a time. If also given a callback, calls the callback
277 repeatedly with those values.
278
279 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
280 my $iter = $object->my_natatime( 2 );
281 say Dumper( [ $iter->() ] ); ## ==> [ 'foo', 'bar' ]
282 say Dumper( [ $iter->() ] ); ## ==> [ 'baz' ]
283
284 "not_all_true( $coderef )"
285 Arguments: CodeRef.
286
287 Like "List::Util::notall()".
288
289 "pairfirst( $coderef )"
290 Arguments: CodeRef.
291
292 Like "List::Util::pairfirst()".
293
294 "pairgrep( $coderef )"
295 Arguments: CodeRef.
296
297 Like "List::Util::pairgrep()".
298
299 "pairkeys()"
300 Like "List::Util::pairkeys()".
301
302 "pairmap( $coderef )"
303 Arguments: CodeRef.
304
305 Like "List::Util::pairmap()".
306
307 "pairs()"
308 Like "List::Util::pairs()".
309
310 "pairvalues()"
311 Like "List::Util::pairvalues()".
312
313 "pick_random( $count )"
314 Arguments: Optional[Int].
315
316 If no $count is given, returns one element of the array at random. If
317 $count is given, creates a new array with that many random elements
318 from the original array (or fewer if the original array is not long
319 enough) and returns that as an arrayref or list depending on context
320
321 "pop()"
322 Removes the last element from the array and returns it.
323
324 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
325 say $object->my_pop; ## ==> 'baz'
326 say $object->my_pop; ## ==> 'bar'
327 say Dumper( $object->attr ); ## ==> [ 'foo' ]
328
329 "print( $fh?, $with? )"
330 Arguments: Optional[FileHandle], Optional[Str].
331
332 Prints a string joining all the elements in the array; if $fh is
333 omitted, defaults to STDOUT; if $with is omitted, defaults to a comma.
334
335 "product()"
336 Like "List::Util::product()".
337
338 "push( @values )"
339 Adds elements to the end of the array.
340
341 my $object = My::Class->new( attr => [ 'foo' ] );
342 $object->my_push( 'bar', 'baz' );
343 say Dumper( $object->attr ); ## ==> [ 'foo', 'bar', 'baz' ]
344
345 "reduce( $coderef )"
346 Arguments: CodeRef.
347
348 Like "List::Util::reduce()".
349
350 "reductions( $coderef )"
351 Arguments: CodeRef.
352
353 Like "List::Util::reductions()".
354
355 "reset()"
356 Resets the attribute to its default value, or an empty arrayref if it
357 has no default.
358
359 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
360 $object->my_reset;
361 say Dumper( $object->attr ); ## ==> []
362
363 "reverse()"
364 Returns the reversed array in list context.
365
366 "sample( $count )"
367 Arguments: Int.
368
369 Like "List::Util::sample()".
370
371 "set( $index, $value )"
372 Arguments: Int, Any.
373
374 Sets the element with the given index to the supplied value.
375
376 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
377 $object->my_set( 1, 'quux' );
378 say Dumper( $object->attr ); ## ==> [ 'foo', 'quux', 'baz' ]
379
380 "shallow_clone()"
381 Creates a new arrayref with the same elements as the original.
382
383 "shift()"
384 Removes an element from the start of the array and returns it.
385
386 my $object = My::Class->new( attr => [ 'foo', 'bar', 'baz' ] );
387 say $object->my_shift; ## ==> 'foo'
388 say $object->my_shift; ## ==> 'bar'
389 say Dumper( $object->attr ); ## ==> [ 'baz' ]
390
391 "shuffle()"
392 Returns the array in a random order; can be called in list context or
393 scalar context and will return an arrayref in the latter case.
394
395 "shuffle_in_place()"
396 Rearranges the array in a random order, and changes the attribute to
397 point to the new order.
398
399 "sort( $coderef? )"
400 Arguments: Optional[CodeRef].
401
402 Like "sort" from perlfunc.
403
404 "sort_in_place( $coderef? )"
405 Arguments: Optional[CodeRef].
406
407 Like "sort" from perlfunc, but changes the attribute to point to the
408 newly sorted array.
409
410 "splice( $index, $length, @values )"
411 Like "splice" from perlfunc.
412
413 "sum()"
414 Like "List::Util::sum0()".
415
416 "tail( $count )"
417 Arguments: Int.
418
419 Returns the last $count elements of the array in list context.
420
421 "uniq()"
422 Returns the array filtered to remove duplicates; can be called in list
423 context or scalar context and will return an arrayref in the latter
424 case.
425
426 "uniq_in_place()"
427 Filters the array to remove duplicates, and changes the attribute to
428 point to the filtered array.
429
430 "uniqnum()"
431 Returns the array filtered to remove duplicates numerically; can be
432 called in list context or scalar context and will return an arrayref in
433 the latter case.
434
435 "uniqnum_in_place()"
436 Filters the array to remove duplicates numerically, and changes the
437 attribute to point to the filtered array.
438
439 "uniqstr()"
440 Returns the array filtered to remove duplicates stringwise; can be
441 called in list context or scalar context and will return an arrayref in
442 the latter case.
443
444 "uniqstr_in_place()"
445 Filters the array to remove duplicates stringwise, and changes the
446 attribute to point to the filtered array.
447
448 "unshift( @values )"
449 Adds an element to the start of the array.
450
451 my $object = My::Class->new( attr => [ 'foo' ] );
452 $object->my_unshift( 'bar', 'baz' );
453 say Dumper( $object->attr ); ## ==> [ 'bar', 'baz', 'foo' ]
454
456 This module provides some shortcut constants for indicating a list of
457 delegations.
458
459 package My::Class {
460 use Moo;
461 use Sub::HandlesVia;
462 use Sub::HandlesVia::HandlerLibrary::Array qw( HandleQueue );
463
464 has things => (
465 is => 'ro',
466 handles_via => 'Array',
467 handles => HandleQueue,
468 default => sub { [] },
469 );
470 }
471
472 These shortcuts can be combined using the " | " operator.
473
474 has things => (
475 is => 'ro',
476 handles_via => 'Array',
477 handles => HandleQueue | HandleStack,
478 default => sub { [] },
479 );
480
481 "HandleQueue"
482 Creates delegations named like "things_is_empty", "things_size",
483 "things_enqueue", "things_dequeue", and "things_peek".
484
485 "HandleStack"
486 Creates delegations named like "things_is_empty", "things_size",
487 "things_push", "things_pop", and "things_peek".
488
490 Using for_each
491 use strict;
492 use warnings;
493
494 package My::Plugin {
495 use Moo::Role;
496 sub initialize {}
497 sub finalize {}
498 }
499
500 package My::Processor {
501 use Moo;
502 use Sub::HandlesVia;
503 use Types::Standard qw( ArrayRef ConsumerOf );
504
505 has plugins => (
506 is => 'ro',
507 isa => ArrayRef[ ConsumerOf['My::Plugin'] ],
508 handles_via => 'Array',
509 handles => {
510 add_plugin => 'push',
511 plugin_do => 'for_each',
512 },
513 default => sub { [] },
514 );
515
516 sub _do_stuff {
517 return;
518 }
519
520 sub run_process {
521 my ( $self, @args ) = @_;
522 $self->plugin_do( sub {
523 my $plugin = shift;
524 $plugin->initialize( $self, @args );
525 } );
526 $self->_do_stuff( @args );
527 $self->plugin_do( sub {
528 my $plugin = shift;
529 $plugin->finalize( $self, @args );
530 } );
531 }
532 }
533
534 my $p = My::Processor->new();
535
536 package My::Plugin::Noisy {
537 use Moo; with 'My::Plugin';
538 sub initialize {
539 my ( $self, $processor, @args ) = @_;
540 say "initialize @args"; ## ==> 'initialize 1 2 3'
541 }
542 sub finalize {
543 my ( $self, $processor, @args ) = @_;
544 say "finalize @args"; ## ==> 'finalize 1 2 3'
545 }
546 }
547
548 $p->add_plugin( My::Plugin::Noisy->new );
549
550 $p->run_process( 1, 2, 3 );
551
552 Job queue using push and shift
553 use strict;
554 use warnings;
555 use Try::Tiny;
556
557 package My::JobQueue {
558 use Moo;
559 use Sub::HandlesVia;
560 use Types::Standard qw( Bool ArrayRef CodeRef HasMethods is_Object );
561 use Try::Tiny;
562
563 has auto_requeue => (
564 is => 'ro',
565 isa => Bool,
566 default => 0,
567 );
568
569 has jobs => (
570 is => 'ro',
571 isa => ArrayRef[ CodeRef | HasMethods['run'] ],
572 handles_via => 'Array',
573 handles => {
574 add_job => 'push',
575 _get_job => 'shift',
576 is_empty => 'is_empty',
577 },
578 default => sub { [] },
579 );
580
581 sub _handle_failed_job {
582 my ( $self, $job ) = @_;
583 $self->add_job( $job ) if $self->auto_requeue;
584 }
585
586 sub run_jobs {
587 my $self = shift;
588 while ( not $self->is_empty ) {
589 my $job = $self->_get_job;
590 try {
591 is_Object($job) ? $job->run() : $job->();
592 }
593 catch {
594 $self->_handle_failed_job( $job );
595 };
596 }
597 }
598 }
599
600 my $q = My::JobQueue->new();
601
602 my $str = '';
603 $q->add_job( sub { $str .= 'A' } );
604 $q->add_job( sub { $str .= 'B' } );
605 $q->add_job( sub { $str .= 'C' } );
606
607 $q->run_jobs;
608
609 say $str; ## ==> 'ABC'
610
611 # Attempt to push invalid value on the queue
612 #
613 try {
614 $q->add_job( "jobs cannot be strings" );
615 }
616 catch {
617 say $q->is_empty; ## ==> true
618 };
619
621 Please report any bugs to
622 <https://github.com/tobyink/p5-sub-handlesvia/issues>.
623
625 Sub::HandlesVia.
626
628 Toby Inkster <tobyink@cpan.org>.
629
631 This software is copyright (c) 2020, 2022 by Toby Inkster.
632
633 This is free software; you can redistribute it and/or modify it under
634 the same terms as the Perl 5 programming language system itself.
635
637 THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
638 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
639 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
640
641
642
643perl v5.36.0 2022S-u1b2:-:1H7andlesVia::HandlerLibrary::Array(3)