If and switch expressions

In some models one wants to produce different values under different circumstances. Or one needs to convert from one type to another type. `if` and `switch` expressions provide means to do this in a concise manner. This lesson provides an introduction to both these expressions. For more practical examples, see the simulation model of the synthesis-based engineering example elsewhere in the documentation.

If expression

Consider the following expression:

``if x > 0: 1 elif x < 0: -1 else 0 end``

This expression takes a real number `x` and produces its sign. The `if` expression is used to detect the different situations, and to produce the correct result in each of those situations.

An `if` expression always consist of the `if` and the `else` parts. In between can optionally be any number of `elif` parts:

``````if x > 0: 1 elif x < 0: -1 else 0 end
if x > 0: 1 else 0 end
if x > 0: 1 elif x < -10: -2 elif x < 0: -1 else 0 end``````

If the 'guard predicate' of an `if` or `elif` (the expression before the `:`) holds, that alternative is chosen. In the following example, if `x` has a value of `2` and `y` a value of `3`, then value `-2.8` is produced:

``if x > 0 and y = 2: 1.5 elif x > 0 and y != 2 or x < 0: -2.8 else 0.1 end``

The `if` and `elif` alternatives are considered in order. The first alternative that has a guard that holds determines what value is produced by the `if` expression. Consider the following `if` expression:

``if x > 0: 1.5 elif x > 0: -2.8 else 0.1 end``

For any value `x > 0`, this `if` expression produces `1.5`. It will never produce `-2.8`, as the `if` part is considered before the `elif` part.

Switch expression

Similar to an `if` expression, a `switch` expression can be used to produce different values under different circumstances. Consider the following partial CIF model:

``````enum mode = OFF, ON1, ON2, ON3, DISCONNECTED;
automaton rotary_switch:
disc mode m = OFF;
...
end

alg int speed = switch rotary_switch.m:
case ON1: 5
case ON2: 10
case ON3: 15
else      0
end;
end``````

This `switch` expression takes the operation mode `rotary_switch.m` and provides the speed corresponding to that mode. If the value of `m` matches one of the cases, the `switch` expression will produce the corresponding value. For example, if `m` has value `ON2`, this `switch` expression produces `10`. If none of the cases match, the value of the `else` case is taken. For example, if `m` has value `DISCONNECTED`, this `switch` expression produces `0`. Note that multiple values can be captured by the `else` case, i.e., you do not have to cover each possible value with a separate case.

One can use different kinds of types as long as the types of the cases match the type of the `switch` expression. In the example above, `m` is of type `mode`, which is an enumeration. Hence all cases should be of type `mode` as well. Below is an example using a ranged integer in the `switch` expression:

``````alg int[0,2] num_products;

alg string display_text = switch num_products:
case 0: "There are no products in the buffer."
case 1: "There is one product in the buffer."
case 2: "There are two products in the buffer."
end;``````

One can also use an automaton as a variable of the `switch` expression, where the cases have to be locations of that automaton:

``````automaton controller:
location accelerate: ...
location decelerate: ...
Note that in this `switch` expression we omitted the `else` case, as the three cases together already cover all possible locations of automaton `controller`.
It is possible to rewrite a `switch` expression into an `if` expression (the other way around is not always possible). This rewrite can be automated using a CIF to CIF transformation.