There's more than one way to do things PerlMonks

### Boolean counter?

by DreamT (Pilgrim)
 on Dec 07, 2009 at 07:57 UTC Need Help??
DreamT has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I'd like to have a counter that is boolean, so when you increment it, it should either become 0 or 1, based on it's previous value. I can do it like this:
```        if (\$Counter == 0)
{
\$Counter = 1;
}
else
{
\$Counter = 0;
}
, but I'd like to do the above in a more elegant way. Is it possible?

Replies are listed 'Best First'.
Re: Boolean counter?
by Corion (Pope) on Dec 07, 2009 at 08:06 UTC

The xor operator will do what you want:

```\$counter = \$counter xor 1

or

```\$counter ^= 1

(tested with perl -wle "print \$counter ^=1 for 1..3")

I agree that the XOR solution is perfectly correct, but why use that instead of NOT? Isn't

\$counter = ! \$counter;

easier to read? That said, I have to admit that I like the snazzyness of the in place ^= syntax. It is hard to get more concise than that.

- doug

The difference is that \$toggle ^= 1; leaves you with a number (0 or 1) while \$toggle = !\$toggle; leaves you with a boolean.

Honestly, it sounds like the OP wants a boolean, so the easier to read negation should be used. If he wants to display the boolean, that's an outputting formatting issue to be resolved then.

Re: Boolean counter?
by ikegami (Pope) on Dec 07, 2009 at 08:08 UTC
For starters,
```if (\$toggle) {
\$toggle = 0;
} else {
\$toggle = 1;
}

can be written as

```\$toggle = \$toggle ? 0 : 1;

And if you wanted a bitwise toggle, you could do

```\$toggle ^= 1;

But you asked for boolean, so you want the even simpler:

```\$toggle = !\$toggle;
Re: Boolean counter?
by Utilitarian (Vicar) on Dec 07, 2009 at 08:06 UTC
What you want is not a counter but a toggle, shortened using the ternary operator, but not sure if it's more elegant
\$toggle=\$toggle?0:1;
Edit...In fact Corion's solution above is way better.

print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
Re: Boolean counter?
by GrandFather (Sage) on Dec 07, 2009 at 08:58 UTC

Of course if you want obscure you can use \$|--. Consider:

```print \$|-- for 1 .. 4;

Prints:

```1010

Although I wouldn't recommend it in a context where you wish to win friends and influence people among the bossing classes.

True laziness is hard work
Re: Boolean counter?
by Ratazong (Monsignor) on Dec 07, 2009 at 12:19 UTC
Just to show that you can make a lot with "lookup-tables" ;-)

\$counter = (1, 0)[\$counter];

Rata

Just to make "lookup-tables" prettier. ;-)

```\$counter = [ 1 => 0 ] -> [ 1 <= \$counter ];

ug, you create two variables every time you toggle it (one of which is an array!), and you rely on the undocumented values of <= returns. And the latter doesn't help make it prettier at all!
Re: Boolean counter?
by moritz (Cardinal) on Dec 07, 2009 at 08:21 UTC
You can just use ++ to increment your counter, but when you ask for its value use \$counter % 2 instead of the counter itself.

Or if you're not interested in the numeric value 0, but rather that it's a false value, you can also use this update step:

```\$counter = !\$counter;
Or if you do want the numerical value:
```\$counter = !\$counter || 0;
Re: Boolean counter?
by eye (Chaplain) on Dec 07, 2009 at 08:18 UTC
One more way...

```\$toggle = 1 - \$toggle;
This lacks elegance since it needs to start at 0 or 1, but it is simple.
Re: Boolean counter?
by vitoco (Friar) on Dec 07, 2009 at 12:47 UTC

Two more approaches:

- Using hashes:

```  my %Next = ( 0 => 1, 1 => 0);
my \$Counter = 0;
#...
\$Counter = \$Next{\$Counter};

```  \$Counter = abs --\$Counter;
\$Counter = - --\$Counter;

Don't modify a variable that you're using elsewhere in an expression. At best, it's unclear. At worse, the result is undefined.

```\$toggle = - --\$toggle;
should be
```\$toggle = -( \$toggle - 1 );
which can be shortened to previously mentioned
```\$toggle = 1 - \$toggle;
The behaviour of that is actually not defined. You may end up with \$Counter being -1, or with purple daemons coming out of your USB port, ready to chew off your fingers.
Re: Boolean counter?
by JavaFan (Canon) on Dec 07, 2009 at 12:00 UTC
Just to prove you can use trigs to solve almost anything:
```\$counter = int cos \$counter * atan2(1, 0);
Re: Boolean counter?
by hdb (Monsignor) on Mar 04, 2015 at 13:07 UTC

I cannot resist. You can also use a closure, every time you call it you get 0 or 1 alternatingly. You can create as many independent toggles as you want.

```use strict;
use warnings;

sub create_toggle {
my \$flag = 0;
return sub { \$flag = 1-\$flag } # your favorite method here
}

my \$toggle = create_toggle;

print \$toggle->()."\n" for 1..10;

UPDATE: ...or like this

```use strict;
use warnings;
{
package Toggler;
sub new {
my \$flag =  0;
return sub { \$flag = 1-\$flag }
}
}

my \$toggle = new Toggler;

print \$toggle->()."\n" for 1..10;
Re: Boolean counter?
by rowdog (Curate) on Dec 07, 2009 at 22:11 UTC

I tend to use \$toggle *= -1;

Update: I stand corrected, thanks LanX. I often use that for alternating rows but it's wrong here.

well it's a toggle but can't be used as boolean as the OP wanted , since 0*-1=0

Cheers Rolf

Your idea works the following way - even if it doesn't look as elegant any more:

```\$toggle = -1 * (\$toggle - 0.5) + 0.5;

Create A New User
Node Status?
node history
Node Type: perlquestion [id://811439]
Approved by lidden
Front-paged by lidden
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (2)
As of 2018-04-22 15:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (83 votes). Check out past polls.

Notices?