comment 0

8 reasons why implicit return in modern languages is wrong

Some languages allow, or even force you, to declare your return statement in your function without any visual difference, only by being the last statement in the function. This is what we can call implicit return.

This covers languages such as Rust, Javascript, Ruby, or even or old Bash.

This article gives 8 reasons on why this is a bad design and should be avoided at all costs for general code, and give the only acceptable case where return might be avoided. For readability and maintainance sake, always use the return  keyword of your language in your functions. Always.

First, what is implicit return vs explicit return?

The principle

Old procedural languages like C or C++ have a keyword named return  for giving instruction to the compiler that it is a end of the code path and should go back to the caller function.

However, modern language tends to be lazy and try to remove as many boilder plates as possible, to ease readability. Some of them has added a principle: the return statement is implicitly the value of the latest expression of the function.

For instance the following C function

would look like this with implicit return:

It has it own, and totally acceptable, logic.

Implicit Return logic

For instance let’s look at this method (customized C/C++ language with implicit return):

It is actually looking good. The return statement would not add any information.

But the logic lies in the following sentence:

The value of the latest expression in a method body will be used as return value by default, except if the return  statement is used in all code path. Prior exit points should anyway use return to be identified so.

But why is it wrong?

The main complains I have against implicit return are the following ones:

1. Invisibility

We cannot see where are the exit point of a given function at first sight. That is a real problem, if we want to follow the “read code as a book” principle. That is really important, reading code should be done easilly, without flaws, without “ah, this is a special case, you should know that…”. It’s is really important for nested method, closures, …

Tell me that is it more readable than

Finding the return statements are easier than finding “evaluate only” statements.

2. Error prone

It is highly error prone, for instance if you happen to add a log after this hidden return statement, during your “add log everywhere session” to find out the damned bug on Friday evening (true story). If do so, you will actually change the behavior of the function, which is bad for your manager when you have to resolve this issue just before customer delivery… adding code after the return  statement should be warned or even forbidden by the compiler but certainly NOT allowed quietly AND actually change your code without telling you.

Ok, most of the time, your powerful Rust compiler might fail if return type have changed, but nothing guaranty that all errors can be caught. Just for this point I would highly recommend NEVER to use implicit return.

3. Does not add anything

Less is better than more, or said otherwise, adding useless words make the code less readable, too much verbose. However, this is not the case here, because, with implicit return, at this line, you would say “the code should end here and return to the caller method”… without actually telling anything. You have to guess “ah, this expression does not do anything, this should be the hidden return statement”.

At the contrary, implicit return force you to take care of the return value of the functions you are calling, take care of not propagating it if you don’t want to.

4. It does not solve a problem

Having return in the code is not a problem by itself. It just say “I end the work here” and tell the compiler to discard code after it. Removing this word does not simplify the code.

5. It introduces ambiguity.

Having two syntax for the same result is not good. Let imagine you read some long files. Some methods uses implicit return while others use explicit every time. After reading a method with explicit return, one would expect the next method being explicit as well, thus introducing useless complexity.

If early return points inside a given function would always use the return  keyword, this is not the case for closure and this might make the resulting code unnecessarily harder to read.

Why the early return statements inside a function would use a different convention than the last one? Things ate better when they are simple. Either no single return at all, either return every time. But since having no return nowhere is not possible, it should exist at least in one case. So just use it everywhere. Keep it damned simple. Follow the KIDS principle!

6. It is not faster. It’s may be even slower

Some reports that using implicit return in languages such as Ruby might make the code run faster. That is wrong. Semantic is the not the same, but the end result is. It might even have huge negative impact:

  • if your method ends by an for loop, this may return the expression value of this loop, like an array
  •  Conditionally call of a method:

 I don’t want to return the return value of call_another_method. What if this function returns a huge data vector that get copied/transferred up the caller function? Even if your compiler can optimize it, it is a necessary job.

In Bash, this is not really a problem, since only return code (integer up to 255) can be returned. Transferring the data to all caller functions is not a real problem. I guess that a properly designed Rust method might return only a box to the vector, but nothing guarantee you that the worst case cannot append. And when it happens it will be silent.

7. False war

It is said that implicit return makes the code more “declarative”, at the contrary of using returns is for old “procedural” languages. Like if declarative would be a kind of language with higher pedigree, higher value, higher “rank” than procedural. Like if procedural means Neanderthal. Rust, Bash, Javascript, all these languages are procedural, live with it! We programmers read procedural codes everyday!

8. It is ugly.

Imagine you want a method that return the null value. Don’t ask why, it is the will of the programmer. In Rust you would write

Do you really find it readable? Same with return :

Doesn’t it look much better, is it?

Do you really find this implicit return factorial function beautiful?

against the version with explicit return:

Conclusion

That is why in Rust I strongly recommend NOT using implicit return for all non-one-liner function.

And what about Lambda function?

Of course, a  rule without exception would not be a good one. The only exception is for lambda function, where the only expression is naturally returned. Just imagine you are in Python… except that this method without return will not return None .

You don’t want to write  arg=lambda x: return x[1] , because lambda methods are made to return. lambda a: b  means “make a lambda method that returns”  b .

Just stick with the rule:

If my function is more than 1 line, no implicit return.

References