Bang Bang Operator
This page explains how the double negation operator in Perl converts any value into a clean boolean.The bang bang operator. It converts any value to a clean boolean.!!
It does not leave truthy or falsy strings sitting around. It returns actual Perl boolean values.!!0 # '' (empty string, false) !!1 # 1 (true) !!'hello' # 1 (true) !!'' # '' (false) !!undef # '' (false)
Part 1: THE TRICK
A single negation flips a true value to false and a false value to true:Double negation flips the value twice so it lands back on its original truthiness:!0 # 1 (false became true) !1 # '' (true became false)
But now you hold a normalized boolean instead of the original value.!!0 # '' (false -> true -> false) !!1 # 1 (true -> false -> true)
Part 2: WHY BOTHER
Consider this:Without bang bang:my $value = 'hello world'; my $truthy = $value; # 'hello world' (keeps original) my $bool = !!$value; # 1 (clean boolean)
The second form is explicitly boolean. It matters when you need to pass a true or false flag rather than the raw value.print $truthy; # hello world print $bool; # 1
.--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
Part 3: PERL'S BOOLEAN VALUES
Perl does not ship withtrue or false keywords. It uses:
The bang bang operator normalizes everything to exactly two values:False: 0, '', '0', undef, empty list True: Everything else
These are Perl's canonical boolean representations.'' for false 1 for true
Part 4: FLAG NORMALIZATION
Storing user input as a boolean:You do not care what they typed. You only care whether the input was truthy.my $input = param('subscribe'); # Could be 'yes', '1', 'on', 'true'... my $flag = !!$input; # Now it's 1 or '' # Later: if ($flag) { send_newsletter(); }
Part 5: COMPARISON RESULTS
Comparisons return1 or '' in Perl:
So bang bang on a comparison is redundant:my $is_big = 10 > 5; # 1 my $is_small = 5 > 10; # ''
But it documents intent, which means "this is meant to be a boolean."my $is_big = !!(10 > 5); # 1 (same as without !!)
Part 6: WITH REGEX
Regex matches return true or false in scalar context:Bang bang does not change it:my $matched = $str =~ m~pattern~; # 1 or ''
But it can help with non-boolean regex returns:my $matched = !!($str =~ m~pattern~); # Still 1 or ''
my @matches = $str =~ m~(\w+)~g; # List of captures my $has_match = !!@matches; # 1 or '' (was it empty?)
Part 7: CONVERTING TO INTEGER
Sometimes you need0 or 1 integers rather than '' or 1:
This is the "Venus Bang Bang" combination:my $bool = !!$value; # '' or 1 my $int = 0 + !!$value; # 0 or 1 (Venus + Bang Bang)
Useful for:0 + !!$anything # Always gives you 0 or 1 integer
- Bit manipulation - JSON output - Database storage - C library interfaces
Part 8: COUNTING TRUES
Count how many values are truthy:Or more tersely with grep:my @values = (1, 0, 'hello', '', undef, 42); my $count = 0; $count += !!$_ for @values; print "True values: $count\n"; # True values: 3
But bang bang makes the intent crystal clear.my $count = grep { $_ } @values; # 3
Part 9: CONDITIONAL DEFAULTS
Set a flag based on existence:Without bang bang, you would have to check defined and truthiness separately.my %opts = (verbose => 1, debug => 0); my $v = !!$opts{verbose}; # 1 my $d = !!$opts{debug}; # '' (0 is false) my $q = !!$opts{quiet}; # '' (doesn't exist)
Part 10: JSON BOOLEANS
Many JSON modules need explicit booleans:The JSON module recognizes Perl's canonical booleans and converts them properly.use JSON; my $data = { active => !!$user->{status}, admin => !!$user->{is_admin}, }; print encode_json($data); # {"active":true,"admin":false}
Part 11: DEBUGGING
When you are unsure what is truthy:Output:for my $val (0, 1, '', 'hello', undef, [], {}) { printf "%s -> %s\n", defined $val ? "'$val'" : 'undef', !!$val ? 'true' : 'false'; }
References are always true because they are neither empty nor zero.'0' -> false '1' -> true '' -> false 'hello' -> true undef -> false 'ARRAY(0x...)' -> true 'HASH(0x...)' -> true
Part 12: THE NAME
Two bangs:Bang. Bang.!!
Some call it "double not" or "not not." But bang bang is funnier, and it sounds like you are shooting truth out of any value.
JavaScript has the same operator with the same name. Perl did it first, of course.
perl.gg!! / \ ! ! / \ false -> true -> normalized Shooting booleans since forever