Delayed computations

Values in Unison are not, by default, lazily evaluated. But it's common to want to express that a value or calculation should be delayed until it's absolutely needed.

For example the termlongTextin the following snippet is evaluated strictly:

longText : Text
longText = "🐡 Imagine infinite monkeys on infinite typewriters πŸ™Šβ€¦"
coinflip longText =
  (bool -> (if bool then longText else "Hi")) : (Boolean -> Text)

But you might not actually need to evaluatelongText--thereare circumstances where the calculation of a value might be very expensive or could introduce surprising behavior if runeagerly.

One way you might solve for this is to create a "thunk": a function with no arguments which returns the desired value or computation when it's called.

longText : () -> Text
longText _ = "🐡 Imagine infinite monkeys on infinite typewriters πŸ™Šβ€¦"

Because this is a common pattern, Unison provides the single quote,',as syntactic sugar for representing a function with the form() -> a.

We can rewrite() -> Textas just'Text.

longText : 'Text
longText = '"🐡 Imagine infinite monkeys on infinite typewriters πŸ™Šβ€¦"

When we want to run the thunk, we could call the value with()to represent "I'm calling this with zero arguments", but Unison also provides syntactic sugar for "forcing" or calling a thunk with the!symbol.

Calling our functionlongTextlooks like:

coinflip : Boolean -> Text
coinflip bool = if bool then !longText else "Hi"

Simple enough… single quote,',introduces athunkand the bang symbol,!,executes it, but what if we want to callcoinflipwith an argumenttrueand then return the result of that function application in a thunk? Our final desired return type is'Text.To do that, we have to surround the function application forcoinflip truein parentheses before prepending the single quote symbol.

delayedText : 'Text delayedText = '(coinflip true) !delayedText
"🐡 Imagine infinite monkeys on infinite typewriters πŸ™Šβ€¦"
It might be tempting to write'coinflip truewith no parentheses in an attempt to get a return type of'Textor() -> Text,but the single quote syntax delays thefunctionin that circumstance, not the result of evaluating the function.'coinflip truehas the signature(() -> Boolean) -> Text)and we're trying to pass it an argument oftrue.πŸ™…πŸ»β€β™€οΈ That may not be what we're looking for. When we want to delay the result ofexecuting a function,we must surround the entire expression in parentheses.