File Coverage

blib/lib/Scalar/Cycle/Manual.pm
Criterion Covered Total %
statement 34 64 53.1
branch 1 14 7.1
condition 2 2 100.0
subroutine 12 19 63.1
pod 9 9 100.0
total 58 108 53.7


line stmt bran cond sub pod time code
1             package Scalar::Cycle::Manual ;
2              
3 1     1   54969 use strict;
  1         2  
  1         30  
4 1     1   5 use warnings ;
  1         1  
  1         50  
5              
6             BEGIN
7             {
8 1         10 use Sub::Exporter -setup =>
9             {
10             exports => [ qw() ],
11             groups =>
12             {
13             all => [ qw() ],
14             }
15 1     1   1004 };
  1         14662  
16            
17 1     1   346 use vars qw ($VERSION);
  1         1  
  1         45  
18 1     1   28 $VERSION = '0.03';
19             }
20              
21             #-------------------------------------------------------------------------------
22              
23             #~ use English qw( -no_match_vars ) ;
24             #~ use Carp qw(carp croak confess) ;
25              
26              
27             =head1 NAME
28              
29             Scalar::Cycle::Manual - Cycle through a list of values (with optional automatic incrementation)
30              
31             =head1 SYNOPSIS
32              
33             use Scalar::Cycle::Manual ;
34            
35             my $cyclic_variable = new 'Scalar::Cycle::Manual', qw( first second third ) ;
36            
37             print $cyclic_variable; # 'first'
38             print $cyclic_variable; # still 'first'
39            
40             print $cyclic_variable->next ; # 'second'
41             print $cyclic_variable; # still 'first'
42            
43             print $cyclic_variable->previous; # 'third'
44             print $cyclic_variable; # still 'first'
45            
46             print $cyclic_variable->increment;
47             print $cyclic_variable; # 'second'
48            
49             print $cyclic_variable->increment;
50             print $cyclic_variable; # 'third'
51            
52             $cyclic_variable->reset;
53             print $cyclic_variable; # first
54            
55             print $cyclic_variable->decrement;
56             print $cyclic_variable; # 'third'
57            
58             $cyclic_variable++;
59             print $cyclic_variable; # 'first'
60            
61             $cyclic_variable--;
62             print $cyclic_variable; # 'third'
63            
64             $cyclic_variable->auto_increment(1) ;
65             print $cyclic_variable; # 'third'
66             print $cyclic_variable; # 'first'
67              
68             =head1 DESCRIPTION
69              
70             There's a bunch of modules implementing a scalar which cycles in a list of values. Take your time to compare them.
71              
72             If you want more control over when the variable cycles, this module may suit your needs.
73              
74             =head1 DOCUMENTATION
75              
76             Use C to go through a list over and over again. Once you get to the end of the list, you go back to the beginning.
77              
78             =head2 Overloaded operator
79              
80             =head3 ++ and --
81              
82             These operator act as the L and L subroutines.
83              
84             =head3 0+ and ""
85              
86             These operators implement the fetching of the current value in scalar and string context.
87              
88             =head3 <>
89              
90             The '<>' operator returns the current value and increments the current position even if L is set to B<0>.
91              
92             =head1 SUBROUTINES/METHODS
93              
94             =cut
95              
96             ## no critic
97 1     1   5 use constant CURRENT_INDEX => 0 ;
  1         2  
  1         57  
98 1     1   3 use constant MAX_INDEX => 1 ;
  1         2  
  1         32  
99 1     1   5 use constant VALUES => 2 ;
  1         1  
  1         31  
100 1     1   4 use constant AUTO_INCREMENT=> 3 ;
  1         11  
  1         88  
101             ## use critic
102             #-------------------------------------------------------------------------------
103              
104             use overload
105 1         13 '=' => \©_constructor,
106             '<>' => \&increment,
107             '++' => \&increment,
108             '--' => \&decrement,
109             '""' => \&as_scalar,
110 1     1   8 '0+' => \&as_scalar;
  1         1  
111              
112             #-------------------------------------------------------------------------------
113              
114             sub new
115             {
116              
117             =head2 new(@value_list)
118              
119             Creates a B object that you can use to cycle through values.
120              
121             use Scalar::Cycle::Manual ;
122            
123             my $cyclic_variable = new 'Scalar::Cycle::Manual'( qw( first second third )) ;
124              
125             B
126              
127             =over 2
128              
129             =item * @value_list - list of values to be cycled through
130              
131             =back
132              
133             B
134              
135             =over 2
136              
137             =item * a B object
138              
139             =back
140              
141             =cut
142              
143 3     3 1 1505 my ($class , @values) = @_ ;
144              
145 3   100     57 return(bless [ 0, scalar(@values) - 1, \@values, 0], ($class || __PACKAGE__)) ;
146             }
147              
148             #-------------------------------------------------------------------------------
149              
150             sub copy_constructor
151             {
152              
153             =head2 copy_constructor
154              
155             This is needed by the B<++> operator.
156              
157             =cut
158              
159 0     0 1 0 my ($self) = @_ ;
160              
161 0         0 return(bless [ @{$self}], __PACKAGE__);
  0         0  
162             }
163              
164             #-------------------------------------------------------------------------------
165              
166             sub auto_increment
167             {
168              
169             =head2 auto_increment([$boolean])
170              
171             When set, the current position in the value list is automatically incremented after the value is accessed.
172              
173             When a B object is created, auto_increment is set to I.
174              
175             my $cyclic_variable = new 'Scalar::Cycle::Manual'( qw( first second third )) ;
176            
177             print $cyclic_variable; # 'first'
178             print $cyclic_variable; # 'first'
179            
180             $cyclic_variable->auto_increment(1) ;
181            
182             print $cyclic_variable; # 'second'
183             print $cyclic_variable; # 'third'
184            
185             my $is_auto_increment_on = $cyclic_variable->auto_increment() ;
186              
187             B
188              
189             =over 2
190              
191             =item * $boolean- an optional value to set the auto_increment state
192              
193             =back
194              
195             B
196              
197             =over 2
198              
199             =item * If $bolean is not defined, the current state is returned
200              
201             =back
202              
203             =cut
204              
205 0     0 1 0 my ($self, $auto_increment) = @_ ;
206              
207             return
208             (
209 0 0       0 defined $auto_increment ? $self->[AUTO_INCREMENT] = $auto_increment : $self->[AUTO_INCREMENT]
210             );
211             }
212              
213             #-------------------------------------------------------------------------------
214             sub as_scalar
215             {
216              
217             =head2 as_scalar
218              
219             Transform the object to the current cycle values. This is automatically called by Perl.
220              
221             use Scalar::Cycle::Manual ;
222            
223             my $cyclic_variable = new 'Scalar::Cycle::Manual'( qw( first second third )) ;
224            
225             my $value = $cyclic_variable ;
226             print $cyclic_variable ;
227            
228              
229             B
230              
231             =over 2
232              
233             =item * the current value extracted from the cycle values.
234              
235             =back
236              
237             =cut
238             #~ my @caller = caller() ;
239             #~ print "@caller as_scalar\n" ;
240              
241 2     2 1 3 my ($self) = @_ ;
242              
243 2         5 my $value = $self->[VALUES][$self->[CURRENT_INDEX]];
244              
245 2 50       7 if($self->[AUTO_INCREMENT])
246             {
247 0         0 $self->[CURRENT_INDEX]++;
248 0 0       0 $self->[CURRENT_INDEX] = 0 if $self->[CURRENT_INDEX] > $self->[MAX_INDEX];
249             }
250              
251 2         10 return($value) ;
252             }
253              
254             #-------------------------------------------------------------------------------
255              
256             sub increment
257             {
258              
259             =head2 increment()
260              
261             Forces the B to change to the next value in the cycle value list.
262              
263             use Scalar::Cycle::Manual ;
264            
265             my $cyclic_variable = new 'Scalar::Cycle::Manual'( qw( first second third )) ;
266            
267             print $cyclic_variable->increment;
268             print $cyclic_variable ;
269            
270             # or
271            
272             print $cyclic_variable->increment;
273              
274             B
275              
276             =over 2
277              
278             =item * the next value, extracted from the cycle values.
279              
280             =back
281              
282             =cut
283              
284 0     0 1   my ($self) = @_ ;
285              
286 0           my $value = $self->[VALUES][$self->[CURRENT_INDEX]] ;
287              
288 0           $self->[CURRENT_INDEX]++ ;
289 0 0         $self->[CURRENT_INDEX] = 0 if $self->[CURRENT_INDEX] > $self->[MAX_INDEX];
290              
291 0           return($value) ;
292             }
293              
294             #-------------------------------------------------------------------------------
295              
296             sub decrement
297             {
298              
299             =head2 decrement()
300              
301             Forces the B to change to the previous value in the value list.
302              
303             print $cyclic_variable->previous;
304             print $cyclic_variable ;
305            
306             # or
307            
308             print $cyclic_variable->previous;
309              
310             B
311              
312             =over 2
313              
314             =item * the previous value, extracted from the cycle values.
315              
316             =back
317              
318             =cut
319              
320 0     0 1   my ($self) = @_ ;
321              
322 0           my $value = $self->[VALUES][$self->[CURRENT_INDEX]] ;
323              
324 0           $self->[CURRENT_INDEX]-- ;
325 0 0         $self->[CURRENT_INDEX] = $self->[MAX_INDEX] if $self->[CURRENT_INDEX] < 0 ;
326              
327 0           return($value) ;
328             }
329              
330             #-------------------------------------------------------------------------------
331              
332             sub reset ## no critic (Subroutines::ProhibitBuiltinHomonyms)
333             {
334              
335             =head2 reset()
336              
337             Makes the current value the first value in the value list.
338              
339             use Scalar::Cycle::Manual ;
340            
341             my $cyclic_variable = new 'Scalar::Cycle::Manual'( qw( first second third )) ;
342            
343             $cyclic_variable->auto_increment(1) ;
344             print $cyclic_variable; # 'first'
345            
346             $cyclic_variable->reset ;
347             print $cyclic_variable; # 'first'
348              
349             =cut
350              
351 0     0 1   my ($self) = @_ ;
352 0           $self->[CURRENT_INDEX] = 0 ;
353              
354 0           return ;
355             }
356              
357             #-------------------------------------------------------------------------------
358              
359             sub previous
360             {
361              
362             =head2 previous()
363              
364             Returns the value prior to the value at the current position. This does not affect the current position in the cycle value list.
365              
366             use Scalar::Cycle::Manual ;
367            
368             my $cyclic_variable = new 'Scalar::Cycle::Manual'( qw( first second third )) ;
369              
370             B
371              
372             =over 2
373              
374             =item * the value prior to the value at the current position
375              
376             =back
377              
378             =cut
379              
380 0     0 1   my ($self) = @_ ;
381              
382 0           my $index = $self->[CURRENT_INDEX] ;
383              
384 0           $index-- ;
385 0 0         $index = $self->[MAX_INDEX] if $index < 0;
386              
387 0           return($self->[VALUES][$index]) ;
388             }
389              
390             #-------------------------------------------------------------------------------
391              
392             sub next ## no critic (Subroutines::ProhibitBuiltinHomonyms)
393             {
394              
395             =head2 next()
396              
397             Returns the value next to the value at the current position. This does not affect the current position in the value list.
398              
399             use Scalar::Cycle::Manual ;
400            
401             my $cyclic_variable = new 'Scalar::Cycle::Manual'( qw( first second third )) ;
402              
403             B
404              
405             =over 2
406              
407             =item * the value next to the value at the current position
408              
409             =back
410              
411             =cut
412              
413 0     0 1   my ($self) = @_ ;
414              
415 0           my $index = $self->[CURRENT_INDEX] ;
416              
417 0           $index++ ;
418 0 0         $index = 0 if $index > $self->[MAX_INDEX];
419              
420 0           return($self->[VALUES][$index]) ;
421             }
422            
423             #-------------------------------------------------------------------------------
424              
425             1 ;
426              
427             =head1 BUGS AND LIMITATIONS
428              
429             None so far.
430              
431             =head1 AUTHOR
432              
433             Khemir Nadim ibn Hamouda
434             CPAN ID: NKH
435             mailto:nadim@khemir.net
436              
437             =head1 LICENSE AND COPYRIGHT
438              
439             This program is free software; you can redistribute
440             it and/or modify it under the same terms as Perl itself.
441              
442             =head1 SUPPORT
443              
444             You can find documentation for this module with the perldoc command.
445              
446             perldoc Scalar::Cycle::Manual
447              
448             You can also look for information at:
449              
450             =over 4
451              
452             =item * AnnoCPAN: Annotated CPAN documentation
453              
454             L
455              
456             =item * RT: CPAN's request tracker
457              
458             Please report any bugs or feature requests to L .
459              
460             We will be notified, and then you'll automatically be notified of progress on
461             your bug as we make changes.
462              
463             =item * Search CPAN
464              
465             L
466              
467             =back
468              
469             =head1 SEE ALSO
470              
471             Scalar-MultiValue
472              
473             by Graciliano Monteiro Passos: Create a SCALAR with multiple values.
474              
475             List-Rotation
476              
477             by Imre Saling: Loop (Cycle, Alternate or Toggle) through a list of values via a singleton object implemented as closure.
478              
479             Tie::FlipFlop
480              
481             by Abigail: Alternate between two values.
482              
483             List::Cycle
484              
485             by Andi Lester: Objects for cycling through a list of values
486              
487             Tie::Cycle
488              
489             by Brian D. Foy: Cycle through a list of values via a scalar.
490              
491             Tie::Toggle
492              
493             by Brian D. Foy: False and true, alternately, ad infinitum.
494              
495             =cut