Destructuring binds

Tuples and data types can be decomposed with pattern matching, but Unison also provides several ways to more concisely bind variable names to the corresponding parts of a data structure.

Destructuring tuples

Variables can be assigned to the constituent parts of a tuple by surrounding the variable definition with parentheses and separating the variables with commas.

use Nat + tuple = (1, 2) let (first, second) = tuple first + second
3

🎨 If a tuple is passed as an argument to a lambda, you can use the cases keyword as a way to destructure the tuple.

distributed.lib.base.data.List.map (cases (first, second) -> second) [(1, 2), (3, 4)]

Destructuring data types

The fields of a data type can also be bound to variables by destructuring their data constructors

Say you have a simple Box type:

You could write a function that adds two Box Nat types together by accessing the Nat elements like this:

addBox : Box Nat -> Box Nat -> Nat
addBox boxA boxB =
  use Nat +
  (Box a) = boxA
  (Box b) = boxB
  a + b

So destructuring a data type takes the form (DataConstructor field1 field2 … fieldN) = instanceOfDataType

Usage notes

Currently, Unison does not support decomposition in term definitions, so a function which accepts a tuple or data type as a parameter cannot be destructured when the function parameter is first named. This means a termDeclaration like addTwo : (Nat, Nat) -> Nat can not be implemented with a term definition which starts with addTwo (one,two) = one + two. The decomposition of the tuple would have to be done on a separate line.

In some languages you can use list constructors like List.+: or List.:+ to name separate elements in the list. We do not currently support that feature for term definitions, but you can use them in pattern matching; see list pattern matching for more details.

-- you can't do this
list = [1,2,3,4]
one +: tail = list
list = [1, 2, 3, 4]

(one +: tail) = list