Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Lately I have seen the emergence of using the following code
return !!$return
It seems to be the same as  return $return
Do you use this in your code and any reason to use this form
-Thanks, K

Replies are listed 'Best First'.
Re: Anybody use !!
by JavaFan (Canon) on Dec 29, 2010 at 18:04 UTC
    return !!$return forces boolean context on $return (it may be an overloaded object). Furthermore, it guarantees the sub returns either 1 or the empty string.

      The value it returns for false is not (simply) an empty string. It`s also zero in numerical context.

      >perl -wE"say 0+!1" 0 >perl -wE"say 0+''" Argument "" isn't numeric in addition (+) at -e line 1. 0
Re: Anybody use !!
by ikegami (Patriarch) on Dec 29, 2010 at 22:14 UTC

    Two possible reasons for doing it:

    • Avoid information leakage (such as references or other special values) by returning a true value that has no relation to the actual value being tested.
    • Avoid large memory allocations that would result from returning long strings.
Re: Anybody use !!
by Anonyrnous Monk (Hermit) on Dec 29, 2010 at 17:52 UTC
    It seems to be the same as return $return

    Depends on what $return is.  For example, if $return is "foo", applying !! makes it to just 1 (true).

Re: Anybody use !!
by Marshall (Canon) on Dec 29, 2010 at 19:28 UTC
    This is confusing syntax although its operation is defined and it does "work". I would seek a better, more clear formulation. Also of course using $return is not the best choice of a name, use $accounts_validated or some other more descriptive term that describes the boolean nature of the return value.

    Updated: Corrected the spelling of "formulation". Also, I would think that a very clear statement of what the $return value is, resolves the problems that ikegami points out. They can happen. I would not use side effects of an operator as a substitute for explicitly saying what you mean in a very clear way. The fact that we are even discussing what does "!!$return mean?", means that it shouldn't be used. It is confusing. And in my mind that is reason enough not to do it. Use some kind of "if", perhaps a ternary statement to resolve this down to an obvious boolean, $flag_all_ok, if necessary. Have the return statement return an obvious thing.

      This is confusing syntax

      You are confused by it?

        Typing "confuse" in Google, first hit:

        1. Cause (someone) to become bewildered or perplexed.
        2. Make (something) more complex or less easy to understand.

        So yes, I would say that this is more complex or less easy to understand.

        I am not bewildered, if that is what you meant.

      I would not use side effects of an operator as a substitute for explicitly saying what you mean in a very clear way.
      ! is a unary operator, and acts like a (pure) function with one mandatory argument. It returns the negated truth value of the argument passed in, regardless how it represents false values. There are no side effects involved at all.
Re: Anybody use !!
by codeacrobat (Chaplain) on Dec 29, 2010 at 21:57 UTC
    Yes I use !! ;-)
    $ perl6 -e '(my $return = @*ARGS.pop ?? "1" !! "0").say' 42 1

    print+qq(\L@{[ref\&@]}@{['@'x7^'!#2/"!4']});
      The question did not have anything to do with Perl 6 operators.
Re: Anybody use !!
by eyepopslikeamosquito (Archbishop) on Dec 31, 2010 at 09:52 UTC

    This !! idiom is mentioned in the recently released Modern Perl book in an excellent section on Numeric, String, and Boolean Context on page eight. After advising you to use the proper operator for the type of context you want, it concludes with:

    In rare circumstances, you may need to force an explicit context where no appropriately typed operator exists. To force a numeric context, add zero to a variable. To force a string context, concatenate a variable with the empty string. To force a boolean context, double the negation operator:
    my $numeric_x = 0 + $x; # forces numeric context my $stringy_x = '' . $x; # forces string context my $boolean_x = !!$x; # forces boolean context

      I am looking at a pre-release version of this book. It stopped short of demonstrating uses of these 3 cases. Books says: In rare circumstances, I show some code below.

      CASE 1: Adding "0" (zero) to a Perl string variable is the fastest way that I know of to "delete leading zeroes". If I do that, I add a comment that explains it. This technique basically allows the use of a simple "print" instead of "printf" for output. But note that $x gets printed whether or not you immediately realize that the leading zeroes are gone or not.

      CASE 2: Using '.' to force scalar context. This technique is seen far more often than any of the other two techniques. I don't have strong opinion about it one way or the other. I use both ways depending upon the situation. Sometimes shortening the line by removing "scalar" aides understandability.

      CASE 3: This is different because the subroutine is_input_valid() is a more normal situation. I can tell that some Monks strongly disagree with me. Fine if you do. I argue that this is a situation where having an "if" statement is far more understandable and means nothing in terms of the execution efficiency of the code. The ease of understanding is worth the extra typing. !!$y is just not necessary for reasons of either understandability or efficiency.

      As has been pointed out in other posts, there can be more complicated things for $y other than a simple scalar, and I would say all the more reason to have some extra logic.

      #!/usr/bin/perl -w use strict; # CASE 1: # use +0 to "delete leading zeros" # avoids having to use a printf %d format # or some kind of slow substitution statement # my $x = "00012"; print "$x\n"; #prints 00012 printf "%d\n",$x; #prints 12 $x+=0; #delete leading zeroes print "$x\n"; #prints 12 # CASE 2: # use '.' concatentation to # avoid having to use an # explict scalar() function # print "Number values= ", scalar(return_array()),"\n"; # prints 2 print "Number values= " .return_array(),"\n"; # prints 2 # CASE 3: # use !! to avoid using an "if" statement # my $y = "abx"; print $y ? 'T': 'F', "\n"; #prints T print $y ? 1 : 0, "\n"; #prints 1 print !!$y, "\n"; #prints 1 ??good idea?? print ''.is_input_valid(),"\n"; #prints 1 sub return_array { my @x = (12,23); return @x; } sub is_input_valid { my $f_validated_input =0; # more code here... $f_validated_input = 1; return $f_validated_input; }