Updated Documentation
- documentation being revised
- open to comments
switch Statement
Warning
Follow the rule that each value <val> used to select cases in a switch statement is unique. Bad things will happen if you break this rule.
If you have a duplicate <val> in a switch statement you may get a crash or an error message that looks like one of:
- A machine-level exception occurred during execution of this statement (signal 11)
- duplicate values in a switch: C_HANDLE and C_HANDLE
- <0063>:: duplicate case value used. case POINTER, HANDLE
That makes three different messages for what should be one error message. There seems to be a bug in the error reporting.
Bad Example:
The switch syntax is being used incorrectly--this example must fail.
include std/dll.e -- this fails switch 1 do case C_HANDLE then case C_POINTER, C_HANDLE then end switch -- on 32-bit OE4.1 --> duplicate values in a switch: C_HANDLE and C_POINTER -- on 64-bit OE4.1 --> A machine-level exception occurred during execution of this statement (signal 11)
The mystery is in the error reporting.
You can write a switch statement that fails:
- A machine-level exception occurred during execution of this statement (signal 11)
This problem may have something to do with how pointers are used internally by the interpreter.
Bad Example:
This example looks like it should work. No obvious answer for the failure.
constant expr = cos(0) constant val = expr switch expr do case val then puts(1, "expr = val \n" ) case else puts(1, "no match! \n") end switch -- this example fails when interpreted, but runs correctly when compiled
It is also true that there are users of the switch statement that do not have problems.
Need to know:
The case <val> must be literal, or a constant assigned its value from a literal, or an enum. It is a bad idea to assign val values by calling a function, it is likely to cause unpredictable results. And of course, they should never be declared as atoms, integers, sequences, or objects.
constant val1 = 1 -- good enum val1 -- good, since enums begin with 1 constant val1 = cos(0) constant val2 = cos(0) -- bad, works when compiled, crashes interpreter constant val1 = cos(0) constant val2 = val1 -- bad, only works when compiled atom val = 1 -- bad, since atoms are variables, as are integers and objects
In the simplest switch statement one case runs, or no cases run:
- one expression <expr> is evaluated
- the expression <expr> is compared against a series of "n" unique literal values <val1>|<val2>|...|<valn>
- a case occurs when an expression and a value matches
then the code for that case is allowed to run
switch <expr> do case <val1> then [case_code_block] case <val2> then [case_code_block] end switch
# every value is known in advance VALUE := literal_atom | literal_string | constant | enum val1 := VALUE val2 := VALUE # every value is unique val1 != val2
You can distribute unique <val> items between case branches in any way you wish. You can have a case with a list of <val> items. Remember, each <val> is a unique value.
The actions possible in a switch statement are known before a program runs. This means the interpreter (or compiler) is able to optimize for performance.
You can write equivalent code using a switch or using if..elsif.. statements:
switch statement |
|
if elsif statement |
atom a = 1 -- switch a do case 1 then ? a case 2 then ? a end switch |
atom a = 1 -- -- if a = 1 then ? a elsif a = 2 then ? a end if |
Nice to know
You can write a switch statement with more features.
- a case else branch
runs when the <expr> does not match any <val>
. - the fallthru keyword
allows the code in the following case branch to run
. - the break keyword
jumps you out of a switch statement
. - you can "label" a switch statement
when you nest switch statements this allows break "label" to specify which switch statement you are jumping out