Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby boolean double negation convention

Tags:

ruby

Can anybody tell me why a lot of Ruby boolean methods use this double negation convention?

!!(boolean expression)
like image 727
Hamish Avatar asked Apr 26 '11 21:04

Hamish


3 Answers

The double negation ensures that no matter the initial value, you will always get true or false, never some mystery value.

This is handy because it avoids dangling references to objects you no longer require, or having to differentiate between two types of false value, nil and false.

Often you will see methods written like this:

def logged_in?
  !!@session_user
end

This will return true or false and that value can be used for whatever purpose is required. Compare that with this:

def logged_in?
  @session_user
end

In this case if you save the value, you're actually saving the whole @session_user object, which could be a fairly significant chunk of memory. This memory cannot be released until your reference to it falls out of scope. Since there is only one true and one false, there's no need for garbage collection.

like image 54
tadman Avatar answered Sep 19 '22 05:09

tadman


Suppose you want to define a method that returns a boolean. For example, whether a string matches a regex.

class String
  def include? regex; self =~ regex end
end

If you do the above, it will return nil when it does not match, and an integer when it matches. In many cases, that does not matter so much (nil is similar to false and true can be substituted for an integer). But if you really wanted a boolean as a return value, if you do

class String
  def include? regex; !!(self =~ regex) end
end

it will return true when it matches, false when it does not.

like image 36
sawa Avatar answered Sep 22 '22 05:09

sawa


In my opinion, Ruby is just a little too clever about Booleans. This is a workaround for the cases when the cleverness causes problems.

Here's the excessive cleverness: there's no Boolean class. Instead, there's a convention under which any value can serve as a boolean. In a context where a true-or-false value is required, nil or false means "false" and anything else means "true". The values true and false are not part of a special class, they're the sole members of their respective classes — they exist only to make code a little more readable.

I guess this works fine most of the time, but every once in a very long while you need a boolean value that is always true or false. For example, I recently needed to compare two boolean values and do something special if they were different; the only problem being, one of them was either true or false, while the other was either 1 or nil. Fix? Utilize the fact that !!nil == false and !!1 == true.

like image 22
Isaac Rabinovitch Avatar answered Sep 22 '22 05:09

Isaac Rabinovitch