Function Basics
Let's start with how to define and call functions in Coco. The syntax is clean and explicit—you'll always know what a function takes and what it returns.
Defining Functions
fn greet() {
echo "Hello!";
}
fn greet_person($name string) {
echo "Hello, {$name}!";
}
fn add($a i32, $b i32): i32 {
return $a + $b;
}
The pattern is: fn name(parameters): return_type { body }
- Parameters use
$name typesyntax - Return type comes after the
: - No return type means the function returns nothing (void)
Calling Functions
greet(); // Hello!
greet_person("Alice"); // Hello, Alice!
$sum = add(2, 3); // 5
Nothing surprising here. Arguments are positional by default.
Return Values
Use return to return a value:
fn square($x i32): i32 {
return $x * $x;
}
The last expression can be returned implicitly if you omit the semicolon:
fn square($x i32): i32 {
$x * $x
}
Both styles are valid. Use whichever reads better in context.
Multiple Return Values
Coco supports multiple return values using tuples:
fn divide($a i32, $b i32): (i32, i32) {
$quotient = $a / $b;
$remainder = $a % $b;
return ($quotient, $remainder);
}
// Destructure the result
($q, $r) = divide(17, 5);
echo "{$q} remainder {$r}"; // 3 remainder 2
This is useful for functions that naturally produce multiple pieces of data.
Default Parameters
Set defaults with =:
fn greet($name string = "World") {
echo "Hello, {$name}!";
}
greet(); // Hello, World!
greet("Alice"); // Hello, Alice!
Parameters with defaults must come after required parameters.
Named Arguments
For clarity, you can use named arguments:
fn create_user($name string, $email string, $age i32) {
// ...
}
// Positional
create_user("Alice", "alice@example.com", 30);
// Named (clearer, especially with many parameters)
create_user(
name: "Alice",
email: "alice@example.com",
age: 30
);
Named arguments can be in any order and are especially helpful when a function has many parameters or several of the same type.
Documentation Comments
Document functions with ///:
/// Calculates the area of a rectangle.
///
/// # Parameters
/// - width: The width in pixels
/// - height: The height in pixels
///
/// # Returns
/// The area in square pixels
fn area($width f64, $height f64): f64 {
return $width * $height;
}
These comments become part of the generated documentation.
Function Overloading
Coco doesn't have function overloading in the traditional sense. Instead, use:
Different names:
fn print_int($value i32) { ... }
fn print_string($value string) { ... }
Generics:
fn print<T: Display>($value T) {
echo "{}", $value;
}
Optional parameters:
fn connect($host string, $port i32 = 80, $timeout i32 = 30) {
// ...
}
This keeps function resolution simple and explicit.
Early Returns
Return early to handle edge cases:
fn find_user($id i32): ?User {
if $id <= 0 {
return null;
}
$user = database.fetch($id);
if $user == null {
return null;
}
return $user;
}
Early returns reduce nesting and make the happy path clearer.
Recursion
Functions can call themselves:
fn factorial($n i32): i32 {
if $n <= 1 {
return 1;
}
return $n * factorial($n - 1);
}
Coco optimizes tail recursion, so tail-recursive functions don't blow the stack:
fn factorial_tail($n i32, $acc i32 = 1): i32 {
if $n <= 1 {
return $acc;
}
return factorial_tail($n - 1, $n * $acc); // Tail call
}
Visibility
By default, functions are private to their module. Use pub for public:
// Private - only accessible within this module
fn helper() {
// ...
}
// Public - accessible from other modules
pub fn process() {
helper();
// ...
}
Best Practices
Keep functions small. A function should do one thing. If it's getting long, split it up.
Use descriptive names. calculate_total_price() is better than calc().
Put the most important parameter first. For methods, that's usually the thing being acted on.
Use named arguments for clarity. When calling a function with multiple similar-typed parameters, names prevent mistakes:
// Which is width, which is height?
resize(100, 200);
// Clear
resize(width: 100, height: 200);
Return early for guard clauses. Handle error cases at the top, then write the main logic without deep nesting.