Ruby, !! operator (a/k/a the double-bang)

50,660

Solution 1

In most programming languages, including Ruby, ! will return the opposite of the boolean value of the operand. So when you chain two exclamation marks together, it converts the value to a boolean.

Solution 2

In Ruby (and many other languages) there are many values that evaluate to true in a boolean context, and a handful that will evaluate to false. In Ruby, the only two things that evaluate to false are false (itself) and nil.

If you negate something, that forces a boolean context. Of course, it also negates it. If you double-negate it, it forces the boolean context, but returns the proper boolean value.

For example:

"hello"   #-> this is a string; it is not in a boolean context
!"hello"  #-> this is a string that is forced into a boolean 
          #   context (true), and then negated (false)
!!"hello" #-> this is a string that is forced into a boolean 
          #   context (true), and then negated (false), and then 
          #   negated again (true)
!!nil     #-> this is a false-y value that is forced into a boolean 
          #   context (false), and then negated (true), and then 
          #   negated again (false)

In your example, the signed_in? method should return a boolean value (as indicated by convention by the ? character). The internal logic it uses to decide this value is by checking to see if the current_user variable is set. If it is set, it will evaluate to true in a boolean context. If not, it will evaluate as false. The double negation forces the return value to be a boolean.

Solution 3

!! is just ! (the boolean negation operator) written twice. It will negate the argument, then negate the negation. It's useful because you can use it to get a boolean from any value. The first ! will convert the argument to a boolean, e.g. true if it's nil or false, and false otherwise. The second will negate that again so that you get the boolean value of the argument, false for nil or false, true for just about everything else.

In Ruby you can use any value in an if statement, e.g. if current_user will execute if the current user is not nil. Most of the time this is great because it saves us typing explicit tests (like if !current_user.nil?, which is at least six characters longer). But sometimes it might be really confusing if you return an object when the method implies that it returns a boolean. Methods whose name ends with ? should return truthy or falsy values, i.e. they return something that will evaluate to true or false. However, it can get really messy if signed_in? returned a user object. For example if you're trying to debug why some code that uses signed_in? doesn't work you will probably get really confused when a user object turns up where you expected true or false. In that situation it's useful to add !! before the return since that guaranteed that the truthy or falsy value will be returned as either true or false.

Solution 4

As you rightly understood it is a double-negative use of the ! operator. That said, while it can be a shorthand way to check for whether a variable can be nil or not, IMO that's too concise. Take a look at this and this post. Note that in Ruby, testing something to nil will evaluate to false.

Share:
50,660

Related videos on Youtube

Vitaly
Author by

Vitaly

Updated on September 09, 2020

Comments

  • Vitaly
    Vitaly over 3 years

    Possible Duplicate:
    What does !! mean in ruby?

    Hi,

    I'm new to Ruby and can't find anywhere description of what "!!" means.

    Here's an example:

    def signed_in?
      !!current_user
    end
    

    If this is a double negative, why not to say:

    def signed_in?
      current_user
    end
    

    Please help.

    • Nakilon
      Nakilon over 13 years
      Did you look on questions, which was given to you after you typed you question's title?
    • Vitaly
      Vitaly over 13 years
      Yeah, there was nothing there. I actually found similar question explaining me the second question, but I had to search by "double bang" which is not so obvious as you might think.
    • liran
      liran over 13 years
      Yeah, the similar questions algorithm gets tricked easily when important parts of the title are punctuation characters.
    • Matthew Flaschen
      Matthew Flaschen over 13 years
      See What does !! mean in ruby? and [What does the “!!” symbol mean in Ruby? ](stackoverflow.com/questions/3821428/…).
    • oligan
      oligan over 11 years
      In future, try using symbolhound.com to search for syntax.
  • berto77
    berto77 over 11 years
    so !"" is force to true and !!"" to false or is the empty string true as well?
  • liran
    liran over 11 years
    !"" is false, because the only false-y values are false and nil. Everything else is truth-y: phrogz.net/ProgrammingRuby/language.html#truthvalues I've edited my answer to make this more clear.
  • Kevin M
    Kevin M over 8 years
    This is the better answer because it explains WHY. Seems like the same type of hack you see in Java sometimes to convert an int to a String by appending a "" to it (which by the way i am NOT advocating for - I believe this is bad practice in Java). Given that this is bad practice in Java, I don't understand why languages like Ruby are embracing it. Everything to use the least number of characters possible?
  • Pistos
    Pistos almost 8 years
    Double banging is almost never actually necessary. The Ruby interpreter will always evaluate the truth value of the expression the same way with or without the double bang. As such, double banging just introduces more computation for no technical gain. (The gain lies in appeasing [some] human minds.) There is actually [at least] one place where double banging is necessary, though: When you are converting to_json, nil will go to null, so if you want the value to actually be true or false in JSON, you need to double bang.
  • FloatingRock
    FloatingRock about 7 years
    So basically, !!foo is equivalent to not (foo == nil or foo == false)