Ruby methods ALWAYS return the evaluated result of the last line of the expression unless an explicit return comes before it. If you wanted to explicitly return a value you can use the return keyword.
Ruby has implicit returns. This means that if a return is the last expression in a path of execution, there's no need for the return keyword.
In Ruby, a method always return exactly one single thing (an object). The returned object can be anything, but a method can only return one thing, and it also always returns something. Every method always returns exactly one object.
You could define method in any order, the order doesn't matter anything.
Old (and "answered") question, but I'll toss in my two cents as an answer.
TL;DR - You don't have to, but it can make your code a lot more clear in some cases.
Though not using an explicit return may be "the Ruby way", it's confusing to programmers working with unfamiliar code, or unfamiliar with this feature of Ruby.
It's a somewhat contrived example, but imagine having a little function like this, which adds one to the number passed, and assigns it to an instance variable.
def plus_one_to_y(x)
@y = x + 1
end
Was this meant to be a function that returned a value, or not? It's really hard to say what the developer meant, as it both assigns the instance variable, AND returns the value assigned as well.
Suppose much later, another programmer (perhaps not that familiar with how Ruby does returns based on last line of code executed) comes along and wants to put in some print statements for logging, and the function becomes this...
def plus_one_to_y(x)
@y = x + 1
puts "In plus_one_to_y"
end
Now the function is broken if anything expects a returned value. If nothing expects a returned value, it's fine. Clearly if somewhere further down the code chain, something calling this is expecting a returned value, it's going to fail as it's not getting back what it expects.
The real question now is this: did anything really expect a returned value? Did this break something or not? Will it break something in the future? Who knows! Only a full code review of all calls will let you know.
So for me at least, the best practice approach is to either be very explicit that you are returning something if it matters, or return nothing at all when it doesn't.
So in the case of our little demo function, assuming we wanted it to return a value, it would be written like this...
def plus_one_to_y(x)
@y = x + 1
puts "In plus_one_to_y"
return @y
end
And it would be very clear to any programmer that it does return a value, and much harder for them to break it without realizing it.
Alternatively, one could write it like this and leave out the return statement...
def plus_one_to_y(x)
@y = x + 1
puts "In plus_one_to_y"
@y
end
But why bother leaving out the word return? Why not just put it in there and make it 100% clear what's happening? It will literally have no impact on your code's ability to perform.
No. Good Ruby style would generally only use an explicit returns for an early return. Ruby is big on code minimalism/implicit magic.
That said, if an explicit return would make things clearer, or easier to read, it won't harm anything.
I personally use the return
keyword to distinguish between what I call functional methods, i.e. methods that are executed primarily for their return value, and procedural methods that are executed primarily for their side-effects. So, methods in which the return value is important, get an extra return
keyword to draw attention to the return value.
I use the same distinction when calling methods: functional methods get parentheses, procedural methods don't.
And last but not least, I also use that distinction with blocks: functional blocks get curly braces, procedural blocks (i.e. blocks that "do" something) get do
/end
.
However, I try not to be religious about it: with blocks, curly braces and do
/end
have different precedence, and rather than adding explicit parentheses to disambiguate an expression, I just switch to the other style. The same goes for method calling: if adding parentheses around the parameter list makes the code more readable, I do it, even if the method in question is procedural in nature.
Actually the important thing is to distinguish between:
Ruby does not have a native way of distinguishing these - which leaves you vulnerable to writing a procedure side_effect()
and another developer deciding to abuse the implicit return value of your procedure (basically treating it as an impure function).
To resolve this, take a leaf out of Scala and Haskell's book and have your procedures explicitly return nil
(aka Unit
or ()
in other languages).
If you follow this, then using explicit return
syntax or not just becomes a matter of personal style.
To further distinguish between functions and procedures:
do/end
()
, whereas when you invoke functions, don'tNote that Jörg W Mittag actually advocated the other way around - avoiding ()
s for procedures - but that's not advisable because you want side effecting method invocations to be clearly distinguishable from variables, particularly when arity is 0. See the Scala style guide on method invocation for details.
The style guide states, that you shouldn't be using return
on your last statement. You can still use it if it's not the last one. This is one of the conventions which the community follows strictly, and so should you if you plan to collaborate with anyone using Ruby.
That being said, the main argument for using explicit return
s is that it's confusing for people coming from other languages.
A common heuristic for method length (excluding getters/setters) in java is one screen. In that case, you might not be seeing the method definition and/or have already forgotten about where you were returning from.
On the other hand, in Ruby it is best to stick to methods less than 10 lines long. Given that, one would wonder why he has to write ~10% more statements, when they are clearly implied.
Since Ruby doesn't have void methods and everything is that much more concise, you are just adding overhead for none of the benefits if you go with explicit return
s.
I agree with Ben Hughes and disagree with Tim Holt, because the question mentions the definitive way Python does it and asks if Ruby has a similar standard.
It does.
This is such a well-known feature of the language that anyone expected to debug a problem in ruby should reasonably be expected to know about it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With