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

Hi, (you see from the title I did a search on the issue, but obfuscated code wasnīt the answer :-))

from time to time the following happens to sneak into my code. Itīs easy: Just flipflop a boolean value.

if($debug eq FALSE) { $debug = TRUE; } else { $debug = FALSE; }
Canīt say why, but this seems unelegant to me. Is there any (or more) more elegant way to do this?

Oh and BTW: Why doesnīt he accept TRUE or FALSE if "use strict" is .. err ... used?

Yeah and while I am at it. Why does one need "eq"? Isnīt true/false a numerical value? Guess Iīm thinking C again...

Ciao

Replies are listed 'Best First'.
Re: Flip Flop IV
by bikeNomad (Priest) on Jun 24, 2001 at 21:39 UTC
    Well, Perl doesn't have any keywords for TRUE and FALSE.

    Since TRUE and FALSE are barewords in your code, I assume that they are subroutine calls.

    Otherwise, they would be caught with use strict (which everyone uses, right?). That is (remembering that use constant defines subroutines),

    use constant FALSE => 0; use constant TRUE => !FALSE;

    Assuming that they return 1 and 0 (or 0 and 1, it doesn't matter), then this would work:

    Just use the xor operator:

    my $debug = FALSE; # or 0 $debug ^= 1; # now it's TRUE, or 1 $debug ^= 1; # now it's FALSE, or 0

    or use this:

    $debug = !$debug; # change 1 to 0 or 0 to 1

    update: added !, explanation/assumption at top.

      It's funny. I have been coding in one language or another since the early 80s, and it was only this year that I encountered Yet Another Way to write a flip-flop.

      my $ff = 0; while( 1 ) { print $ff ? 'hee ' : 'haw ', "\n"; $ff = 1 - $ff; }

      For some perverse reason this really appeals to me, although I refrain from using it in production code. It has a certain mathematical elegance.


      --
      g r i n d e r
Re: Flip Flop IV
by japhy (Canon) on Jun 24, 2001 at 22:41 UTC
    "TRUE" and "FALSE" are meaningless to Perl, unless you give them meaning. Watch:
    $debug = bungee; if ($debug eq bungee) { $debug = SPELUNK; } else { $debug = bungee; }
    See? All I did was change "TRUE" to "SPELUNK" and "FALSE" to "bungee", and the code works as before.

    There is NO Perl literature that says TRUE is true and FALSE is false; if there is, the author deserves to be spat upon by an angry camel. Use true/false values that everyone else (who knows) does.

    if ($debug) { # $debug is true } else { # $debug is false } $debug = 1; $debug = !$debug; # flip-flop
    Or, make your own boolean class.
    package boolean; use overload ( '+0' => sub { $_[0][0] }, fallback => 1, ); sub new { bless [ $_[1] ? 1 : 0 ], $_[0] } sub flip { $_[0][0] = 1 - $_[0][0] }
    And then use it
    use boolean; $debug = boolean->new(1); print "hi\n" if $debug; $debug->flip; print "bye\n" if $debug;


    japhy -- Perl and Regex Hacker
Re: Flip Flop IV
by Beatnik (Parson) on Jun 24, 2001 at 21:44 UTC
    $debug = $debug ? 0 : 1; $debug = !$debug;
    Update:Perl does that !$debug thing too... kudos to bikeNomad.

    Greetz
    Beatnik
    ... Quidquid perl dictum sit, altum viditur.
Re: Flip Flop IV
by holygrail (Scribe) on Jun 24, 2001 at 21:59 UTC
    True and false aren't "values" in Perl. There is no boolean datatype. That is why you get errors when you use strict If you want to do it more elegantly and still use the "True" and "False" things, you could do something like this:
    sub TRUE {return 1} sub FALSE {return 0} # Some assignments to $debug, doing something like # my $debug = TRUE; if ($debug == FALSE) { $debug = TRUE; } else { $debug = FALSE; }
    Now you don't need to use 'eq' and just use '==', because TRUE and FALSE are now subroutines returning numerical values.

    --HolyGrail
Re: Flip Flop IV
by MeowChow (Vicar) on Jun 24, 2001 at 23:59 UTC
    Actually, the answer you seek can be found in the enigmatic cliffhanger ending of Flip Flop II, heralded by audiences and critics alike as being the most poignant, moving, and epic episode of the Flip Flop trilogy released to date:
    ... sub a {$ _ ^=1}
    Our trustworthy Ovaltine decoder ring translates this cryptic message to reveal the following bit of wisdom:
    sub flip_flop { $_ ^= 1; }
    Of course, you shouldn't mess with globals such as $_ in real code, but the principal is what matters here :-)

    warning: "Flip Flop" is a trademark of CatFood Entertainment in association Dreamworks SKG and Evil Media Conglomerate Incorporated. All our trademarks are belong to us, not you. Duh.

       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
Re: Flip Flop IV
by PetaMem (Priest) on Jun 24, 2001 at 21:45 UTC
    I found something...
    $debug = ($debug eq FALSE) ? TRUE : FALSE;
    But not that it seems THAT much more elegant to me...

    Update: Yeah but you all use "0" and "1" instead of "TRUE" and "FALSE". That was not my intention.

    Update2: Sorry to stretch that blatant things here, but I feel like like a really novice. So in perl 5.7.1 and 5.6.0 $debug == FALSE always evals to "TRUE", while the īeqī operator works ok.

    HOWEVER: before I used the use constant FALSE => 0; perl 5.6.0 kept complaining when used "==". No - itīs not too hot here, my computer hasnīt faulty memory nor do have I :-)

    Update3: And I hope the last one. First, I would like to thank all of you who responded, youīve pointed me the right way in a fundamental question I was convinced to know the "truth". Well. I went for the use constant solution. My perhaps nitpicking question is:

    use strict; use constant TRUE => 1; use constant FALSE => 0; (use other Modules)
    use constant TRUE => 1; use constant FALSE => 0; use strict; (use other Modules)
    The first solution seems consistent, but the second doesnīt have constant definitions spliting up the use field.

    Ciao

      If you're testing on TRUE or FALSE, use ==.
      You should check What is true and false in Perl? on the boolean topic.
      Basically true is everything except 0, "" (empty string), undef (or statements resulting in any of the previous).
      Also check perlop on when to use eq and when to use ==. True values can be tested without actually supplying an eq or == operator.
      if ($truevalue) { print 'foo'; } Update:Removed dup info
      Greetz
      Beatnik
      ... Quidquid perl dictum sit, altum viditur.
(tye)Re: Flip Flop IV
by tye (Sage) on Jun 25, 2001 at 09:07 UTC

    If you ever see code that says something like $debug == TRUE, then you need to change that code. Why not write it as: if(  TRUE == ( $debug == TRUE )  ) { or if(  ( ( $debug == TRUE ) == TRUE ) == TRUE  ) { To test for truth, you write: if(  $debug  ) { Most languages create problems for this since there are a ton of "true" values that aren't all == nor eq. But it is even more true in Perl since Perl has multiple "false" values that aren't all eq and that can generate warnings if you use ==.

            - tye (but my friends call me "Tye")