perl.gg / secret-operators

Bang Bang Operator

2026-01-01

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.
!!0 # '' (empty string, false) !!1 # 1 (true) !!'hello' # 1 (true) !!'' # '' (false) !!undef # '' (false)
It does not leave truthy or falsy strings sitting around. It returns actual Perl boolean values.

Part 1: THE TRICK

A single negation flips a true value to false and a false value to true:
!0 # 1 (false became true) !1 # '' (true became false)
Double negation flips the value twice so it lands back on its original truthiness:
!!0 # '' (false -> true -> false) !!1 # 1 (true -> false -> true)
But now you hold a normalized boolean instead of the original value.

Part 2: WHY BOTHER

Consider this:
my $value = 'hello world'; my $truthy = $value; # 'hello world' (keeps original) my $bool = !!$value; # 1 (clean boolean)
Without bang bang:
print $truthy; # hello world print $bool; # 1
The second form is explicitly boolean. It matters when you need to pass a true or false flag rather than the raw value.
.--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/

Part 3: PERL'S BOOLEAN VALUES

Perl does not ship with true or false keywords. It uses:
False: 0, '', '0', undef, empty list True: Everything else
The bang bang operator normalizes everything to exactly two values:
'' for false 1 for true
These are Perl's canonical boolean representations.

Part 4: FLAG NORMALIZATION

Storing user input as a boolean:
my $input = param('subscribe'); # Could be 'yes', '1', 'on', 'true'... my $flag = !!$input; # Now it's 1 or '' # Later: if ($flag) { send_newsletter(); }
You do not care what they typed. You only care whether the input was truthy.

Part 5: COMPARISON RESULTS

Comparisons return 1 or '' in Perl:
my $is_big = 10 > 5; # 1 my $is_small = 5 > 10; # ''
So bang bang on a comparison is redundant:
my $is_big = !!(10 > 5); # 1 (same as without !!)
But it documents intent, which means "this is meant to be a boolean."

Part 6: WITH REGEX

Regex matches return true or false in scalar context:
my $matched = $str =~ m~pattern~; # 1 or ''
Bang bang does not change it:
my $matched = !!($str =~ m~pattern~); # Still 1 or ''
But it can help with non-boolean regex returns:
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 or 1 integers rather than '' or 1:
my $bool = !!$value; # '' or 1 my $int = 0 + !!$value; # 0 or 1 (Venus + Bang Bang)
This is the "Venus Bang Bang" combination:
0 + !!$anything # Always gives you 0 or 1 integer
Useful for:
- Bit manipulation - JSON output - Database storage - C library interfaces

Part 8: COUNTING TRUES

Count how many values are truthy:
my @values = (1, 0, 'hello', '', undef, 42); my $count = 0; $count += !!$_ for @values; print "True values: $count\n"; # True values: 3
Or more tersely with grep:
my $count = grep { $_ } @values; # 3
But bang bang makes the intent crystal clear.

Part 9: CONDITIONAL DEFAULTS

Set a flag based on existence:
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)
Without bang bang, you would have to check defined and truthiness separately.

Part 10: JSON BOOLEANS

Many JSON modules need explicit booleans:
use JSON; my $data = { active => !!$user->{status}, admin => !!$user->{is_admin}, }; print encode_json($data); # {"active":true,"admin":false}
The JSON module recognizes Perl's canonical booleans and converts them properly.

Part 11: DEBUGGING

When you are unsure what is truthy:
for my $val (0, 1, '', 'hello', undef, [], {}) { printf "%s -> %s\n", defined $val ? "'$val'" : 'undef', !!$val ? 'true' : 'false'; }
Output:
'0' -> false '1' -> true '' -> false 'hello' -> true undef -> false 'ARRAY(0x...)' -> true 'HASH(0x...)' -> true
References are always true because they are neither empty nor zero.

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.

!! / \ ! ! / \ false -> true -> normalized Shooting booleans since forever
perl.gg