Ruby, !! operator (a/k/a the double-bang) [duplicate]
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.
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
.