Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I avoid nested if statements in Perl?

I'm doing some Perl and seeing my nested "if" statements is driving me mad. I managed to reduce some of them with guard blocks in another section, but I'm stuck here.

Do you think I may leave the code as is, or is there a "proper" way to refactor the following ? (I also admit being relatively new to Perl)

This is actually a subroutine asking for user input on each parameters of a list (external file). $[3] is the matching pattern, $[2] is the default value for the considered parameter (NULL if there is none), $_[1] specifies if it is mandatory or not. the 'next' statement refers to the next parameter read (while loop).

With everyone's help (thanks !), here's the newest version.

100         if ( $input ne '' && ( $input !~ $match || $input =~ /'.+'/ ) ) {
101             print "! Format not respected. Match : /$match/ (without \' \')\n";
102             next;
103         }
104         if ( $input eq '' ) {
105             if ( $default eq 'NULL' ) {
106                 if ( $manda eq 'y' ) {
107                     print "! Mandatory parameter not filled in\n";
108                     next;
109                 }
110                 print "+ Ignoring parameter.\n";
111                 $input = '';
112             }
113             else {
114                 print "+ Using default value\n";
115                 $input = $default;
116             }
117         }

 98        if($input eq ''){
 99             if($_[2] eq 'NULL'){
100                 if($_[1] eq 'y'){
101                     print "! Mandatory parameter not filled in\n";
102                     next;
103                 }
104                 else{
105                     print "+ Ignoring parameter.\n";
106                     $input = '';
107                 }
108             }
109             else{
110                 print "+ Using default value\n";
111                 $input = $_[2];
112             }
113         }
114         elsif($input !~ $_[3] || $input =~ /'.+'/){
115                 print "! Format not respected. Match : /$_[3]/ (without \' \')\n"; 
116                 next;
117             }
118         }
like image 498
Isaac Clarke Avatar asked Jul 28 '09 12:07

Isaac Clarke


People also ask

Should you use nested if statements?

In most cases, you'd use an IF formula to test your condition and return one value if the condition is met, another value if the condition is not met. To evaluate more than one condition and return different values depending on the results, you nest multiple IFs inside each other.

Are nested if statements faster?

A nested if...else statement can perform much faster than a series of single-selection if statements because of the possibility of early exit after one of the conditions is satisfied.

Why are nested if statements Good?

A nested if statement is an if statement placed inside another if statement. Nested if statements are often used when you must test a combination of conditions before deciding on the proper action.


2 Answers

Here's a slightly more readable version of chaos' answer:

# Set sane variable names...
my ($is_required, $default, $pattern) = @_

# Convert the external string convention for simpler evaluation...
$default = undef if $default eq 'NULL'

# Refuse problematic input before going any further...
if ($input ne '' && $input !~ $pattern || $input =~ /'.+'/) {
    print "! Format not respected. Match : /$pattern/ (without \' \')\n"; 
    next;
}


# If there was no input string...
if($input eq '') {

    # Set the default, if one was provided...
    if( $default ) {
        print "+ Using default value\n";
        $input = $default;
    } 
    # otherwise, complain if a default was required...
    else {
        if( $is_required eq 'y' ){
            print "! Mandatory parameter not filled in\n";
            next;
        }
        print "+ Ignoring parameter (no input or default provided).\n";
    }
}

The key points are:

  • You don't need else if you are exiting the current loop with next
  • Exceptional cases should be handled first
  • You can greatly improve readability by using named variables
like image 156
ire_and_curses Avatar answered Oct 06 '22 00:10

ire_and_curses


An alternative approach that sometimes helps with readability is to put some or all of the branches in well-named code references. Here is a start on the idea:

$format_not_respected = sub {
    return 0 if ...;
    print "! Format not respected....";
    return 1;
}
$missing_mandatory_param = sub {
    return 0 if ...;
    print "! Mandatory parameter not filled in\n";
    return 1;
}

next if $format_not_respected->();
next if $missing_mandatory_param->();
etc...
like image 20
FMc Avatar answered Oct 05 '22 23:10

FMc