summaryrefslogtreecommitdiff
path: root/tests/typ/code/closure.typ
blob: 3b8b426199a5cb2fbb8b8c5d882cbcddf33093b5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Test closures.
// Ref: false

---
// Don't parse closure directly in template.
// Ref: true

#let x = "\"hi\""

// Should output `"hi" => "bye"`.
#x => "bye"

---
// Basic closure without captures.
{
  let adder = (x, y) => x + y
  test(adder(2, 3), 5)
}

---
// Pass closure as argument and return closure.
// Also uses shorthand syntax for a single argument.
{
  let chain = (f, g) => (x) => f(g(x))
  let f = x => x + 1
  let g = x => 2 * x
  let h = chain(f, g)
  test(h(2), 5)
}

---
// Capture environment.
{
  let mark = "?"
  let greet = {
    let hi = "Hi"
    name => {
        hi + ", " + name + mark
    }
  }

  test(greet("Typst"), "Hi, Typst?")

  mark = "!"
  test(greet("Typst"), "Hi, Typst!")
}

---
// Redefined variable.
{
  let x = 1
  let f() = {
    let x = x + 2
    x
  }
  test(f(), 3)
}

---
// Don't leak environment.
{
  // Error: 16-17 unknown variable
  let func() = x
  let x = "hi"
  func()
}

---
// Too few arguments.
{
  let types(x, y) = "[" + type(x) + ", " + type(y) + "]"
  test(types(14%, 12pt), "[relative, length]")

  // Error: 13-21 missing argument: y
  test(types("nope"), "[string, none]")
}

---
// Too many arguments.
{
  let f(x) = x + 1

  // Error: 8-13 unexpected argument
  f(1, "two", () => x)
}

---
// Named arguments.
{
  let greet(name, birthday: false) = {
    if birthday { "Happy Birthday, " } else { "Hey, " } + name + "!"
  }

  test(greet("Typst"), "Hey, Typst!")
  test(greet("Typst", birthday: true), "Happy Birthday, Typst!")

  // Error: 23-35 unexpected argument
  test(greet("Typst", whatever: 10))
}