# This one constructs a simple glob and returns the sub that will # iterate through it. sub iter_powerset { my @elems = @_; my $glob_str = join 'X', map {"{$_,}"} 0..$#elems; sub { @elems[grep length, split 'X', scalar glob $glob_str] }; } # This is an auxiliary to iter_powerset2 (below). The glob expression is # more complex, in order to get the desired order of output. As the number # of elements grows, the glob string balloons, quickly becoming too large # to work. sub powerset_glob { my ($car, @cdr) = @_; if (@cdr) { my $cdr_globstr = powerset_glob(@cdr); return (join ',', "{$car", "$car+$cdr_globstr", "$cdr_globstr}"); } else { return $car } } # Call the glob string builder and return the iterator subroutine sub iter_powerset2 { my @elems = @_; my $glob_str = powerset_glob(0..$#elems); sub { @elems[grep length, split /\+/, scalar glob $glob_str] }; } # Demonstration code. Call either iter_powerset function my $iter = iter_powerset2(2,3,5,7); while (my @set = $iter->()) { print "<@set>\n"; }