In languages such as javascript or (maybe?) lua, all functions by default are treated as if they had a return
statement at the end:
function() {
// do
return;
}
Is equal to
function() {
// do
}
I'm wondering if returning from an inner block at the end of the function changes anything in the core, the compiling process, the VM.
function() {
if (condition) {
return;
}
// end of function
}
Same question applies to breaking a loop:
function() {
for ( loop ) {
return;
}
// end of function
}
Does the machine "look" for anything when a loop is broken, or a condition check has ended?
This is not a stylistic question, please don't tell me to make code readable.
TL:DR / optimization advice: you don't need to do anything special to gain performance. if(condition) return
inside an inner loop is typically at least as efficient as an if(condition)break;
to reach the end of the function.
Putting nested loops inside a function so you can use a return
as a multi-level break
is a good way of being able to express the logic efficiently without a goto
, easy for humans and easy for compilers/interpreters.
Making loop conditions more complicated to avoid multiple return
statements in one function is not helpful for performance.
Generally no, a return
in the middle of a function is not fundamentally different or more or less efficient than reaching the implicit return at the end. And an explicit return at the bottom of a function isn't special either.
(We're talking about void functions that never return a value, I assume. Obviously returning a value is different from not returning a value.)
Restructuring your code to break
out of a loop and reach the implicit return
at the bottom of a function is not more efficient (but could easily be less efficient in some interpreted languages, especially if they aren't JITed.) e.g. if the interpreter does a jump within the function and then has to do another jump. (A good ahead-of-time compiler or JIT optimizer could see what was happening and make good machine code anyway.)
Some compilers / interpreters may handle a return
by just jumping to a common block of cleanup (epilogue) that all return
statements share. But tail-duplication is possible: when compiled to machine code, a function can have multiple copies of epilogue + ret
instructions, reachable from different paths.
(JavaScript implementations do typically JIT functions to machine code; IDK about LUA. And of course they can inline functions. return
statements in functions that get inlined can be just plain jumps, or could get optimized away entirely.)