Ruby, !! operator (a/k/a the double-bang)
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.
Related videos on Youtube
Vitaly
Updated on September 09, 2020Comments
-
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 over 13 yearsDid you look on questions, which was given to you after you typed you question's title?
-
Vitaly over 13 yearsYeah, 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 over 13 yearsYeah, the similar questions algorithm gets tricked easily when important parts of the title are punctuation characters.
-
Matthew Flaschen over 13 yearsSee What does !! mean in ruby? and [What does the “!!” symbol mean in Ruby? ](stackoverflow.com/questions/3821428/…).
-
oligan over 11 yearsIn future, try using symbolhound.com to search for syntax.
-
-
berto77 over 11 yearsso !"" is force to true and !!"" to false or is the empty string true as well?
-
liran over 11 years
!""
isfalse
, because the only false-y values arefalse
andnil
. Everything else is truth-y: phrogz.net/ProgrammingRuby/language.html#truthvalues I've edited my answer to make this more clear. -
Kevin M over 8 yearsThis 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 almost 8 yearsDouble 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 tonull
, so if you want the value to actually betrue
orfalse
in JSON, you need to double bang. -
FloatingRock about 7 yearsSo basically,
!!foo
is equivalent tonot (foo == nil or foo == false)