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


in reply to Re: Avoiding if/else knots
in thread Avoiding if/else knots

The trouble with dispatch tables in Perl is that the conditions need to be exact keys. In other words, if you want any value in the range 1-999 to do the same thing, you need to create keys for each of those integers.

If you need integers in a range, you've still got a discrete set of values and mapping that to the dispatch table isn't hard.

use strict; use warnings; sub action_1_to_999 { print "1 to 999\n"; } my %dispatch = ( 0 => sub { print "Zero\n" }, map { $_ => \&action_1_to_999 } ( 1 .. 999 ), 1000 => sub { print "1e3\n" }, ); $dispatch{0}->(); $dispatch{23}->();

The challenge is for non-integer conditions or non-bounded ones. What if N > 1000? What if N = 3.14159265358979323? What if N = 'PI'? In that case, you still need to have the advance logic, if/else or otherwise, to convert inputs to a smaller number of well-defined cases.

My advice in that case is keep the case logic in one place and the actions all somewhere else via subroutines. Dispatch tables probably don't help unless you're already starting with a discrete, bounded set of inputs (or need to dynamically add cases as your program runs).

-xdg

Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Replies are listed 'Best First'.
Re^3: Avoiding if/else knots
by ikegami (Patriarch) on Aug 18, 2006 at 18:20 UTC

    When dealing strictly with small positive integers like in your example, an array might be better than a hash.

    sub action_1_to_999 { print "1 to 999\n"; } my @dispatch = ( sub { print "Zero\n" }, map { \&action_1_to_999 } ( 1 .. 999 ), sub { print "1e3\n" }, ); $dispatch[0]->(); $dispatch[23]->();
Re^3: Avoiding if/else knots
by Limbic~Region (Chancellor) on Aug 18, 2006 at 13:40 UTC
    xdg,
    No offense, but you really haven't added anything to what I said.

    To quote myself, "The trouble with dispatch tables in Perl is that the conditions need to be exact keys". I didn't say that creating a range was hard, I said "you need to create keys for each of those integers".

    In other words, there is no short-cut to make that a single key and anything that can't be done as a straight lookup (requires logic) doesn't work. That is, it doesn't work without additional if/elsif/else knots to determine the correct key to dispatch.

    Cheers - L~R

      No offense, but you really haven't added anything to what I said.

      Well, we can agree to disagree.

      You said 'if you want any value in the range 1-999' but then said 'each of those integers'. Those aren't the same thing. My post was an attempt to differentiate the easy case (integers) from the hard case (non-integers).

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

        xdg,
        Yes, we can agree to disagree. My opinion is that we are talking past each other and you are countering a position I don't hold. Update You are correct that I did make a typo s/value/integer/ - it definately does change the meaning of the sentence.</Update>

        My example was to illustrate that a simple question such as "is the integer in this range" can't be answered with a single key in the dispatch table. This immediately followed my first assertion that the problem was each condition had to be an exact key. It was a simple example that illustrated the point.

        I didn't bother moving on to more complex examples because I believe I had already made my point and because I referenced Roy Johnson's great tutorial - Implementing Dispatch Tables which covers these difficult cases and some work arounds.

        Cheers - L~R

Re^3: Avoiding if/else knots
by planetscape (Chancellor) on Feb 19, 2012 at 15:44 UTC