Macros & Attributes
Here's a secret about the syntax you've been using: fn, while, for and so on aren't keywords. They're macros.
Macro syntax
The syntax a b c applies the macro a to the inputs b and c. Macros read to the end of the line – but lines absorbed by brackets don't count, so
if cond {
truth
} else {
falth
}
invokes the if macro with four arguments: cond, { truth }, else and { falth }. This is why multi-line constructs hang together the way they do, and why bodies want braces: the macro sees a handful of trees, and { ... } is how you hand it a block.
User-defined macros are not yet implemented, but many basic constructs (for, match) are AST transforms over this scheme, and there are some handy built-in macros:
show x– print an expression and its value:(2 + 2) = 4.test x– printpass: ...orfail: ...depending on whetherxis true. The standard library's own tests are written with it.bundle,for,match– covered in earlier chapters.async { ... }– run a block concurrently (early days; see Status).
Attributes
The @foo attribute syntax is general. Attributes are somewhat like macros – they read arguments up to the end of the line, and apply to the next line. But unlike macros they are passive: they get passed as metadata to the relevant macro, which decides how to interpret them.
The ones you'll meet:
@label names a loop or block, as a target for break and continue (Control Flow):
@label outer
for i = range(0, 3) { ... }
@extend adds a method to a function from another module (Multiple Dispatch):
@extend
fn Float32(x: Float64) {
wasm { f32.demote_f64(x: f64): f32 }
}
@doc attaches a markdown doc string to a definition:
@doc """
identity(x) == x
The identity function.
"""
fn identity(x) { x }
Template strings
Strings can be tagged too, with a prefix that alters how the string is interpreted – r for regexes, js for inline JavaScript. See Strings and Calling JavaScript.