|
| 1 | +# Return |
| 2 | + |
| 3 | +In Ruby, `return` is used to explicitly return a value from a method or block. While Ruby automatically returns the value of the last evaluated expression, `return` allows you to exit the method early and specify the return value. |
| 4 | + |
| 5 | +```ruby |
| 6 | +def greet(name) |
| 7 | + return "Hello, #{name}!" |
| 8 | +end |
| 9 | + |
| 10 | +puts greet("Ruby") # => "Hello, Ruby!" |
| 11 | +``` |
| 12 | + |
| 13 | +When no value is provided to `return`, it returns `nil`: |
| 14 | + |
| 15 | +```ruby |
| 16 | +def early_exit |
| 17 | + return if condition? |
| 18 | + # Code here won't execute if condition? is true |
| 19 | + perform_task |
| 20 | +end |
| 21 | +``` |
| 22 | + |
| 23 | +## Multiple values |
| 24 | + |
| 25 | +Ruby allows returning multiple values, which are automatically converted into an array: |
| 26 | + |
| 27 | +```ruby |
| 28 | +def calculate_stats(numbers) |
| 29 | + sum = numbers.sum |
| 30 | + average = sum / numbers.length.to_f |
| 31 | + return sum, average |
| 32 | +end |
| 33 | + |
| 34 | +total, mean = calculate_stats([1, 2, 3, 4]) |
| 35 | +puts total # => 10 |
| 36 | +puts mean # => 2.5 |
| 37 | +``` |
| 38 | + |
| 39 | +## Early returns |
| 40 | + |
| 41 | +Using `return` for early exits can help make code more readable by reducing nesting: |
| 42 | + |
| 43 | +```ruby |
| 44 | +# Without early return |
| 45 | +def process_user(user) |
| 46 | + if user.active? |
| 47 | + if user.admin? |
| 48 | + perform_admin_task |
| 49 | + else |
| 50 | + perform_regular_task |
| 51 | + end |
| 52 | + else |
| 53 | + puts "Inactive user" |
| 54 | + end |
| 55 | +end |
| 56 | + |
| 57 | +# With early return |
| 58 | +def process_user(user) |
| 59 | + return puts "Inactive user" unless user.active? |
| 60 | + return perform_admin_task if user.admin? |
| 61 | + perform_regular_task |
| 62 | +end |
| 63 | +``` |
| 64 | + |
| 65 | +## Return in blocks |
| 66 | + |
| 67 | +When used inside a block, `return` will exit from the method that yielded to the block: |
| 68 | + |
| 69 | +```ruby |
| 70 | +def process_items |
| 71 | + [1, 2, 3].each do |item| |
| 72 | + return item if item > 1 |
| 73 | + puts "Processing #{item}" |
| 74 | + end |
| 75 | + puts "Done processing" |
| 76 | +end |
| 77 | + |
| 78 | +result = process_items |
| 79 | +# Prints "Processing 1" |
| 80 | +puts result # => 2 |
| 81 | +``` |
| 82 | + |
| 83 | +## Return in procs vs lambdas |
| 84 | + |
| 85 | +The behavior of `return` differs between procs and lambdas: |
| 86 | + |
| 87 | +```ruby |
| 88 | +# In a proc, return exits the enclosing method |
| 89 | +def proc_return |
| 90 | + proc = Proc.new { return "From proc" } |
| 91 | + proc.call |
| 92 | + "From method" # Never reached |
| 93 | +end |
| 94 | + |
| 95 | +puts proc_return # => "From proc" |
| 96 | + |
| 97 | +# In a lambda, return only exits the lambda itself |
| 98 | +def lambda_return |
| 99 | + lambda = -> { return "From lambda" } |
| 100 | + lambda.call |
| 101 | + "From method" # This is reached |
| 102 | +end |
| 103 | + |
| 104 | +puts lambda_return # => "From method" |
| 105 | +``` |
| 106 | + |
| 107 | +When using `return`, consider: |
| 108 | +- Whether an implicit return would be clearer |
| 109 | +- If early returns improve code readability |
| 110 | +- The context (proc vs lambda) when using `return` in blocks |
| 111 | +- Using multiple returns judiciously |
0 commit comments