Comparison of Classes using the `===` (subsumption operator) - ruby

The fact that TypeOfClass === TypeOfClass is false strikes me as counter-intuitive. In the following code, even if field.class is the same class, it evaluates to false:
case field.class
when Fixnum, Float
field + other_field
when Date, DateTime, Time
field
else
puts 'WAT?'
end
I did this:
Fixnum === Fixnum # => false
Class === Class # => true
I found another thread:
Integer === 3 # => true
Fixnum === 3 # => true
3.class # => Fixnum
I fail to find a reason for this language design. What were the language designers thinking when they baked in this behavior?
I think this is relevant to the answer provided in another thread. It is not unnatural to assume that Numeric === Integer since an Integer is a more specific type of Numeric. But, it isn't:
Numeric === Integer #=> false
I think case statements or === requires caution. If this operator is what we think it is , then, a Numeric should be a Numeric, an Integer should be a Numeric, etc.
Does anyone have an explanation of why this feature doesn't extend to classes? It seems like it would be easy enough to return true if the compared class is a member of the class' ancestors.
Based on an answer submitted below, the code was originally classifying Time (as extended by ActiveSupport:CoreExtensions::Integer::Time and ActiveSupport:CoreExtensions::Float::Time):
Timeframe = Struct.new(:from, :to) do
def end_date
case self.to
when Fixnum, Float
self.from + self.to
when Date, DateTime, Time
self.to
else
raise('InvalidType')
end
end
end
and in the console, I get:
tf = Timeframe.new(Time.now, 5.months)
# => #<struct Timeframe from=Tue Dec 10 11:34:34 -0500 2013, to=5 months>
tf.end_date
# => RuntimeError: InvalidType
# from timeframe.rb:89:in `end_date'

I do not really see the problem here. For classes, the case equality operator asks whether the left hand argument is an instance of the class (or any subclass). So Fixnum === Fixnum really asks: "Is the Fixnum class itself a subclass of Fixnum?" No it is not.
Is the class Class itself a class? Class === Class, yes it is.
The point of the operator is that you should not need to go look for the class. What is wrong with using the case statement without the .class method in the beginning?
case field
when Fixnum, Float
field + other_field
when Date, DateTime, Time
field
else
puts 'WAT?'
end
If you have a more complex example you can write your own lambdas to make the case statement easier:
field_is_number = -> x {[Fixnum, Float].include? x.class}
field_is_time = -> x {[Date, DateTime, Time].include? x.class}
case field.class
when field_is_number
field + other_field
when field_is_time
field
else
puts 'WAT?'
end

That's Module#=== and its intended behavior:
mod === obj → true or false
Case Equality—Returns true if anObject is an instance of mod or one of
mod’s descendants. Of limited use for modules, but can be used in case
statements to classify objects by class.
It simply returns obj.kind_of? mod:
Fixnum === Fixnum #=> false
Fixnum.kind_of? Fixnum #=> false
Class === Class #=> true
Class.kind_of? Class #=> true
String === "foo" #=> true
"foo".kind_of? String #=> true
3 is both, an Integer and a Fixnum because of its class hierarchy:
3.kind_of? Integer #=> true
3.kind_of? Fixnum #=> true
3.class.ancestors #=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
Numeric is not an Integer, it's a Class:
Numeric.kind_of? Integer #=> false
Numeric.kind_of? Class #=> true
But 3, (2/3) and 1.23 are all Numeric:
3.kind_of? Numeric #=> true
Rational(2, 3).kind_of? Numeric #=> true
1.23.kind_of? Numeric #=> true
Bottom line: for case statements, just use case obj instead of case obj.class.
Update
You are getting this error because 5.months doesn't return an Integer, but a ActiveSupport::Duration:
Integer === 5.months #=> false
ActiveSupport::Duration === 5.months #=> true
Calling your method with 5.months.to_i or adding ActiveSupport::Duration to your classes should fix it.

If one of the operands is a class, it is checking whether the second one is this class instance. If they are both classes it will return false unless at least one of them is Class.
Note that Class is both a class and an instance of itself - it's probably biggest ruby weird TBH, but it makes perfect sense.
The reason I would vote for keeping this logic is that we can write those nice case statements without adding .class to objects.
Summary:
ClassName === object <=> object.kind_of? ClassName
However, if you really want to override this use:
class Class
def ===(object)
return object == self if object.is_a? Class
super
end
end

Related

Creating a Special Integer

I want to define a constant FOO in the namespace of Integer that is similar to Float::NAN in Float, which is itself an instance of Float. It will be used somewhat similar to symbols, i.e., to mark a special case (of an integer). I don't need it to be used in calculation, but I need it to have the following properties:
Its class must be Integer or a subclass of Integer, and it must behave so to methods related to class:
Integer::FOO.kind_of?(Integer) # => true
Optionally (if the class is Integer):
Integer::FOO.class # => Integer
Integer === Integer::FOO # => true
Integer::FOO.instance_of?(Integer) # => true
It must be distinct from (ideally all) other integers:
Integer::FOO == 0 # => false
Ideally, I want it distinct from any other integer, but if that is not possible, I can live with a dirty hack that, say makes Integer::FOO be identical to the largest or the smallest integer, which are the least likely to hit any random given integer.
What is the best way to go about this?
Ruby's metaprogramming methods make it easy to twist a generic object into the shape you desire:
class Integer
FOO = Object.new
end
Integer::FOO.define_singleton_method(:kind_of?) do |klass|
Integer.ancestors.include? klass
end
Integer::FOO.define_singleton_method(:class) do
Integer
end
Integer::FOO.define_singleton_method(:instance_of?) do |klass|
klass == Integer
end
oldteq = Integer.method(:===)
Integer.define_singleton_method(:===) do |obj|
obj == Integer::FOO ? true : oldteq.call(obj)
end
Integer::FOO.kind_of? Integer
# true
Integer::FOO.class
# Integer
Integer === Integer::FOO
# true
Integer::FOO.instance_of? Integer
# true
Integer::FOO == 0
# false
The tricky part is making sure you cover all of the use cases. My code handles all of the requirements you listed but I have no idea what kind of weird side effects such a strange object would create.
Another option is to create a true Integer instance using a C extension:
// IntegerFoo.c
#include "ruby.h"
void Init_integer_foo() {
// this should be the equivalent of "Integer.new"
NEWOBJ_OF(obj, struct RObject, rb_cInteger, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 0));
rb_define_const(rb_cInteger, "FOO", (VALUE)obj);
}
# extconf.rb
require 'mkmf'
dir_config('integer_foo')
create_makefile('integer_foo')
After building the extension ...
$ ruby extconf.rb
creating Makefile
$ make
compiling IntegerFoo.c
linking shared-object integer_foo.bundle
... the new constant can be used in Ruby and it seems to work as expected:
require './integer_foo'
Integer::FOO #=> #<Integer:0x007fe40c02c040>
Integer::FOO.kind_of? Integer #=> true
Integer::FOO.class #=> Integer
Integer === Integer::FOO #=> true
Integer::FOO.instance_of? Integer #=> true
Integer::FOO == 0 #=> false
I think the hack of picking an number you won't encounter anywhere is likely to be the cleanest solution.
class Integer
FOO = (1..100).map{rand(10)}.join.to_i
end
Satisfies all of your criteria, aside from being equal to a random 100-digit number.
You can still introduce some custom behavior with this trick:
# Allow singleton methods on Bignums
class Bignum
def singleton_method_added(meth)
true
end
end
class Integer
FOO = (1..100).map{rand(10)}.join.to_i
FOO.define_singleton_method(:to_s){'FOO'}
end
#Disallow singleton methods on Bignums once we've added all we're going to
class Bignum
def singleton_method_added(meth)
super
end
end
p Integer::FOO # FOO
1111111111111111111111111111111.define_singleton_method(:will_raise){}

What's the difference between equal?, eql?, ===, and ==?

I am trying to understand the difference between these four methods. I know by default that == calls the method equal? which returns true when both operands refer to exactly the same object.
=== by default also calls == which calls equal?... okay, so if all these three methods are not overridden, then I guess
===, == and equal? do exactly the same thing?
Now comes eql?. What does this do (by default)? Does it make a call to the operand's hash/id?
Why does Ruby have so many equality signs? Are they supposed to differ in semantics?
I'm going to heavily quote the Object documentation here, because I think it has some great explanations. I encourage you to read it, and also the documentation for these methods as they're overridden in other classes, like String.
Side note: if you want to try these out for yourself on different objects, use something like this:
class Object
def all_equals(o)
ops = [:==, :===, :eql?, :equal?]
Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })]
end
end
"a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false}
== — generic "equality"
At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.
This is the most common comparison, and thus the most fundamental place where you (as the author of a class) get to decide if two objects are "equal" or not.
=== — case equality
For class Object, effectively the same as calling #==, but typically overridden by descendants to provide meaningful semantics in case statements.
This is incredibly useful. Examples of things which have interesting === implementations:
Range
Regex
Proc (in Ruby 1.9)
So you can do things like:
case some_object
when /a regex/
# The regex matches
when 2..4
# some_object is in the range 2..4
when lambda {|x| some_crazy_custom_predicate }
# the lambda returned true
end
See my answer here for a neat example of how case+Regex can make code a lot cleaner. And of course, by providing your own === implementation, you can get custom case semantics.
eql? — Hash equality
The eql? method returns true if obj and other refer to the same hash key. This is used by Hash to test members for equality. For objects of class Object, eql? is synonymous with ==. Subclasses normally continue this tradition by aliasing eql? to their overridden == method, but there are exceptions. Numeric types, for example, perform type conversion across ==, but not across eql?, so:
1 == 1.0 #=> true
1.eql? 1.0 #=> false
So you're free to override this for your own uses, or you can override == and use alias :eql? :== so the two methods behave the same way.
equal? — identity comparison
Unlike ==, the equal? method should never be overridden by subclasses: it is used to determine object identity (that is, a.equal?(b) iff a is the same object as b).
This is effectively pointer comparison.
I love jtbandes answer, but since it is pretty long, I will add my own compact answer:
==, ===, eql?, equal?
are 4 comparators, ie. 4 ways to compare 2 objects, in Ruby.
As, in Ruby, all comparators (and most operators) are actually method-calls, you can change, overwrite, and define the semantics of these comparing methods yourself. However, it is important to understand, when Ruby's internal language constructs use which comparator:
== (value comparison)
Ruby uses :== everywhere to compare the values of 2 objects, eg. Hash-values:
{a: 'z'} == {a: 'Z'} # => false
{a: 1} == {a: 1.0} # => true
=== (case comparison)
Ruby uses :=== in case/when constructs. The following code snippets are logically identical:
case foo
when bar; p 'do something'
end
if bar === foo
p 'do something'
end
eql? (Hash-key comparison)
Ruby uses :eql? (in combination with the method hash) to compare Hash-keys. In most classes :eql? is identical with :==.
Knowledge about :eql? is only important, when you want to create your own special classes:
class Equ
attr_accessor :val
alias_method :initialize, :val=
def hash() self.val % 2 end
def eql?(other) self.hash == other.hash end
end
h = {Equ.new(3) => 3, Equ.new(8) => 8, Equ.new(15) => 15} #3 entries, but 2 are :eql?
h.size # => 2
h[Equ.new(27)] # => 15
Note: The commonly used Ruby-class Set also relies on Hash-key-comparison.
equal? (object identity comparison)
Ruby uses :equal? to check if two objects are identical. This method (of class BasicObject) is not supposed to be overwritten.
obj = obj2 = 'a'
obj.equal? obj2 # => true
obj.equal? obj.dup # => false
Equality operators: == and !=
The == operator, also known as equality or double equal, will return true if both objects are equal and false if they are not.
"koan" == "koan" # Output: => true
The != operator, also known as inequality, is the opposite of ==. It will return true if both objects are not equal and false if they are equal.
"koan" != "discursive thought" # Output: => true
Note that two arrays with the same elements in a different order are not equal, uppercase and lowercase versions of the same letter are not equal and so on.
When comparing numbers of different types (e.g., integer and float), if their numeric value is the same, == will return true.
2 == 2.0 # Output: => true
equal?
Unlike the == operator which tests if both operands are equal, the equal method checks if the two operands refer to the same object. This is the strictest form of equality in Ruby.
Example:
a = "zen"
b = "zen"
a.object_id # Output: => 20139460
b.object_id # Output :=> 19972120
a.equal? b # Output: => false
In the example above, we have two strings with the same value. However, they are two distinct objects, with different object IDs. Hence, the equal? method will return false.
Let's try again, only this time b will be a reference to a. Notice that the object ID is the same for both variables, as they point to the same object.
a = "zen"
b = a
a.object_id # Output: => 18637360
b.object_id # Output: => 18637360
a.equal? b # Output: => true
eql?
In the Hash class, the eql? method it is used to test keys for equality. Some background is required to explain this. In the general context of computing, a hash function takes a string (or a file) of any size and generates a string or integer of fixed size called hashcode, commonly referred to as only hash. Some commonly used hashcode types are MD5, SHA-1, and CRC. They are used in encryption algorithms, database indexing, file integrity checking, etc. Some programming languages, such as Ruby, provide a collection type called hash table. Hash tables are dictionary-like collections which store data in pairs, consisting of unique keys and their corresponding values. Under the hood, those keys are stored as hashcodes. Hash tables are commonly referred to as just hashes. Notice how the word hashcan refer to a hashcode or to a hash table. In the context of Ruby programming, the word hash almost always refers to the dictionary-like collection.
Ruby provides a built-in method called hash for generating hashcodes. In the example below, it takes a string and returns a hashcode. Notice how strings with the same value always have the same hashcode, even though they are distinct objects (with different object IDs).
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
The hash method is implemented in the Kernel module, included in the Object class, which is the default root of all Ruby objects. Some classes such as Symbol and Integer use the default implementation, others like String and Hash provide their own implementations.
Symbol.instance_method(:hash).owner # Output: => Kernel
Integer.instance_method(:hash).owner # Output: => Kernel
String.instance_method(:hash).owner # Output: => String
Hash.instance_method(:hash).owner # Output: => Hash
In Ruby, when we store something in a hash (collection), the object provided as a key (e.g., string or symbol) is converted into and stored as a hashcode. Later, when retrieving an element from the hash (collection), we provide an object as a key, which is converted into a hashcode and compared to the existing keys. If there is a match, the value of the corresponding item is returned. The comparison is made using the eql? method under the hood.
"zen".eql? "zen" # Output: => true
# is the same as
"zen".hash == "zen".hash # Output: => true
In most cases, the eql? method behaves similarly to the == method. However, there are a few exceptions. For instance, eql? does not perform implicit type conversion when comparing an integer to a float.
2 == 2.0 # Output: => true
2.eql? 2.0 # Output: => false
2.hash == 2.0.hash # Output: => false
Case equality operator: ===
Many of Ruby's built-in classes, such as String, Range, and Regexp, provide their own implementations of the === operator, also known as case-equality, triple equals or threequals. Because it's implemented differently in each class, it will behave differently depending on the type of object it was called on. Generally, it returns true if the object on the right "belongs to" or "is a member of" the object on the left. For instance, it can be used to test if an object is an instance of a class (or one of its subclasses).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
The same result can be achieved with other methods which are probably best suited for the job. It's usually better to write code that is easy to read by being as explicit as possible, without sacrificing efficiency and conciseness.
2.is_a? Integer # Output: => true
2.kind_of? Integer # Output: => true
2.instance_of? Integer # Output: => false
Notice the last example returned false because integers such as 2 are instances of the Fixnum class, which is a subclass of the Integer class. The ===, is_a? and instance_of? methods return true if the object is an instance of the given class or any subclasses. The instance_of method is stricter and only returns true if the object is an instance of that exact class, not a subclass.
The is_a? and kind_of? methods are implemented in the Kernel module, which is mixed in by the Object class. Both are aliases to the same method. Let's verify:
Kernel.instance_method(:kind_of?) == Kernel.instance_method(:is_a?) # Output: => true
Range Implementation of ===
When the === operator is called on a range object, it returns true if the value on the right falls within the range on the left.
(1..4) === 3 # Output: => true
(1..4) === 2.345 # Output: => true
(1..4) === 6 # Output: => false
("a".."d") === "c" # Output: => true
("a".."d") === "e" # Output: => false
Remember that the === operator invokes the === method of the left-hand object. So (1..4) === 3 is equivalent to (1..4).=== 3. In other words, the class of the left-hand operand will define which implementation of the === method will be called, so the operand positions are not interchangeable.
Regexp Implementation of ===
Returns true if the string on the right matches the regular expression on the left.
/zen/ === "practice zazen today" # Output: => true
# is the same as
"practice zazen today"=~ /zen/
Implicit usage of the === operator on case/when statements
This operator is also used under the hood on case/when statements. That is its most common use.
minutes = 15
case minutes
when 10..20
puts "match"
else
puts "no match"
end
# Output: match
In the example above, if Ruby had implicitly used the double equal operator (==), the range 10..20 would not be considered equal to an integer such as 15. They match because the triple equal operator (===) is implicitly used in all case/when statements. The code in the example above is equivalent to:
if (10..20) === minutes
puts "match"
else
puts "no match"
end
Pattern matching operators: =~ and !~
The =~ (equal-tilde) and !~ (bang-tilde) operators are used to match strings and symbols against regex patterns.
The implementation of the =~ method in the String and Symbol classes expects a regular expression (an instance of the Regexp class) as an argument.
"practice zazen" =~ /zen/ # Output: => 11
"practice zazen" =~ /discursive thought/ # Output: => nil
:zazen =~ /zen/ # Output: => 2
:zazen =~ /discursive thought/ # Output: => nil
The implementation in the Regexp class expects a string or a symbol as an argument.
/zen/ =~ "practice zazen" # Output: => 11
/zen/ =~ "discursive thought" # Output: => nil
In all implementations, when the string or symbol matches the Regexp pattern, it returns an integer which is the position (index) of the match. If there is no match, it returns nil. Remember that, in Ruby, any integer value is "truthy" and nil is "falsy", so the =~ operator can be used in if statements and ternary operators.
puts "yes" if "zazen" =~ /zen/ # Output: => yes
"zazen" =~ /zen/?"yes":"no" # Output: => yes
Pattern-matching operators are also useful for writing shorter if statements. Example:
if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin"
true
end
Can be rewritten as:
if meditation_type =~ /^(zazen|shikantaza|kinhin)$/
true
end
The !~ operator is the opposite of =~, it returns true when there is no match and false if there is a match.
More info is available at this blog post.
I would like to expand on the === operator.
=== is not an equality operator!
Not.
Let's get that point really across.
You might be familiar with === as an equality operator in Javascript and PHP, but this just not an equality operator in Ruby and has fundamentally different semantics.
So what does === do?
=== is the pattern matching operator!
=== matches regular expressions
=== checks range membership
=== checks being instance of a class
=== calls lambda expressions
=== sometimes checks equality, but mostly it does not
So how does this madness make sense?
Enumerable#grep uses === internally
case when statements use === internally
Fun fact, rescue uses === internally
That is why you can use regular expressions and classes and ranges and even lambda expressions in a case when statement.
Some examples
case value
when /regexp/
# value matches this regexp
when 4..10
# value is in range
when MyClass
# value is an instance of class
when ->(value) { ... }
# lambda expression returns true
when a, b, c, d
# value matches one of a through d with `===`
when *array
# value matches an element in array with `===`
when x
# values is equal to x unless x is one of the above
end
All these example work with pattern === value too, as well as with grep method.
arr = ['the', 'quick', 'brown', 'fox', 1, 1, 2, 3, 5, 8, 13]
arr.grep(/[qx]/)
# => ["quick", "fox"]
arr.grep(4..10)
# => [5, 8]
arr.grep(String)
# => ["the", "quick", "brown", "fox"]
arr.grep(1)
# => [1, 1]
Ruby exposes several different methods for handling equality:
a.equal?(b) # object identity - a and b refer to the same object
a.eql?(b) # object equivalence - a and b have the same value
a == b # object equivalence - a and b have the same value with type conversion.
Continue reading by clicking the link below, it gave me a clear summarized understanding.
https://www.relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/equality-matchers
Hope it helps others.
=== #---case equality
== #--- generic equality
both works similar but "===" even do case statements
"test" == "test" #=> true
"test" === "test" #=> true
here the difference
String === "test" #=> true
String == "test" #=> false
.eql? - This operator returns true if the receiver and argument have both the same type and equal values.
for example - 10.eql?(10.0) is false.
=== - it will test equality in case statement.
for example - (1...10) === 1 is true
== - This operator checks whether the two given operands are equal or not. If equals, it returns TRUE, Otherwise it returns FALSE.
for example - (1...10) == 1 is false
for more example click here
I wrote a simple test for all the above.
def eq(a, b)
puts "#{[a, '==', b]} : #{a == b}"
puts "#{[a, '===', b]} : #{a === b}"
puts "#{[a, '.eql?', b]} : #{a.eql?(b)}"
puts "#{[a, '.equal?', b]} : #{a.equal?(b)}"
end
eq("all", "all")
eq(:all, :all)
eq(Object.new, Object.new)
eq(3, 3)
eq(1, 1.0)

Checking if a variable is an integer

Does Rails 3 or Ruby have a built-in way to check if a variable is an integer?
For example,
1.is_an_int #=> true
"dadadad#asdasd.net".is_an_int #=> false?
You can use the is_a? method
>> 1.is_a? Integer
=> true
>> "dadadad#asdasd.net".is_a? Integer
=> false
>> nil.is_a? Integer
=> false
If you want to know whether an object is an Integer or something which can meaningfully be converted to an Integer (NOT including things like "hello", which to_i will convert to 0):
result = Integer(obj) rescue false
Use a regular expression on a string:
def is_numeric?(obj)
obj.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end
If you want to check if a variable is of certain type, you can simply use kind_of?:
1.kind_of? Integer #true
(1.5).kind_of? Float #true
is_numeric? "545" #true
is_numeric? "2aa" #false
If you're uncertain of the type of the variable (it could be a string of number characters), say it was a credit card number passed into the params, so it would originally be a string but you want to make sure it doesn't have any letter characters in it, I would use this method:
def is_number?(obj)
obj.to_s == obj.to_i.to_s
end
is_number? "123fh" # false
is_number? "12345" # true
#Benny points out an oversight of this method, keep this in mind:
is_number? "01" # false. oops!
There's var.is_a? Class (in your case: var.is_a? Integer); that might fit the bill. Or there's Integer(var), where it'll throw an exception if it can't parse it.
You can use triple equal.
if Integer === 21
puts "21 is Integer"
end
A more "duck typing" way is to use respond_to? this way "integer-like" or "string-like" classes can also be used
if(s.respond_to?(:match) && s.match(".com")){
puts "It's a .com"
else
puts "It's not"
end
In case you don't need to convert zero values, I find the methods to_i and to_f to be extremely useful since they will convert the string to either a zero value (if not convertible or zero) or the actual Integer or Float value.
"0014.56".to_i # => 14
"0014.56".to_f # => 14.56
"0.0".to_f # => 0.0
"not_an_int".to_f # 0
"not_a_float".to_f # 0.0
"0014.56".to_f ? "I'm a float" : "I'm not a float or the 0.0 float"
# => I'm a float
"not a float" ? "I'm a float" : "I'm not a float or the 0.0 float"
# => "I'm not a float or the 0.0 float"
EDIT2 : be careful, the 0 integer value is not falsey it's truthy (!!0 #=> true) (thanks #prettycoder)
EDIT
Ah just found out about the dark cases... seems to only happen if the number is in first position though
"12blah".to_i => 12
To capitalize on the answer of Alex D, using refinements:
module CoreExtensions
module Integerable
refine String do
def integer?
Integer(self)
rescue ArgumentError
false
else
true
end
end
end
end
Later, in you class:
require 'core_ext/string/integerable'
class MyClass
using CoreExtensions::Integerable
def method
'my_string'.integer?
end
end
I have had a similar issue before trying to determine if something is a string or any sort of number whatsoever. I have tried using a regular expression, but that is not reliable for my use case. Instead, you can check the variable's class to see if it is a descendant of the Numeric class.
if column.class < Numeric
number_to_currency(column)
else
column.html_safe
end
In this situation, you could also substitute for any of the Numeric descendants: BigDecimal, Date::Infinity, Integer, Fixnum, Float, Bignum, Rational, Complex
Basically, an integer n is a power of three, if there exists an integer x such that n == 3x.
So to verify that you can use this functions
def is_power_of_three(n)
return false unless n.positive?
n == 3**(Math.log10(n)/Math.log10(3)).to_f.round(2)
end
Probably you are looking for something like this:
Accept "2.0 or 2.0 as an INT but reject 2.1 and "2.1"
num = 2.0
if num.is_a? String num = Float(num) rescue false end
new_num = Integer(num) rescue false
puts num
puts new_num
puts num == new_num

How to check if a Ruby object is a Boolean

I can't seem to check if an object is a boolean easily. Is there something like this in Ruby?
true.is_a?(Boolean)
false.is_a?(Boolean)
Right now I'm doing this and would like to shorten it:
some_var = rand(1) == 1 ? true : false
(some_var.is_a?(TrueClass) || some_var.is_a?(FalseClass))
Simplest way I can think of:
# checking whether foo is a boolean
!!foo == foo
I find this to be concise and self-documenting:
[true, false].include? foo
If using Rails or ActiveSupport, you can even do a direct query using in?
foo.in? [true, false]
Checking against all possible values isn't something I'd recommend for floats, but feasible when there are only two possible values!
There is no Boolean class in Ruby, the only way to check is to do what you're doing (comparing the object against true and false or the class of the object against TrueClass and FalseClass). Can't think of why you would need this functionality though, can you explain? :)
If you really need this functionality however, you can hack it in:
module Boolean; end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end
true.is_a?(Boolean) #=> true
false.is_a?(Boolean) #=> true
As stated above there is no boolean class just TrueClass and FalseClass however you can use any object as the subject of if/unless and everything is true except instances of FalseClass and nil
Boolean tests return an instance of the FalseClass or TrueClass
(1 > 0).class #TrueClass
The following monkeypatch to Object will tell you whether something is an instance of TrueClass or FalseClass
class Object
def boolean?
self.is_a?(TrueClass) || self.is_a?(FalseClass)
end
end
Running some tests with irb gives the following results
?> "String".boolean?
=> false
>> 1.boolean?
=> false
>> Time.now.boolean?
=> false
>> nil.boolean?
=> false
>> true.boolean?
=> true
>> false.boolean?
=> true
>> (1 ==1).boolean?
=> true
>> (1 ==2).boolean?
=> true
If your code can sensibly be written as a case statement, this is pretty decent:
case mybool
when TrueClass, FalseClass
puts "It's a bool!"
else
puts "It's something else!"
end
An object that is a boolean will either have a class of TrueClass or FalseClass so the following one-liner should do the trick
mybool = true
mybool.class == TrueClass || mybool.class == FalseClass
=> true
The following would also give you true/false boolean type check result
mybool = true
[TrueClass, FalseClass].include?(mybool.class)
=> true
So try this out (x == true) ^ (x == false) note you need the parenthesis but this is more beautiful and compact.
It even passes the suggested like "cuak" but not a "cuak"... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)
Note: See that this is so basic that you can use it in other languages too, that doesn't provide a "thing is boolean".
Note 2: Also you can use this to say thing is one of??: "red", "green", "blue" if you add more XORS... or say this thing is one of??: 4, 5, 8, 35.
This gem adds a Boolean class to Ruby with useful methods.
https://github.com/RISCfuture/boolean
Use:
require 'boolean'
Then your
true.is_a?(Boolean)
false.is_a?(Boolean)
will work exactly as you expect.
No. Not like you have your code. There isn't any class named Boolean. Now with all the answers you have you should be able to create one and use it. You do know how to create classes don't you? I only came here because I was just wondering this idea myself. Many people might say "Why? You have to just know how Ruby uses Boolean". Which is why you got the answers you did. So thanks for the question. Food for thought. Why doesn't Ruby have a Boolean class?
NameError: uninitialized constant Boolean
Keep in mind that Objects do not have types. They are classes. Objects have data. So that's why when you say data types it's a bit of a misnomer.
Also try rand 2 because rand 1 seems to always give 0. rand 2 will give 1 or 0
click run a few times here.
https://repl.it/IOPx/7
Although I wouldn't know how to go about making a Boolean class myself. I've experimented with it but...
class Boolean < TrueClass
self
end
true.is_a?(Boolean) # => false
false.is_a?(Boolean) # => false
At least we have that class now but who knows how to get the right 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