At my lovely new job, we got a trainer to teach us about Ruby, Rails, and agile methodologies. She was pretty good overall, but one thing she mentioned a few times really got on my nerves: “use implicit returns in Ruby because there is a performance hit when explicitly returning”.
So first, what do we mean by implicit vs. explicit returning in Ruby? Here’s an example: say you have a method that needs to return a number based on a comparison, as is typically useful for
sort and family. (Obviously this is a very contrived use case, and you wouldn’t likely implement a comparison function like this. It’s an example.)
Here are two ways we could implement this method:
# Implicit return - Ruby returns the last value evaluated, so # with if/elsif/else, we can be sure we return the right value! def comparison(a, b) if (a.field < b.field) -1 elsif (a.field > b.field) 1 else 0 end end # Explicit returns - we add "return" all over the code def comparison(a, b) if (a.field < b.field) return -1 elsif (a.field > b.field) return 1 else return 0 end end
At first glance, it seems pretty obvious what’s different between the two, and it would seem that calling “return” explicitly is a waste of time….
But then again, if you’re not a complete programmer noob, you might notice something that sets the two apart: ease of refactoring.
In the implicit return scenario, your code can’t be cleaned up much. You could go with a targetless
case statement, but that’s awkward to look at and makes the return less obvious. You could nest ternary operators, but again, that’s making the returns hard to find. Furthermore, if you decide to add some logic to the code for some reason, adding it at the bottom would destroy the function since Ruby will return the last evaluated statement — this means complex code can break without it being very obvious.
In the explicit return scenario, on the other hand, you can not only make it more concise, but also easier to read for some people by returning early and avoiding the use of else. And by explicitly returning, anybody looking at the function can quickly see that the function returns at three very clear points. And unlike what could happen in the first scenario, adding code at the end of this function will not break the return value.
So to illustrate a more concise, safe, and explicit example:
# Using statement modifiers for very few lines of code def comparison(a, b) return -1 if a.field < b.field return 1 if a.field > b.field return 0 end # Simpler but longer example - still avoids elsif and else # and is safe from adding code at the end def comparison(a, b) if a.field < b.field return -1 end if a.field > b.field return 1 end return 0 end
Obviously I favor explicit returns, and nobody will convince me that doing it implicitly is better (isn’t Ruby supposed to be about readability?) So to hear there is a performance hit and that alone is a good reason to use implicit returns makes me really wonder about people.
A performance hit? In Ruby?!? Okay, let’s take a second here. Ruby as a language is SLOW, and you need to accept that to write good Ruby, because you have to be ready for it if you need a particularly CPU-intense algorithm or application. You need to know how to cut corners, how to implement C libraries, etc. So naturally on hearing somebody discussing the “fast” way to do something so trivial in Ruby, my skeptic senses tingled.
I ran a quick benchmark and found that over one million iterations, implicit and explicit returns showed a difference of about 3/10 of a second. Percentage-wise, implicit returns are the clear winner, clocking about 30% less time over multiple million-iteration runs — but the overall difference works out to a cost of about 300 nanoseconds per call. In an app where this difference will EVER matter, Ruby is absolutely the wrong choice of language.