Functions
Functions in Oxide are declared using the fn keyword with a clean, readable syntax.
Basic Syntax
fn add(a: Int, b: Int): Int {
return a + b
}
fn greet(name: String) {
println!("Hello, $name!")
}
Transpiles to:
fn add(a: isize, b: isize) -> isize {
return a + b;
}
fn greet(name: &String) {
println!("Hello, {}!", name);
}
Implicit Returns
Like Rust, Oxide supports implicit returns: the last expression in a function body (without a semicolon) is automatically returned:
// Implicit return in block body
fn double(x: Int): Int {
x * 2
}
// Implicit return with control flow
fn max(a: Int, b: Int): Int {
if a > b {
a
} else {
b
}
}
// Explicit return also works
fn early_return(x: Int): Int {
if x < 0 {
return 0
}
x * 2
}
Named Arguments
Call functions with named arguments for clarity:
fn createUser(name: String, age: Int, active: Bool): User {
return User(name, age, active)
}
// Call with named arguments
let user = createUser(name = "Alice", age = 30, active = true)
Default Arguments
Provide default values for optional parameters:
fn connect(host: String, port: Int = 8080, secure: Bool = false) {
// ...
}
connect("localhost") // Uses defaults
connect("api.example.com", port = 443, secure = true)
Transpiles to:
fn connect(host: &str, port: isize, secure: bool) {
// ...
}
// Calls are expanded with default values
Generic Functions
Place generic parameters before the function name (Kotlin-style):
fn <T> identity(x: T): T { x }
fn <T: Clone> duplicate(x: T): (T, T) { (x.clone(), x) }
fn <T, U> transform(x: T): U where T: Clone, U: From<T> {
U::from(x.clone())
}
Transpiles to:
fn identity<T>(x: T) -> T { x }
fn duplicate<T: Clone>(x: T) -> (T, T) { (x.clone(), x) }
fn transform<T, U>(x: T) -> U where T: Clone, U: From<T> {
U::from(x.clone())
}
Async Functions
Mark functions as async for asynchronous execution:
async fn fetchData(url: String): String {
let response = await http::get(url)
return response.text()
}
async fn loadAll() {
let data = await fetchData("https://api.example.com")
println!("Got: $data")
}
Transpiles to:
async fn fetch_data(url: String) -> String {
let response = http::get(url).await;
return response.text();
}
async fn load_all() {
let data = fetch_data("https://api.example.com").await;
println!("Got: {}", data);
}
See Async for comprehensive async/await documentation.
Const Functions
Use const fn for compile-time evaluable functions:
const fn square(n: Int): Int { n * n }
const fn max(a: Int, b: Int): Int { if a > b { a } else { b } }
const SIZE: Int = square(10) // Evaluated at compile time
Transpiles to:
const fn square(n: isize) -> isize { n * n }
const fn max(a: isize, b: isize) -> isize { if a > b { a } else { b } }
const SIZE: isize = square(10);
Unsafe Functions
Mark functions that perform unsafe operations:
unsafe fn dangerousOperation(ptr: *const Int): Int {
return *ptr
}
fn main() {
let value = 42
let result = unsafe {
dangerousOperation(&value as *const Int)
}
}
Transpiles to:
unsafe fn dangerous_operation(ptr: *const isize) -> isize {
return *ptr;
}
fn main() {
let value = 42;
let result = unsafe {
dangerous_operation(&value as *const isize)
};
}
Error-Throwing Functions
Use throws to indicate a function can return an error:
fn parseNumber(s: String) throws: Int {
if s.isEmpty() {
throw "Empty string"
}
return s.parse().unwrap()
}
Transpiles to:
fn parse_number(s: &str) -> Result<isize, Box<dyn std::error::Error>> {
if s.is_empty() {
return Err("Empty string".into());
}
return Ok(s.parse().unwrap());
}
See Error Handling for more on throws, try, and do-catch.
Visibility
Control function visibility with modifiers:
public fn publicApi(): String { "visible everywhere" }
internal fn crateOnly(): String { "visible in this crate" }
protected fn parentOnly(): String { "visible to parent module" }
private fn moduleOnly(): String { "visible in this module" }
Transpiles to:
pub fn public_api() -> String { "visible everywhere".to_string() }
pub(crate) fn crate_only() -> String { "visible in this crate".to_string() }
pub(super) fn parent_only() -> String { "visible to parent module".to_string() }
fn module_only() -> String { "visible in this module".to_string() }
Combined Modifiers
Modifiers can be combined:
public async fn fetchPublic(): Data { ... }
async unsafe fn unsafeAsync(): Int { ... }
public const fn publicConst(): Int { 42 }
See Also
- Closures - Anonymous functions and lambdas
- Async - Async/await patterns
- Error Handling -
throwsandtrysyntax - Ownership - Parameter ownership modifiers