http://www.perlmonks.org?node_id=1000286


in reply to Pivoting parts of a database table into an HTML table

I suppose I need to post my half-solution, too. (My original post was getting long.) It's supposed to replace the rather common looping code:

my $lastid = 0; while ($sth->fetch) { print $row; if ($lastid != $id) { print "</tr><tr>"; } }

with this:

alternate( sub { $sth->fetch }, sub { print $row }, sub { $id }, # which variable to monitor sub { print "</tr><tr>" } # what to do when variable changes );

Currently it has at least an off-by-one error (the words go into the wrong columns), but I can't spot the error.

sub alternate { my $iter = shift; my $loop = shift; # main loop callback my @conds; while (@_ > 0) { # sub to get value, sub to call if value changed push @conds, [ shift, shift ]; } my @memory; return unless $iter->(); # starting values @memory = map { $_->[0]->() } @conds; do { $loop->(); while (my ($idx, $cond) = each @conds) { my $new = $cond->[0]->(); next if $memory[$idx] eq $new; $cond->[1]->(); # callback $memory[$idx] = $new; # reset subsequent values $memory[$_] = $conds[$_][0]->() for ($idx + 1 .. $#conds); last; } } while ($iter->()); } my $gen = make_generator(\my ($day, $type, $word)); alternate( $gen, sub { print "$word, " }, sub { $day }, sub { print "</td></tr>\n<tr><td>$day</td><td>" }, sub { $type }, sub { print "</td><td>" } );