## 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: ...
      location steady: ...
    end

    alg int acceleration = switch controller:
                             case accelerate:  5
                             case decelerate: -3
                             case steady:      0
                           end;

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.