http://qs321.pair.com?node_id=136097

This is not a rant, but instead mantra. Nested if-else statements should be avoided!

Impossible you say? It is true that not all problems can avoid a mess of nested if-else blocks, but, with the help of Perl's syntax and use of hashes as lookup (or dispatch) tables, you might be suprised at how much your code could be cleaned up.

<update> Ovid made me realize that another important decision to make about using nested if-else blocks or avoiding them is to determine which style produces the least redundant code. </update>

Caveat - don't get caught up in Premature optimization - meeting all the specification requirements is much more important. But then again, somebody is going to have to maintain it. If you are interested in job security through obscurity then this node is not for you. ;)

Consider this object method that accepts either a scalar argument or an array reference (of course, most other languages require you provide two seperate methods):

sub foo { my ($self,$ref) = @_; if (ref $ref eq 'ARRAY') { if ($#$ref) { # do case number 1 } else { # do case number 2 } } else { # do case number 2 } }
I have to determine if the user passed an array reference or a scalar no matter what. But, in this case i also want to know how many elements were passed in an array reference, because if they pass only one element, then that really should be the same as passing a scalar. (Also note that i am not checking to make sure $ref is not undef or is a another kind of reference - keepin it simple.)

The problem is that i can't just test for $#$ref, because that will cause a syntax error under strict if $ref is a scalar. So, i have to use another if-else block inside the block for the case of an array reference. Yuck. And on top of that, i am repeating a whole code block. Super yuck.

However, if i make sure that $ref is indeed an array reference even if it isn't, then i can condense this down to two blocks:

sub foo { my ($self,$ref) = @_; $ref = [$ref] unless ref $ref eq 'ARRAY'; if ($#$ref) { # do case number 1 } else { # do case number 2 } }
Now, there is more than one way to condense the original problem, this is just one. I am not necessarily looking for other ways to solve this problem.

The reason i post this meditation is because i am interested in what others have done to condense and refactor if-elsif-else blocks for simplicity. And using Switch doesn't count! ;) But using dispatch tables definitely does.

P.S. In school i studied Karnough maps which are used to simplify circuit design. Turns out that conditionals (if (this or that and not the other) {}) are not at all different and K-Maps can be used to simply them. Very neat stuff.

jeffa

L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
F--F--F--F--F--F--F--F--
(the triplet paradiddle)