McDarren has asked for the wisdom of the Perl Monks concerning the following question:

Howdy :)

I have a piece of code that looks like this:

$send_flag = $bbstatus ne $last_bbstatus ? 1 : ($now - $last_send_time) > $min_frequency ? 1 : defined($OPTS::opts{f}) + ? 1 : + 0;
Basically, it just sets a flag (or not) if any one of multiple conditions are met. It seems to work fine as I have it, but I now find that I need to extend it so that a message is presented to the user, indicating which condition was met. I'm trying to avoid a series of if/elsif's, so my initial thought was to do something like:
$send_flag = $bbstatus ne $last_bbstatus ? 1 : ($now - $last_send_time) > $min_frequency ? 2 : defined($OPTS::opts{f}) + ? 3 : + 10;
And then....
my %send_messages = ( 1 => "Status has changed", 2 => "Last send too old", 3 => "Forced send requested", 10 => "No changes" );

However, the above seems a bit unsightly, and I'm wondering if this is a situation where a dispatch table would be appropriate? And if so, how would this be structured? (I don't have any experience with dispatch tables, and although I've read a few related threads here and here, I'm afraid I'm having trouble grasping exactly when they are appropriate and how they are constructed).

Appreciate any advice.

Thanks,
Darren :)

Replies are listed 'Best First'.
Re: Is a Dispatch Table appropriate here?
by Belgarion (Chaplain) on Dec 14, 2005 at 05:38 UTC

    Since your first line really wants a boolean, I would have changed your first line to something like:

    $send_flag = ($bbstatus ne $last_bbstatus) or (($now - $last_send_time) > $min_frequency) or defined($OPTS::opts{f});

    If you're really looking for a dispatch table you could do something like:

    my @messages = ( [ sub { $bbstatus ne $last_bbstatus }, "Status not changed" ], [ sub { ($now - $last_send_time) > $min_frequency }, "Last send too +old" ], [ sub { defined($OPTS::optf{f}) }, "Forced send requested" ], [ sub { 1 }, "No changes" ], ); foreach my $m (@messages) { print $m->[1], last if $m->[0]->(); }

    Note: the above is completely untested.

    Update: I thought of another way of implementing this while in the shower. It does avoid the dispatch table, and it does set the correct variables based on the booleans. Still, it may not be easy to read for newer Perl developers.

    my $send_message = ($bbstatus ne $last_bbstatus and "Status no changed") or (($now - $last_send_time) > $min_frequency and "Last send too o +ld") or (defined($OPTS::opts{f}) and "Forced send requested") or "No changes"; my $send_flag = $send_message ne "No changes";
Re: Is a Dispatch Table appropriate here?
by NetWallah (Canon) on Dec 14, 2005 at 06:32 UTC
    Your question, and Belgarion's fine answer (++) are wandering into the territory of "Discrete Finite Automata".

    If your set of conditions and actions start to get complex, you may want to consider DFA::Simple and other DFA modules.

         You're just jealous cause the voices are only talking to me.

         No trees were killed in the sending of this message.    However, a large number of electrons were terribly inconvenienced.

Re: Is a Dispatch Table appropriate here?
by Roy Johnson (Monsignor) on Dec 14, 2005 at 15:32 UTC
    I'm trying to avoid a series of if/elsif's
    I think you have made a poor choice of goals. This is not a situation where you have one input value that you want to test for a bunch of mutually exclusive possible values, where a dispatch table would be appropriate. You have several apparently unrelated conditions that you need to test in order. That calls for a chain of if/elsifs, and you're not saving anything by avoiding them (except perhaps some Confusing warning with if/elsif/else).

    Caution: Contents may have been coded under pressure.
Re: Is a Dispatch Table appropriate here?
by planetscape (Chancellor) on Dec 14, 2005 at 14:27 UTC
Re: Is a Dispatch Table appropriate here?
by GrandFather (Saint) on Dec 14, 2005 at 08:30 UTC

    I don't see a need for a dispatch table here. I thought for a while that a comma operator might be a usefull thing, but in the end I suspect that the following is fairly tidy and efficient:

    my $msg = "Status has changed" if $bbstatus ne $last_bbstatus; $msg = "Last send too old" if ! length $msg and ($now - $last_send_time) > $min_frequency; $msg = "Forced send requested" if ! length $msg and defined($OPTS::opts{f}); $send_flag = length $msg; $msg ||= "No changes";

    BTW, if you are interested in seeing an almost dispatch table in use take a look at Ook interpreter. %xlate could be used as is as a dispatch table, but instead it is used to 'compile' the source to generate 'machine code' in @code


    DWIM is Perl's answer to Gödel