Polyglot
Languages MATLAB pattern matching
MATLAB § pattern-matching

Switch and dispatch

MATLAB does not have pattern matching in the algebraic sense — there is no decomposing destructuring of values into constructors and bound names. It does, however, have a switch statement that dispatches on a scalar value through a sequence of case branches. The construct is convenient for finite enumerations, mode strings, and the dispatch of small finite state machines; it is appreciably more readable than a chain of elseif clauses.

switch syntax

switch expr
    case value1
        block1
    case value2
        block2
    case {value3a, value3b}            % cell — matches any of the values
        block3
    otherwise
        defaultBlock
end

The expression is evaluated once; each case value is compared to it with isequal-like semantics (numerical or string equality, no type coercion). The first matching branch is executed; control then falls out of the switch — there is no fall-through and no break is needed or permitted.

A cell argument to case matches when the expression equals any of the cell’s elements; it is the most-used MATLAB shortcut for the “or” case.

function speed = describe(mode)
    switch mode
        case "fast"
            speed = "quick";
        case {"medium", "default"}
            speed = "normal";
        case "slow"
            speed = "leisurely";
        otherwise
            error("Unknown mode: %s", mode)
    end
end

The otherwise branch is optional but is the conventional place to raise an error or to set a default; falling out of a switch without matching is silently OK.

Scalar dispatch only

MATLAB’s switch matches with equality and dispatches on a scalar expression. There is no:

  • range matching (case 1..10),
  • type matching (case Integer),
  • destructuring (case (x, y)),
  • guard clauses (case x when x > 0),
  • regular-expression matching.

Each of these patterns has a MATLAB idiom — if/elseif, isa, deconstruct-by-assignment, regexp — but the switch is not the place for them. For tagged-union style dispatch, the conventional approach is switch class(x) plus dispatch by class name; for state-machine style code, switch state plus reassignment.

A finite state machine

The canonical use of switch is a small state machine:

function transition(state, event)
    switch state
        case "idle"
            switch event
                case "start"
                    state = "running";
                case "configure"
                    state = "configuring";
            end
        case "running"
            switch event
                case "stop"
                    state = "idle";
                case "fault"
                    state = "error";
            end
        case "error"
            if event == "reset"
                state = "idle";
            end
    end
end

The doubly nested switch is the most-idiomatic MATLAB way to express the transitions; for larger state machines the Stateflow toolbox is the recommended alternative.

Switching on class

A canonical pattern in functions that accept multiple input classes is switch class(x):

function describe(x)
    switch class(x)
        case "double"
            fprintf("double of size %s\n", mat2str(size(x)))
        case "single"
            fprintf("single of size %s\n", mat2str(size(x)))
        case "char"
            fprintf("char string: %s\n", x)
        case "string"
            fprintf("string scalar: %s\n", x)
        case "cell"
            fprintf("cell of length %d\n", numel(x))
        otherwise
            fprintf("class: %s\n", class(x))
    end
end

The dispatch is convenient and is clearer than a chain of isa(x, ...) tests. For function dispatch on class — the OO-style polymorphism — classdef methods provide the cleaner mechanism (see Classes and OOP).

Why no destructuring

MATLAB’s value model is array-based: a value is an array of a single class, possibly nested through cells and structs. Algebraic destructuring requires either tagged unions (which MATLAB does not have natively) or types as patterns (which MATLAB’s switch does not support). The closest MATLAB has is the comma-separated-list expansion [a, b, c] = deal(...) — a multiple-return assignment that names the elements of an expanded list:

[m, n] = size(A);
[Q, R] = qr(A);
[V, D] = eig(A);

s = struct('x', 1, 'y', 2, 'z', 3);
[x, y, z] = deal(s.x, s.y, s.z);     % three separate scalars

c = {1, "two", [3 4 5]};
[a, b, d] = c{:};                     % brace expansion into LHS

These forms are not pattern matching; they are multiple assignment, with the right-hand side already producing N separate values. They cover the most common need: “this thing has known structure; give me the parts in named variables”.

A note on try/catch as dispatch

For dispatch by kind of failure — when the question is “did this raise an error of a specific class?” — the try/catch construct (covered on Error handling) is the appropriate mechanism. The ME.identifier is a colon-separated string that can be examined or matched with regexp. The convention is for the catch block to be a small bit of dispatch logic, not a full pattern match.

A note on regular expressions

Where another language would write a pattern match against a structured string, MATLAB writes a regexp:

[tokens, match] = regexp("name: Ada Lovelace; year: 1815", ...
                         'name: (\w+) (\w+); year: (\d+)', ...
                         'tokens', 'match', 'once');
% tokens = {'Ada', 'Lovelace', '1815'}
% match = "name: Ada Lovelace; year: 1815"

For text-extraction-as-pattern-match, regexp with 'tokens' and 'names' is the canonical mechanism; for typed pattern matching on structured data, no mechanism exists in the base language.