<- ^ ->
Pattern matching unions

13   Pattern matching unions

Similarly as with tuples, pattern matching is the only way to get to the value of union. Union patterns consists of field name followed by nothing, [], pattern enclosed in [] or tuple pattern. This mimics ways, one can construct union value.

Following example utilizes pattern matching in simple symbolic expression computations environment.

        union exp {
                int Const;
                void Var;
                *[exp, exp] Add;
                *[exp, exp] Sub;
                *[exp, exp] Mul;
                *[exp, exp] Div;
        }
        
        int compute(exp e, int v)
        {
                switch e {
                case Const[x]    : return x;
                case Var         : return v;
                case Add[e1, e2] : return compute(e1, v) + compute(e2, v);
                case Mul[e1, e2] : return compute(e1, v) * compute(e2, v);
                case Div[e1, e2] : return compute(e1, v) / compute(e2, v);
                case Sub[e1, e2] : return compute(e1, v) - compute(e2, v);
                }
        }

        exp diff(exp e)
        {
                switch e {
                case Const[_]    : return Const[0];
                // both Var and Var[] are legal
                case Var[]       : return Const[1];
                case Add[e1, e2] : return Add[diff(e1), diff(e2)];
                case Sub[e1, e2] : return Sub[diff(e1), diff(e2)];
                case Div[e1, e2] :
                        exp up = Sub[Mul[diff(e1), e2], Mul[e1, diff(e2])];
                        exp down = Mul[e2, e2];
                        return Div[up, down];
                case Mul[e1, e2] : 
                        return Add[Mul[diff(e1), e2], Mul[e1, diff(e2])];
                }
        }

13.1   What happen to C's switch and enums?!?

Hmm... they are still there:

        union color {
                void Red;
                void Green;
                void Blue;
        }
This is roughly equivalent of C's:

        typedef enum {
                Red, 
                Green, 
                Blue 
        } color 
Then we do:

        string color_name(color c)
        {
                string r;
                
                switch (c) {
                case Red: 
                        r = "red";
                case Green: 
                        r = "green";
                // Blue[] is also legal
                case Blue: 
                        r = "blue";
                }

                return r;
        }
This looks almost like C, modulo one little issue. There is no fall through. Each case is separate branch or program execution. One doesn't need to write break statements. In fact, break would break loop enclosing switch, if there is any!

13.2   Fall through disclaimer

If you don't like the no-fall-through clause, please first consider following snippet of code:

        switch e {
        case Mult[e1, e2]:
                // here we do fall through
        case Const[x]:
                // hmm... what does x mean, if we fall through from Mult[...]?
                // and what can e1 and e2 mean here, if we didn't fall
                // through?
        }
Because case can bind new variables, it has to introduce new scope. So fall through is impossible.

<- ^ ->
Pattern matching unions