sub make_combo_iter { my $array_ref = shift; # last index of top level my $size = scalar( @{$array_ref} ); # create array of last indices my @array_limits; for my $i (0..$size-1) { $array_limits[$i] = scalar( @{$array_ref->[$i]} ) - 1; } # one counter for each sub-array my @array_counter = (0) x $size; my $done = 0; my $iter = sub { if ($done) { $done = 0; return undef; } my @next_combo; # compute @next_combo for my $i (0..$size-1) { push @next_combo, $array_ref->[$i][$array_counter[$i]]; } # increment counters, set $done if the last one rolls over my $rollover = 0; for my $c (0..$size-1) { if (++$array_counter[$c] > $array_limits[$c]) { $array_counter[$c] = 0; # reset $rollover = 1; # carry } else { $rollover = 0; # no carry last; # no more increments } } # if the last array rolled over, set the done flag if ( $rollover ) { $done = 1; } return \@next_combo; }; # anonymous iterator sub return $iter; } # make_combo_iter