This content has been automatically translated from Ukrainian.
In Ruby, there are several ways to compare. They may seem similar at first glance, but they work quite differently.
== (value equality check)
- Checks if the objects have the same content.
- Often overridden in classes (String, Array, Hash) to compare values rather than identity.
a = "hello" b = "hello" a == b # => true a.equal?(b) # => false
== asks: "Do these objects have the same content?"
equal? (object identity check)
- Checks if this is the same object in memory.
- Not overridden in classes, always compares object ids.
a = "hello" b = "hello" c = a a.equal?(b) # => false a.equal?(c) # => true
Here, to understand all of this, you need to know what an object is in Ruby.
eql? (strict equality check for hashes and numbers)
- Checks value and type.
- Mainly used in hashes for keys.
1 == 1.0 # => true 1.eql?(1.0) # => false, because different classes (Integer vs Float)
eql? is stricter than ==.
=== (case-match operator)
- Used primarily in the case construct (we'll discuss this below).
- Behaves differently for different classes:
- For classes (String, Integer) - checks if the object belongs to the class (is_a?).
- In regular expressions - checks if the string matches the pattern.
- In Range - checks if the object is within the range.
case 5 when 1..10 "In range" # => "In range" end String === "hello" # => true /ell/ === "hello" # => true
Let's take a closer look at the example with case. How does case … when work in Ruby?
Syntax:
case object when pattern1 code1 when pattern2 code2 else default_code end
What happens under the hood
Ruby does something like this:
if pattern1 === object code1 elsif pattern2 === object code2 else default_code end
So when automatically uses === to compare with the case value.
Next, examples for different types
Range
case 5 when 1..10 "In range" else "Out of range" end # => "In range"
It works as if Ruby executes (this is pseudocode):
(1..10) === 5 # => true
But it's important to note that using === on numbers or other types does not necessarily work the same way:
10 === (1..20) # => false 10 == (1..20) # => false (1..20) == 10 # => false
Here, Range#=== checks if the number is within the range.
Class
case "hello" when String "It's a string" when Integer "It's a number" end # => "It's a string"
Ruby executes:
String === "hello" # => true Integer === "hello" # => false
For classes, === is shorthand for obj.is_a?(Class).
c) Regular expression
case "hello" when /ell/ "Match with pattern" else "No match" end # => "Match with pattern"
Under the hood:
/ell/ === "hello" # => true
For Regexp, === checks if the string matches the pattern.
We have slightly deviated from the topic of === and moved to case (because === is under the hood). Such a simple operator, but it does different things.
To remember more easily:
- case x; when y - this is not x == y, but y === x.
- === works differently depending on the type of y:
- Class -> is_a?
- Range -> include?
- Regexp -> =~ (string match)
This allows for very flexible condition writing.
Like it?React
🧵
This post doesn't have any additions from the author yet.