函数
函数是基本的代码块, 用于执行一个任务.
你可以通过函数来划分不同功能, 逻辑上每个函数执行的是指定的任务.
Z1h 语言标准库提供了多种可动用的内置的函数. 例如, len() 函数可以接受不同类型参数并返回该类型的长度. 如果我们传入的是字符串则返回字符串的长度, 如果传入的是数组, 则返回数组中包含的元素个数.
函数定义
函数定义格式如下
函数名 = 参数 => {
函数体
}
或
函数名 = (参数1, 参数2...) => {
函数体
}
或
func 函数名(参数1, 参数2...) { // 这种情况只能声明局部的函数
函数体
}
也可以将形参的内容解出, 如
// 将第一个参数的key1、key2值解出
函数名 = ({key1, key2}, 参数2) => {
函数体
}
// 将第一个参数(数组)的key1、key2值解出
函数名 = ([item1, item2], 参数2) => {
函数体
}
示例
add1 = num => {
return num + 1
}
add = (num1, num2) => num1 + num2
func minus(num1, num2) {
return num1 - num2
}
hello = {name, age} => {
printf('Hello, name = %v, age = %v', name, age)
}
hi = ([p1, p2], a2) => {
printf({p1, p2, a2})
}
定义解析
名称 | 描述 |
---|---|
func | 函数由 func 开始声明 |
函数名称 | 函数名就是这个函数的变量名 |
参数列表 | 参数就像一个占位符, 当函数被调用时, 你可以将值传递给参数, 这个值被称为实际参数. 参数列表指定的是参数类型、顺序、及参数个数. 参数是可选的, 也就是说函数也可以不包含参数. |
函数体 | 函数定义的代码集合. |
函数调用
当创建函数时, 你定义了函数需要做什么, 通过调用该函数来执行指定任务.
调用函数, 向函数传递参数, 并返回值, 例如:
func getDouble(num) {
return num * 2;
}
getDouble(100);
// 输出200
函数返回多个值
Z1h 函数可以返回多个值, 调用得到的值是一个数组, 例如:
func nameAndSuffix(str) {
var suffix = $file.ext(str, '');
return (suffix ? str[:suffix.length+1]: str), suffix;
}
print(nameAndSuffix("hello.z1h"));
// 输出[ "hello", ".z1h" ]
[foo, bar] = nameAndSuffix('index.html');
print(`${foo} and ${bar}`)
示例
add = e => {
e + 1
}
print(add(3))
plus = (num1, num2) => {
num1 + num2
}
print(plus(3, 7))
func minus(n1, n2) {
n1 - (n2 || 0)
}
minus(8, 7)
自动关闭的对象
如果一个对象包含Close函数
(包括自定义结构体/map/原生对象), 可以使用该函数自动关闭
这个使用方式与Python很相似
// os.Create 返回的是 *os.File 类型, 包含Close函数
with assert(os.Create(`test.txt`)) as f {
assert(f.Write("你好啊".bytes))
}
或者
with {
tag: '测试',
Close: e=>{print(`关闭: 标记=${this.tag}, 名称=${this.name}`)},
} as obj {
obj.name = "haha"
print('设置了name')
}
逃逸对象(闭包)
如果你的函数返回了函数(或函数的某种形式的引用), 包含了上层定义的变量, 此时就需要进行变量的逃逸
(相当于js里的闭包
概念)
Z1h也是支持逃逸(闭包)的, 在产生函数的时候会保存当前的栈环境, 示例代码如下:
// 声明一个函数, 这个函数返回了三个函数
f = e => {
var i = 1 // 三个函数共用的变量
return [
e => { i++ },
e => { i += 2 },
e => { i = nil; print('I=' + i) },
]
};
// 获取一套函数
[f1, f2, f3] = f()
// 以下函数逐行调用, 并观察结果
f1()
f2()
f3()
f2()
f1()
print(i) // 报错: 没有i这个变量
与Go原生交互
如果一个函数需要转成Go的原生函数, 只需要使用以下方式即可创建:
f = (e=>`传入参数的平方为${e*e}`).native_int_return_string
// 后面的部分也可以简写成 .native_i_return_s
print('Go类型:', type(f))
// func(int) string
print('返回结果:', f(20))
// "传入参数的平方为400"
如果需要创建有复杂类型的函数, 可以通过native方法:
f = new('func',
['', z1h.ElemType(os.FileInfo.Ptr), z1h.ElemType(errors.Interface)],
z1h.ElemType(errors.Interface),
(name, info, err)=>{
print(`Name: ${name}, Size: ${info.Size()?? 'No info'}`)
return z1h.NilValue(errors.Interface)
}
)
print(type(f))
// func(string, os.FileInfo, error) error
path_filepath.Walk(".", f)