use strict; use warnings; use feature qw/say/; use Data::Dump qw/pp/; sub gen_listiter { my @init=@_; my @list=@init; sub { if (@list) { return shift @list } else { @list=@init; return () } } } sub get_array { my $iter=shift; my @res; while ( my ($res)= $iter->() ) { push @res,$res; } return @res; } my %operations =( '+' => sub { defined $_[1] ? $_[0] + $_[1]->[0] : $_[0] }, ); sub X (&;$) { my ($cr,$tail_itr)=@_; # my $op = $operations{$tail_itr} if defined $tail_itr; # undef $tail_itr if $op; $tail_itr //= gen_listiter([]); my $head_itr = gen_listiter($cr->()); my $state='INIT'; my $head; my $tail; my $op //= sub { [ $_[0],@{$_[1]} ] }; my $cross_itr = sub { goto $state; INIT: $state="RESUME"; while ( ($head) = $head_itr->() ) { while ( ($tail) = $tail_itr->() ) { return $op->($head,$tail); RESUME: } } $state='INIT'; return; }; if (wantarray) { return get_array($cross_itr); } else { return $cross_itr; } } pp X {"a".."d"}; pp X {"a".."b"} X {1..2} X {'x','y'}; my $iter = X {"a","b"} X {1..2} X {'x','y'}; while ( my ($aref)= $iter->() ) { pp $aref; }