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?

Chankey Pathak
  • 21,187
  • 12
  • 85
  • 133

2 Answers2

45

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.
ikegami
  • 367,544
  • 15
  • 269
  • 518
ronalchn
  • 12,225
  • 10
  • 51
  • 61
  • 1
    Your answer + http://stackoverflow.com/a/2168511/257635 = Satisfaction! :P – Chankey Pathak Sep 05 '12 at 10:14
  • `'null'` would evaluate to true in Perl. Did you mean `undef`? – Zaid Sep 05 '12 at 10:36
  • this is not my native language... (I mean in terms of programming languages) – ronalchn Sep 05 '12 at 10:37
  • @amon : What about the empty list `()`? – Zaid Sep 05 '12 at 11:01
  • @Zaid … I have to read perlsyn more often, thanks – amon Sep 05 '12 at 11:50
  • 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). – cjm Sep 05 '12 at 15:33
  • 1
    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. – ikegami Sep 05 '12 at 17:54
  • I like using `!!0` as a shorthand for "that special empty string that Perl's standard relational and equality operators produce". As discussed in http://stackoverflow.com/questions/39541833/what-values-should-a-boolean-function-in-perl-return, 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`. – Krazy Glew Sep 22 '16 at 21:30
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;
Zaid
  • 36,680
  • 16
  • 86
  • 155
  • 1
    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. :) – memowe Sep 05 '12 at 12:02
  • @memowe : Yeah, thanks for that.. like I said I hadn't tested it :) – Zaid Sep 05 '12 at 12:11