If I have a value I want to convert to a boolean, I use $x = $x && 1. I've also seen $x = !! $x. Are these the only ones? Which one(s) do you use? Is there a difference?
------
We are the carpenters and bricklayers of the Information Age.
Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose
I shouldn't have to say this, but any code, unless otherwise stated, is untested
Re: Converting to boolean
by Zaxo (Archbishop) on Jun 17, 2004 at 03:49 UTC
|
There is also a variation on yours; $x &&= 1; and there is the corresponding pair on or; $x = $x || 0; $x ||= 0;. Update: Also trinary, $x = $x ? 1 : 0; and all sorts of variations on that, which have the advantage that truth and falsity are what you say they are.</Update>
None of the basic three are equivalent. Here is a comparison:
Expr | Value | Result | Value | Result |
$x = $x && 1; | true | 1 | false | unchanged |
$x = $x || 0; | true | unchanged | false | 0 |
$x = !! $x; | true | 1 | false | '' |
But see diotalevi's fine reply for what !! actually returns. Context is everything! |
Only $x = !! $x; gives you what I think you want.
But perl generally limps along just fine without any boolean type at all. See What is truth? (Curiosity corner).
| [reply] [d/l] [select] |
Re: Converting to boolean
by diotalevi (Canon) on Jun 17, 2004 at 03:41 UTC
|
An update ... though stuff like '=' assignments make this entirely less than obvious. Check these stats out.
use Devel::Size 'total_size';
$ARY[ $_ ] = ? for 1 .. 1_000_000;
print total_size( \ @ARY ) . "\n";
# Do this as a comparison of a sparse array
$ARY_B[ 1_000_000 ] = 1;
print total_size( \ @ARY_B );
Code | Size |
sparse | 4,000,072 |
undef | 16,194,340 |
1 | 20,195,340 |
\ undef | 20,194,352 |
\ !1 | 20,194,377 |
\ !!1 | 20,194,378 |
\ 1 | 20,195,340 |
( 1 + $| ) | 24,194,340 |
\ ( 1 + $| ) | 40,194,340 |
!1 | 41,194,340 |
!!1 | 42,194,340 |
I use !! $x because the return value is one of the values PL_sv_yes or PL_sv_no both of which are a single scalar that is shared through the entire process, forever. It is somewhat like undef being shared everywhere. You can have a million return values from !! $x and have them take up no space or you can have a million 1's and every one takes up a whole SV's worth of memory. The choice is obvious. | [reply] [d/l] [select] |
Re: Converting to boolean
by Sidhekin (Priest) on Jun 17, 2004 at 03:50 UTC
|
I use !!$x for this. Perl6 will give us ?$x, which ought to be clearer.
If I wanted to store the boolean back into
the same variable, I might prefer a
mutator: $x &&= 1.
However, there is a real difference:
sidhekin@blackbox:~$ perl
my ($x, $y) = (0, 0);
$x = $x && 1; # or $x &&= 1;
$y = !!$y;
print "\$x: '$x'\n\$y: '$y'\n";
__END__
$x: '0'
$y: ''
sidhekin@blackbox:~$
... something to be aware of :-)
print "Just another Perl ${\(trickster and hacker)},"
The Sidhekin proves Sidhe did it!
| [reply] [d/l] [select] |
Re: Converting to boolean
by davido (Cardinal) on Jun 17, 2004 at 04:32 UTC
|
package Tie::MyBoolean;
sub TIESCALAR {
my($class, $value ) = @_;
my $boolval = ( $value ) ? 1 : 0;
return bless \$boolval, $class;
}
sub STORE {
my $self = shift;
${$self} = ( shift ) ? 1 : 0;
return ${$self};
}
sub FETCH {
my $self = shift;
return ${$self};
}
1;
package main;
use strict;
use warnings;
tie my $bool, 'Tie::MyBoolean';
$bool = 100;
print "$bool\n";
$bool = 0;
print "$bool\n";
$bool = ! $bool;
print "$bool\n";
This has the characteristic of working a lot like $| (the autoflush special variable), which can only take on 0 or 1 as a value.
| [reply] [d/l] |
Re: Converting to boolean
by hv (Prior) on Jun 17, 2004 at 14:19 UTC
|
When I want clarity, or when I specifically want to avoid an undefined value, I tend to use the trinary operator:
$bool = $x ? 1 : 0;
When I want shortness I tend to use !!$x.
When I'm comparing truthness of two expressions, I factor out one of the !s: if (!$x == !$y) { ... }
Hugo | [reply] [d/l] [select] |
Re: Converting to boolean
by dvergin (Monsignor) on Jun 17, 2004 at 15:53 UTC
|
My first reaction was: Why would one want do do that? Any value will act as a boolean if used in a boolean context.
But I note that this question has been posed and answered by experienced monks who give every indication of taking this matter quite seriously.
So clearly I'm missing something. I've never been aware of a need for this. Could someone offer a few cases where converting to such a "boolean" value is better than simply using the variable as-is in a boolean context.
------------------------------------------------------------
"Perl is a mess
and that's good because the
problem space is also a mess." - Larry Wall
| [reply] |
|
For my own code, sometimes it is to ensure I have a number somewhere that a number is required, eg when calling a function that treats undef differently (".. or if bool is undef, starts a game of nethack"), or badly ("use of uninitialised value"), or for storing in a NOT NULL database field. Another reason is where I need to use a different criterion for truthfulness:
sub has_file {
my $self = shift;
my $filename = $self->filename;
(defined($filename) && length($filename)) ? 1 : 0;
}
.. which would otherwise do the wrong thing for a filename such as "0".
Primarily, though, it is for clarity: to make it clear in the code (and to allow me to make it clear in the docs) that this routine returns either 0 or 1 and nothing else. I think the concept of a boolean value is very useful, and have always considered it a shame that perl didn't have such a thing as a first class data type.
The main benefit is to prevent leakage, both actual and conceptual. By 'actual', I mean returning (say) an object (that is of course TRUE in a boolean context) that means the reference count on the object is bumped, and the object may no longer be released when it could otherwise have been because someone is still holding on to the (conceptual) boolean that tells them whether they actually had the object.
Similarly if such a quasi-boolean is used in some polymorphic context, it may do entirely the wrong thing: there are many examples of methods that allow a parameter to be any of (0 or 1 or a coderef), and various other cases where a particular type of object is allowed.
The conceptual leakage is about clarity of thinking: if I am not sure that I have a true boolean value, I need always to consider whether it will do the right thing when I'm passing it around or using it in various ways. When I know that I definitely have either 0 or 1, my mind is freed to consider it in a much more simplistic fashion, and I can throw it around confident that it won't blow up in my face.
Hugo | [reply] [d/l] |
|
| [reply] [d/l] [select] |
|
| [reply] |
Re: Converting to boolean
by Roy Johnson (Monsignor) on Jun 17, 2004 at 14:40 UTC
|
Nobody's mentioned $x != 0, which might be expected to work, but gets tripped up by the "0 but true" phenomenon, as does $x ^ ''. $x xor 0 should work, because xor is a logical op.
Disclaimer: I've only got perl4 to test on.
We're not really tightening our belts, it just feels that way because we're getting fatter.
| [reply] [d/l] [select] |
|
Incidental trick, there is not need to use "0 but true" since "0.0" has the exact same effect. (Note that the quotes matter.)
I'm not sure how that would run under flea-bitten corpses of dead camels though. (Can you tell that I'm somewhat flabbergasted at your using a version of Perl that is about a decade out of date?)
| [reply] |
|
| [reply] |
Re: Converting to boolean
by itub (Priest) on Jun 17, 2004 at 15:40 UTC
|
I don't really use "explicit Booleans" in Perl because they aren't needed, but in those rare cases where I want to convert something to 0 or 1 because some other program expects it that way, I use $x = $x ? 1 : 0. It might not be the shortest, cleverest, or most illegible way available, but it's simple, clear, and gets the job done. | [reply] [d/l] |
Re: Converting to boolean
by Anonymous Monk on Jun 17, 2004 at 03:26 UTC
|
perl doesn't have booleans | [reply] |
|
|