Cuando se llama a un constructor de iteradores, el constructor retorna una subrutina que es capaz de iterar sobre los elementos de la lista.
Son ejemplos de iteradores
open
crea el iterador y el operador de lectura <>
nos da el siguiente),
opendir
es el constructor, readdir
el
iterador)
g
(la posición
del siguiente lugar de búsqueda puede ser consultada
mediante el operador pos
):
DB<1 $x = 'un ejemplo sencillo' DB<2> print "$&(".pos($x).") " while $x =~ m{[aeiou]}g u(1) e(4) e(6) o(10) e(13) i(16) o(19)
El siguiente ejemplo muestra la construcción de un iterador. El generador podria usarse como sigue:
16 my $row = iterator 1, 4; # creación de un iterador de 1 a 4 17 my $col = iterator 1, 5, 2; # de 1 a 5 pero con paso 2 18 my ($r, $c); 19 while ($row->($r)) { 20 print "$r: "; 21 while ($col->($c)) { 22 print "$c "; 23 } 24 print "\n"; 25 }
Cada llamada a iterators
crea un conjunto nuevo de variables léxicas
y una nueva subrutina anónima. Es posible
simultanear de este modo dos clausuras, cada una con
su propio rango y paso:
lhp@nereida:~/Lperl/src$ perl iterators.pl 1: 1 3 5 2: 1 3 5 3: 1 3 5 4: 1 3 5 lhp@nereida:~/Lperl/src$
El código del constructor iterator
retorna la subrutina de iteración.
Esta última controla el agotamiento
de la lista en la línea 9.
En tal caso se vuelve a iniciar el
contador ($next = $from-$step
)
y se retorna undef
(obsérvese el
uso de la coma).
lhp@nereida:~/Lperl/src$ cat -n iterators.pl 1 use strict; 2 3 sub iterator { 4 my ($from, $to, $step) = @_; 5 $step = 1 unless defined($step); 6 my $next = $from-$step; # iniciar contador 7 my $closure_ref = sub { 8 $next += $step; 9 $next = $from-$step, return if $next > $to; 10 $_[0] = $next; 11 return 1; 12 }; 13 return $closure_ref; 14 }
Para saber mas sobre iteradores consulte el libro Higher Order Perl [13].