for my $x ( $sub_x->() ) { for my $y ( $sub_y->() ) { return [ $x,$y ]; } } #### use 5.12.0; use strict; use warnings; use Data::Dump qw/pp dd/; my $DBG; ;;; # skipped $DBG = 0; my $i_cross = cross( sub {"A".."B"}, sub {1..2}, sub {"a".."b"}, ); my $count = 4; while ( my ($v) = $i_cross->() ) { warn "*** First 5 RESULTs: ", pp $v; last unless $count--; } warn "stopped"; while ( my ($v) = $i_cross->() ) { warn "*** Remaining RESULT: ", pp $v; } sub cross { my @stack = @_; my $level = 0; my @ranges = (); my @res; return sub { while ( $level >= 0 ) { my $ra_range = \ $ranges[$level]; # ENTER LOOP unless (defined $$ra_range ) { $$ra_range = [ $stack[$level]->() ]; warn "ENTER level=$level left \@ranges=" ,pp \@ranges if $DBG; } # LOOP OVER if ( @$$ra_range ) { $res[$level] = shift @$$ra_range ; # deepest level? if ( $level == $#stack ) { return [@res]; } # go deeper else { $level++; } } #EXIT LOOP: else { $level--; $$ra_range = undef; } } return; } } #### *** First 5 RESULTs: ["A", 1, "a"] at d:/exp/iter/cross.pl line 92. *** First 5 RESULTs: ["A", 1, "b"] at d:/exp/iter/cross.pl line 92. *** First 5 RESULTs: ["A", 2, "a"] at d:/exp/iter/cross.pl line 92. *** First 5 RESULTs: ["A", 2, "b"] at d:/exp/iter/cross.pl line 92. *** First 5 RESULTs: ["B", 1, "a"] at d:/exp/iter/cross.pl line 92. stopped at d:/exp/iter/cross.pl line 96. *** Remaining RESULT: ["B", 1, "b"] at d:/exp/iter/cross.pl line 99. *** Remaining RESULT: ["B", 2, "a"] at d:/exp/iter/cross.pl line 99. *** Remaining RESULT: ["B", 2, "b"] at d:/exp/iter/cross.pl line 99.