Bang Bang Operator
Two negations. That's the trick:The bang bang operator. It converts any value to a clean boolean.!!
Not just truthy or falsy - actual Perl boolean values.!!0 # '' (empty string, false) !!1 # 1 (true) !!'hello' # 1 (true) !!'' # '' (false) !!undef # '' (false)
Part 1: THE TRICK
Single negation flips true to false and vice versa:Double negation flips twice - back to the original truthiness:!0 # 1 (false became true) !1 # '' (true became false)
But now you have a normalized boolean, not 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. Useful when you need to pass a true/false flag, not the actual value.print $truthy; # hello world print $bool; # 1
.--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
Part 3: PERL'S BOOLEAN VALUES
Perl doesn't have true/false keywords. It uses:The bang bang operator normalizes 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 don't care what they typed. You care if it 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 return 1 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 - "this is meant to be a boolean."my $is_big = !!(10 > 5); # 1 (same as without !!)
Part 6: WITH REGEX
Regex matches return true/false in scalar context:Bang bang doesn't 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 need 0/1 integers, not ''/ 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'd 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're unsure what's truthy:Output:for my $val (0, 1, '', 'hello', undef, [], {}) { printf "%s -> %s\n", defined $val ? "'$val'" : 'undef', !!$val ? 'true' : 'false'; }
References are always true (they're not empty or 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're shooting truth out of any value.
JavaScript has the same operator with the same name. Perl did it first, of course.
!! / \ ! ! / \ false -> true -> normalized Shooting booleans since forever
Created By: Wildcard Wizard. Copyright 2026