ControlBreak

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

    Return the level number for the most recent invocation of the test()
    method.

  level_numbers
    Return a list of level numbers corresponding to the levels defined in
    new(). This can be useful, for example, when you want to set up some
    lexical variables for use as indexes into a list you might use to
    accumulate subtotals.

        my $cb = ControlBreak->new( qw( L1 L2 EOD ) );
        my @totals;
        my ($L1, $L2, $EOD) = $cb->level_numbers;

        foreach my $sublist (@list_of_lists) {
            my ($control1, $control2, $number) = $sublist->@*;
            ...
            my $sub_totals = sub {
                if ($cb->break('L1')) {
                    # report the L1 subtotal here
                    $totals[$L1] = 0; # clear the subtotal
                }
                ...
                # accumulate subtotals
                map { $totals[$_] += $number } $cb->level_numbers;
            };

            $cb->test_and_do(
                $control1,
                $control2,
                $cb->iteration == $list_of_lists - 1,
                $sub_totals
            );
        }

  reset
    Resets the state of the object so it can be used again for another set
    of iterations using the same number and type of controls establish when
    the object was instantiated with new(). Any comparisons that were
    subsequently modified are retained.

  test ( $var1 [, $var2 ]... )
    Submits the control variables for testing against the values from the
    previous iteration.

    Testing is done in reverse order, from highest to lowest (major to
    minor) and stops once a change is detected. Where it stops determines
    the control break level. For example, if $var2 changed, method levelnum
    will return 2. If $var2 did not change, but $var1 did, then method
    levelnum() will return 1. If nothing changes, then levelnum() will
    return 0.

    Note that the level numbers set by test(...) are true if there was a
    level change, and false if there wasn't. So, they can be used as a
    simple boolean test of whether there was a change. Or you can use the
    break() method to determine whether any control break has occurred.

    Because level numbers correspond to the hierarchical data order, they
    can be use to trigger multiple actions; e.g. levelnum() >= 1 could be
    used to print subtotals for levels 1 whenever a control break occurred
    for level 1, 2 or 3. It is usually the case that higher control breaks
    are meant to cascade to lower control levels and this can be achieved in
    this fashion. The break() method simplifies this.

    Note that method continue() must be called at the end of each iteration
    in order to save the values of the iteration for the next iteration. If
    not, the next test(...) invocation will croak.

  test_and_do ( $var1 [, $var2 ]... $var_end, $coderef )
    The test_and_do() method is similar to test(). It takes the same
    arguments as test(), plus one additional argument that is an anonymous
    code reference. Internally, it calls test() and then, if there is a
    control break, calls the anonymous subroutine provided in the last
    argument. Typically, that code will perform work related to subtotals or
    other actions necessary when a control break occurs.

    But test_and_do() does one other thing. It expects the last control
    variable ($var_end) to be an end of data indicator, such as the perl
    builtin operator eof. This indicator should return false on each
    iteration over the data until the very last iteration -- when it should
    change to true, thereby triggering a major control break.

    What test_and_do does then is to add an extra loop. This simulates a
    final record and will trigger test() to signal control breaks at all
    levels. Thus, the code provided will be executed between every change of
    data AND after all data has been iterated over.

    This avoids the necessity of repeating the control break actions you've
    put inside the data loop immediately after the loop's closing bracket.
    When you just use test and continue(), an end-of-data control break
    won't occur and the simplest workaround is to just duplicate your
    control break code after the loops closing bracket.

    Here's a typical use case involving end of file processing. Note the
    extra control level, named 'EOF', and the use of the eof builtin
    function as the second last argument of test_and_do():

        my $cb = ControlBreak->new( qw( L1 L2 EOF ) );

        my $lev1_subtotal = 0;
        my $lev2_subtotal = 0;
        my $grand_total = 0;

        while (my $line = <>) {
            chomp $line;

            my ($lev1, $lev2, $data) = split "\t", $line;

            my $subtotal_coderef = sub {
                if ($cb->break('L1')) {
                    say $cb->last('L1'), $cb->last('L2'), $lev1_subtotal . '*';
                    $lev1_subtotal = 0;
                }
                ...
                if ($cb->break('EOF')) {
                    say 'Grand total,,', $grand_total, '***';
                }

                $lev1_subtotal  += $data;
                $lev2_subtotal  += $data;
                $gran_total     += $data;
            }



( run in 2.356 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )