I'd call it 'bad form' because it simply isn't necessary. You don't need to boolean convert in Perl. And so at best it's redundant, and at worst it's an obfuscation.
While there are some really nice tricks you can use in Perl, one of the biggest problems with the language (perceptually at least) is that it's rather prone to "write once" code.
After all - why do you ever need to 'double-negate' a scalar to get a boolean, when you can just test the scalar?
my $state = !! 'some_string';
if ( $state ) { print "It was true\n" };
Or:
if ( 'some_string' ) { print "It was true\n" };
And it's true - you can write some horrifically unintelligible Perl code thanks to "secret" operators, punctuation-based variables, etc. And it'll work fine - for example - I still consider this a masterpiece: 3-D Stereogram, Self replicating source
But it isn't 'good code'. For 'real world' usage, your code needs to be clear, intelligible and easy to troubleshoot.
Regarding alternatives;
while (my $line = <$F>) {
# snip
exists $counts{lines} and $counts{lines} += !! chomp $line;
}
This is ... counting how often you've successfully chomp
ed a line I think? So basically it just counts numbers of lines in your input.
For that, I'd be thinking 'use $.
'. Unless I've missed something profound about your code?
"What if it's not chomp?"
Well, OK. How about:
$counts{lines}++ if foo();
For this:
sub foo {
my ($input) = @_;
my %responses = ( "" => "False", 1 => "True" );
return $responses{ !! $input };
}
I'd be writing that as:
sub foo {
my ($input) = @_;
return $input ? "True" : "False";
}
For the last condition - packing flags into a byte:
sub flags {
my @boolean_flags = @_;
my $flags = 0;
for ( @boolean_flags ) {
$flags<<=1;
$flags++ if $_;
}
return $flags;
}
print flags ( 1, 1, 1 );
Or perhaps if you are doing something like that - taking a leaf from how Fcntl
does it by defining values to add based on position, so you're not having to worry about the positional arguments problem:
You can request that the flock() constants (LOCK_SH, LOCK_EX, LOCK_NB and LOCK_UN) be provided by using the tag :flock
.
And then you can:
flock ( $fh, LOCK_EX | LOCK_NB );
They're defined bitwise, so they 'add' via the or
operator - but that means it's an idempotent operation, where setting LOCK_NB
twice wouldn't be.
For example,
LOCK_UN = 8
LOCK_NB = 4
LOCK_EX = 2
LOCK_SH = 1
If we expand the question to the less subjective:
I'm asking for the reasons to avoid !!
- Perl evaluates "truth" of variables, so there's not really much need for an actual logical boolean.
- Conditional statements are clearer than their equivalent boolean algebra.
if ( $somecondition ) { $result++ }
is clearer than $result += !! $somecondition
.
- It's on a secret operator list because it's obscure. Your future maintenance programmers may not appreciate that.
!!1
is 1
, !!0
is dualvar('', 0)
. While that's quite flexible, it can surprise, especially since most people don't even know what a dualvar is, much less that !
returns one. If you use a ternary, it's explicit what values you get:$value ? 1 : 0
sub Bool { shift ? 1 : "" }
should be same assub Bool { !!shift }
– Northmansub doublebang($){return $_[0]?1:''}
. – Contraventionsub Bool { shift ? 1 : "" }
is not the same assub Bool { !!shift }
. TryBool(0)+0
when warnings are on. – GraphicMany of those "operators" are not suitable for production code, because they are obscure to the uninitiated
-- perlsecret – DebbidebbieBang bang
operator. I love it. I will forever call it this. – Silurid!!f()
to normalize a boolean value (that could be a long string) into a simple value (except to question whether it's actually needed at all). – Graphic!!
adopted that for the literal syntax for boolean type construction. See my answer below for more information. – Ministry