Whats the ruby !! operator? [duplicate] - ruby

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does !! mean in ruby?
I'm learning ruby/rails and found a tutorial with the following code example:
def role?(role)
return !!self.roles.find_by_name(role.to_s.camelize)
end
I don't have any idea for what the !! do, neither the !!self do.
I really googled about that, but doesn't find anything.
Can anyone give a short explanation? Thanks in advance.

It's the "not" operator (!) repeated twice, so that it's argument will be coerced to its negated boolean and then its corresponding boolean. Basically, it's a way to coerce any object into its boolean value.
!!false # => false
!!nil # => false
!!true # => true
!!{} # => true
!![] # => true
!!1 # => true
!!0 # => true (Surprised? Only 'false' and 'nil' are false in Ruby!)

It's usually employed to force-cast an arbitrary value into one of true or false.
This is often useful for converting between arbitrary numbers, strings, or potential nil values.
In your example this is extremely inefficient since an entire model is loaded only to be discarded. It would be better written as:
def role?(role)
self.roles.count_by_name(role.to_s.camelize) > 0
end
That query will return a singular value that is used for comparison purposes, the result of which is automatically a boolean.

This confirms that the operation will always return the boolena value
!!1 #gives you true
!!nil #gives you false
In ruby nil, false is consider as false and 0, 0.0 and other objects are consider as true

Related

Why does an empty String returns false when comparing to boolean in ruby?

It might be a dumb question, but can someone please explain this:
if ""
true
else
false
end
=> true (OK)
!!("")
=> true (OK)
"" === true
=> false (OK)
"" == true
=> false (But why?)
Have a nice day!
The basic concept of this question is a deep misunderstanding of Ruby operators. Here's the short of it - there's no such thing as operators in Ruby! All this !, =, == and === that you throw around - these are not operators.
So what's going on?
Ruby is an object oriented language (a real one, not like that fake Java and JavaScript things) and all these fancy character sequences you think of as operators are actually method calls on the object in their left:
== method usually checks for equality - is the object on the right equal in content.
=== method is not used for "strict equality" or "identity" like it is often in other languages - some Ruby objects that implement it use it for "membership" tests, like in ranges ((1..3) === 2 ==> true) or regular expressions (/el/ === "hello" ==> true you can think of regular expressions as the group of all strings that would match), others implement it as equals.
So - how is the if working? Well, if and other "forced boolean contexts" check for "falsehood". In Ruby we recognize two false values - false and nil, everything else will run the truth branch of an if. This is actually the method ! that you also used in your second example. This method is implemented in BasicObject to return true for all objects, except if the object's type is the type of false - FalseClass or the type for nil - NilClass, in which case it returns true.
So your examples actually mean:
Check for the truthiness of "". Because that value's type is neither FalseClass or NilClass, it is always true.
For the value "", call the method ! - which will return false because the object is neither a FalseClass or a NilClass - then call ! on the result, which will return true because false is a FalseClass instance.
For the value "" call the method === with the argument true, but since it is an alias for == - call that instead (see 4).
For the value "" call the method == with the argument true. String's implementation of == will never return true for an argument that isn't a String type.
The only falsy values in Ruby are false and nil. Everything else is "truthy," but not necessarily equal to true. This includes empty objects like a String, Hash, or Array.
Pragmatically, it might help to think of == as "comparably equivalent to" rather than "equals." For example:
1 == 1.0 #=> true
This is true even though one is an Integer and one is a Float because they are comparably equivalent in value, even if they aren't the same object or of the same type.
In the same way, "" is truthy because it is not comparably equivalent to false or nil. However, it's also not the same object type as true, nor comparably equivalent to true. An empty String is simply "not falsy," which makes it truthy but not actually true.
Remember, only false and nil are falsy. Everything else, and I mean everything, is truthy even if it isn't strictly speaking true.
In Ruby, the only "falsey types" are FalseClass and NilClass, which have the instances false and nil respectively. All other values are considered "truthy". This is possibly different to what you'd expect coming from other C-like values, in which we do things like this pretty freely:
int x = get_value();
if (x) { /* implied x != 0 }
So, if you had something like this in Ruby:
puts 0 if 0 # => "0"
puts 1 if "" # => "1"
puts 2 if [] # => "2"
puts 3 if false # => nil
puts 4 if true # => "4"
puts 5 if nil # => "5"
So, if "" acts truthy, why isn't it equal to true? If that were how we defined ==, then this would also need to resolve to true then, since both values are truthy:
"1" == "2"
The difference here is that == is asking if two things are the same, which "" and true are most certainly not. Further, Ruby does not automatically convert types for you (like other languages like JavaScript do), so "" does not automatically get converted to a boolean during its comparison.

Why does `defined?` keyword not return boolean? [duplicate]

This question already has answers here:
Why does `defined?` return a string or nil?
(2 answers)
Closed 7 years ago.
In ruby, most methods or keywords that end with ? return boolean values. And we except them to behave like this. Why does defined? keyword return somethings else? Or why is there ? at the end of it?
This question can be understood in two ways:
Why doesn't it simply return true or false?
It's because it encodes more information than simply if something is defined or not:
defined? Class # => "constant"
defined? 42 # => "expression"
defined? nil # => "nil"
defined? x # => nil
Why does it have ? at the end since as the convention goes, the question mark is reserved for predicates?
You are right that this is inconsistent. The most likely reasons are:
Almost always, you will use it as predicate anyway
if defined? x
# do something
end
The shortest alternative, which doesn't sound like a predicate I can think of is definition_type_of. Generally, you want to keep the reserved words in your language short
Developers chose to return something more meaningfull than true or false because the only case that breaks by not having boolean returned is explicit comparison:
defined?(:x) == true
# => always `false`
Such comparison is something you should usually not do, as logical operators like || and && are just as likely to return some truthy object instead of true. This is barely needed for anything.
The "defined?"-method can return more than "true" or "false". It tells you what type of variable it is if it's defined at all.
Check
Checking if a variable is defined?
and
http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-defined-3F

Ruby (Rails 4.0.2): (1 == true) => false?

My understanding is that in the Ruby programming language, only nil and false are considered false, and EVERYTHING else is considered true.
Thus, 1 == true SHOULD return true.
I was working on a Rails 4.0.2 project using MS SQL Server (boolean field, tinyint(1)) and couldn't get the boolean working properly. The value in the DB column was 1.
Stumped, I started testing some things in the console. Here's what I got in my Rails console:
1 == true # => false
0 == true # => false
"test" == true # => false
"" == true # => false
Why is everything registering as false? I thought they were all supposed to be true?
I ended up having to do my boolean check via <attribute>.to_i == 1 to get a valid true/false value.
Am I missing something in the Ruby language or was it updated in some version I wasn't aware of? I'm using RVM, ruby 2.0.0p481 (2014-05-08 revision 45883) on a Mac machine.
Updated: 2014-10-28 09:00
After reading the excellent answers below, I understand where my thinking was wrong.
I think one of the problems is that most of the DB adapters I use (PostgreSQL, MySQL, etc...) converted boolean values in the DB for me.
For instance, in a lot of my code bases I have:
# User has an :admin boolean attribute
class User < ActiveRecord::Base
def admin?
admin == true
end
end
And I suspect this works "fine" because the DB adapter takes care of converting the DB value to a proper boolean for me.
However, I'm currently work on a project where I'm required to use MS SQL Server, and I've run into many "gotchas" with the DB adapter, one of which is I don't believe it treats boolean fields the same as the other adapters do.
Thus, I always considered any TRUTHY value to be equal to true, which it is not. I guess that's why rspec and others have moved to use be_truthy in their own syntax instead of purely be_true.
I'm just surprised it took me a few years before I ran into a problem like this!
My understanding is that in the Ruby programming language, only nil and false are considered false, and EVERYTHING else is considered true
This is true.
However,
"Thus, 1 == true SHOULD return true."
is false.
Explanation: in Ruby everything except false/nil is considered true. However when testing for equality, like x == true you're actually not testing "is this value considered true" but "is this value equal to true".
And of course 1 isn't equal to true, 1 is a number and true is a boolean value. You can read a very good blog post about equality in Ruby at "Ruby Equality And Object Comparison".
If you really, really want to test it that way, you need to convert the expression like 1 to its boolean value, which you can do by double negating it. So !!1 # => true.
So, your examples will look like this:
!!1 == true # => true
!!0 == true # => true
!!"test" == true # => true
!!"" == true # => true
However I believe it isn't necessary in most cases.
When working with MSSQL you should let Active Record do all the conversions for you. Declare the field in a migration, with type boolean, and when you do your where search in the database, do it like this:
Model.where(['attribute = ?', true])
Model.where(:attribute=> true)
This way ActiveRecord will do all the work related to converting the type to a database compatible one for you.
In terms of logical predicates every object besides nil and false are TRUTHY. What basically means that statement corresponding our predicate (condition) will be executed.
While nil and false are FALSEY predicate.
In practice it means:
if predicate
statement_a
else
statement_b
end
Whatever is not a predicate, except nil and false statement_a will be executed. Otherwise statement_b will get the jack pot.
First off, your assumption that everything in Ruby that isn't false or nil is considered true, is true.
Let's take each of your four examples:
1 == true # => false
When evaluating this expression, Ruby takes the class of the first argument, looks for the operator method and evaluates. So, for Fixnums, it evaluates whether or not 1 is equal to another Numeric number. Fixnum#== docs that is equivalent to 1.
0 == true # => false
Same as above.
"test" == true # => false
This is doing an equality test through the String class. As stated in the String#== docs, the class is tested on the right side and if it isn't a string, but responsed to to_str (true does), then the Object#=== method is used and the evaluation asks if the two are the same object, which is not the case here.
"" == true # => false
This is the same as above.
Esse's answer is correct in showing that all objects other than false and nil are true.
!!false # => false
!!nil # => false
The == is a method just like any other method in Ruby that a class uses to decide whether the passed parameter (the parameter on the right side) is equal to its object or not, just like you can define your own == method for your classes. In fact you could even modify the way == methods works for any Ruby basic object such as Fixnum if you wish.
So when you say 1 == true what you are actually saying is 1.==(true) in which case the class Fixnum doesn't like to consider the passed parameter true to be equal to its object 1.
Now when you say everything in Ruby except nil and false are considered true, the correct statement is that in Ruby only false and nil are falsey and everything else is truthy. So when Ruby has to decide whether a value or object count as or evaluates as true (such as in an if statement: if ('test')), it determines whether it is truthy or falsey, but not whether (object).==(true) returns true or false

Is there a simple way to evaluate a value to true/false without using an expression?

Is there a simple way in Ruby to get a true/false value from something without explicitly evaluating it to true or false
e.g. how would one more succinctly express
class User
def completed_initialization?
initialization_completed == 1 ? true : false
end
end
is there some way to do something along the lines of
initialization_completed.true?
There's obviously not much in it but since I'm in the zen garden of Ruby I might as well embrace it
EDIT (I've updated the example)
This question was extremely badly phrased as was very gently pointed out by #Sergio Tulentsev. The original example (below) does of course evaluate directly to a boolean. I'm still struggling to find an example of what I mean however Sergio's double-negative was in fact exactly what I was looking for.
Original example
class User
def top_responder
responses.count > 10 ? true : false
end
end
> operator already returns boolean value. So it can be just
def top_responder
responses.count > 10
end
To convert arbitrary values to booleans, I offer you this little double-negation trick.
t = 'foo'
!!t # => true
t = 1
!!t # => true
t = 0
!!t # => true
t = nil
!!t # => false
The first negation "casts" value to boolean and inverts it. That is, it will return true for nil / false and false for everything else. We need another negation to make it produce "normal" values.

What does !! mean in ruby?

Just wondering what !! is in 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.
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
! 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.
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
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
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?
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.
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?

Resources