In the days of old...
In Pascal and Algol one could really only do the first style. This was known as structured programming.
A function in pascal and the style of programing was:
Function abs(arg:real;) : real;
Begin
real retval;
if retval > 0 then
reval = arg;
else
retval = arg * -1;
functionName := returnVal;
End;
The function returned one parameter that was assigned to it at the end. This pseudo-variable was influenced likely from Fortran which has a similar notation (but can have multiple returns). Fortran's multiple entry (one could use the ENTRY
statement to have a call jump into the middle of a function) and multiple exit points was one of the reasons that Go To Statement Considered Harmful was written and structured programming came as a reaction from).
In Algol (another influential early language), the return value of a procedure was the last expression evaluated by the procedure. If you wanted to return something, you needed to carry it all the way to the end and then evaluate it.
This particular style/constraint of programming was often used in academia and influenced a generation of programmers and was a move to more elegant languages away from the 'goto' style code before with Fortran and assembly.
In the modern world...
The second style, if
it acts as a guard statement is almost always preferable.
public static boolean returnMulti(Object arg) {
if (!validArg) {
return false;
}
more stuff;
return true;
}
Note the 'more stuff' that indicates processing which could be reasonably sizable. By kicking out the invalid case early, one should be able to read more stuff
more easily.
On the other hand, the only one return means that when you are walking backwards through code, there is only one spot that you need to look at.
funcA
stuff;
foo = funcB();
stuff;
Ok, so foo is the return value of funcB()
...
funcB
stuff;
if(bar) return something;
stuff;
if(qux) return somethingElse;
stuff;
if(bletch) return anotherThing;
stuff;
if(blarg) return yetAnotherThing;
stuff;
return defaultThingy;
At this point, you have 5 different spots where you can return from. You don't know which one and what conditions caused the return value for funcB
, it could have been any of then. This isn't to say the above code is good code, but it isn't uncommon to see.
Using a return variable one would have code that one could find the one return statement in the function and say "it was 5 at this point" and walk backwards through the code to see the flow.
Furthermore, when you have a language with explicit resource management (malloc and free rather than garbage collection), you will find that it is easiest to do a single cleanup of the resources allocated in the function at the end rather than calling them multiple times and missing one.
As to the temproary variable... one will find in many languages that when dissasembling the code for:
func foo()
retval = something;
return retval;
func bar()
return something;
The two compile to exactly the same instructions (with a temporary variable - the compiler has to put the memory somewhere).
See also