Table of contentsClick link to navigate to the desired location
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 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 cover 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 case example. 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 ordinary use of === 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've strayed a bit from the topic of === and moved to case (because === is under the hood there). 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.
This post doesn't have any additions from the author yet.