1.12 Tuples and Options🔗ℹ

If you want to combine a small number of values in a single value, and if the values have different types (so that a list doesn’t work), you can use a tuple as an alternative to creating a new datatype with a single variant.

The values form creates a tuple from any number of values. The type of a tuple reveals the type of every component value in the tuple, separating the types with *.

> values(1, "milk", #'apple)

- Int * String * Symbol

values(1, "milk", #'apple)

> values([1, 2, 3], #false)

- Listof(Int) * Boolean

values([1, 2, 3], #false)

Using values, this consume function can effectively return two values each time that it is called:

fun consume(s :: String) :: (Symbol * String):

  cond

  | s == "milk": values(#'drink, "Mmm....")

  | s == "beets": values(#'eat, "Ugh....")

  | ~else: values(#'sleep, "Zzz...")

> consume("milk")

- Symbol * String

values(#'drink, "Mmm....")

To extract the component values from a tuple, match the tuple with names using def values.

> def values(action, response) = consume("beets")

> action

- Symbol

#'eat

> response

- String

"Ugh...."

The convenience functions fst and snd can be used in the special case of a 2-value tuple to extract the first or second component.

> snd(consume("milk"))

- String

"Mmm...."

Sometimes, instead of always returning multiple values, you’ll want a function that returns either one value or no value. A tuple is no help for that case, but Shplait predefines a helpful datatype called Optionof:

type Optionof(?a)

| none()

| some(v :: ?a)

The ?a in this definition of Optionof indicates that you get to pick the type of value every time that you use some.

fun get_slogan(s :: String) :: Optionof(String):

  cond

  | s == "milk": some("It does a body good")

  | ~else: none()

> get_slogan("milk")

- Optionof(String)

some("It does a body good")

> get_slogan("iced tea")

- Optionof(String)

none()

> match get_slogan("moon pie"):

  | some(s): s

  | none(): "no comment"

- String

"no comment"