-
Notifications
You must be signed in to change notification settings - Fork 69
/
03-Functions.coffee
232 lines (187 loc) · 5.69 KB
/
03-Functions.coffee
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
require './prelude'
# Pure functions
show '--- Pure functions ---'
add = (a, b) -> a + b
show add 2, 2
power = (base, exponent) ->
result = 1
for count in [0...exponent]
result *= base
result
show power 2, 10
# Exercise 7
show '--- Exercise 7 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Declarative tests
show '--- Declarative tests ---'
testAbsolute = (name, property) ->
qc.testPure absolute, [qc.arbInt], name, property
testAbsolute 'returns positive integers',
(c, arg, result) -> result >= 0
testAbsolute 'positive returns positive',
(c, arg, result) -> c.guard arg >= 0; result is arg
testAbsolute 'negative returns positive',
(c, arg, result) -> c.guard arg < 0; result is -arg
qc.testPure power, [qc.arbInt, qc.arbInt],
'power == Math.pow for integers',
(c, base, exponent, result) ->
result == c.note Math.pow base, exponent
qc.testPure power, [qc.arbWholeNum, qc.arbWholeNum],
'power == Math.pow for positive integers',
(c, base, exponent, result) ->
result == c.note Math.pow base, exponent
qc.test()
# Quick hack to avoid garbling of output
# when async test cases are reported.
# A better idea is one test suite in one file.
setTimeout ( ->
# Exercise 8
intensify = (n) ->
2 # This will fail
show '--- Exercise 8 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
qc.testPure intensify, [qc.arbInt],
'intensify grows by 2 when positive',
(c, arg, result) ->
c.guard arg > 0
arg + 2 == result
qc.testPure intensify, [qc.arbInt],
'intensify grows by 2 when negative',
(c, arg, result) ->
c.guard arg < 0
arg - 2 == result
qc.testPure intensify, [qc.arbConst(0)],
'only non-zero intensify grows',
(c, arg, result) ->
result is arg
qc.test()
setTimeout ( ->
# Return revisited
show '--- Return revisited ---'
yell = (message) ->
show message + '!!'
return
yell 'Yow'
# Local scopes
show '--- Local scopes ---'
dino = 'I am alive'
reptile = 'I am A-OK'
meteor = (reptile) ->
show reptile # Argument
dino = 'I am extinct'
reptile = 'I survived'
possum = 'I am new'
show dino # Outer
meteor 'What happened?'
show dino # Outer changed
show reptile # Outer unchanged
try show possum catch e
show e.message # Error undefined
# Local environment
show '--- Local environment ---'
variable = 'first' # Definition
showVariable = ->
show 'In showVariable, the variable holds: ' +
variable # second
test = ->
variable = 'second' # Assignment
show 'In test, the variable holds ' +
variable + '.' # second
showVariable()
show 'The variable is: ' + variable # first
test()
show 'The variable is: ' + variable # second
# Siblings and children
show '--- Siblings and children ---'
andHere = ->
try show aLocal # Not defined
catch e then show e.message
isHere = ->
aLocal = 'aLocal is defined'
andHere()
isHere()
isHere = ->
andHere = ->
try show aLocal # Is defined
catch e then show e.message
aLocal = 'aLocal is defined'
andHere()
isHere()
# Internal function variable
show '--- Internal function variable ---'
varWhich = 'top-level'
parentFunction = ->
varWhich = 'local'
childFunction = ->
show varWhich
childFunction
child = parentFunction()
child()
# Synthesized function
show '--- Synthesized function ---'
makeAddFunction = (amount) ->
add = (number) -> number + amount
addTwo = makeAddFunction 2
addFive = makeAddFunction 5
show addTwo(1) + addFive(1)
# Recursion
show '--- Recursion ---'
powerRec = (base, exponent) ->
if exponent == 0
1
else
base * powerRec base, exponent - 1
show 'power 3, 3 = ' + powerRec 3, 3
# Timing
show '--- Timing ---'
timeIt = (func) ->
start = new Date()
for i in [0...1000000] then func()
show "Timing: #{(new Date() - start)*0.001}s"
timeIt -> p = add 9,18 # 0.042s
timeIt -> p = Math.pow 9,18 # 0.049s
timeIt -> p = power 9,18 # 0.464s
timeIt -> p = powerRec 9,18 # 0.544s
# Indirect recursion
show '--- Indirect recursion ---'
chicken = ->
show 'Lay an egg'
egg()
egg = ->
show 'Chick hatched'
chicken()
try show chicken() + ' came first.'
catch error then show error.message
# Recursive puzzle solving
show '--- Recursive puzzle solving ---'
findSequence = (goal) ->
find = (start, history) ->
if start == goal
history
else if start > goal
null
else
find(start + 5, '(' + history + ' + 5)') ? \
find(start * 3, '(' + history + ' * 3)')
find 1, '1'
show findSequence 24
# Anonymous functions
show '--- Anonymous functions ---'
makeAddFunction = (amount) ->
(number) -> number + amount
show makeAddFunction(11) 3
# Exercise 9
show '--- Exercise 9 ---'
process.exit() # Replace this line with your solution
show '--- End of Exercise ---'
# Extra function arguments
show '--- Extra function arguments ---'
yell 'Hello', 'Good Evening', 'How do you do?'
yell()
# Variable number of arguments
show '--- Variable number of arguments ---'
console.log 'R', 2, 'D', 2
),300
),300