Skip to main content

Advanced topics

Attributes

Attributes are given to module-level declarations to control how they are treated by the compiler. Attributes appear in #[...] before the declaration and can be applied to module-level type, function, and constant declarations.

implicit attribute

Refer to the implicits for information on #[implicit].

The link attribute links a function against a function implemented in Erlang. It accepts two parameters: an Erlang module name and an Erlang function name. The linked function and the name of the function in Fuyu may be different. It is a compile-time error if this function is not found.

#[link "lists" "last"]
last: List a -> a

The module name can be a path to a file. In this case, it must start with either ./ or ../.

#[link "./wrapper.erl" "last"]
last: List a -> a

public attribute

The public attribute makes a declaration available outside of the module. Refer to visibility.

test attribute

The test attribute is given to functions that run test code. They will be ignored in compilation except for when generating tests.

import std/assert

#[test]
test_equals: () -> ()
test_equals () = assert.eq 123 123

test_helper attribute

The test_helper attribute is given to functions, types, and constants that are used only in tests.

import std/assert
import std/list

#[test_helper]
all_eq: &[Eq a] -> List a
all_eq xs = xs match
[x, y, *rs] ->
assert.eq x y
all_eq [y, ..rs]
_ -> ()

#[test]
test_all_eq: () -> ()
test_all_eq () = all_eq [123, 123, 123]

transparent attribute

The transparent attribute marks a type as transparent. Refer to transparency.

Panic

A panic is used when a non-recoverable error state is reached and the chosen solution is to terminate the process.

checked_div: Float -> Float -> Float
checked_div x 0 = panic
checked_div x y = x / y

An optional message for the panic can be given by any expression that evaluates to a string.

checked_div: Float -> Float -> Float
checked_div x 0 = panic "Cannot divide by zero."
checked_div x y = x / y

Todo

A todo is used to mark incomplete code with the intention to complete it later. It will produce a compile-time warning and panic if evaluated.

greatest_common_divisor: Int -> Int -> Int
greatest_common_divisor a b = todo

Using todo has another benefit for this function: it will only produce one warning instead of three. When todo appears in a function, warnings about unused variables are not emitted, as it is assumed that they will be used once the function is implemented.

An expression evaluating to a string can be used with todo as the panic message.

greatest_common_divisor: Int -> Int -> Int
greatest_common_divisor a b = todo "Implement using the Euclidean algorithm."
tip

For functions that are not implemented and with no intent to do so, use unimplemented instead.

Unimplemented

An unimplemented is used to mark incomplete code with no intention to complete it later. It will produce a compile-time warning and panic if evaluated. This is most commonly used in implicits and higher-order functions for which it is known the function is never called.

The unimplemented behaves exactly like todo. The difference is that unimplemented is used when there is no intent to implement the function, and todo is used when there is.

tip

When a function is not yet implemented but there is intent to do so, use todo.

Unreachable

An unreachable expression is used to mark a branch of code that will never be reached. If it happens to be evaluated, it will panic.

describe: Option Int -> String
describe (Some x) if x > 0 = "positive"
describe (Some x) if x == 0 = "zero"
describe (Some x) if x < 0 = "negative"
describe (Some _) = unreachable // Required for pattern exhaustion.
describe None = "nothing"

An expression evaluating to a string can optionally be added that is displayed as the panic message.

describe_as_square: Int -> String
describe_as_square n =
let x = when
n > 100 -> 100
n < 0 -> 0
else -> n
let s = math.sqrt x
when
x <= 3 -> "small square"
x <= 7 -> "medium square"
x <= 10 -> "large square"
else -> unreachable "The square root can never be greater than 10."