函数
Alia 语言中的函数对应 alias 定义。该定义同时完成语法模式的注册与 Alias 对象的声明。
1. 函数定义
alias 支持多种定义形式:alias <Keys pattern> -> <Stack implementation> 定义语法关键字及其实现;alias <Keys pattern> -> <Type> <Stack implementation> 另外声明返回类型;alias <Keys pattern> => <Key aliasName> 指定注册名称;省略实现栈时为无体声明,仅注册签名。
命名定义的首个键为函数名称;匿名定义位于赋值右侧,求值为 Alias 对象。
alias add <Number a> and <Number b> -> Number { a + b }
const greet = alias <String name> -> String { 'Hello, ' .. name }
第一行的名称为首个键 add,and 为形参之间的辅助关键字。第二行的右侧为 Alias 对象,.. 为字符串连接运算符。
remove、disable、enable 分别用于移除、禁用与启用别名。多个模式能匹配同一段代码时,匹配更长的模式优先。
2. 函数调用
语法式调用按定义的模式直接书写参数,是首选调用方式。
add 1 and 1
greet 'Alice'
const sum = add 1 and 1
print (add 1 and 2)
第三行的右侧为语法式调用的值。第四行中位于实参位置的嵌套调用由括号界定。
当调用目标在运行时才确定,或无法在表达式位置书写语法式调用时,使用 call 动态分发。call 支持三种形式:call <Alias>、call <Alias> [<Array>] 与 call <Alias> *[<Object>]。
call add [1, 2]
call add *[a: 1, b: 2]
call greet ['Alice']
Alia 没有函数式调用语法,add(1, 1) 与以逗号分隔参数的写法都不被支持。
3. 匿名函数
匿名函数的定义位于赋值右侧,其值为 Alias 对象 。
const add = alias <Number a> and <Number b> -> Number { a + b }
add 1 and 1
call add [1, 2]
第二行为语法式调用,第三行以数组形式按顺序传入参数,两种写法的参数顺序一致;省略 and 时该模式不会匹配。
4. 高阶函数
<Alias> 类型参数接受 Alias 对象,可以是 alias 字面量、持有 Alias 的变量或命名 alias 标识符。传入数字、栈字面量等非 Alias 值时,检查期报类型失配错误,运行期报类型错误。
const applyOperation = alias <Alias op> and <Number a> and <Number b> -> Number { call op [a, b] }
const add = alias <Number x> and <Number y> -> Number { x + y }
call applyOperation [add, 5, 3]
call op [a, b] 的目标为变量 op,其值在运行时确定。(call applyOperation [add, 5, 3]) 的值为 8。
返回值为 Alias 的定义中,内层字面量为栈末尾的值。
const createMultiplier = alias <Number factor> -> Alias {
const inner = alias <Number num> -> Number { num * factor }
inner }
const double = createMultiplier 2
print (double 5)
(double 5) 的值为 10。
5. 函数参数
<Stack> 参数的值为栈字面量、持有 Stack 的变量或返回 Stack 的表达式。<Type?> 为可空类型,其值为目标类型的值或 Null,?? 为空安全合并运算符。<Value> 为泛型,运算前的类型收窄经由 typeOf、Ok、as 完成。
辅助关键字在模式与内置方法调用中充当分隔。and 连接并列参数,to 分隔区间,with 分隔目标,at 分隔位置,or 给出可选默认值,limit 给出可选限 制,in 与 from 标识容器与来源,on 与 as 标识连接列与角色,row 与 column 标识行列位置,named、keyed、returning 为动词化标签。
arr.slice 0 to 5
Object.get config keyed 'name' or 'fallback'
str.split ',' limit 2
Math.randomInt from 1 to 10
sheet.lookup 2 returning 'city' in 'id'
sheet.getCell at row 0 column 'name'
each item in arr { item }
str.replace 'old' with 'new'
Math.max 1 and 2 and 3
users.join depts on 'dept_id' and 'dept_id' as 'inner'
new Person named 'Alice' aged 30
'42' as Number
import 'fs' as fs
基本参数与可选参数的定义如下。
alias calculate <Number a> and <String op> and <Number b> -> Number {
if op == '+' { return a + b } else { return a - b }
}
const greetOptional = alias <String name> and <String? greeting> -> String { (greeting ?? 'Hello') .. ', ' .. name }
calculate 10 and '+' and 5
greetOptional 'Bob' and 'Hi'
call greetOptional ['Alice', null]
(calculate 10 and '+' and 5) 的值为 15。(greetOptional 'Bob' and 'Hi') 的值为 'Hi, Bob'。call greetOptional ['Alice', null] 的值为 'Hello, Alice'。
6. 递归函数
递归即在定义内部调用同名函数,括号界定嵌套调用的运算顺序。
alias factorial <Number n> -> Number {
if n <= 1 { return 1 } else { return n * (factorial n - 1) }
}
print (factorial 5)
(factorial 5) 的值为 120。return <Value> 表示提前返回,无参数的 return 对应 0 值返回,栈末尾的值为隐式返回,末尾的 return 与落值等价。
7. 示例代码
alias square <Number num> -> Number { num * num }
alias sumArray <Array arr> -> Number {
let sum = 0
let i = 0
while i < arr.length {
sum = sum + (arr[i] as Number)
i ++
}
sum
}
const isEven = alias <Number num> -> Boolean { num % 2 == 0 }
alias filterArray <Array arr> and <Alias predicate> -> Array {
let result: [Value, ...] = []
for { let i = 0 } i < arr.length { i ++ } { if call predicate [arr[i]] { result.push arr[i] } }
result
}
const numbers = [1, 2, 3, 4, 5]
print ('平方 5: ' .. (square 5))
print (sumArray numbers)
print (call filterArray [numbers, isEven])
for { let k = 0 } k < 3 { k ++ } { print k }
栈末尾的 sum 与 result 为隐式返回。(square 5) 的值为 25。(sumArray numbers) 的值为 15。