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

Hi monks,

A very smallish quesiton...

What is the difference between the two conditionals below and when do you choose one over the other?

# conditional type1 if ($x1) { if ($x2) { print "here\n"; } } # conditional type2 if ($x1 && $x2) { print "here\n"; }
Thanks for reading and helping :)

update: Ah, there's indeed quite a lot to be learnt from that little code. Thanks to all for taking time to help with my question :)

Replies are listed 'Best First'.
Re: Any difference in conditionals?
by davido (Cardinal) on Apr 27, 2004 at 01:43 UTC
    You might be interested in how this parses with B::Deparse.

    First, the test code:

    if ($x1) { if ($x2) { print "here\n"; } } if ( $x1 && $x2 ) { print "here\n"; }

    And now the output under 'deparse,-x9' (the greatest degree of deparsing):

    C:\Perl\scripts>perl -MO=Deparse,-x9 mytest.pl $x1 and do { $x2 and do { print "here\n" } }; $x1 and $x2 and do { print "here\n" }; mytest.pl syntax OK

    Surprised? :)

    They are different, but also similar in more ways than you might initially guess. The biggest difference is nesting.


    Dave

Re: Any difference in conditionals?
by Zaxo (Archbishop) on Apr 27, 2004 at 01:36 UTC

    As they stand, they are logically equivalent.

    Your type1 is noisier, but more flexible. If steps may be added for other logical combinations, it will be easier to modify. Readibility declines rapidly with that.

    I would prefer type2 for anything that is expected to be stable. It can be reduced further by modifier syntax, print 'here', $/ if $x1 && $x2; or logical operators, $x1 && $x2 && print 'here', $/; which some regard as unreadable, but I like for the lack of noise. The modifier syntax suffers from the need to squeeze everything in the conditional into a single Perl expression.

    After Compline,
    Zaxo

      Um, your logical operator expression also squeezes the conditional into a single Perl expression. It just happens to use the same operator inside as the conditional.
Re: Any difference in conditionals?
by jeffa (Bishop) on Apr 27, 2004 at 06:19 UTC

    Debugging. Type 1 has an additional break point that type 2 does not:

    # conditional type1 if ($x1) { warn "x1 was true\n"; if ($x2) { warn "x2 was true\n"; print "here\n"; } } # conditional type2 if ($x1 && $x2) { warn "well, they were both true ... still don't see the bug\n"; print "here\n"; }
    Now, the examples are very trivial, but i really have picked a more verbose style over another just so i could debug easier -- verbose can still be terse with Perl, though. ;)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      This thought got me thinking...
      if($x1 && (warn '$x1 OK... ') && $x2) { print "here\n"; }
      ... works like one might want it to work :)

      So _technically_ even this method allows for debugging.

      --Brock

Re: Any difference in conditionals?
by pbeckingham (Parson) on Apr 27, 2004 at 02:16 UTC

    when I use perl -MO=Concise test.pl, I get:

    if ($x1) { if ($x2) { print "here\n"; } } a <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 5 if.pl:1) v ->3 - <1> null vK/1 ->a 4 <|> and(other->5) vK/1 ->a - <1> ex-rv2sv sK/1 ->4 3 <#> gvsv[*x1] s ->4 - <@> scope vK ->- - <0> ex-nextstate v ->5 - <1> null vK/1 ->- 6 <|> and(other->7) vK/1 ->a - <1> ex-rv2sv sK/1 ->6 5 <#> gvsv[*x2] s ->6 - <@> scope vK ->- - <0> ex-nextstate v ->7 9 <@> print vK ->a 7 <0> pushmark s ->8 8 <$> const[PV "here\n"] s ->9
    And then the more concise:
    if ($x1 && $x2) { print "here\n"; } a <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 3 if.pl:1) v ->3 - <1> null vK/1 ->a 6 <|> and(other->7) vK/1 ->a - <1> null sK/1 ->6 4 <|> and(other->5) sK/1 ->6 - <1> ex-rv2sv sK/1 ->4 3 <#> gvsv[*x1] s ->4 - <1> ex-rv2sv sK/1 ->- 5 <#> gvsv[*x2] s ->6 - <@> scope vK ->- - <0> ex-nextstate v ->7 9 <@> print vK ->a 7 <0> pushmark s ->8 8 <$> const[PV "here\n"] s ->9
    ...and if I have ignored the optimized-out ops properly, they are identical.

Re: Any difference in conditionals?
by pboin (Deacon) on Apr 27, 2004 at 16:15 UTC

    The way you wrote it, no (real) difference, 'cause you're just accessing the values in $x1 and $x2. If, on the other hand, you were doing something like incrementing one of them, they are *very* different.

    The logical AND is lazy. By that I mean when perl is doing the test, if the first half evaluates to false, the second half doesn't get evaluated at all. It can get you into trouble if you don't know to expect it.

    In method #2 below, the $x1 gets incrmented and $x2 doesn't.

    #!/usr/bin/perl use strict; my $x1 = 1; my $x2 = 1; print "\$x1 starts as $x1 and \$x2 starts as $x2.\n"; # method 1 if ($x1++) { if ($x2++) { print "We incremented \$x1 to $x1 and \$x2 to $x2.\n"; } } undef $x1; undef $x2; print "Undefine them both...\n"; #method 2 if ($x1++ && $x2++){ print "Shouldn't ever get here!\n"; } print "Now, we incremented \$x1 to '$x1' and \$x2 is still '$x2'.\n";

      Your tests aren't equivalent. In method 1, both variables start out as 1. In method 2, both variables start undefined. If you start with the same state in both tests, the results will be identical, both for the 'start as 1' case and the 'start undefined' case.

Re: Any difference in conditionals?
by kragen (Sexton) on Apr 27, 2004 at 16:09 UTC
    The first one is harder to read. I choose the first one never, the second one always. (Sometimes more complex logic justifies nested conditionals.)
      I prefer print "Here\n" if $x1 and $x2; for most circumstances.