dankogaiさんの nested list comprehension のperl版に対抗(?)して、
eval() を使わない版を書いてみました。
# 2008-07-08 追記 コードが長いので続きに移動しました。
sub _comprehend_list_inner
{
my @pairs = @_;
my $dim = pop @pairs;
my $cond_sub = pop @pairs;
if (@pairs) {
my ($start, $end) = splice @pairs, -2;
my $next_sub = sub {
my @list_ = @_;
my $result_ = pop @list_;
for my $i ( $start .. $end ) {
my @next_list_ = @list_;
push @next_list_, $i;
push(@$result_, \@next_list_)
if $cond_sub->(@next_list_, (@next_list_ $dim ? () : $result_)) &&
@next_list_ $dim;
}
return @$result_;
};
return _comprehend_list_inner(@pairs, $next_sub, $dim);
}
# no pairs
my $result_ = [];
return $cond_sub->($result_);
}
sub comprehend_list
{
my @pairs = @_;
my $cond_sub = do {
if ( ref($pairs[$#pairs]) =~ /^CODE/ ) {
pop @pairs;
}
else {
sub { 1 };
}
};
die "ranges are not pairs" if (@pairs % 2);
my $pairs_cnt = @pairs / 2;
return _comprehend_list_inner(@pairs, $cond_sub, $pairs_cnt);
}
use Data::Dumper;
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Indent = 0;
print Dumper(
comprehend_list(
0 => 9,
0 => 9,
sub { $_[0] + $_[1] == 5 && $_[0] > $_[1] }
)
), "\n";
print Dumper(
comprehend_list(
0 => 4,
0 => 4,
)
);
普段curry化とか使わないから、若干頭がこんがらがってみたり..





コメントする