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.3. Anonymous functions and closures

The previous section introduced the basic usage of function values. Since functions can be regarded as values, can function literals be declared inside functions in the same way as basic type literals? The answer is yes, for example:

// 版权 @2023 凹语言 作者。保留所有权利。

func useFunc(i: i32, f: func(i32) => i32) {
    if f == nil {
        println("f == nil")
        return
    }
    println(f(i))
}

func main {
    f := func(i: i32) => i32 { return i * i } // Declare an anonymous function and assign it to f
    useFunc(3, f) // 9
}

Among them, f is a function value, its initial value is the literal func(i: i32) => i32 { return i * i }, which is a function without a name. In Wa-lang, this kind of function literal without a name is called an anonymous function. In application scenarios such as visitor mode and custom quick sorting, it is often necessary to pass in some function value parameters, and these functions may only appear once. For this reason, it is inconvenient to define additional module-level global functions. You can use anonymous functions.

Anonymous function B declared inside function A can access local variables inside A, for example:

// 版权 @2023 凹语言 作者。保留所有权利。

func useFunc(i: i32, f: func(i32) => i32) {
    if f == nil {
        println("f == nil")
        return
    }
    println(f(i))
}

func main {
    n: i32 = 0
    f := func(i: i32) => i32 {
        n = i * i
        return n
    }
    useFunc(3, f)
    println(n) // 9
}

Obviously the function value f can read and write the outer local variable n. Let’s look at a more complex example:

// 版权 @2023 凹语言 作者。保留所有权利。
func genClosure(i: i32) => func() => i32 {
    n := i
    return func() => i32 {
        n = n + 1
        return n
    }
}

func main {
    c := genClosure(0)
    d := genClosure(99)

    println(c()) // 1
    println(d()) // 100
    println(c()) // 2
    println(d()) // 101
}

Each call to genFunc will generate a function value. This function value captures the local variable n. Each time the function value is executed, the captured n will be incremented by 1. The function obtained by executing genFunc multiple times value, the n they capture is different, and each time it is executed, a new instance is captured.

The anonymous function value declared within the function carries the state of the local variables captured during this run. Obviously, this function value is essentially a closure.