Strings, pipes & defaults
ImplementedTemplate strings with ${...}, the pipe operator ->, and ?? for options. Each one desugars before hashing.
Interpolation
A template string is written with backticks. ${...} holds any expression; the checker picks the conversion from the
expression’s type (string as is, int, float, and bool as "true" or "false"). It desugars to the
++ chain you would have written by hand, so the two hash identically.
let greet = (name: string, n: int): string => `Hello, ${name}! You are number ${n}.`
let flag = (b: bool): string => `it is ${b}`Escapes are \`, \$, \\, \n, \r, \t and \"; a $ not followed by { is plain text and a template may
span lines. Records, variants, lists and tuples are not converted for you (convert them yourself), and a parameter
with no annotation has no type to pick a conversion from, so annotate it. Int.toText(n) is also callable directly.
The pipe
a->f(b) is f(a, b): the left value goes in as the first argument. A single _ among the arguments says where it
goes instead. It is a pure rewrite, so the pipe and the direct call share one hash.
let double = (n: int): int => n * 2
let sub = (a: int, b: int): int => a - b
let a = 4->double->double
let b = 10->sub(3, _)
let c = [1, 2, 3]->List.map(double)Not built: piping directly into a lambda literal.
Defaults with ??
d["k"] ?? 0 gives the value, or the default when the key (or list element) is missing. It is a switch on the
option, the default is only evaluated when needed, and it binds between a comparison and +, right-associatively.
See Lists, dictionaries & options.