The content on this page is written in Chinese, and then traslated into English by machine. More accurate traslations are welcome at: https://github.com/wa-lang/man/tree/master/en
Ending's law: "Any application that can be compiled to WebAssembly, will be compiled to WebAssembly eventually."
4.2. Function values
In Wa-lang, functions can be treated as special values, for example:
// 版权 @2023 凹语言 作者。保留所有权利。
func Inc(i: i32) => i32 { return i + 1 }
func Dec(i: i32) => i32 { return i - 1 }
func main {
f := Inc
println(f(42)) // 43
f = Dec
println(f(42)) // 41
}
In the above example, f
is the function value. The function value can be called, and the calling method is the same as the function call.
The type of a function is determined by its parameters and return value type. Usually this information is called function signature (Signature). If two functions A and B have the same signature, it means that they:
- Their number of parameters is the same;
- Their number of return values is the same;
- For any n, the nth parameter of function A is of the same type as the nth parameter of B;
- For any m, the mth return value of function A is of the same type as the mth return value of B.
The type of function value is also defined through function signature. For example, the type of function value f
in the above example is func(i32) => i32
, so the short-declaration of f
in the above example is f := Inc
, etc. Priced at:
f: func(i32) => i32 // f == nil
f = Inc
Like other types of values, function values are also initialized to 0, and the corresponding value is
nil
In Wa-lang, values of different types cannot be assigned to each other. This is also valid for function values. Since the function type is determined by the signature, it is considered illegal to assign a function to a function value with different signatures. For example:
func Inc(i: i32) => i32 { return i + 1 }
func main {
f: func(i32)
f = Inc // 编译错误
}
Since it is called a "value", it means that function values can be passed between different functions as parameters and return values, for example:
// 版权 @2023 凹语言 作者。保留所有权利。
func inc(i: i32) => i32 { return i + 1 }
func dec(i: i32) => i32 { return i - 1 }
func getFunc(opCode: i32) => func(i32) => i32 {
if opCode == 0 {
return inc
} else if opCode == 1 {
return dec
} else {
return nil
}
}
func useFunc(i: i32, f: func(i32) => i32) {
if f == nil {
println("f == nil")
return
}
println(f(i))
}
func main {
useFunc(42, getFunc(0)) // 43
useFunc(42, getFunc(1)) // 41
useFunc(42, getFunc(2)) // f == nil
getFunc(2)(42) // 运行时异常
}
Unlike other basic types, function values can only be compared with nil
, that is: when the function value is on the left side of operators ==
, !=
, the right side can only be nil
, comparing two non-constants function value is considered illegal.
If the called function value is nil
, an unrecoverable runtime exception will be triggered.
Function values are similar to function pointers in C language, and can dynamically adjust execution branches more flexibly. However, it needs to be pointed out that compared to calling the function directly, calling the function value has some additional consumption, and performance-sensitive occasions require special attention.