vxx / vlib / v / gen / wasm / tests / fn_value.vv
90 lines · 71 sloc · 1.98 KB · 863a2090f8eda7dc75e061b26e0bca252f167e24
Raw
1type Callback = fn (int) int
2
3fn add1(x int) int {
4 return x + 1
5}
6
7fn double(x int) int {
8 return x * 2
9}
10
11struct Box {
12 op fn (int) int @[required]
13}
14
15fn apply(f fn (int) int, x int) int {
16 return f(x)
17}
18
19// apply_cb takes a function-type *alias* parameter, which must be unwrapped to
20// its underlying fn type for the indirect call.
21fn apply_cb(f Callback, x int) int {
22 return f(x)
23}
24
25// a fn-typed const, called through the const name
26const cb = add1
27
28// make_cb returns a function value, so `make_cb()(x)` is an expression callee
29fn make_cb() fn (int) int {
30 return double
31}
32
33// logged_box / logged_arg make the evaluation order observable: the callee
34// (the receiver) must be evaluated before the argument.
35fn logged_box() Box {
36 println('callee')
37 return Box{
38 op: add1
39 }
40}
41
42fn logged_arg() int {
43 println('arg')
44 return 100
45}
46
47fn main() {
48 // a top-level fn taken as a local fn value, then called through the value
49 f := add1
50 println(f(10)) // 11
51
52 // a fn value stored in a struct field, called through the field
53 b := Box{
54 op: double
55 }
56 println(b.op(20)) // 40
57
58 // a top-level fn passed as a fn-typed argument and called indirectly
59 println(apply(add1, 41)) // 42
60
61 // a non-capturing anonymous function as a value
62 h := fn (x int) int {
63 return x * x
64 }
65 println(h(7)) // 49
66
67 // reassign a fn value and call again (dynamic dispatch through the table)
68 mut g := add1
69 println(g(0)) // 1
70 g = double
71 println(g(50)) // 100
72
73 // a fn-typed const, called through the const name
74 println(cb(99)) // 100
75
76 // an expression callee that evaluates to a function value
77 println(make_cb()(5)) // 10
78
79 // the callee is evaluated before the argument: prints `callee`, then `arg`
80 println(logged_box().op(logged_arg())) // 101
81
82 // function type alias as a value: passed as a param, and cast into a local
83 println(apply_cb(add1, 5)) // 6
84 ac := Callback(double)
85 println(ac(6)) // 12
86
87 // a real function value must be distinct from `nil` (table slot 0 is reserved)
88 nf := add1
89 println(unsafe { nf == nil }) // false
90}
91