emersonthis
emersonthis

Reputation: 33378

Why does Ruby have no !== operator?

Is all equality in Ruby is "strict", analogous to === in PHP? I notice that there is a === operator in Ruby but it does something different.

Upvotes: 3

Views: 665

Answers (4)

akuhn
akuhn

Reputation: 27793

=== is not an equality operator!

Not.

But, what is it?

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 from other languages.

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

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
  # value matches one of a, b, c 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.

I can only guess why there's no !== method but Tadman's intuition seems spot on, === is mostly used indirectly through case when and grep and thus likely didn't seem to need an explicit inverse operator. Most style guides for production code ban the use of === operator anyway.

If you are looking for other equality operators, check .eql? and .equal?

Upvotes: 8

tadman
tadman

Reputation: 211670

Ruby doesn't need a strict ===-type operator because the default comparator == is already quite strict, unlike PHP and others. It's not often the case any sort of conversion is done, so the cases where it is performed stand out as exceptional:

0 == ""
# => false

0 == "0"
# => false

"" == " "
# => false

0 == nil
# => false

0 == 0.0
# => true

In fact when you do use === you're often asking for trouble by being overly specific or inviting unexpected behaviour:

"" === String
# => false

String === ""
# => true

String === Object
# => false

Object === String
# => false

The meaning of === is defined by various classes in different ways to mean things often unrelated to "equality". It's just a shorthand like << is at times. Object === String is actually Object.===(String) which is why it produces different results from String.===(Object). In that case it means "is equal to or a derived class of...".

It's because of this relative rarity that !== doesn't really need to exist in the first place. === is often used only indirectly, as it's the default method for comparing things via a case statement.

Upvotes: 3

Eli Sadoff
Eli Sadoff

Reputation: 7308

Ruby's equality is not strict using ==, at least not like === in JavaScript. Ruby has stricter equality methods, such as eql? and equal?, but the === is not for strict equality. The === method is called the subsumption operator. It's most used implicitly in case statements. This is to say that

case a 
when b ...
when c ...
else ...
end

is equivalent to

if b === a
...
elsif c === a
...
else
...
end

Having said that, !== could exist, but instead it is just left for the user to do !(a === b). Note that === is not commutative as in a === b is not the same as b === a.

Upvotes: 1

emersonthis
emersonthis

Reputation: 33378

Ah... after digging deeper I think I answered my own question. Ruby has .eql? .equal? link

Upvotes: 1

Related Questions