Functions¶
Functions are the basic building blocks of FastC programs.
Function Declaration¶
Example¶
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
fn multiply(x: i32, y: i32) -> i32 {
return x * y;
}
Void Functions¶
Functions that don't return a value omit the return type:
fn greet(name: slice(u8)) {
// Do something with name
}
fn log_error(code: i32) {
// Log the error
}
Calling Functions¶
The main Function¶
Every executable needs a main function:
The return value becomes the process exit code.
Parameters¶
Pass by Value¶
By default, parameters are passed by value (copied):
Pass by Reference¶
Use reference types to pass by reference:
fn increment(x: mref(i32)) {
deref(x) = deref(x) + 1;
}
fn main() -> i32 {
let value: i32 = 10;
increment(addr(value));
// value is now 11
return 0;
}
Recursion¶
Functions can call themselves:
fn factorial(n: i32) -> i32 {
if n <= 1 {
return 1;
}
return n * factorial(n - 1);
}
fn fibonacci(n: i32) -> i32 {
if n <= 1 {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
Forward References¶
Functions can be called before they're defined:
Unsafe Functions¶
Functions that require unsafe context to call:
unsafe fn dangerous_operation(ptr: rawm(i32)) {
deref(ptr) = 42;
}
fn main() -> i32 {
let x: i32 = 0;
unsafe {
dangerous_operation(addr(x));
}
return 0;
}
See Unsafe Code for details.
Public Functions¶
In a library, mark functions as public with pub:
Generated C Code¶
A FastC function:
Compiles to:
int32_t add(int32_t a, int32_t b) {
int32_t __tmp0;
if (__builtin_add_overflow(a, b, (&__tmp0))) {
fc_trap();
}
return __tmp0;
}
Note the automatic overflow checking for safe arithmetic.
Best Practices¶
- Keep functions small - Each function should do one thing
- Use descriptive names -
calculate_totalnotcalc - Document parameters - Comment what each parameter means
- Return early - Use early returns for error cases
- Prefer references for large types - Avoid copying large structs