函数¶
1. 函数声明¶
// 声明一个函数
fn 函数名[捕获列表](参数列表) -> 返回类型;
- 使用
fn
关键字声明函数。 - 函数名:函数的标识符,用于在程序中调用该函数。
- 捕获列表:可选项,指定函数中使用的外部变量的捕获方式。
- 参数列表:可选项,包含函数的输入参数列表。
- 返回类型:可选项,指定函数返回值的类型。
2. 函数定义¶
// 定义一个函数
fn 函数名[捕获列表](参数列表) -> 返回类型 {函数体}
- 使用
fn
关键字定义函数。 - 函数名、捕获列表、参数列表和返回类型的含义同函数声明。
- 函数体:包含了函数的实际实现代码。
3. 单语句函数定义¶
// 定义一个单语句的函数
fn 函数名[捕获列表](参数列表) = 表达式;
- 适用于只包含一条语句的函数,可以将函数体直接定义为一个表达式。
- 表达式的计算结果将作为函数的返回值。
4. Lambda 表达式¶
// 定义一个 lambda 表达式
fn [捕获列表](参数列表) -> 返回类型 {函数体}
- 可以直接定义匿名函数,称为 Lambda 表达式。
- 不需要指定函数名,直接使用捕获列表、参数列表、返回类型和函数体定义 Lambda 函数。
5. 返回类型推断¶
- 当函数体中所有
return
处的类型一致时,可以省略返回类型。 - 若函数体中没有
return
语句,则返回类型推断为void
。
6. 捕获列表¶
- 捕获列表用于指定函数中引用外部变量的方式。
- 可以省略捕获列表,默认为引用捕获所有外部变量。
- 支持引用捕获和值捕获两种方式。
7. 参数列表¶
- 参数列表用于指定函数的输入参数。
- 可以省略参数列表,表示函数没有参数。
- 当函数没有参数时,参数列表可以是
()
,但不能像 C 语言那样写作(void)
。
示例¶
fn add(int a, int b) {
return a + b;
}
fn main {
return add(1, -1);
}
调用简写¶
对于没有参数的函数,可以直接使用函数名来调用。
如果有以下函数:
fn rand() {
@static
int seed = 1;
seed = seed * 114514 + 1919810;
return seed;
}
我们就可以:
println(rand());
println(rand);
对于单个参数的函数,我们可以省略括号:
println("Hello world!");
println "Hello world!";
规范¶
我们明确:一个函数只应该做一件事情,这样可以使代码更加清晰。
函数一般不超过 20 行语句,超过的话应该考虑拆分。
函数尽量不依赖全局状态,这样可以使函数更加独立,也便于进行单元测试。
函数的参数应该尽量少,大多数不超过 3 个,少数可以达到 6 个,超过的话应该考虑拆分。
对于输入状态特别多的函数,应当使用结构体引用传参。
函数的参数应该尽量避免使用未进行限制的指针,除非有必要。