参数详解 (Parameter Details)
函数通过参数接收输入数据。Flurry 提供了多种参数类型,以满足不同的编程需求和代码风格。
1. 普通参数 (Positional Parameters)
这是最基本的参数形式,通过位置进行传递。
定义: parameter_name: Type
fn process_data(data: Slice<u8>, length: usize) { {- ... -} }
调用: 按定义顺序提供值。
let buffer = [1, 2, 3];
process_data(buffer[..], buffer.len());
2. 可选参数 (Optional Parameters)
参数类型为option type
, 则可以选择性传递该参数,不传递则传递null
。
定义: parameter_name: ?Type
-- timeout 是一个可选的毫秒数
fn connect(address: String, timeout: ?u64) -> bool {
let resolved_timeout = timeout.unwrap_or(5000); -- 使用默认值 5000ms
-- ... 连接逻辑使用 resolved_timeout ...
true -- 假设连接成功
}
调用:
connect("example.com".to_string()); -- 不提供超时
connect("example.com".to_string(), 10000); -- 提供 10 秒超时
3. 具名参数 (Named Parameters)
用于提高函数调用的可读性,尤其是在参数较多或参数意义不明显时。
定义: .parameter_name: Type = default_value
- 必须以点
.
开头。 - 必须提供一个默认值。
-- 配置选项通常使用具名参数
fn configure_service(
.retries: usize = 3,
.use_tls: bool = true,
.log_level: LogLevel = LogLevel.info,
) { {- ... -} }
调用: 调用时必须使用参数名,顺序任意。可以省略使用默认值的参数。
-- 使用部分默认值
configure_service(.log_level = LogLevel.Debug);
-- 指定多个参数,顺序随意
configure_service(.use_tls = false, .retries = 5);
-- 使用所有默认值
configure_service();
-- configure_service(5, false); -- 错误!必须使用名称
4. 变长参数 (Variadic Parameters)
允许函数接受不定数量的参数。
定义: ...parameter_name: TupleType
(通常放在最后)
- 使用
...
前缀。 - 调用时传递给该部分的所有参数会被收集到一个元组 (tuple) 中。
TupleType
指定了期望的元组类型。
调用: 正常传递参数,它们会被自动收集。
-- 接受任意数量 i32 的函数
fn sum_all(...numbers: T) -> i32
where T, requires Type.is_tuple(T)
{
let total = 0;
inline for num in numbers {
inline if num'type != i32 {
build.error("All arguments must be i32");
} else {
total += num;
}
}
total
}
test {
println("Sum: {}", sum_all(1, 2, 3, 4)); -- numbers 是 (1, 2, 3, 4)
println("Sum: {}", sum_all(10)); -- numbers 是 (10,)
println("Sum: {}", sum_all()); -- numbers 是 ()
}
编译时类型安全的变长参数: 结合 comptime
参数,可以实现一些依赖类型特性。
-- format 在编译时确定,varargs 的类型也随之确定
fn println(comptime format: str, ...varargs: fmt.Args(format)) {
-- 内部使用 inline for 安全处理
-- ...
}
双变参调用: Flurry 支持一种特殊的双变参函数和调用语法,用于构建 DSL。(详见相关章节)
5. 隐式参数 (Implicit Parameters)
由编译器自动提供的参数,无需在调用点显式传递。
定义: implicit parameter_name: Type
-- 获取源代码位置
fn log(message: String, implicit __src__: builtin.SourceLocation) {
println("{}:{}: {}", src.file, src.line, message);
}
调用: 调用者像调用普通函数一样,编译器负责查找并传入合适的隐式参数。
-- let memory = allocate_memory(1024); -- 编译器自动传入默认分配器
log("Initialization complete."); -- 编译器自动传入调用点的源代码位置
隐式参数的解析规则(如何查找、优先级等)需要语言明确定义。它们是实现上下文传递、依赖注入等模式的有力工具。
6. 编译时参数 (comptime
)
参数值必须在编译时可知。
定义: comptime parameter_name: Type
- 可以与其他参数种类(普通、可选、具名、变长)结合。
- 值在编译时确定。
- 后续参数的类型或值可以依赖于前面的
comptime
参数(依赖类型)。
-- T 和 N 都是编译时参数
fn create_array(initial_value: T) -> Array<T, N>
where T:- Copy, N: usize -- 约束 T 必须是可复制的,N 必须是无符号整数
{
Array<T, N>.new(initial_value) -- 使用 T 和 N 创建数组
}
-- alignment 必须是编译时常量
fn aligned_alloc(size: usize, comptime alignment: usize) -> !AllocErr *u8 {
-- ... 使用 alignment 进行内存分配 ...
}
test {
let arr = create_array(0); -- T 是 i32,N 是 10
println("Array: {:?}", arr);
let ptr = aligned_alloc(1024, 16)!; -- alignment 是 16
println("Aligned pointer: {:?}", ptr);
}
comptime
参数是 Flurry 实现泛型、元编程和零成本抽象的关键。每次使用不同的编译时参数调用函数时,编译器会生成一个该函数特化(单态化)的版本。