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) - (Number * String * Symbol)
(values 1 "milk" 'apple)
> (values '(1 2 3) #f) - ((Listof Number) * Boolean)
(values '(1 2 3) #f)
Using values, this consume function can effectively return two values each time that it is called:
(define (consume [s : String]) : (Symbol * String) (cond [(equal? s "milk") (values 'drink "Mmm....")] [(equal? s "beets") (values 'eat "Ugh....")] [else (values 'sleep "Zzz...")]))
To extract the component values from a tuple, match the tuple with names using define-values.
> (consume "milk") - (Symbol * String)
(values 'drink "Mmm....")
> (define-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 Plait predefines a helpful datatype called Optionof:
(define-type (Optionof 'a) (none) (some [v : 'a]))
The 'a in this definition of Optionof indicates that you can return any kind of value in a some.
> (define (get-slogan [s : String]) : (Optionof String) (cond [(equal? 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)
> (type-case (Optionof String) (get-slogan "moon pie") [(some s) s] [(none) "no comment"]) - String
"no comment"