X 1,2 X #produces ('a', 1, 'x'), ('a', 1, 'y'), ('a', 2, 'x'), ('a', 2, 'y'), ('b', 1, 'x'), ('b', 1, 'y'), ('b', 2, 'x'), ('b', 2, 'y') #### 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; } __DATA__ (["a"], ["b"], ["c"], ["d"]) ( ["a", 1, "x"], ["a", 1, "y"], ["a", 2, "x"], ["a", 2, "y"], ["b", 1, "x"], ["b", 1, "y"], ["b", 2, "x"], ["b", 2, "y"], ) ["a", 1, "x"] ["a", 1, "y"] ["a", 2, "x"] ["a", 2, "y"] ["b", 1, "x"] ["b", 1, "y"] ["b", 2, "x"] ["b", 2, "y"] #### 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; } #### my @a = 1, 2; my @b = 3, 4; my @c = @a X+ @b; # 1+3, 1+4, 2+3, 2+4 #### my @a = 1, 2; my @b = 3, 4; my @c = X{@a} X{@b} '+'