Use of double negation (!!) [duplicate]
Asked Answered
C

2

31

Okay so I came across a code which looks like

@documents_names = sort {
         !!$deleted_documents_names{$a} == !!$deleted_documents_names{$b}
          ? uc($a) cmp uc($b)
          : !!$deleted_documents_names{$a}
          cmp !!$deleted_documents_names{$b}
         } @documents_names;

It's the first time I'm seeing the use of double negation. What's the use of it? When would a person use it?

Crandale answered 5/9, 2012 at 10:5 Comment(1)
#2168906Stevestevedore
T
44

It converts non-boolean types to boolean (dualvar(0,"") or 1).

It is a shortcut way of doing this, instead of trying to cast it explicitly (which may take more characters). The ! operator negates the truthness of its argument. Hence, two of them are used.

Many object types are "truthy", and others are "falsey".

  • The only false values are 0, undef, "", "0" and some overloaded objects.
  • Examples of true values are 1, "asdf", and all other values.
Tenatenable answered 5/9, 2012 at 10:7 Comment(7)
Your answer + https://mcmap.net/q/24578/-what-does-double-exclamation-point-mean = Satisfaction! :PCrandale
'null' would evaluate to true in Perl. Did you mean undef?Cordwood
this is not my native language... (I mean in terms of programming languages)Tenatenable
@amon : What about the empty list ()?Cordwood
BTW, !! does not produce the empty string exactly. Perl's canonical false value is an empty string in string context, but 0 in numeric context (without any warning about a non-numeric value, which a normal empty string would generate in numeric context).Pickled
It's impossible to pass an empty list to a boolean test, so empty lists are neither true nor false. () (an operator that returns undef in scalar context) should no more be in the list than -f "nonexistant" (an operator that returns undef). Values are true or false, not operators.Killy
I like using !!0 as a shorthand for "that special empty string that Perl's standard relational and equality operators produce". As discussed in #39542333, you cannot refactor, i.e. you cannot get exactly the same behavior, return $a<$b into if($a<$b){return 1} else{return 0}, but you can if you do return !!0.Lorislorita
C
10

That is a lot of funk for a sort block!

It's essentially a two-level sort :

  1. ascii-betical
  2. deleted files first, then undeleted

So one could rewrite it as (untested):

@documents = sort {  exists $deleted_documents_names{$a} # same effect as '!!'
                       <=> 
                     exists $deleted_documents_names{$b}
                  ||
                     uc( $a ) cmp uc( $b )
                  }
             @documents;
Cordwood answered 5/9, 2012 at 11:14 Comment(2)
That's not completely right since <=> is an operator for numbers. You should use cmp instead to work with the alphabetical comparison of strings. Nice sort clarification though. :)Incite
@Incite : Yeah, thanks for that.. like I said I hadn't tested it :)Cordwood

© 2022 - 2024 — McMap. All rights reserved.