Function Calls
Positional arguments, named arguments, default parameters, methods, and generic calls.
Function calls use parentheses.
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
let value = add(20, 22);
fn example(path: str, force: bool = false) -> i32 {
if force {
return path.size as i32;
}
return (path.size as i32) + 1;
}
let a = example("/tmp");
let b = example("/tmp", true);
let value = add(a: 1, b: 2);
Named arguments are checked against parameter names and overload candidates. They must follow parameter order; use them to clarify a call or skip defaulted parameters, not to reorder required parameters.
fn open(path: str, mode: str = "r", buffered: bool = true) -> bool {
_ = path;
_ = mode;
return buffered;
}
let ok = open("config.zx", buffered: false);
open(buffered: false, path: "config.zx") is rejected because the named
arguments move backward through the parameter list.
Reference-typed arguments are explicit in ordinary calls. When a parameter
expects &T or const &T, pass &value or another reference-valued expression.
fn add_one(value: &i32) {
value = *value + 1;
}
fn main() {
let count = 1;
add_one(&count);
assert count == 2;
}
Method receivers keep auto-borrowing for self: &T and self: const &T.
Operator overload operands keep receiver-style borrowing because operator
syntax has no explicit argument list. Non-receiver method arguments and
callable values follow the ordinary explicit-borrow rule.
Calls can borrow common text and byte inputs as views without extra overloads. This applies only while matching call arguments:
import std.bytes;
import std.hash;
import std.io;
import std.mem;
import {
String
} from std.string;
fn text_len(value: str) -> usize {
return value.size;
}
fn byte_len(value: bytes.Bytes) -> usize {
return value.length;
}
fn main() {
let text = try String("hello");
let label = "hello";
let raw = [65 as u8, 66 as u8, 67 as u8];
let slice = mem.slice_of<u8>(raw.ptr, raw.length);
assert text_len(text) == 5;
assert byte_len("hello") == 5;
assert byte_len(text) == 5;
assert byte_len("{label}") == 5;
assert byte_len(slice) == 3;
assert hash.crc32.sum("hello") == 0x3610a686;
let stream = io.MemoryStream();
try stream.write("{label}");
try stream.write(text);
assert text.str() == "hello";
}
Supported call-only conversions are String and const &String to str, plus
str, interpolated format strings, String, const &String, and [u8]
slices to bytes.Bytes. These are borrowed, zero-copy views, so passing a
String this way does not move it.
Stored views stay explicit. A declaration such as
let data: bytes.Bytes = "abc" is rejected; use bytes.Bytes(...),
text.str(), or text.utf8() when a view needs to be stored or returned.
Generic arguments can be explicit or inferred from value arguments:
fn id<T>(value: T) -> T {
return value;
}
let a = id<i32>(42);
let b = id("zynx");
Generic argument lists can contain integer literals for const generic
parameters, for example SizedArray<i32, 3>. See
Generics.