Pattern Matching

Pattern matching brings together the POSIX regex(3) with a form of cond clauses.

Broadly, an expression is evaluated and expected to return a string. That string is then used to match against with a series of pattern/regular expressions.

If the match is successful then the result of the pattern matching expression is the result of evaluating the expr part of the clause as though it were an implicit => clause with r as the supplied parameter. Something like:

function (r) {
  expr
}

r will be the result of regexec and therefore an array of at least one element which is the entire matched string. If the pattern match contained any parenthesised sub-expressions they will be subsequent elements of the array.

Note

The pattern matching expressions stash any compiled literal string regular expressions in a global table. This means that in loops the regular expression doesn’t need to be recompiled. It also means the compiled regular expressions are not reaped until Idio exits.

Note

These examples put parenthesis around the whole pattern matching expression. That doesn’t change the way it is interpreted, any expression with multiple elements is treated as a list by the reader.

Here, it probably helps your $EDITOR indent the text properly with clauses on separate lines!

regex-case

The general form is regex-case e [clauses] with each clause being ("regex" expr).

Suppose we want to match a common var=value assignment:

(regex-case (read-line)
  ("^([:alpha:][[:alnum:]_]*)=(.*)" {
    printf "%s is '%s'\n" r.1 r.2
  }))

Here we use read-line to read a line of input from the current input handle. If that string matched the POSIX regex "^([:alpha:][[:alnum:]_]*)=(.*)" then the regexec result, an array, will be passed as the parameter r to the given expression.

That expression prints out the two regex sub-expressions, the var and value.

pattern-case

pattern-case is a derivative of regex-case where the “pattern matches” have * and ? replaced with .* and . and the code continues like regex-case.

Suppose we want an unreliable method to determine if this is a BSD-style operating system:

(pattern-case (collect-output uname -s)
  ("*BSD" {
    printf "%s is a BSD\n" r.0
  }))

Here we collect the output from the command uname -s and compare it to the pattern "*BSD". Operating systems like FreeBSD and OpenBSD will match.

Last built at 2026-01-04T22:40:02Z+0000 from da47fd3 (dev)