Switches seem so useless as they can be replaced with if-else statements, which can do much more than just match a char/int/enum etc. I can only think of one good use for a switch, and that would be for interpreting command line args.
What are some realistic uses for a switch statement?
There are a few cases where switch is more readable and comes in handy. Usually when you have grouping of options.
Here is one of them:
int numDays = 0;
int month = 2;
int year = 2010;
// find the number of days in the month
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if ( ((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0) )
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
There's two reasons to use a switch vs if/else, in my mind:
The compiler may be able to optimize for the switch better.
The switch statement more clearly expresses the logic of the code better. Specifically, the idea that you're taking a different branch depending on the value of something, rather than depending on more complicated logic. This is, by far, the more important reason to me.
You need to remember that switches are easier to maintain - a whole bunch of nested ifs and elses can quickly become a pain to maintain.
Switches allow for easier insertion of a new case.
I use switches when I am using an enum to dictate what actions my method should take. It helps when the actions are mutually exclusive.
Switches are optimized in many languages for certain contexts. Often when possible they create a jump table or even hash table. Really, when it's possible to use a switch, it's very likely going to perform better than the (logically) same code using if/else.
There are a number of situations, one that we have to deal with a lot is if you have a lot of options, the syntax is a bit more compressed, and sometimes is easier to read than a if/then syntax.
Although an argument can be made to go either way, I find that switches, in the case of multiple options is easier to read, maintain and understand. I also have used it in a factory pattern type situation, which helps to document.
I always use switches if I'm comparing the same variable for multiple values - a switch is a lot quicker to code (and easier to maintain) than a long if-elseif chain. Imagine changing the variable name, with a switch it'll be a single edit, with an if-elseif chain it'll be several.
Also, depending on the language of choice you can use the case fall through "feature" where as with the if-elseif chain you'd end up with duplicated code.
Switch statements are great for writing finite state machine,Click here to learn more about them
It's the proper way to use the language. It lets the compiler do some optimizations and makes the code easier to read by someone who isn't you.
Also, in some languages you can switch an enum, and the compiler will warn if you miss values (I think).
well you can remove breaks from a switch statement. That way you can have this:
CASE_A:
...
BASE_B
...
so that way you can have case_a combine all the other cases below it until it hits a break. Not as nice to do that with just ifs.
A couple of points:
Some languages let you switch on other value types, such as string (Coldfusion case in point)
A switch statement may very well be much easier code to read than a big block of if/elseif/else statements
In switch statements you can break at the end of a case or allow the code to continue processing further cases in the statement. This functionality allows you to easily model some rules that if/elseif/else statements would not let you do as easily.
As others mention, keep in mind compilers and engines have optimizers, and switch statements are optimized differently.
In the case of Perl, using the switch statement can significantly reduce the complexity of your code.
Just compare these two examples.
Using given/when:
use feature qw'switch';
my $num_days;
given( $month) {
when( [ 1,3,5,7,8,10,12 ] ){ $num_days = 31 }
when( [ 4,6,9,11 ] ){ $num_days = 30 }
when( 2 ){
$num_days = 29;
$num_days = 28 if $year % 4;
$num_days = 28 unless $year % 100;
$num_days = 29 unless $year % 400;
default{ print "Invalid month.\n" }
}
Using for as a replacement for the new ~~ (smart-match) operator.
my $num_days;
for( 1,3,5,7,8,10,12 ){
if( $month == $_ ){
$num_days = 31;
last;
}
}
for( 4,6,9,11 ){
if( $month == $_ ){
$num_days = 30;
last;
}
}
if( $month == 2 ){
$num_days = 29;
$num_days = 28 if $year % 4;
$num_days = 28 unless $year % 100;
$num_days = 29 unless $year % 400;
}
unless( defined $num_days ){
print "Invalid month.\n"
}
Seems to me that the main advantage of a switch is that it makes it immediately obvious to the reader that all the options depend on the same variable. You certainly could write an if/elseif/elseif block that accomplished the same thing, but then the reader would have to carefully check that indeed it is the same variable being tested every time.
There's also the nightmare maintenance scenario where you have a long if/elseif on the same variable and someone decides to change the variable name, and so he changes all of the if's ... except he misses one.
As others have pointed out, there's also the fact that the compiler can usually optimize it better.
Duff's Device. Its usefulness in modern times is debatable, but its awesomeness is not.
It helps readability - at a glance, I know that the decision for which block of code should run is based on different values of the same variable.
It may be easier for the compiler to turn a switch statement into a dispatch table than it would be to turn the equivalent if/else soup into a dispatch table. If (and only if) that's true, you should then have O(1) dispatch to the relevant code, instead of O(log n) (or O(n), if the if/else soup is badly written).
In some (although not all) cases it may also be easier to check that you've covered the necessary tests using switch than a wodge of if/else.
I prefer using a map to a switch in most cases.
if (actionMap.contains(choice)) {
Action a = actionMap.get(choice);
a.execute();
} else {
//do something else
}
But in cases where the choices are too complicated to turn into a map or when multiple actions might be taken a switch is better.
switch (choice) {
case 1: actionOne(); break;
case 2: if(actionOne()) {actionTwo()}; break;
case 3: if(!actionOne() && (actionTwo() > 1)) {actionThree()}; result = 7;break;
default: result = actionTwo();
}
Sadly, sometimes requirements are complicated. Switch is useful in those cases where is simplified version of nested if/else constrcts.
Don't ask a python programmer this question as the language doesn't have a switch statement and encourage the use of dictionaries instead.
To answer your question, I can think of one case where a switch statement is useful.
It is useful when the language / compiler / static analyzer can make sure that you're checking all cases. This works good with enums.
If you add another item to an enumeration, you can now get warnings in all of the places where you are doing a switch on that kind of enumeration telling you that you're missing a case.
Related
Switch statements: I know what they do - I use them so many times, as per convention normally when I want to do different stuff based on the value of an Enum, but now it just hit me: Why are we using it? What was its original purpose? I mean, this:
switch(myVar) {
case Foo:
doSomething();
break;
case Bar:
doSomethingElse();
break;
default:
justAnotherThing();
break;
}
Has the exact same behaviour as:
if(myVar == Foo) {
doSomething()
}else if(myVar == Bar) {
doSomethingElse();
}else {
justAnotherThing();
}
Plus if's lets you make inequality comparisons (>, <, !=) if you need it. The only case that I may find a switch more useful is when you don't use the break statement inside: but this happens not too often and I find it terrible on code-quality.
I really can't find any benefit of using switch over if... So why was it defined for?
Some languages allow inequality comparisons in switch statements as well, e.g. Visual Basic:
Select Case x
Case < 5
// ...
Case 7
// ...
Case 10 To 15
// ...
Case Else
// ...
End Select
Basically, yes, the switch can often be written as an if/else if ladder, with the distinction that switch compares one value against a number of comparison values, if/else if can do anything in every single branch. But even that isn't the case in all languages, e.g. in PowerShell a switch can do plenty of things that you usually have to use if for:
switch -Regex ($x) {
'^\d+$' {'Number'}
}
or
switch ($x) {
{ $_ is [int] -or $_ is [double] } {'Number'}
{ $_ is [string] } {'Text'}
}
Generally, however, switch is easier to read for the common case of comparing a single value against a finite set of options. Furthermore, it enables the compiler to do certain optimizations which are harder to analyse on if/else if, such as using binary search to determine the correct case instead of linear search, or even using a jump table or arithmetic. E.g. the following switch
switch (x) {
case 0:
// Do something with 0
break;
case 1:
// Do something with 1
break;
case 2:
// Do something with 2
break;
...
}
could be compiled into the equivalent of
Action[] actions = {
() => { /* Do something with 0 */ },
() => { /* Do something with 1 */ },
() => { /* Do something with 2 */ },
...
};
if (x >=0 && x <= n) {
actions[x]();
}
The simplicity and limitations of switch are helpful in this case for an optimizing compiler because there's much less to analyse to determine what the overall structure is trying to do.
There are other features (sometimes maybe of dubious value), such as Duff's device, or being able to fall through to other cases (or goto arbitrary other cases, which, e.g. C# allows).
You may just as well ask the question why we have if statements and loops instead of just using goto. Yes, structured programming constructs are, taken one by one, strictly inferior in what they can express, compared to the more general construct. But they are more readable, make the intent clearer, and tend to be safer and easier to maintain.
switch is a pretty low-level statement, in the sense that the code in the case statements is compiled into a continuous block of instructions in memory which is simply conditionally jumped into (depends on the language in question of course, modern high-level languages may behave quite different under the hood). That's also why you have the fall-through behaviour, once a starting address is determined simply all following instructions are executed unless broken out of.
So initially it was a very natural way to jump over or into a block of instructions. Many languages have adopted the switch statement, many likely due to familiarity, but many likely also because it is indeed rather readable for certain cases, e.g.:
switch (someComplicatedCalculation($foo, $bar)) {
case CONSTANT_A:
...
case CONSTANT_B:
...
...
}
That's a pretty succinct way to express this, especially if you're maybe also depending on the fall-through behaviour.
Of course, other languages have never adopted switch, e.g. Python, and require the use of if..elif..else instead. In the end you can write similar code using either language construct, it's up to you.
I've got 3 different switch functions that have about 4 cases each. Would it really be so bad to jam all the cases into one big switch function instead? I know it would have to go through more cases that way until it found the proper one, but wouldn't the performance hit be negligible? I'm trying to cut down on needless code so I don't have to scroll through it so much. It would save on some function declarations as well.
To clarify, I have several functions where the user can choose something. Each of those functions has a corresponding handler that uses a switch statement to see what the user chose. I'm considering just using 1 handler instead that has all of the cases.
if you mean that.
if(x < 4)
{
switch(x)
{
case 0:
case 1:
case 2:
case 3:
}
}
else if(x < 8)
{
switch(x)
{
case 4:
case 5:
case 6:
case 7:
}
}
else
{
switch(x)
{
case 8:
case 9:
case 10:
case 11:
default:
}
}
it's better you make a big switch for all because of "code readability". That switch stuff doesn't effect on performance if you're just asking for 3 switches and 4 cases each... you don't need to do that for now...
I think that's really relative to your project. A complete relative discussion depends on project. You're the one who's gonna decide about that stuff.
Putting them into one switch statement is a better practice, if the condition is the same of course. SWITCH statement does not exist in the bytecode level, so if you use more SWITCH statements then the bytecode will be way longer. Check this article.
This question is motivated by something I've lately started to see a bit too often, the if..else if..else structure. While it's simple and has its uses, something about it keeps telling me again and again that it could be substituted with something that's more fine-grained, elegant and just generally easier to keep up-to-date.
To be as specific as possible, this is what I mean:
if (i == 1) {
doOne();
} else if (i == 2) {
doTwo();
} else if (i == 3) {
doThree();
} else {
doNone();
}
I can think of two simple ways to rewrite that, either by ternary (which is just another way of writing the same structure):
(i == 1) ? doOne() :
(i == 2) ? doTwo() :
(i == 3) ? doThree() : doNone();
or using Map (in Java and I think in C# too) or Dictionary or any other K/V structure like this:
public interface IFunctor() {
void call();
}
public class OneFunctor implemets IFunctor() {
void call() {
ref.doOne();
}
}
/* etc. */
Map<Integer, IFunctor> methods = new HashMap<Integer, IFunctor>();
methods.put(1, new OneFunctor());
methods.put(2, new TwoFunctor());
methods.put(3, new ThreeFunctor());
/* .. */
(methods.get(i) != null) ? methods.get(i).call() : doNone();
In fact the Map method above is what I ended up doing last time but now I can't stop thinking that there has to be better alternatives in general for this exact issue.
So, which other -and most likely better- ways to replace the if..else if..else are out there and which one is your favorite?
Your thoughts below this line!
Okay, here are your thoughts:
First, most popular answer was switch statement, like so:
switch (i) {
case 1: doOne(); break;
case 2: doTwo(); break;
case 3: doThree(); break;
default: doNone(); break;
}
That only works for values which can be used in switches, which at least in Java is quite a limiting a factor. Acceptable for simple cases though, naturally.
The other and perhaps a bit fancier way you seem to sugges is to do it using polymorphism. The Youtube lecture linked by CMS is an excellent watch, go see it here: "The Clean Code Talks -- Inheritance, Polymorphism, & Testing" As far as I understood, this would translate to something like this:
public interface Doer {
void do();
}
public class OneDoer implements Doer {
public void do() {
doOne();
}
}
/* etc. */
/* some method of dependency injection like Factory: */
public class DoerFactory() {
public static Doer getDoer(int i) {
switch (i) {
case 1: return new OneDoer();
case 2: return new TwoDoer();
case 3: return new ThreeDoer();
default: return new NoneDoer();
}
}
}
/* in actual code */
Doer operation = DoerFactory.getDoer(i);
operation.do();
Two interesting points from the Google talk:
Use Null Objects instead of returning nulls (and please throw only Runtime Exceptions)
Try to write a small project without if:s.
Also in addition one post worth mentioning in my opinion is CDR who provided his perverse habits with us and while not recommended to use, it's just very interesting to look at.
Thank you all for the answers (so far), I think I might have learned something today!
These constructs can often be replaced by polymorphism. This will give you shorter and less brittle code.
In Object Oriented languages, it's common to use polymorphism to replace if's.
I liked this Google Clean Code Talk that covers the subject:
The Clean Code Talks -- Inheritance, Polymorphism, & Testing
ABSTRACT
Is your code full of if statements?
Switch statements? Do you have the
same switch statement in various
places? When you make changes do you
find yourself making the same change
to the same if/switch in several
places? Did you ever forget one?
This talk will discuss approaches to
using Object Oriented techniques to
remove many of those conditionals. The
result is cleaner, tighter, better
designed code that's easier to test,
understand and maintain.
A switch statement:
switch(i)
{
case 1:
doOne();
break;
case 2:
doTwo();
break;
case 3:
doThree();
break;
default:
doNone();
break;
}
Depending on the type of thing you are if..else'ing, consider creating a hierarchy of objects and using polymorphism. Like so:
class iBase
{
virtual void Foo() = 0;
};
class SpecialCase1 : public iBase
{
void Foo () {do your magic here}
};
class SpecialCase2 : public iBase
{
void Foo () {do other magic here}
};
Then in your code just call p->Foo() and the right thing will happen.
There's two parts to that question.
How to dispatch based on a value? Use a switch statement. It displays your intent most clearly.
When to dispatch based on a value? Only at one place per value: create a polymorphic object that knows how to provide the expected behavior for the value.
The switch statement of course, much prettier then all those if's and else's.
Outside of using a switch statement, which can be faster, none. If Else is clear and easy to read. having to look things up in a map obfuscates things. Why make code harder to read?
switch (i) {
case 1: doOne(); break;
case 2: doTwo(); break;
case 3: doThree(); break;
default: doNone(); break;
}
Having typed this, I must say that there is not that much wrong with your if statement. Like Einstein said: "Make it as simple as possible, but no simpler".
I use the following short hand just for fun! Don't try anyof these if code clearity concerns you more than the number of chars typed.
For cases where doX() always returns true.
i==1 && doOne() || i==2 && doTwo() || i==3 && doThree()
Ofcourse I try to ensure most void functions return 1 simply to ensure that these short hands are possible.
You can also provide assignments.
i==1 && (ret=1) || i==2 && (ret=2) || i==3 && (ret=3)
Like instad of writting
if(a==2 && b==3 && c==4){
doSomething();
else{
doOtherThings();
}
Write
a==2 && b==3 && c==4 && doSomething() || doOtherThings();
And in cases, where not sure what the function will return, add an ||1 :-)
a==2 && b==3 && c==4 && (doSomething()||1) || doOtherThings();
I still find it faster to type than using all those if-else and it sure scares all new noobs out. Imagine a full page of statement like this with 5 levels of indenting.
"if" is rare in some of my codes and I have given it the name "if-less programming" :-)
In this simple case you could use a switch.
Otherwise a table-based approach looks fine, it would be my second choice whenever the conditions are regular enough to make it applicable, especially when the number of cases is large.
Polymorphism would be an option if there are not too many cases, and conditions and behaviour are irregular.
The example given in the question is trivial enough to work with a simple switch. The problem comes when the if-elses are nested deeper and deeper. They are no longer "clear or easy to read," (as someone else argued) and adding new code or fixing bugs in them becomes more and more difficult and harder to be sure about because you might not end up where you expected if the logic is complex.
I've seen this happen lots of times (switches nested 4 levels deep and hundreds of lines long--impossible to maintain), especially inside of factory classes that are trying to do too much for too many different unrelated types.
If the values you're comparing against are not meaningless integers, but some kind of unique identifier (i.e. using enums as a poor man's polymorphism), then you want to use classes to solve the problem. If they really are just numeric values, then I would rather use separate functions to replace the contents of the if and else blocks, and not design some kind of artificial class hierarchy to represent them. In the end that can result in messier code than the original spaghetti.
Use a switch/case it's cleaner :p
switch statement or classes with virtual functions as fancy solution. Or array of pointers to functions. It's all depends on how complex conditions are, sometimes there's no way around those if's. And again, creating series of classes to avoid one switch statement is clearly wrong, code should be as simple as possible (but not simpler)
I would go so far as to say that no program should ever use else. If you do you are asking for trouble. You should never assume if it's not an X it must be a Y. Your tests should test for each individually and fail following such tests.
In OO paradigm you could do it using good old polymorphism. Too big if - else structures or switch constructs are sometimes considered a smell in the code.
The Map method is about the best there is. It lets you encapsulate the statements and breaks things up quite nicely. Polymorphism can complement it, but its goals are slightly different. It also introduces unnecessary class trees.
Switches have the drawback of missing break statements and fall through, and really encourage not breaking the problem into smaller pieces.
That being said: A small tree of if..else's is fine (in fact, i argued in favor for days about have 3 if..elses instead of using Map recently). Its when you start to put more complicated logic in them that it becomes a problem due to maintainability and readability.
In python, I would write your code as:
actions = {
1: doOne,
2: doTwo,
3: doThree,
}
actions[i]()
I regard these if-elseif-... constructs as "keyword noise". While it may be clear what it does, it is lacking in conciseness; I regard conciseness as an important part of readability. Most languages provide something like a switch statement. Building a map is a way to get something similar in languages that do not have such, but it certainly feels like a workaround, and there is a bit of overhead (a switch statement translates to some simple compare operations and conditional jumps, but a map first is built in memory, then queried and only then the compare and jump takes place).
In Common Lisp, there are two switch constructs built in, cond and case. cond allows arbitrary conditionals, while case only tests for equality, but is more concise.
(cond ((= i 1)
(do-one))
((= i 2)
(do-two))
((= i 3)
(do-three))
(t
(do-none)))
(case i
(1 (do-one))
(2 (do-two))
(3 (do-three))
(otherwise (do-none)))
Of course, you could make your own case-like macro for your needs.
In Perl, you can use the for statement, optionally with an arbitrary label (here: SWITCH):
SWITCH: for ($i) {
/1/ && do { do_one; last SWITCH; };
/2/ && do { do_two; last SWITCH; };
/3/ && do { do_three; last SWITCH; };
do_none; };
Use a Ternary Operator!
Ternary Operator(53Characters):
i===1?doOne():i===2?doTwo():i===3?doThree():doNone();
If(108Characters):
if (i === 1) {
doOne();
} else if (i === 2) {
doTwo();
} else if (i === 3) {
doThree();
} else {
doNone();
}
Switch((EVEN LONGER THAN IF!?!?)114Characters):
switch (i) {
case 1: doOne(); break;
case 2: doTwo(); break;
case 3: doThree(); break;
default: doNone(); break;
}
this is all you need! it is only one line and it is pretty neat, way shorter than switch and if!
Naturally, this question is language-dependent, but a switch statement might be a better option in many cases. A good C or C++ compiler will be able to generate a jump table, which will be significantly faster for large sets of cases.
If you really must have a bunch of if tests and want to do different things whenwver a test is true I would recommend a while loop with only ifs- no else. Each if does a test an calls a method then breaks out of the loop. No else there's nothing worse than a bunch of stacked if/else/if/else etc.
When reviewing, I sometimes encounter this kind of loop:
i = begin
while ( i != end ) {
// ... do stuff
if ( i == end-1 (the one-but-last element) ) {
... do other stuff
}
increment i
}
Then I ask the question: would you write this?
i = begin
mid = ( end - begin ) / 2 // (the middle element)
while ( i != end ) {
// ... do stuff
if ( i > mid ) {
... do other stuff
}
increment i
}
In my opinion, this beats the intention of writing a loop: you loop because there is something common to be done for each of the elements. Using this construct, for some of the elements you do something different. So, I conclude, you need a separate loop for those elements:
i = begin
mid = ( end - begin ) / 2 //(the middle element)
while ( i != mid ) {
// ... do stuff
increment i
}
while ( i != end ) {
// ... do stuff
// ... do other stuff
increment i
}
Now I even saw a question on SO on how to write the if-clause in a nice way... And I got sad: something isn't right here.
Am I wrong? If so, what's so good about cluttering the loop body with special cases, which you are aware of upfront, at coding time?
I don't think this question should be answered by a principle (e.g. "in a loop, treat every element equally"). Instead, you can look at two factors to evaluate if an implementation is good or bad:
Runtime effectivity - does the compiled code run fast, or would it be faster doing it differently?
Code maintainability - Is it easy (for another developer) to understand what is happening here?
If it is faster and the code is more readable by doing everything in one loop, do it that way. If it is slower and less readable, do it another way.
If it is faster and less readably, or slower but more readable, find out which of the factors matters more in your specific case, and then decide how to loop (or not to loop).
I know I've seen this when people tried to join elements of an array into a comma-seperated string:
for(i=0;i<elements.size;i++) {
if (i>0) {
string += ','
}
string += elements[i]
}
You either have that if clause in there, or you have to duplicate the string += line again at the end.
The obvious solution in this case is
string = elements.join(',')
But the join method does the same loop internally. And there isn't always a method to do what you want.
#xtofl,
I agree with your concern.
Million times I encountered similar problem.
Either developer adds special handling for first or for last element.
In most cases it is worth to just loop from startIdx + 1 or to endIdx - 1 element or even split one long loop into multiple shorter loops.
In a very rare cases it's not possible to split loop.
In my opinion uncommon things should be handled outside of the loop whenever possible.
I came to a realization that when I put special cases in a for loop, I'm usually being too clever for my own good.
In the last snippet you posted, you are repeating code for // .... do stuff.
It makes sense of keeping 2 loops when you have completely different set of operations on a different set of indices.
i = begin
mid = ( end - begin ) / 2 //(the middle element)
while ( i != mid ) {
// ... do stuff
increment i
}
while ( i != end ) {
// ... do other stuff
increment i
}
This not being the case, you would still want to keep one single loop. However fact remains that you still save ( end - begin ) / 2 number of comparisons. So it boils down to whether you want your code to look neat or you want to save some CPU cycles. Call is yours.
I think you have it entirely nailed. Most people fall into the trap of including conditional branches in loops, when they could do them outside: which is simply faster.
For example:
if(items == null)
return null;
StringBuilder result = new StringBuilder();
if(items.Length != 0)
{
result.Append(items[0]); // Special case outside loop.
for(int i = 1; i < items.Length; i++) // Note: we start at element one.
{
result.Append(";");
result.Append(items[i]);
}
}
return result.ToString();
And the middle case you described is just plain nasty. Imagine if that code grows and needs to be refactored into different methods.
Unless you are parsing XML <grin> loops should be kept as simple and concise as possible.
I think you are right about the loop being meant to deal with all elements equally. Unfortunately sometimes there are special cases though and these should be dealt with inside the loop construct via if statements.
If there are lots of special cases though you should probably think about coming up with some way to deal with the two different sets of elements in separate constructs.
I prefer to simply, exclude the element from the loop
and give a spearate treatment outside the loop
For eg: Lets consider the case of EOF
i = begin
while ( i != end -1 ) {
// ... do stuff for element from begn to second last element
increment i
}
if(given_array(end -1) != ''){
// do stuff for the EOF element in the array
}
Of course, special-casing things in a loop which can be pulled out is silly. I wouldn't duplicate the do_stuff either though; I'd either put it in a function or a macro so I don't copy-paste code.
Another thing I hate to see is the for-case pattern:
for (i=0; i<5; i++)
{
switch(i)
{
case 0:
// something
break;
case 1:
// something else
break;
// etc...
}
}
I've seen this in real code.
Which one performs better?
If the number of items is very large then I would always loop once, especially if you are going to perform some operation on every item. The cost of evaluating the conditional is likely to be less than looping twice.
Oops, of course you are not looping twice... In which case two loops is preferable. However, I maintain that the primary consideration should be performance. There's no need to incur the conditional in the loop (N times) if you can partition the work by a simple manipulation of the loop bounds (once).
The special case should be done outside the loop if it is only to be performed once.
However, there may be an index or some other variable(s) that are just easier to keep inside the loop due to scoping. There may also be a contextual reason for keeping all the operations on the datastructure together inside the loop control structure, though I think that is a weak argument on its own.
Its just about using it as per need and convenience. There is as such no mentions to treat elements equally and there is certainly no harm clubbing the features which language provides.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
Are there good reasons why it's a better practice to have only one return statement in a function?
Or is it okay to return from a function as soon as it is logically correct to do so, meaning there may be many return statements in the function?
I often have several statements at the start of a method to return for "easy" situations. For example, this:
public void DoStuff(Foo foo)
{
if (foo != null)
{
...
}
}
... can be made more readable (IMHO) like this:
public void DoStuff(Foo foo)
{
if (foo == null) return;
...
}
So yes, I think it's fine to have multiple "exit points" from a function/method.
Nobody has mentioned or quoted Code Complete so I'll do it.
17.1 return
Minimize the number of returns in each routine. It's harder to understand a routine if, reading it at the bottom, you're unaware of the possibility that it returned somewhere above.
Use a return when it enhances readability. In certain routines, once you know the answer, you want to return it to the calling routine immediately. If the routine is defined in such a way that it doesn't require any cleanup, not returning immediately means that you have to write more code.
I would say it would be incredibly unwise to decide arbitrarily against multiple exit points as I have found the technique to be useful in practice over and over again, in fact I have often refactored existing code to multiple exit points for clarity. We can compare the two approaches thus:-
string fooBar(string s, int? i) {
string ret = "";
if(!string.IsNullOrEmpty(s) && i != null) {
var res = someFunction(s, i);
bool passed = true;
foreach(var r in res) {
if(!r.Passed) {
passed = false;
break;
}
}
if(passed) {
// Rest of code...
}
}
return ret;
}
Compare this to the code where multiple exit points are permitted:-
string fooBar(string s, int? i) {
var ret = "";
if(string.IsNullOrEmpty(s) || i == null) return null;
var res = someFunction(s, i);
foreach(var r in res) {
if(!r.Passed) return null;
}
// Rest of code...
return ret;
}
I think the latter is considerably clearer. As far as I can tell the criticism of multiple exit points is a rather archaic point of view these days.
I currently am working on a codebase where two of the people working on it blindly subscribe to the "single point of exit" theory and I can tell you that from experience, it's a horrible horrible practice. It makes code extremely difficult to maintain and I'll show you why.
With the "single point of exit" theory, you inevitably wind up with code that looks like this:
function()
{
HRESULT error = S_OK;
if(SUCCEEDED(Operation1()))
{
if(SUCCEEDED(Operation2()))
{
if(SUCCEEDED(Operation3()))
{
if(SUCCEEDED(Operation4()))
{
}
else
{
error = OPERATION4FAILED;
}
}
else
{
error = OPERATION3FAILED;
}
}
else
{
error = OPERATION2FAILED;
}
}
else
{
error = OPERATION1FAILED;
}
return error;
}
Not only does this make the code very hard to follow, but now say later on you need to go back and add an operation in between 1 and 2. You have to indent just about the entire freaking function, and good luck making sure all of your if/else conditions and braces are matched up properly.
This method makes code maintenance extremely difficult and error prone.
Structured programming says you should only ever have one return statement per function. This is to limit the complexity. Many people such as Martin Fowler argue that it is simpler to write functions with multiple return statements. He presents this argument in the classic refactoring book he wrote. This works well if you follow his other advice and write small functions. I agree with this point of view and only strict structured programming purists adhere to single return statements per function.
As Kent Beck notes when discussing guard clauses in Implementation Patterns making a routine have a single entry and exit point ...
"was to prevent the confusion possible
when jumping into and out of many
locations in the same routine. It made
good sense when applied to FORTRAN or
assembly language programs written
with lots of global data where even
understanding which statements were
executed was hard work ... with small methods and mostly local data, it is needlessly conservative."
I find a function written with guard clauses much easier to follow than one long nested bunch of if then else statements.
In a function that has no side-effects, there's no good reason to have more than a single return and you should write them in a functional style. In a method with side-effects, things are more sequential (time-indexed), so you write in an imperative style, using the return statement as a command to stop executing.
In other words, when possible, favor this style
return a > 0 ?
positively(a):
negatively(a);
over this
if (a > 0)
return positively(a);
else
return negatively(a);
If you find yourself writing several layers of nested conditions, there's probably a way you can refactor that, using predicate list for example. If you find that your ifs and elses are far apart syntactically, you might want to break that down into smaller functions. A conditional block that spans more than a screenful of text is hard to read.
There's no hard and fast rule that applies to every language. Something like having a single return statement won't make your code good. But good code will tend to allow you to write your functions that way.
I've seen it in coding standards for C++ that were a hang-over from C, as if you don't have RAII or other automatic memory management then you have to clean up for each return, which either means cut-and-paste of the clean-up or a goto (logically the same as 'finally' in managed languages), both of which are considered bad form. If your practices are to use smart pointers and collections in C++ or another automatic memory system, then there isn't a strong reason for it, and it become all about readability, and more of a judgement call.
I lean to the idea that return statements in the middle of the function are bad. You can use returns to build a few guard clauses at the top of the function, and of course tell the compiler what to return at the end of the function without issue, but returns in the middle of the function can be easy to miss and can make the function harder to interpret.
Are there good reasons why it's a better practice to have only one return statement in a function?
Yes, there are:
The single exit point gives an excellent place to assert your post-conditions.
Being able to put a debugger breakpoint on the one return at the end of the function is often useful.
Fewer returns means less complexity. Linear code is generally simpler to understand.
If trying to simplify a function to a single return causes complexity, then that's incentive to refactor to smaller, more general, easier-to-understand functions.
If you're in a language without destructors or if you don't use RAII, then a single return reduces the number of places you have to clean up.
Some languages require a single exit point (e.g., Pascal and Eiffel).
The question is often posed as a false dichotomy between multiple returns or deeply nested if statements. There's almost always a third solution which is very linear (no deep nesting) with only a single exit point.
Update: Apparently MISRA guidelines promote single exit, too.
To be clear, I'm not saying it's always wrong to have multiple returns. But given otherwise equivalent solutions, there are lots of good reasons to prefer the one with a single return.
Having a single exit point does provide an advantage in debugging, because it allows you to set a single breakpoint at the end of a function to see what value is actually going to be returned.
In general I try to have only a single exit point from a function. There are times, however, that doing so actually ends up creating a more complex function body than is necessary, in which case it's better to have multiple exit points. It really has to be a "judgement call" based on the resulting complexity, but the goal should be as few exit points as possible without sacrificing complexity and understandability.
No, because we don't live in the 1970s any more. If your function is long enough that multiple returns are a problem, it's too long.
(Quite apart from the fact that any multi-line function in a language with exceptions will have multiple exit points anyway.)
My preference would be for single exit unless it really complicates things. I have found that in some cases, multiple exist points can mask other more significant design problems:
public void DoStuff(Foo foo)
{
if (foo == null) return;
}
On seeing this code, I would immediately ask:
Is 'foo' ever null?
If so, how many clients of 'DoStuff' ever call the function with a null 'foo'?
Depending on the answers to these questions it might be that
the check is pointless as it never is true (ie. it should be an assertion)
the check is very rarely true and so it may be better to change those specific caller functions as they should probably take some other action anyway.
In both of the above cases the code can probably be reworked with an assertion to ensure that 'foo' is never null and the relevant callers changed.
There are two other reasons (specific I think to C++ code) where multiple exists can actually have a negative affect. They are code size, and compiler optimizations.
A non-POD C++ object in scope at the exit of a function will have its destructor called. Where there are several return statements, it may be the case that there are different objects in scope and so the list of destructors to call will be different. The compiler therefore needs to generate code for each return statement:
void foo (int i, int j) {
A a;
if (i > 0) {
B b;
return ; // Call dtor for 'b' followed by 'a'
}
if (i == j) {
C c;
B b;
return ; // Call dtor for 'b', 'c' and then 'a'
}
return 'a' // Call dtor for 'a'
}
If code size is an issue - then this may be something worth avoiding.
The other issue relates to "Named Return Value OptimiZation" (aka Copy Elision, ISO C++ '03 12.8/15). C++ allows an implementation to skip calling the copy constructor if it can:
A foo () {
A a1;
// do something
return a1;
}
void bar () {
A a2 ( foo() );
}
Just taking the code as is, the object 'a1' is constructed in 'foo' and then its copy construct will be called to construct 'a2'. However, copy elision allows the compiler to construct 'a1' in the same place on the stack as 'a2'. There is therefore no need to "copy" the object when the function returns.
Multiple exit points complicates the work of the compiler in trying to detect this, and at least for a relatively recent version of VC++ the optimization did not take place where the function body had multiple returns. See Named Return Value Optimization in Visual C++ 2005 for more details.
Having a single exit point reduces Cyclomatic Complexity and therefore, in theory, reduces the probability that you will introduce bugs into your code when you change it. Practice however, tends to suggest that a more pragmatic approach is needed. I therefore tend to aim to have a single exit point, but allow my code to have several if that is more readable.
I force myself to use only one return statement, as it will in a sense generate code smell. Let me explain:
function isCorrect($param1, $param2, $param3) {
$toret = false;
if ($param1 != $param2) {
if ($param1 == ($param3 * 2)) {
if ($param2 == ($param3 / 3)) {
$toret = true;
} else {
$error = 'Error 3';
}
} else {
$error = 'Error 2';
}
} else {
$error = 'Error 1';
}
return $toret;
}
(The conditions are arbritary...)
The more conditions, the larger the function gets, the more difficult it is to read. So if you're attuned to the code smell, you'll realise it, and want to refactor the code. Two possible solutions are:
Multiple returns
Refactoring into separate functions
Multiple Returns
function isCorrect($param1, $param2, $param3) {
if ($param1 == $param2) { $error = 'Error 1'; return false; }
if ($param1 != ($param3 * 2)) { $error = 'Error 2'; return false; }
if ($param2 != ($param3 / 3)) { $error = 'Error 3'; return false; }
return true;
}
Separate Functions
function isEqual($param1, $param2) {
return $param1 == $param2;
}
function isDouble($param1, $param2) {
return $param1 == ($param2 * 2);
}
function isThird($param1, $param2) {
return $param1 == ($param2 / 3);
}
function isCorrect($param1, $param2, $param3) {
return !isEqual($param1, $param2)
&& isDouble($param1, $param3)
&& isThird($param2, $param3);
}
Granted, it is longer and a bit messy, but in the process of refactoring the function this way, we've
created a number of reusable functions,
made the function more human readable, and
the focus of the functions is on why the values are correct.
I would say you should have as many as required, or any that make the code cleaner (such as guard clauses).
I have personally never heard/seen any "best practices" say that you should have only one return statement.
For the most part, I tend to exit a function as soon as possible based on a logic path (guard clauses are an excellent example of this).
I believe that multiple returns are usually good (in the code that I write in C#). The single-return style is a holdover from C. But you probably aren't coding in C.
There is no law requiring only one exit point for a method in all programming languages. Some people insist on the superiority of this style, and sometimes they elevate it to a "rule" or "law" but this belief is not backed up by any evidence or research.
More than one return style may be a bad habit in C code, where resources have to be explicitly de-allocated, but languages such as Java, C#, Python or JavaScript that have constructs such as automatic garbage collection and try..finally blocks (and using blocks in C#), and this argument does not apply - in these languages, it is very uncommon to need centralised manual resource deallocation.
There are cases where a single return is more readable, and cases where it isn't. See if it reduces the number of lines of code, makes the logic clearer or reduces the number of braces and indents or temporary variables.
Therefore, use as many returns as suits your artistic sensibilities, because it is a layout and readability issue, not a technical one.
I have talked about this at greater length on my blog.
There are good things to say about having a single exit-point, just as there are bad things to say about the inevitable "arrow" programming that results.
If using multiple exit points during input validation or resource allocation, I try to put all the 'error-exits' very visibly at the top of the function.
Both the Spartan Programming article of the "SSDSLPedia" and the single function exit point article of the "Portland Pattern Repository's Wiki" have some insightful arguments around this. Also, of course, there is this post to consider.
If you really want a single exit-point (in any non-exception-enabled language) for example in order to release resources in one single place, I find the careful application of goto to be good; see for example this rather contrived example (compressed to save screen real-estate):
int f(int y) {
int value = -1;
void *data = NULL;
if (y < 0)
goto clean;
if ((data = malloc(123)) == NULL)
goto clean;
/* More code */
value = 1;
clean:
free(data);
return value;
}
Personally I, in general, dislike arrow programming more than I dislike multiple exit-points, although both are useful when applied correctly. The best, of course, is to structure your program to require neither. Breaking down your function into multiple chunks usually help :)
Although when doing so, I find I end up with multiple exit points anyway as in this example, where some larger function has been broken down into several smaller functions:
int g(int y) {
value = 0;
if ((value = g0(y, value)) == -1)
return -1;
if ((value = g1(y, value)) == -1)
return -1;
return g2(y, value);
}
Depending on the project or coding guidelines, most of the boiler-plate code could be replaced by macros. As a side note, breaking it down this way makes the functions g0, g1 ,g2 very easy to test individually.
Obviously, in an OO and exception-enabled language, I wouldn't use if-statements like that (or at all, if I could get away with it with little enough effort), and the code would be much more plain. And non-arrowy. And most of the non-final returns would probably be exceptions.
In short;
Few returns are better than many returns
More than one return is better than huge arrows, and guard clauses are generally ok.
Exceptions could/should probably replace most 'guard clauses' when possible.
You know the adage - beauty is in the eyes of the beholder.
Some people swear by NetBeans and some by IntelliJ IDEA, some by Python and some by PHP.
In some shops you could lose your job if you insist on doing this:
public void hello()
{
if (....)
{
....
}
}
The question is all about visibility and maintainability.
I am addicted to using boolean algebra to reduce and simplify logic and use of state machines. However, there were past colleagues who believed my employ of "mathematical techniques" in coding is unsuitable, because it would not be visible and maintainable. And that would be a bad practice. Sorry people, the techniques I employ is very visible and maintainable to me - because when I return to the code six months later, I would understand the code clearly rather seeing a mess of proverbial spaghetti.
Hey buddy (like a former client used to say) do what you want as long as you know how to fix it when I need you to fix it.
I remember 20 years ago, a colleague of mine was fired for employing what today would be called agile development strategy. He had a meticulous incremental plan. But his manager was yelling at him "You can't incrementally release features to users! You must stick with the waterfall." His response to the manager was that incremental development would be more precise to customer's needs. He believed in developing for the customers needs, but the manager believed in coding to "customer's requirement".
We are frequently guilty for breaking data normalization, MVP and MVC boundaries. We inline instead of constructing a function. We take shortcuts.
Personally, I believe that PHP is bad practice, but what do I know. All the theoretical arguments boils down to trying fulfill one set of rules
quality = precision, maintainability
and profitability.
All other rules fade into the background. And of course this rule never fades:
Laziness is the virtue of a good
programmer.
I lean towards using guard clauses to return early and otherwise exit at the end of a method. The single entry and exit rule has historical significance and was particularly helpful when dealing with legacy code that ran to 10 A4 pages for a single C++ method with multiple returns (and many defects). More recently, accepted good practice is to keep methods small which makes multiple exits less of an impedance to understanding. In the following Kronoz example copied from above, the question is what occurs in //Rest of code...?:
void string fooBar(string s, int? i) {
if(string.IsNullOrEmpty(s) || i == null) return null;
var res = someFunction(s, i);
foreach(var r in res) {
if(!r.Passed) return null;
}
// Rest of code...
return ret;
}
I realise the example is somewhat contrived but I would be tempted to refactor the foreach loop into a LINQ statement that could then be considered a guard clause. Again, in a contrived example the intent of the code isn't apparent and someFunction() may have some other side effect or the result may be used in the // Rest of code....
if (string.IsNullOrEmpty(s) || i == null) return null;
if (someFunction(s, i).Any(r => !r.Passed)) return null;
Giving the following refactored function:
void string fooBar(string s, int? i) {
if (string.IsNullOrEmpty(s) || i == null) return null;
if (someFunction(s, i).Any(r => !r.Passed)) return null;
// Rest of code...
return ret;
}
One good reason I can think of is for code maintenance: you have a single point of exit. If you want to change the format of the result,..., it's just much simpler to implement. Also, for debugging, you can just stick a breakpoint there :)
Having said that, I once had to work in a library where the coding standards imposed 'one return statement per function', and I found it pretty tough. I write lots of numerical computations code, and there often are 'special cases', so the code ended up being quite hard to follow...
Multiple exit points are fine for small enough functions -- that is, a function that can be viewed on one screen length on its entirety. If a lengthy function likewise includes multiple exit points, it's a sign that the function can be chopped up further.
That said I avoid multiple-exit functions unless absolutely necessary. I have felt pain of bugs that are due to some stray return in some obscure line in more complex functions.
I've worked with terrible coding standards that forced a single exit path on you and the result is nearly always unstructured spaghetti if the function is anything but trivial -- you end up with lots of breaks and continues that just get in the way.
Single exit point - all other things equal - makes code significantly more readable.
But there's a catch: popular construction
resulttype res;
if if if...
return res;
is a fake, "res=" is not much better than "return". It has single return statement, but multiple points where function actually ends.
If you have function with multiple returns (or "res="s), it's often a good idea to break it into several smaller functions with single exit point.
My usual policy is to have only one return statement at the end of a function unless the complexity of the code is greatly reduced by adding more. In fact, I'm rather a fan of Eiffel, which enforces the only one return rule by having no return statement (there's just a auto-created 'result' variable to put your result in).
There certainly are cases where code can be made clearer with multiple returns than the obvious version without them would be. One could argue that more rework is needed if you have a function that is too complex to be understandable without multiple return statements, but sometimes it's good to be pragmatic about such things.
If you end up with more than a few returns there may be something wrong with your code. Otherwise I would agree that sometimes it is nice to be able to return from multiple places in a subroutine, especially when it make the code cleaner.
Perl 6: Bad Example
sub Int_to_String( Int i ){
given( i ){
when 0 { return "zero" }
when 1 { return "one" }
when 2 { return "two" }
when 3 { return "three" }
when 4 { return "four" }
...
default { return undef }
}
}
would be better written like this
Perl 6: Good Example
#Int_to_String = qw{
zero
one
two
three
four
...
}
sub Int_to_String( Int i ){
return undef if i < 0;
return undef unless i < #Int_to_String.length;
return #Int_to_String[i]
}
Note this is was just a quick example
I vote for Single return at the end as a guideline. This helps a common code clean-up handling ... For example, take a look at the following code ...
void ProcessMyFile (char *szFileName)
{
FILE *fp = NULL;
char *pbyBuffer = NULL:
do {
fp = fopen (szFileName, "r");
if (NULL == fp) {
break;
}
pbyBuffer = malloc (__SOME__SIZE___);
if (NULL == pbyBuffer) {
break;
}
/*** Do some processing with file ***/
} while (0);
if (pbyBuffer) {
free (pbyBuffer);
}
if (fp) {
fclose (fp);
}
}
This is probably an unusual perspective, but I think that anyone who believes that multiple return statements are to be favoured has never had to use a debugger on a microprocessor that supports only 4 hardware breakpoints. ;-)
While the issues of "arrow code" are completely correct, one issue that seems to go away when using multiple return statements is in the situation where you are using a debugger. You have no convenient catch-all position to put a breakpoint to guarantee that you're going to see the exit and hence the return condition.
The more return statements you have in a function, the higher complexity in that one method. If you find yourself wondering if you have too many return statements, you might want to ask yourself if you have too many lines of code in that function.
But, not, there is nothing wrong with one/many return statements. In some languages, it is a better practice (C++) than in others (C).