return / Implicit Return Value (Ruby)
In Ruby, omitting return causes the value of the last evaluated expression in a method to become the return value automatically. Mixing explicit return with implicit return values produces readable code.
Syntax
# Explicitly return a value. def method_name return value end # Implicit return value (the last expression is returned automatically). def method_name value end # Return multiple values as an array. def method_name return value1, value2, value3 end # Early return (guard clause): return immediately when a condition is not met. def method_name(arg) return if condition # main logic end
Syntax Reference
| Syntax | Description |
|---|---|
| return value | Exits the method immediately and returns the specified value. |
| return | Returns nil when no value is specified. |
| return value1, value2 | Returns multiple values packed into an array. |
| Implicit return | When return is omitted, the value of the last evaluated expression becomes the return value. |
| Early return | Checks preconditions at the top of a method and returns immediately if they are not met. Also called a guard clause. |
Sample Code
Comparing explicit return with implicit return values.
return_basic.rb
def greet_explicit(name)
return "Hello, #{name}!"
end
def greet_implicit(name)
"Hello, #{name}!"
end
puts greet_explicit("Shinji")
puts greet_implicit("Rei")
def square(n)
n * n
end
puts square(7)
ruby return_basic.rb Hello, Shinji! Hello, Rei! 49
Returning multiple values as an array.
return_multiple.rb
def pilot_info(name, sync_rate)
return name, sync_rate
end
def unit_info(pilot, unit)
[pilot, unit]
end
name, rate = pilot_info("Shinji Ikari", 400)
puts "Pilot: #{name}, Sync rate: #{rate}%"
pilot, unit = unit_info("Asuka Langley", "Unit-02")
puts "#{pilot} -> #{unit}"
result = pilot_info("Rei Ayanami", 300)
puts result.inspect
ruby return_multiple.rb Pilot: Shinji Ikari, Sync rate: 400% Asuka Langley -> Unit-02 ["Rei Ayanami", 300]
Using early return (guard clauses) to consolidate condition checks at the top of a method.
return_guard.rb
def launch_unit_nested(pilot, sync_rate)
if pilot
if sync_rate >= 40
"#{pilot} launching. Sync rate: #{sync_rate}%"
else
"Sync rate too low."
end
else
"No pilot assigned."
end
end
def launch_unit(pilot, sync_rate)
return "No pilot assigned." unless pilot
return "Sync rate too low." if sync_rate < 40
"#{pilot} launching. Sync rate: #{sync_rate}%"
end
puts launch_unit(nil, 80)
puts launch_unit("Misato Katsuragi", 20)
puts launch_unit("Shinji Ikari", 400)
puts launch_unit("Kaworu Nagisa", 99)
ruby return_guard.rb No pilot assigned. Sync rate too low. Shinji Ikari launching. Sync rate: 400% Kaworu Nagisa launching. Sync rate: 99%
Using the implicit return value of a conditional expression directly as the method's return value.
return_implicit_cond.rb
def classify_pilot(sync_rate)
if sync_rate >= 300
"Ace Pilot"
elsif sync_rate >= 100
"Standard Pilot"
else
"Needs training"
end
end
pilots = [
["Shinji Ikari", 400],
["Rei Ayanami", 300],
["Asuka Langley", 180],
["Kaworu Nagisa", 99],
]
pilots.each do |name, rate|
rank = classify_pilot(rate)
puts "#{name} (#{rate}%): #{rank}"
end
ruby return_implicit_cond.rb Shinji Ikari (400%): Ace Pilot Rei Ayanami (300%): Ace Pilot Asuka Langley (180%): Standard Pilot Kaworu Nagisa (99%): Needs training
Notes
In Ruby, omitting return still returns the value of the last expression in the method. This is called an implicit return value and is widely used as a concise Ruby idiom. When returning multiple values, writing return value1, value2 packs them into an array.
Early return (guard clause) checks preconditions at the top of a method and returns immediately if they are not satisfied. Using guard clauses reduces nested conditions and allows the main logic to be written flat, which improves readability. Guard clauses use the form return value if condition or return value unless condition.
Both explicit return and implicit return values are correct. Ruby style guides show a pattern of using implicit return by default and reserving explicit return for early returns only — this style is commonly seen in Ruby codebases.
Common Mistakes
Mistake 1: Method ending with puts, making the return value nil
puts always returns nil. When the last expression in a method is puts, the implicit return value is also nil. If the caller tries to treat the result as a string, unexpected behavior occurs.
ng_return_puts.rb
def status(name)
puts "#{name}'s status: on mission"
end
result = status("Shinji Ikari")
puts result.upcase
ruby ng_return_puts.rb Shinji Ikari's status: on mission ng_return_puts.rb:6:in `<main>': undefined method `upcase' for nil (NoMethodError)
When a method needs to return a string, make the last expression a string. Output should be done by the caller.
ok_return_puts.rb
def status(name)
"#{name}'s status: on mission"
end
result = status("Shinji Ikari")
puts result.upcase
ruby ok_return_puts.rb SHINJI IKARI'S STATUS: ON MISSION
Mistake 2: return inside a Proc exits the entire method (difference from lambda)
Using return inside a Proc causes the method in which the Proc was defined to return. If you pass a Proc to each or a similar block, this can make the method exit unexpectedly. A lambda's return exits only the lambda itself, so this problem does not occur.
ng_proc_return.rb
def launch_pilots
pilots = ["Shinji Ikari", "Rei Ayanami", "Asuka Langley"]
checker = Proc.new { |name| return "Stopped at #{name}" if name == "Rei Ayanami" }
pilots.each { |p| checker.call(p) }
"All pilots launched"
end
puts launch_pilots
ruby ng_proc_return.rb Stopped at Rei Ayanami
Use next to skip to the next iteration inside a block. Use a lambda's return when you only want to return a value from the lambda.
ok_proc_return.rb
def launch_pilots
pilots = ["Shinji Ikari", "Rei Ayanami", "Asuka Langley"]
checker = ->(name) { return "#{name}: stand by" if name == "Rei Ayanami"; name }
results = pilots.map { |p| checker.call(p) }
results.each { |r| puts r }
"All pilots processed"
end
puts launch_pilots
ruby ok_proc_return.rb Shinji Ikari Rei Ayanami: stand by Asuka Langley All pilots processed
Mistake 3: Return type varies by branch, mixing in nil
When a conditional branch has a path that returns no value, the implicit return value for that path is nil. If the caller assumes a string or number is always returned, NoMethodError or TypeError can occur.
ng_mixed_nil_return.rb
def sync_rate_label(rate)
if rate >= 300
"Ace Pilot"
elsif rate >= 100
"Standard Pilot"
end
# Returns nil when rate < 100.
end
pilots = [["Shinji Ikari", 400], ["Kaworu Nagisa", 99]]
pilots.each do |name, rate|
label = sync_rate_label(rate)
puts "#{name}: #{label.upcase}"
end
ruby ng_mixed_nil_return.rb Shinji Ikari: ACE PILOT ng_mixed_nil_return.rb:13:in `<main>': undefined method `upcase' for nil (NoMethodError)
Add an else clause so that every branch returns a value.
ok_mixed_nil_return.rb
def sync_rate_label(rate)
if rate >= 300
"Ace Pilot"
elsif rate >= 100
"Standard Pilot"
else
"Needs training"
end
end
pilots = [["Shinji Ikari", 400], ["Kaworu Nagisa", 99]]
pilots.each do |name, rate|
label = sync_rate_label(rate)
puts "#{name}: #{label.upcase}"
end
ruby ok_mixed_nil_return.rb Shinji Ikari: ACE PILOT Kaworu Nagisa: NEEDS TRAINING
If you find any errors or copyright issues, please contact us.