8.16.0.4

7.2 Annotations for Optional Values🔗ℹ

Sometimes, a function accepts an optional value, and it makes sense to allow #false to indicate “nothing.” A function could annotate such an option with || False.

fun name(first :: String, last :: String || False):

  first ++ (if last | " " ++ last | "")

> name("Homer", "Simpson")

"Homer Simpson"

> name("Stu", #false)

"Stu"

A drawback of using || is that static information is lost in the case of a non-#false value. In the preceding example, " " ++ last is not statically resolved to string concatenation.

The maybe annotation constructor is a shorthand for || False, but it also cooperates with operators like !!, which returns its argument only if it is non-#false and throws an exception otherwise. If the argument to !! has static information from maybe(annot), then the result from !! has the static information of annot.

fun name(first :: String, last :: maybe(String)):

  use_static

  first ++ (if last | " " ++ (last!!) | "")

> name("Homer", "Simpson")

"Homer Simpson"

> name("Stu", #false)

"Stu"

The ?. operator is like the . operator, but it produces #false without accessing a field or method if the expression before ?. produces #false. It also recognizes maybe static information for the expression before ?., which enables static dispatch for a non-#false value.

fun len(str :: maybe(String)) :: Int:

  use_static

  str?.length() || 0

> len("apple")

5

> len(#false)

0

The || operator similarly cooerates with maybe for the left-hand argument to ||. Since a #false result from the left-hand argument is never used as the result, if it has static information from maybe(annot), then it can be treated as having the static information of annot.

fun len(str :: maybe(String)) :: Int:

  use_static

  (str || "").length()

> len("apple")

5

> len(#false)

0

Along similar lines, the static information of a && expression corresponds to the static information of its right-hand argument, but adjusted in the same way as by maybe.

The && operator can serve the same role as the elvis operator ?: that is provided some other languages.

fun ms(name :: maybe(String)) :: maybe(String):

  use_static

  (name && "Ms. ")?.append(name)

> ms("Smith")

"Ms. Smith"

> ms(#false)

#false