⛅ Coming soon: create Unison Cloud clusters in minutes on your own infrastructure. Learn more

Pattern matching on List

Pattern matching on List elements has its own special syntax.

Head and tail pattern matching

You can use pattern matching to scrutinize the first (left-most) element of a list with the +: syntax.

match ["a", "b", "c"] with head +: tail -> head _ -> "empty list"
"a"

The +: is unpacking the first element head to its text value "a" while keeping the remaining elements tail as a List. The underscore will match the "empty list" case. We could have also expressed _ -> "empty list" as [] -> "empty list" or List.empty -> "empty list". All three are valid ways of testing for the empty list case.

You can also pattern match on the last (right-most) element of a list in Unison:

match ["a", "b", "c"] with firsts :+ last -> last _ -> "empty list"
"c"

Put together, you can even pattern match on both ends of the list:

match ["a", "b", "c"] with first +: midSection :+ last -> first Text.++ last _ -> "fallback"
"ac"
If you find that you're mixing up :+ and +: in your pattern matches, remember that the colon : goes on the side of the COL-lection.

However, let's say you wanted to pattern match on the first 2 elements of a given list. It might be tempting to do a multi-item pattern match with successive +: operators, but recall that function application for operators always starts at the leftmost sub-expression.

🙅🏻‍♀️ This will not work:

match ["a","b","c"] with
  first +: second +: remainder -> "nope"
  _ -> "empty list"

first +: second is expecting second to be a type List, but what we're trying to express is that it's the unwrapped second element. Instead, if you want to pattern match on a particular list segment length or list segment values, you can use the [_] list constructor syntax.

Our example above can be rewritten:

match ["a", "b", "c"] with [first, second] ++ remainder -> first Text.++ " yes!" _ -> "fallback"
"a yes!"

Or if we don't care about binding the list elements to variables, we can use underscores to pattern match on any list that has exactly [_] elements:

match ["a", "b", "c"] with [_, _] ++ remainder -> "list has at least two elements" _ -> "fallback"
"list has at least two elements"