Ruby Operators
Operators are symbols or keywords that perform specific operations. Ruby provides a rich set of operators that make code more concise and expressive. This chapter will introduce in detail the various operators in Ruby and how to use them.
🎯 Operator Overview
Operators in Ruby can be divided into the following categories:
- Arithmetic Operators - Perform mathematical operations
- Comparison Operators - Compare values
- Logical Operators - Perform boolean logic operations
- Assignment Operators - Assign values to variables
- Bitwise Operators - Perform bit-level operations
- Range Operators - Create range objects
- Other Operators - Operators for special purposes
➕ Arithmetic Operators
Basic Arithmetic Operators
ruby
# Addition
puts 10 + 5 # 15
puts "Hello" + " " + "World" # Hello World
# Subtraction
puts 10 - 5 # 5
# Multiplication
puts 10 * 5 # 50
puts "Ruby" * 3 # RubyRubyRuby
# Division
puts 10 / 5 # 2
puts 10 / 3 # 3 (integer division)
puts 10.0 / 3 # 3.3333333333333335 (floating point division)
# Modulo (remainder)
puts 10 % 3 # 1
puts 10.5 % 3 # 1.5
# Exponentiation
puts 2 ** 3 # 8
puts 9 ** 0.5 # 3.0 (square root)Unary Operators
ruby
# Positive sign
puts +5 # 5
# Negative sign
puts -5 # -5
puts -(-5) # 5
# Increment/Decrement (Ruby doesn't have ++ and -- operators)
counter = 5
counter += 1 # Equivalent to counter = counter + 1
puts counter # 6
counter -= 1 # Equivalent to counter = counter - 1
puts counter # 5🔄 Comparison Operators
Basic Comparison Operators
ruby
# Equality comparison
puts 5 == 5 # true
puts 5 == "5" # false (different types)
puts 5.eql?("5") # false (strict equality)
puts 5 === 5 # true (equality in case statements)
# Inequality comparison
puts 5 != 3 # true
puts 5 != 5 # false
# Magnitude comparison
puts 5 > 3 # true
puts 5 < 3 # false
puts 5 >= 5 # true
puts 5 <= 3 # false
# String comparison
puts "apple" < "banana" # true (lexicographical)
puts "Apple" < "apple" # true (uppercase letters have smaller ASCII values)Special Comparison Operators
ruby
# Safe comparison operator <=>
result = 5 <=> 3 # 1 (left is greater than right)
result = 5 <=> 5 # 0 (equal)
result = 3 <=> 5 # -1 (left is less than right)
# Application in range checking
case 75
when 90..100
puts "Excellent"
when 80...90
puts "Good"
when 60...80
puts "Pass"
else
puts "Fail"
end
# Output: PassObject Comparison
ruby
# equal? - Check if it's the same object
a = "hello"
b = "hello"
c = a
puts a.equal?(b) # false (different objects)
puts a.equal?(c) # true (same object)
# == - Check if values are equal
puts a == b # true (values are equal)
# eql? - Check if both value and type are equal
puts 1 == 1.0 # true
puts 1.eql?(1.0) # false (different types)🔣 Logical Operators
Boolean Logic Operators
ruby
# And operations (and, &&)
puts true && true # true
puts true && false # false
puts false && true # false
puts false && false # false
# Or operations (or, ||)
puts true || true # true
puts true || false # true
puts false || true # true
puts false || false # false
# Not operations (not, !)
puts !true # false
puts !false # true
puts !!true # true (double negation)Priority Differences
ruby
# && and || have higher priority than and and or
result1 = true || false and false
puts result1 # true (equivalent to (true || false) and false)
result2 = true or false and false
puts result2 # false (equivalent to true or (false and false))
# Recommended to use && and || to avoid confusionShort-Circuit Evaluation
ruby
# && short-circuit: If left is false, don't evaluate right
def expensive_operation
puts "Executing expensive operation"
true
end
false && expensive_operation # Won't output "Executing expensive operation"
# || short-circuit: If left is true, don't evaluate right
true || expensive_operation # Won't output "Executing expensive operation"
# Use short-circuit evaluation to set default values
name = nil
display_name = name || "Anonymous User"
puts display_name # Anonymous User
# Safe navigation
user = nil
user_name = user&.name || "Default Name"
puts user_name # Default Name📝 Assignment Operators
Basic Assignment Operators
ruby
# Simple assignment
x = 10
puts x # 10
# Compound assignment operators
x += 5 # Equivalent to x = x + 5
puts x # 15
x -= 3 # Equivalent to x = x - 3
puts x # 12
x *= 2 # Equivalent to x = x * 2
puts x # 24
x /= 4 # Equivalent to x = x / 4
puts x # 6
x %= 5 # Equivalent to x = x % 5
puts x # 1
x **= 3 # Equivalent to x = x ** 3
puts x # 1Parallel Assignment
ruby
# Basic parallel assignment
a, b = 1, 2
puts "a = #{a}, b = #{b}" # a = 1, b = 2
# Swap variable values
a, b = b, a
puts "a = #{a}, b = #{b}" # a = 2, b = 1
# Array destructuring
first, *rest = [1, 2, 3, 4, 5]
puts "first = #{first}" # first = 1
puts "rest = #{rest}" # rest = [2, 3, 4, 5]
# Ignore certain values
_, second, _ = [10, 20, 30]
puts "second = #{second}" # second = 20Conditional Assignment Operators
ruby
# ||= Conditional assignment (assign only if variable is nil or false)
name = nil
name ||= "Default Name"
puts name # Default Name
name ||= "New Name"
puts name # Default Name (won't change)
# &&= Conditional assignment (assign only if variable is truthy)
value = 10
value &&= value * 2
puts value # 20
value = nil
value &&= value * 2
puts value # nil🔢 Bitwise Operators
Basic Bitwise Operators
ruby
# Bitwise AND (&)
puts 5 & 3 # 1 (101 & 011 = 001)
# Bitwise OR (|)
puts 5 | 3 # 7 (101 | 011 = 111)
# Bitwise XOR (^)
puts 5 ^ 3 # 6 (101 ^ 011 = 110)
# Bitwise NOT (~)
puts ~5 # -6 (two's complement)
# Left shift (<<)
puts 5 << 1 # 10 (101 << 1 = 1010)
puts 5 << 2 # 20 (101 << 2 = 10100)
# Right shift (>>)
puts 20 >> 1 # 10 (10100 >> 1 = 1010)
puts 20 >> 2 # 5 (10100 >> 2 = 101)Bitwise Operations Application Example
ruby
# Permission check example
class Permissions
READ = 1 << 0 # 1 (001)
WRITE = 1 << 1 # 2 (010)
EXECUTE = 1 << 2 # 4 (100)
def initialize(permissions = 0)
@permissions = permissions
end
def grant(permission)
@permissions |= permission
end
def revoke(permission)
@permissions &= ~permission
end
def has_permission?(permission)
(@permissions & permission) != 0
end
def permissions
perms = []
perms << "Read" if has_permission?(READ)
perms << "Write" if has_permission?(WRITE)
perms << "Execute" if has_permission?(EXECUTE)
perms.empty? ? "No permissions" : perms.join(", ")
end
end
# Use permission system
user_perms = Permissions.new
puts user_perms.permissions # No permissions
user_perms.grant(Permissions::READ)
user_perms.grant(Permissions::WRITE)
puts user_perms.permissions # Read, Write
user_perms.revoke(Permissions::WRITE)
puts user_perms.permissions # Read📏 Range Operators
Range Creation
ruby
# Range including end value (..)
inclusive_range = 1..5
puts inclusive_range.include?(5) # true
puts inclusive_range.to_a # [1, 2, 3, 4, 5]
# Range excluding end value (...)
exclusive_range = 1...5
puts exclusive_range.include?(5) # false
puts exclusive_range.to_a # [1, 2, 3, 4]
# Character ranges
letter_range = 'a'..'e'
puts letter_range.to_a.join(',') # a,b,c,d,eRange Applications
ruby
# Using ranges in case statements
def grade(score)
case score
when 90..100
"Excellent"
when 80...90
"Good"
when 70...80
"Average"
when 60...70
"Pass"
else
"Fail"
end
end
puts grade(95) # Excellent
puts grade(85) # Good
puts grade(75) # Average
# Range iteration
(1..5).each { |n| print "#{n} " } # 1 2 3 4 5
puts
('a'..'e').each { |c| print "#{c} " } # a b c d e
puts🎯 Other Operators
Method Call Operators
ruby
# Dot operator (.)
class Calculator
def add(a, b)
a + b
end
end
calc = Calculator.new
result = calc.add(2, 3)
puts result # 5
# Safe navigation operator (&.)
user = nil
name_length = user&.name&.length # Won't raise NoMethodError
puts name_length # nilArray and Hash Access Operators
ruby
# Array access
arr = [1, 2, 3, 4, 5]
puts arr[0] # 1
puts arr[-1] # 5
puts arr[1..3] # [2, 3, 4]
# Hash access
hash = {name: "Zhang San", age: 25}
puts hash[:name] # Zhang San
puts hash["name"] # nil (key doesn't exist)
# Default value access
scores = Hash.new(0)
scores[:math] = 95
puts scores[:english] # 0 (default value)Regular Expression Operators
ruby
# Match operator (=~)
text = "Hello, Ruby!"
puts text =~ /Ruby/ # 7 (match position)
puts text =~ /python/ # nil (no match)
# Non-match operator (!~)
puts text !~ /Ruby/ # false
puts text !~ /python/ # true
# Access match data
if match_data = "2023-12-25".match(/(\d{4})-(\d{2})-(\d{2})/)
year, month, day = match_data[1], match_data[2], match_data[3]
puts "Year: #{year}, Month: #{month}, Day: #{day}" # Year: 2023, Month: 12, Day: 25
end⚖️ Operator Precedence
Precedence List (from High to Low)
ruby
# 1. ! ~ + - (unary operators)
# 2. ** (exponentiation)
# 3. * / % (multiplication, division, modulo)
# 4. + - (addition, subtraction)
# 5. << >> (bit shift)
# 6. & (bitwise AND)
# 7. | ^ (bitwise OR, XOR)
# 8. > >= < <= (comparison)
# 9. <=> == === != =~ !~ (equality)
# 10. && (logical AND)
# 11. || (logical OR)
# 12. .. ... (range)
# 13. ? : (ternary operator)
# 14. = += -= *= /= %= **= &= |= ^= <<= >>= (assignment)
# 15. not (logical NOT)
# 16. and or (logical operations)
# Example: Understanding precedence
result = 2 + 3 * 4 # 14 (multiplication has higher precedence than addition)
result = (2 + 3) * 4 # 20 (parentheses change precedence)
result = true || false && false # true (&& has higher precedence than ||)
result = true or false and false # false (and/or have lower precedence than ||)Use Parentheses to Clarify Intent
ruby
# Good practice: Use parentheses to clarify operation order
average = (score1 + score2 + score3) / 3
is_valid = (user.active? && user.verified?) || admin?
result = (base_value * multiplier) + adjustment
# Avoid relying on memorizing operator precedence
# bad: is_adult = age >= 18 && has_id && !is_banned
# good: is_adult = (age >= 18) && has_id && (!is_banned)🧪 Operator Overloading
Custom Operators
ruby
class Vector
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
# Overload addition operator
def +(other)
Vector.new(@x + other.x, @y + other.y)
end
# Overload subtraction operator
def -(other)
Vector.new(@x - other.x, @y - other.y)
end
# Overload multiplication operator
def *(scalar)
Vector.new(@x * scalar, @y * scalar)
end
# Overload equality operator
def ==(other)
other.is_a?(Vector) && @x == other.x && @y == other.y
end
# Overload string conversion operator
def to_s
"(#{@x}, #{@y})"
end
end
# Use custom operators
v1 = Vector.new(1, 2)
v2 = Vector.new(3, 4)
v3 = v1 + v2
puts v3 # (4, 6)
v4 = v2 - v1
puts v4 # (2, 2)
v5 = v1 * 3
puts v5 # (3, 6)
puts v1 == Vector.new(1, 2) # true🎯 Operator Best Practices
1. Choose Appropriate Operators
ruby
# Good practice: Use intuitive operators
if user.age >= 18
puts "Adult"
end
# Avoid complex operator combinations
# bad: result = a && b || c && d
# good:
has_permission = a && b
has_exception = c && d
result = has_permission || has_exception2. Use Short-Circuit Evaluation Reasonably
ruby
# Safe conditional checks
def process_user(user)
# Use short-circuit evaluation to avoid nil errors
if user && user.active? && user.profile && user.profile.complete?
# Process user
end
end
# Use safe navigation operator (Ruby 2.3+)
def process_user_modern(user)
if user&.active? && user&.profile&.complete?
# Process user
end
end3. Use Operator Overloading Carefully
ruby
class Money
attr_reader :amount, :currency
def initialize(amount, currency = "USD")
@amount = amount
@currency = currency
end
# Only overload meaningful operators
def +(other)
if other.currency == @currency
Money.new(@amount + other.amount, @currency)
else
# Currency conversion logic
raise "Currency mismatch"
end
end
# Provide clear comparison methods
def >(other)
@amount > other.amount
end
def <(other)
@amount < other.amount
end
def ==(other)
other.is_a?(Money) && @amount == other.amount && @currency == @currency
end
def to_s
"#{@amount} #{@currency}"
end
end
# Use money class
price1 = Money.new(100, "USD")
price2 = Money.new(50, "USD")
total = price1 + price2
puts total # 150 USD🧪 Practice Examples
Mathematical Expression Calculator
ruby
class ExpressionCalculator
def self.evaluate(expression)
# Simple expression parsing (example only)
# In practice, use a more complex parser
# Remove spaces
expression = expression.gsub(/\s+/, "")
# Process multiplication and division
while expression.match?(/[\*\/]/)
expression.sub!(/(\d+(?:\.\d+)?)\*([+-]?\d+(?:\.\d+)?)/) do |match|
$1.to_f * $2.to_f
end
expression.sub!(/(\d+(?:\.\d+)?)\/([+-]?\d+(?:\.\d+)?)/) do |match|
$1.to_f / $2.to_f
end
end
# Process addition and subtraction
while expression.match?(/[+-]/)
expression.sub!(/([+-]?\d+(?:\.\d+)?)\+([+-]?\d+(?:\.\d+)?)/) do |match|
$1.to_f + $2.to_f
end
expression.sub!(/([+-]?\d+(?:\.\d+)?)\-([+-]?\d+(?:\.\d+)?)/) do |match|
$1.to_f - $2.to_f
end
end
expression.to_f
end
end
# Use calculator
puts ExpressionCalculator.evaluate("2 + 3 * 4") # 14.0
puts ExpressionCalculator.evaluate("10 / 2 - 3") # 2.0
puts ExpressionCalculator.evaluate("2.5 * 4 + 1") # 11.0Permission Management System
ruby
class PermissionSystem
# Implement permission management using bitwise operations
PERMISSIONS = {
read: 1 << 0, # 1
write: 1 << 1, # 2
execute: 1 << 2, # 4
delete: 1 << 3, # 8
admin: 1 << 4 # 16
}.freeze
def initialize(initial_permissions = 0)
@permissions = initial_permissions
end
def grant(*permissions)
permissions.each do |perm|
if PERMISSIONS.key?(perm)
@permissions |= PERMISSIONS[perm]
else
raise ArgumentError, "Unknown permission: #{perm}"
end
end
self
end
def revoke(*permissions)
permissions.each do |perm|
if PERMISSIONS.key?(perm)
@permissions &= ~PERMISSIONS[perm]
end
end
self
end
def has_permission?(permission)
PERMISSIONS.key?(permission) && (@permissions & PERMISSIONS[permission]) != 0
end
def can_read?
has_permission?(:read)
end
def can_write?
has_permission?(:write)
end
def can_execute?
has_permission?(:execute)
end
def is_admin?
has_permission?(:admin)
end
def permissions_list
PERMISSIONS.select { |name, value| (@permissions & value) != 0 }.keys
end
def to_s
permissions_list.empty? ? "No permissions" : permissions_list.join(", ")
end
end
# Use permission system
user = PermissionSystem.new
puts user # No permissions
user.grant(:read, :write)
puts user # read, write
puts user.can_read? # true
puts user.can_execute? # false
user.grant(:admin)
puts user # read, write, admin
puts user.is_admin? # true
user.revoke(:write)
puts user # read, admin📚 Next Steps
After mastering Ruby operators, it is recommended to continue learning:
- Ruby Expressions and Statements - Learn more complex expression combinations
- Ruby Control Structures - Master conditional and loop statements
- Ruby Method Definition - Learn how to create and use methods
- Ruby Operator Overloading - Deep dive into custom operators
Continue your Ruby learning journey!