function syntax
function syntax
ferrule uses function for everything. named functions, anonymous functions, inline lambdas. no arrows, no fn, no shorthands. one way to write functions.
declaration form
function name<TypeParams>(params...) -> ReturnType error ErrorDomain effects [...] {
// body
}
everything after ReturnType is optional.
named functions
function add(x: i32, y: i32) -> i32 {
return x + y;
}
function greet(name: String) -> String {
return "hello, " ++ name;
}
anonymous functions
same function keyword:
const double = function(x: i32) -> i32 {
return x * 2;
};
const greet = function(name: String) -> String {
return "hello, " ++ name;
};
inline functions
when passing functions as arguments:
map(items, function(item: Item) -> String {
return item.name;
});
filter(numbers, function(n: i32) -> Bool {
return n > 0;
});
prefer named functions for clarity:
function getName(item: Item) -> String {
return item.name;
}
function isPositive(n: i32) -> Bool {
return n > 0;
}
map(items, getName);
filter(numbers, isPositive);
parameters
basic
function add(x: i32, y: i32) -> i32 {
return x + y;
}
inout (by reference)
function increment(inout counter: u32) -> Unit {
counter = counter + 1;
}
the mutation is visible to the caller. see ../core/declarations.md.
capabilities
function readFile(path: Path, cap fs: Fs) -> Bytes error IoError effects [fs] {
return check fs.readAll(path);
}
see ../modules/capabilities.md.
return types
every function must declare a return type:
function greet(name: String) -> String {
return "hello, " ++ name;
}
use Unit for functions that don't return a meaningful value:
function log(message: String, cap io: Io) -> Unit effects [io] {
io.println(message);
}
generic functions
function identity<T>(x: T) -> T {
return x;
}
function swap<T, U>(pair: { first: T, second: U }) -> { first: U, second: T } {
return { first: pair.second, second: pair.first };
}
see ../core/generics.md.
error clauses
functions that can fail declare their error domain:
function parsePort(s: String) -> Port error ParseError {
// can use ok/err/check/ensure
}
effects declaration
function fetch(url: Url, cap net: Net, cap clock: Clock) -> Response error ClientError effects [net, time] {
// may perform net and time effects
}
see effects.
function types
function types in type annotations:
type Predicate<T> = (T) -> Bool;
type Mapper<T, U> = (T) -> U;
type Handler<T, E> = (T) -> Unit error E effects [io];
const isEven: Predicate<i32> = function(n: i32) -> Bool {
return n % 2 == 0;
};
complete example
function save(
path: Path,
data: View<u8>,
cap fs: Fs
) -> Unit error IoError effects [fs] {
return check fs.writeAll(path, data);
}
summary
| form | syntax |
|---|---|
| named | function name(...) -> T { ... } |
| anonymous | const f = function(...) -> T { ... }; |
| inline | map(items, function(x: T) -> U { ... }) |
| generic | function name<T>(...) -> T { ... } |
| with effects | function name(...) -> T effects [...] { ... } |
| with error | function name(...) -> T error E { ... } |