I come from a C/Java background where switch cases have a cascading effect unless you put a break statement
switch(index)
{
case 0: doSomething();
case 1: doSomethingElse();
// ...
}
So case 0 cascades to case 1.
Is this the case with VB? Will case 0 cascade to case 1 automatically as above?
Select Case Index
Case 0 ' code
Case 1 ' code
...
End Select
No, the Select/Case in VB6 does not have a "break" statement. In fact, I don't think that "break" is even a reserved word in VB6.
If code in case 0 runs, then it will not cascade to case 1.
Related
I ran across this piece of pascal code. I am curious as to how this does not repeat endlessly.
repeat
if xs>(torgx+xlim)
then begin
x:=xlim;
BREAK;
end;
if xs<(torgx-xlim)
then begin
x:=0-xlim;
BREAK;
end;
x:=xs-torgx;
BREAK;
until 0<>0;
I am confused as to how zero would ever be greater than or less than zero.
A loop that continues until 0 <> 0 is supposed to be endless.
But inside the loop there are some conditions that will break the loop, hence the use of the keyword break.
In fact, the repeat..until loop will only run once. The comparison is made that if a value is larger than a condition or less than another it will break out of the loop. If none of those conditions are met, it will break anyway.
To start with, I'll show some code:
//Declarations
bool cmp=filter();
//case 1
cmp && mainOperation();
cmp || elseOperation();
//case 2 :void*
cmp ?
mainOperatiom() &&
elseOperation() ;
//case 3
cmp || goto other;
mainOperation();
goto end;
other:
elseOperation();
end:
//case 0
if(cmp){
mainOperation();
} else {
elseOperation();
}
I'm actually not sure what the differences are between these codes from complexity view.
I'd like to know which case compiles the same as case 0? I mean which set of instructions will compile the same bytecode as the if statement.
Use case 0. It's readable, it's what any serious developer would use, it's the code that you are not asked to change in a code review, it's the code that I can read without thinking "what kind of xxxxx wrote this".
If you are even thinking about using another version to make your code run faster, then you need to learn how to save microseconds or milliseconds, not nanoseconds.
I am trying to understand the switch/fallthrough keyword. Using fallthrough statement in a switch block means the next block is entered even if the expression doesn't match but this is only valid when there has already been a match right? The code below seems to work that way but I just want to be sure.
package main
import "fmt"
func main() {
integer := 5
switch integer {
case 4:
fmt.Println("integer <= 4")
fallthrough
case 5:
fmt.Println("integer <= 5")
fallthrough
case 6:
fmt.Println("integer <= 6")
fallthrough
case 7:
fmt.Println("integer <= 7")
fallthrough
case 8:
fmt.Println("integer <= 8")
fallthrough
default:
fmt.Println("default case")
}
}
Yes. The fallthrough statement transfers control to the next case clause in an expression switch. The expression on the next case is not considered when transferring control.
The specification says this about the fallthrough statement:
A "fallthrough" statement transfers control to the first statement of the next case clause in an expression "switch" statement. It may be used only as the final non-empty statement in such a clause.
and this about expression switches:
In a case or default clause, the last non-empty statement may be a (possibly labeled) "fallthrough" statement to indicate that control should flow from the end of this clause to the first statement of the next clause. Otherwise control flows to the end of the "switch" statement. A "fallthrough" statement may appear as the last statement of all but the last clause of an expression switch.
That's right. The fallthrough statement causes it to go from the last statement on a case clause to the first statement of the next skipping the later case evaluation. From the spec:
In a case or default clause, the last non-empty statement may be a
(possibly labeled) "fallthrough" statement to indicate that control
should flow from the end of this clause to the first statement of the
next clause. Otherwise control flows to the end of the "switch"
statement. A "fallthrough" statement may appear as the last statement
of all but the last clause of an expression switch.
I have the following code:
package main
import (
"fmt"
)
func main() {
switch {
case 1 == 1:
fmt.Println("1 == 1")
fallthrough
case 2 == 1:
fmt.Println("2 == 1")
}
}
Which prints both lines on the go playground - see example here. I would have expected the fallthrough statement to include evaluation of the next case statement, but this seems not to be the case.
Of course, I can always use a bunch of if statements, so this is not a real impediment, but I am curious what the intention here is, since this seems to me to be a non-obvious result.
Anyone care to explain? For example: in this code, how can I get the 1st and 3rd cases to execute?
Switch is not a bunch of ifs. It's more akin to if {} else if {} construct, but with a couple of twists - namely break and fallthrough. It's not possible to make switch execute first and third cases - a switch does not check each condition, it finds first match and executes it. That's all.
It's primary purpose is to walk through a list of possible values and execute a different code for each value. In fact, in C (where switch statement came from) switch expression can only be of integral type and case values can only be constants that switch expression will be compared too. It's only relatively recently, languages started adding support for strings, boolean expressions etc in switch cases.
As to fallthrough logic it also comes from C. There is no fallthrough operator in C. In C execution falls through into next case (without checking case values) unless break operator encountered. The reason for this design is that sometimes you need to do something special and then do same steps as in another case. So, this design merely allows that. Unfortunately, it's rather rarely useful, so falling through by default was causing more trouble when programmer forgotten to put a break statement in, then actually helping when truly omitted that break intentionally. So, many modern languages change this logic to never fall through by default and to require explicit fallthrough statement if falling through is actually required.
Unfortunately, it's a it hard to come up with a non contrived example of fallthrough being useful that would be short enough to fit into an answer. As I said it's relatively rare. But sometimes you need to write code similar to this:
if x == a || x == b {
if x == a {
// do action a
}
// do action ab
} else if x == c {
// do action c
} else if x == d {
// do action d
}
In fact, I needed code of similar structure quite recently in one of my projects. So, I used switch statement instead. And it looked like this:
switch x {
case a: // do action a
fallthrough
case b: // do action ab
case c: // do action c
case d: // do action d
}
And your switch from the question is functionally equivalent to this:
if 1 == 1 || 2 == 1 {
if 1 == 1 {
fmt.Println("1 == 1")
}
fmt.Println("2 == 1")
}
Presumably, Go's fallthrough behavior is modeled after C, which always worked like this. In C, switch statements are just shorthands for chains of conditional gotos, so your particular example would be compiled as if it was written like:
# Pseudocode
if 1 == 1 goto alpha
if 2 == 1 goto beta
alpha:
fmt.Println("1 == 1")
beta:
fmt.Println("2 == 1")
As you can see, once execution enters the alpha case, it would just keep flowing down, ignoring the beta label (since labels by themselves don't really do anything). The conditional checks have already happened and won't happen again.
Hence, the non-intuitive nature of fallthrough switch statements is simply because switch statements are thinly veiled goto statements.
From the language spec:
A "fallthrough" statement transfers control to the first statement of the next case clause in an expression "switch" statement. It may be used only as the final non-empty statement in such a clause.
That seems to perfectly describe your observed behavior.
I'm refactoring some code I wrote and I have to decide if I wanna put a switch statement into a while loop or repeat the while loop into each case blocks. The two different ways are something like the following pseudocode:
Option 1)
while (cnt > 0) {
switch (value) {
case A:
doSomething();
break;
case B:
doSomethingElse();
break;
...
default:
default();
break;
}
cnt--;
}
Option 2)
switch (value) {
case A:
while( cnt > 0){
doSomething();
cnt--;
}
case B:
while( cnt > 0){
doSomethingElse();
cnt--;
}
...
default:
while( cnt > 0){
default();
cnt--;
}
}
I think the first option follows better the DRY principle because I don't repeat every time the while and the cnt--. Although I like a bit better the second option because once it picks a case in the switch statement, it starts to loop in the while and it doesn't have to evaluate the switch condition anymore.
So, which of these two solutions would you pick and why?
NB: We can assume that the switch-condition (i.e. the variable "value" in the code below) doesn't change for the entire while loop, in other words: the operations doSomething(), doSomethingElse() etc. do not affect the switch statement.
NB2: In the real code I'm working on, the while loop can be very huge. "Cnt", for some test cases, can be of the order of 10^9
In most cases, a Loop-switch sequence is an antipattern you should avoid for the sake of clarity, and since you mention cnt can become quite huge also for the sake of performance.
If cnt is used only to control how many times doSomething(), etc., are called, you should consider passing it into the method and looping inside the method. Normally I would say don't worry about performance, but if you're actually talking about 10^9 iterations, you should avoid repeating the switch.
Option 2 is more straightforward as you are putting the emphasis on the switch-statement and having to work through a case in every iteration might consume more time.