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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
describe "advanced functions", ->
it "should support fat arrow with self", ->
obj =
value: 10
getValue: => @value
assert.same obj\getValue!, 10
it "should work with argument defaults", ->
fn = (name = "something", height = 100) ->
"#{name}, #{height}"
assert.same fn!, "something, 100"
assert.same fn("test"), "test, 100"
assert.same fn("test", 50), "test, 50"
it "should handle defaults with previous arguments", ->
fn = (x = 100, y = x + 1000) ->
x + y
assert.same fn!, 1200
assert.same fn(50), 1150
it "should work with multi-line arguments", ->
my_func = (a, b, c, d, e, f) -> a + b + c + d + e + f
result = my_func 5, 4, 3,
8, 9, 10
assert.same result, 39
it "should support nested function calls", ->
result = my_func 5, 6, 7,
6, another_func 6, 7, 8,
9, 1, 2,
5, 4
another_func = (a, b, c, d, e, f) -> a + b + c + d + e + f
my_func = (a, b, c, d, e, f) -> a + b + c + d + e + f
assert.same result, 52
it "should handle implicit return", ->
sum = (x, y) -> x + y
assert.same sum 10, 20, 30
it "should work with explicit return", ->
difference = (x, y) -> return x - y
assert.same difference 20, 10, 10
it "should support multiple return values", ->
mystery = (x, y) -> x + y, x - y
a, b = mystery 10, 20
assert.same a, 30
assert.same b, -10
it "should work with function as argument", ->
apply = (fn, x, y) -> fn x, y
result = apply ((a, b) -> a + b), 5, 10
assert.same result, 15
it "should handle function returning function", ->
create_adder = (x) -> (y) -> x + y
add_five = create_adder 5
assert.same add_five(10), 15
it "should support immediately invoked function", ->
result = ((x) -> x * 2) 5
assert.same result, 10
it "should work with varargs", ->
sum_all = (...) ->
total = 0
for i = 1, select '#', ...
total += select(i, ...) if type(select(i, ...)) == "number"
total
assert.same sum_all(1, 2, 3, 4, 5), 15
it "should handle named varargs", ->
fn = (...t) ->
count = 0
for i = 1, t.n
count += 1
count
assert.same fn(1, 2, 3), 3
it "should support prefixed return", ->
findValue: "not found" ->
items = [1, 2, 3]
for item in *items
if item == 5
return item
result = findValue!
assert.same result, "not found"
it "should work with parameter destructuring", ->
fn = (:a, :b, :c) ->
a + b + c
assert.same fn(a: 1, b: 2, c: 3), 6
it "should handle default values in destructuring", ->
fn = ({a: a1 = 123, :b = 'abc'}) ->
a1 .. " " .. b
assert.same fn{}, "123 abc"
assert.same fn({a: 456}), "456 abc"
it "should support empty function body", ->
empty_fn = ->
assert.same empty_fn!, nil
it "should work with function in table", ->
tb =
value: 10
double: => @value * 2
assert.same tb\double!, 20
it "should handle function with no arguments", ->
fn = ->
"result"
assert.same fn!, "result"
assert.same fn(), "result"
it "should support calling function with !", ->
fn = -> 42
assert.same fn!, 42
it "should work with nested functions", ->
outer = (x) ->
inner = (y) -> x + y
inner
add_five = outer 5
assert.same add_five(10), 15
it "should handle function in expression", ->
result = if ((x) -> x > 10) 15
"large"
else
"small"
assert.same result, "large"
it "should support function as return value", ->
get_operation = (op) ->
switch op
when "add"
(a, b) -> a + b
when "subtract"
(a, b) -> a - b
else
-> 0
add = get_operation "add"
assert.same add 5, 3, 8
|