Ruby, !! operator (a/k/a the double-bang) [duplicate] Ruby, !! operator (a/k/a the double-bang) [duplicate] ruby ruby

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


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.


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.


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