What does !! mean in ruby?

Ruby

Ruby Problem Overview


Just wondering what !! is in Ruby.

Ruby Solutions


Solution 1 - Ruby

Not not.

It's used to convert a value to a boolean:

!!nil   #=> false
!!"abc" #=> true
!!false #=> false

It's usually not necessary to use though since the only false values to Ruby are nil and false, so it's usually best to let that convention stand.

Think of it as

!(!some_val)

One thing that is it used for legitimately is preventing a huge chunk of data from being returned. For example you probably don't want to return 3MB of image data in your has_image? method, or you may not want to return your entire user object in the logged_in? method. Using !! converts these objects to a simple true/false.

Solution 2 - Ruby

It returns true if the object on the right is not nil and not false, false if it is nil or false

def logged_in?   
  !!@current_user
end

Solution 3 - Ruby

! means negate boolean state, two !s is nothing special, other than a double negation.

!true == false
# => true

It is commonly used to force a method to return a boolean. It will detect any kind of truthiness, such as string, integers and what not, and turn it into a boolean.

!"wtf"
# => false

!!"wtf"
# => true

A more real use case:

def title
  "I return a string."
end

def title_exists?
  !!title
end

This is useful when you want to make sure that a boolean is returned. IMHO it's kind of pointless, though, seeing that both if 'some string' and if true is the exact same flow, but some people find it useful to explicitly return a boolean.

Solution 4 - Ruby

Note that this idiom exists in other programming languages as well. C didn't have an intrinsic bool type, so all booleans were typed as int instead, with canonical values of 0 or 1. Takes this example (parentheses added for clarity):

!(1234) == 0
!(0) == 1
!(!(1234)) == 1

The "not-not" syntax converts any non-zero integer to 1, the canonical boolean true value.

In general, though, I find it much better to put in a reasonable comparison than to use this uncommon idiom:

int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious

Solution 5 - Ruby

It's useful if you need to do an exclusive or. Copying from Matt Van Horn's answer with slight modifications:

1 ^ true
TypeError: can't convert true into Integer

!!1 ^ !!true
=> false

I used it to ensure two variables were either both nil, or both not nil.

raise "Inconsistency" if !!a ^ !!b

Solution 6 - Ruby

It is "double-negative", but the practice is being discouraged. If you're using rubocop, you'll see it complain on such code with a Style/DoubleNegation violation.

The rationale states:

> As this is both cryptic and usually redundant, it should be avoided > [then paraphrasing:] Change !!something to !something.nil?

Solution 7 - Ruby

Understanding how it works can be useful if you need to convert, say, an enumeration into a boolean. I have code that does exactly that, using the classy_enum gem:

class LinkStatus < ClassyEnum::Base
  def !
    return true
  end
end

class LinkStatus::No < LinkStatus
end

class LinkStatus::Claimed < LinkStatus
  def !
    return false
  end
end

class LinkStatus::Confirmed < LinkStatus
  def !
    return false
  end
end

class LinkStatus::Denied < LinkStatus
end

Then in service code I have, for example:

raise Application::Error unless !!object.link_status   # => raises exception for "No" and "Denied" states.

Effectively the bangbang operator has become what I might otherwise have written as a method called to_bool.

Solution 8 - Ruby

Other answers have discussed what !! does and whether it is good practice or not.

However, none of the answers give the "standard Ruby way" of casting a value into a boolean.

true & variable

TrueClass, the class of the Ruby value true, implements a method &, which is documented as follows:

> Returns false if obj is nil or false, true otherwise.

Why use a dirty double-negation when the standard library has you covered?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCameronView Question on Stackoverflow
Solution 1 - RubyAlex WayneView Answer on Stackoverflow
Solution 2 - RubyRichHView Answer on Stackoverflow
Solution 3 - RubyAugust LilleaasView Answer on Stackoverflow
Solution 4 - RubyTomView Answer on Stackoverflow
Solution 5 - RubyAndrew GrimmView Answer on Stackoverflow
Solution 6 - RubyMicah ElliottView Answer on Stackoverflow
Solution 7 - RubyinopinatusView Answer on Stackoverflow
Solution 8 - RubyRichard-DegenneView Answer on Stackoverflow