函数
函数是组织和重用代码的基本单元。本章将详细介绍 Sii 2 中函数的定义、调用、参数传递和返回值处理。
函数基础
函数定义
函数使用 func 关键字定义,基本语法如下:
func 函数名(参数列表): 返回类型 {
函数体
back 返回值; // 如果有返回值
}
简单函数示例
// 无参数、无返回值
func greet(): void {
sii.io.print("Hello, World!");
}
// 有参数、有返回值
func add(a: int, b: int): int {
back a + b;
}
// 有参数、无返回值
func printSum(a: int, b: int): void {
let sum: int = a + b;
sii.io.print("Sum: " + sum.toString());
}
函数调用
函数定义后,可以通过函数名和参数列表调用:
// 调用无返回值函数
greet();
// 调用有返回值函数
let result: int = add(3, 5); // result = 8
// 调用函数但不使用返回值
printSum(10, 20);
函数参数
参数声明
函数参数必须明确指定类型:
func calculate(a: int, b: int, operation: string): int {
if (operation == "add") {
back a + b;
} else if (operation == "subtract") {
back a - b;
} else {
back 0;
}
}
多个参数
函数可以有多个参数,用逗号分隔:
func createUser(name: string, age: int, email: string, isActive: bool): void {
sii.io.print("Creating user: " + name);
sii.io.print("Age: " + age.toString());
sii.io.print("Email: " + email);
sii.io.print("Active: " + isActive.toString());
}
参数类型
参数可以是任何类型:
// 基础类型参数
func processNumber(n: int): void { }
func processString(s: string): void { }
func processBoolean(b: bool): void { }
// 数组参数
func processArray(numbers: arr): void { }
// 对象参数
func processObject(data: obj): void { }
返回值
使用 back 关键字
函数使用 back 关键字返回值:
func getGreeting(): string {
back "Hello, World!";
}
func getMax(a: int, b: int): int {
if (a > b) {
back a;
} else {
back b;
}
}
void 返回类型
没有返回值的函数使用 void 作为返回类型:
func printMessage(msg: string): void {
sii.io.print(msg);
// 不需要 back 语句
}
多个返回点
函数可以有多个返回点:
func findValue(numbers: arr<int>, target: int): int {
forloop (let i: int = 0; i < numbers.length(); i.getUp(1)) {
if (numbers[i] == target) {
back i; // 找到后立即返回
}
}
back -1; // 未找到返回 -1
}
函数类型
纯函数
纯函数是指给定相同输入总是返回相同输出的函数,且没有副作用:
// 纯函数示例
func square(x: int): int {
back x * x;
}
func multiply(a: int, b: int): int {
back a * b;
}
有副作用的函数
有副作用的函数会修改外部状态或执行 I/O 操作:
let counter: int = 0;
func increment(): void {
counter = counter + 1; // 修改外部变量
}
func logMessage(msg: string): void {
sii.io.print(msg); // I/O 操作
}
递归函数
函数可以调用自身,实现递归:
// 计算阶乘
func factorial(n: int): int {
if (n <= 1) {
back 1;
}
back n * factorial(n - 1);
}
// 计算斐波那契数列
func fibonacci(n: int): int {
if (n <= 1) {
back n;
}
back fibonacci(n - 1) + fibonacci(n - 2);
}
递归注意事项
- 基准情况:必须有一个或多个基准情况,避免无限递归
- 递归深度:注意递归深度,避免栈溢出
- 性能:某些递归可以用迭代优化
函数作用域
局部变量
函数内部定义的变量只在函数内部可见:
func example(): void {
let local: int = 10; // 局部变量
sii.io.print(local.toString());
}
// local 在这里不可访问
访问外部变量
函数可以访问外部作用域的变量:
let global: int = 100;
func accessGlobal(): void {
sii.io.print(global.toString()); // 可以访问全局变量
global = 200; // 可以修改全局变量
}
变量遮蔽
局部变量可以遮蔽外部同名变量:
let x: int = 10;
func test(): void {
let x: int = 20; // 遮蔽外部变量 x
sii.io.print(x.toString()); // 输出 20
}
函数最佳实践
1. 单一职责
每个函数应该只做一件事:
// 好的设计
func calculateTotal(items: arr): int {
let total: int = 0;
forloop (let i: int = 0; i < items.length(); i.getUp(1)) {
total = total + items[i];
}
back total;
}
// 不好的设计:函数做了太多事情
func processOrder(order: obj): void {
// 验证订单
// 计算总价
// 更新库存
// 发送邮件
// ...
}
2. 有意义的函数名
函数名应该清楚表达函数的功能:
// 好的命名
func calculateTax(amount: int): int { }
func validateEmail(email: string): bool { }
func getUserById(id: int): obj { }
// 不好的命名
func calc(x: int): int { }
func check(s: string): bool { }
func get(id: int): obj { }
3. 参数数量
避免参数过多,通常不超过 3-5 个:
// 好的设计:参数较少
func createUser(name: string, email: string): void { }
// 不好的设计:参数过多
func createUser(name: string, email: string, age: int, phone: string, address: string, city: string, country: string): void { }
// 改进:使用对象参数
func createUser(userData: obj): void { }
4. 返回值一致性
保持返回值的类型和含义一致:
// 好的设计:返回值含义明确
func findUser(id: int): obj | void {
// 找到返回对象,未找到返回 void
}
// 不好的设计:返回值含义不明确
func findUser(id: int): int {
// 返回什么?用户对象?ID?状态码?
}
5. 错误处理
考虑函数可能失败的情况:
func divide(a: int, b: int): int | void {
if (b == 0) {
sii.io.print("Error: Division by zero");
back; // 返回 void 表示失败
}
back a / b;
}
函数示例
示例 1:数学运算函数
func add(a: int, b: int): int {
back a + b;
}
func subtract(a: int, b: int): int {
back a - b;
}
func multiply(a: int, b: int): int {
back a * b;
}
func divide(a: int, b: int): int | void {
if (b == 0) {
sii.io.print("Error: Cannot divide by zero");
back;
}
back a / b;
}
func power(base: int, exponent: int): int {
let result: int = 1;
forloop (let i: int = 0; i < exponent; i.getUp(1)) {
result = result * base;
}
back result;
}
示例 2:字符串处理函数
func reverseString(s: string): string {
let reversed: string = "";
// 假设有 length() 和 charAt() 方法
forloop (let i: int = s.length() - 1; i >= 0; i.toDn(1)) {
// reversed = reversed + s.charAt(i);
}
back reversed;
}
func capitalize(s: string): string {
if (s.length() == 0) {
back s;
}
// 假设有字符操作方法
// let first: str = s.charAt(0).toUpperCase();
// let rest: string = s.substring(1);
// back first + rest;
back s; // 占位
}
示例 3:数组操作函数
func findMax(numbers: arr<int>): int | void {
if (numbers.length() == 0) {
back;
}
let max: int = numbers[0];
forloop (let i: int = 1; i < numbers.length(); i.getUp(1)) {
if (numbers[i] > max) {
max = numbers[i];
}
}
back max;
}
func sumArray(numbers: arr<int>): int {
let sum: int = 0;
forloop (let i: int = 0; i < numbers.length(); i.getUp(1)) {
sum = sum + numbers[i];
}
back sum;
}
func contains(numbers: arr<int>, value: int): bool {
forloop (let i: int = 0; i < numbers.length(); i.getUp(1)) {
if (numbers[i] == value) {
back true;
}
}
back false;
}
小结
本章介绍了 Sii 2 中函数的所有重要概念:
- 函数定义:使用
func关键字 - 参数传递:必须明确指定参数类型
- 返回值:使用
back关键字返回 - 函数类型:纯函数和有副作用的函数
- 递归:函数可以调用自身
- 作用域:局部变量和外部变量访问
- 最佳实践:编写清晰、可维护的函数
下一章我们将学习控制流,掌握条件语句、循环语句和跳转语句的使用。