111

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.

Community
  • 1
  • 1
Vitaly
  • 2,567
  • 5
  • 29
  • 34
  • 1
    Did you look on questions, which was given to you after you typed you question's title? – Nakilon Oct 22 '10 at 05:06
  • 5
    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. – Vitaly Oct 22 '10 at 05:13
  • 3
    Yeah, the similar questions algorithm gets tricked easily when important parts of the title are punctuation characters. – pkaeding Oct 22 '10 at 05:16
  • 3
    See [What does !! mean in ruby?](http://stackoverflow.com/questions/524658/what-does-mean-in-ruby) and [What does the “!!” symbol mean in Ruby? ](http://stackoverflow.com/questions/3821428/what-does-the-symbol-mean-in-ruby). – Matthew Flaschen Oct 22 '10 at 05:23
  • In future, try using symbolhound.com to search for syntax. – Andrew Grimm Aug 16 '12 at 00:38

4 Answers4

165

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.

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
pkaeding
  • 36,513
  • 30
  • 103
  • 141
  • so !"" is force to **true** and !!"" to **false** or is the empty string true as well? – berto77 Aug 15 '12 at 15:11
  • 1
    `!""` is `false`, because the only false-y values are `false` and `nil`. Everything else is truth-y: http://phrogz.net/ProgrammingRuby/language.html#truthvalues I've edited my answer to make this more clear. – pkaeding Aug 15 '12 at 23:17
  • 2
    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? – Kevin M Jan 05 '16 at 21:32
  • 1
    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. – Pistos Jul 20 '16 at 17:34
  • 2
    So basically, `!!foo` is equivalent to `not (foo == nil or foo == false)` – FloatingRock Mar 30 '17 at 15:43
  • Some methods might behave differently whether a passed argument is `false` vs `nil`; so in that kind of case, if you want to avoid the `nil` case, `!!` can be useful. – Aaron Wallentine Jun 09 '23 at 04:13
133

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.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
40

!! 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.

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
Theo
  • 131,503
  • 21
  • 160
  • 205
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.

Zabba
  • 64,285
  • 47
  • 179
  • 207