98 | 98 |
-> Functionality "Interpret Decoy Program" is implemented by shell command
|
99 | 99 |
-> "./bin/decoy eval -m stdenv -I lib/ %(test-body-file)"
|
100 | 100 |
|
101 | |
> -> Functionality "Interpret Decoy Program" is implemented by shell command
|
102 | |
> -> "./bin/decoy compile -m stdenv -I lib/ %(test-body-file) && node out.mjs"
|
103 | |
|
104 | |
-> Tests for functionality "Interpret Decoy Program"
|
|
101 |
|-> Functionality "Interpret Decoy Program" is implemented by shell command
|
|
102 |
|-> "./bin/decoy compile -m stdenv -I lib/ %(test-body-file) && node out.mjs"
|
|
103 |
|
|
104 |
-> Functionality "Interpret Consful Decoy Program" is implemented by shell command
|
|
105 |
-> "./bin/decoy eval -m stdenv -I lib/ %(test-body-file)"
|
105 | 106 |
|
106 | 107 |
Constructing and Manipulating Data
|
107 | 108 |
----------------------------------
|
108 | 109 |
|
109 | |
`quote` evaluates to literally what is in the head of the tail of
|
110 | |
the cons cell whose head is `quote`.
|
111 | |
|
112 | |
(quote hello)
|
113 | |
===> hello
|
114 | |
|
115 | |
(quote (quote quote))
|
116 | |
===> (quote quote)
|
117 | |
|
118 | |
Atomic symbols may contain letters, `*`s, `?`s, and `-`s.
|
119 | |
|
120 | |
(quote abcdef-ghijklm*nopqrst?uvwxyz)
|
121 | |
===> abcdef-ghijklm*nopqrst?uvwxyz
|
122 | |
|
123 | |
`cons` lets you create a list from some thing and another list.
|
124 | |
|
125 | |
(cons (quote thing) (quote (rest)))
|
126 | |
===> (thing rest)
|
127 | |
|
128 | |
`cons` can be used to create an improper list.
|
129 | |
(The `.` syntax for improper lists is not supported in the reader though.)
|
130 | |
|
131 | |
(cons (quote thing) (quote rest))
|
132 | |
===> (thing . rest)
|
133 | |
|
134 | |
`car` extracts the head of a list.
|
135 | |
|
136 | |
(car (quote (foo bar)))
|
137 | |
===> foo
|
138 | |
|
139 | |
`cdr` extracts the tail of a list.
|
140 | |
|
141 | |
(cdr (quote (foo bar)))
|
142 | |
===> (bar)
|
|
110 |
-> Tests for functionality "Interpret Decoy Program"
|
|
111 |
|
|
112 |
### Strings
|
|
113 |
|
|
114 |
String literals evaluate to literally that string.
|
|
115 |
|
|
116 |
"hello"
|
|
117 |
===> "hello"
|
143 | 118 |
|
144 | 119 |
Predicates and Types
|
145 | 120 |
--------------------
|
146 | 121 |
|
147 | |
`equal?` works on symbols.
|
148 | |
|
149 | |
(cond (
|
150 | |
(equal? (quote a) (quote a))
|
151 | |
(quote true)) (else (quote false)))
|
152 | |
===> true
|
153 | |
|
154 | |
(cond (
|
155 | |
(equal? (quote a) (quote b))
|
156 | |
(quote true)) (else (quote false)))
|
157 | |
===> false
|
158 | |
|
159 | |
`equal?` works on lists.
|
160 | |
|
161 | |
(cond (
|
162 | |
(equal? (quote (one (two three)))
|
163 | |
(cons (quote one) (quote ((two three)))))
|
164 | |
(quote true)) (else (quote false)))
|
165 | |
===> true
|
166 | |
|
167 | |
A symbol is not a list.
|
168 | |
|
169 | |
(cond (
|
170 | |
(list? (quote a))
|
171 | |
(quote true)) (else (quote false)))
|
172 | |
===> false
|
173 | |
|
174 | |
A list whose final cons cell's tail contains a null, is a list.
|
175 | |
|
176 | |
(cond (
|
177 | |
(list? (cons (quote a) (quote ())))
|
178 | |
(quote true)) (else (quote false)))
|
179 | |
===> true
|
180 | |
|
181 | |
(cond (
|
182 | |
(list? (quote (a b c d e f)))
|
183 | |
(quote true)) (else (quote false)))
|
184 | |
===> true
|
185 | |
|
186 | |
A pair is not a list.
|
187 | |
|
188 | |
Actually, pairs aren't defined at all in Decoy, so I wouldn't
|
189 | |
blame an implementation for just freaking out at this one.
|
190 | |
|
191 | |
(cond (
|
192 | |
(list? (cons (quote a) (quote b)))
|
193 | |
(quote true)) (else (quote false)))
|
194 | |
===> false
|
195 | |
|
196 | |
Booleans are not lists.
|
197 | |
|
198 | |
(cond (
|
199 | |
(list? (equal? (quote a) (quote b)))
|
200 | |
(quote true)) (else (quote false)))
|
201 | |
===> false
|
202 | |
|
203 | |
Lambda functions are not lists.
|
204 | |
|
205 | |
(cond (
|
206 | |
(list? (lambda (x y) (y x)))
|
207 | |
(quote true)) (else (quote false)))
|
208 | |
===> false
|
209 | |
|
210 | |
But the empty list is a list.
|
211 | |
|
212 | |
(cond (
|
213 | |
(list? (quote ()))
|
214 | |
(quote true)) (else (quote false)))
|
215 | |
===> true
|
216 | |
|
217 | |
(cond (
|
218 | |
(list? (cdr (quote (foo))))
|
219 | |
(quote true)) (else (quote false)))
|
220 | |
===> true
|
221 | |
|
222 | |
The empty list can be expressed as `(quote ())`.
|
223 | |
|
224 | |
(cond (
|
225 | |
(equal? (cdr (quote (foo))) (quote ()))
|
226 | |
(quote true)) (else (quote false)))
|
227 | |
===> true
|
|
122 |
`cond` can be used to compare values.
|
|
123 |
`equal?` works on strings.
|
|
124 |
|
|
125 |
(cond
|
|
126 |
((equal? "a" "a") "true")
|
|
127 |
(else "false"))
|
|
128 |
===> "true"
|
|
129 |
|
|
130 |
(cond
|
|
131 |
((equal? "a" "b") "true")
|
|
132 |
(else "false"))
|
|
133 |
===> "false"
|
228 | 134 |
|
229 | 135 |
Binding to Names
|
230 | 136 |
----------------
|
|
232 | 138 |
`let*` lets you bind identifiers to values. An identifier can be bound
|
233 | 139 |
to a symbol.
|
234 | 140 |
|
235 | |
(let* ((a (quote hello))) a)
|
236 | |
===> hello
|
|
141 |
(let* ((a "hello")) a)
|
|
142 |
===> "hello"
|
237 | 143 |
|
238 | 144 |
`let*` can appear in the binding expression in a `let*`.
|
239 | 145 |
|
240 | |
(let* ((a (let* ((b (quote c))) b))) a)
|
241 | |
===> c
|
|
146 |
(let* ((a (let* ((b "c")) b))) a)
|
|
147 |
===> "c"
|
242 | 148 |
|
243 | 149 |
`let*` can bind a symbol to a function value.
|
244 | 150 |
|
245 | |
(let* ((a (lambda (x y) (cons x y))))
|
246 | |
(a (quote foo) (quote ())))
|
247 | |
===> (foo)
|
|
151 |
(let* ((a (lambda (x y) y)))
|
|
152 |
(a "foo" "bar"))
|
|
153 |
===> "bar"
|
248 | 154 |
|
249 | 155 |
Bindings established in a binding in a `let*` can be seen in
|
250 | 156 |
subsequent bindings in the same `let*`.
|
251 | 157 |
|
252 | |
(let* ((a (quote hello)) (b (cons a (quote ())))) b)
|
253 | |
===> (hello)
|
|
158 |
(let* ((a "hello") (b (equal? a "hello"))) b)
|
|
159 |
===> #t
|
254 | 160 |
|
255 | 161 |
Shadowing happens.
|
256 | 162 |
|
257 | |
(let* ((a (quote hello))) (let* ((a (quote goodbye))) a))
|
258 | |
===> goodbye
|
|
163 |
(let* ((a "hello")) (let* ((a "goodbye")) a))
|
|
164 |
===> "goodbye"
|
259 | 165 |
|
260 | 166 |
`let*` can have an empty list of bindings.
|
261 | 167 |
|
262 | |
(let* () (quote hi))
|
263 | |
===> hi
|
|
168 |
(let* () "hi")
|
|
169 |
===> "hi"
|
264 | 170 |
|
265 | 171 |
Decision-making
|
266 | 172 |
---------------
|
267 | 173 |
|
268 | 174 |
`if`.
|
269 | 175 |
|
270 | |
(if (equal? (quote a) (quote a)) (quote true) (quote false))
|
271 | |
===> true
|
272 | |
|
273 | |
(if (equal? (quote a) (quote b)) (quote true) (quote false))
|
274 | |
===> false
|
|
176 |
(if (equal? "a" "a") "true" "false")
|
|
177 |
===> "true"
|
|
178 |
|
|
179 |
(if (equal? "a" "b") "true" "false")
|
|
180 |
===> "false"
|
275 | 181 |
|
276 | 182 |
All non-booleans are considered true. This at least coincides with
|
277 | 183 |
what Chicken tells me.
|
278 | 184 |
|
279 | |
(if (list 1) (quote true) (quote false))
|
280 | |
===> true
|
281 | |
|
282 | |
(if (list) (quote true) (quote false))
|
283 | |
===> true
|
284 | |
|
285 | |
(if 1 (quote true) (quote false))
|
286 | |
===> true
|
287 | |
|
288 | |
(if 0 (quote true) (quote false))
|
289 | |
===> true
|
290 | |
|
291 | |
(if "hey" (quote true) (quote false))
|
292 | |
===> true
|
293 | |
|
294 | |
(if "" (quote true) (quote false))
|
295 | |
===> true
|
|
185 |
(if 1 "true" "false")
|
|
186 |
===> "true"
|
|
187 |
|
|
188 |
(if 0 "true" "false")
|
|
189 |
===> "true"
|
|
190 |
|
|
191 |
(if "hey" "true" "false")
|
|
192 |
===> "true"
|
|
193 |
|
|
194 |
(if "" "true" "false")
|
|
195 |
===> "true"
|
296 | 196 |
|
297 | 197 |
`cond` works.
|
298 | 198 |
|
299 | |
(let* ((true (equal? (quote a) (quote a))))
|
300 | |
(cond (true (quote hi)) (else (quote lo))))
|
301 | |
===> hi
|
302 | |
|
303 | |
(let* ((true (equal? (quote a) (quote a)))
|
304 | |
(false (equal? (quote a) (quote b))))
|
305 | |
(cond (false (quote hi)) (true (quote med)) (else (quote lo))))
|
306 | |
===> med
|
307 | |
|
308 | |
(let* ((true (equal? (quote a) (quote a)))
|
309 | |
(false (equal? (quote a) (quote b))))
|
310 | |
(cond (false (quote hi)) (false (quote med)) (else (quote lo))))
|
311 | |
===> lo
|
|
199 |
(let* ((true (equal? "a" "a")))
|
|
200 |
(cond (true "hi") (else "lo")))
|
|
201 |
===> "hi"
|
|
202 |
|
|
203 |
(let* ((true (equal? "a" "a"))
|
|
204 |
(false (equal? "a" "b")))
|
|
205 |
(cond (false "hi") (true "med") (else "lo")))
|
|
206 |
===> "med"
|
|
207 |
|
|
208 |
(let* ((true (equal? "a" "a"))
|
|
209 |
(false (equal? "a" "b")))
|
|
210 |
(cond (false "hi") (false "med") (else "lo")))
|
|
211 |
===> "lo"
|
312 | 212 |
|
313 | 213 |
`cond` can have zero tests before the `else`.
|
314 | 214 |
|
315 | |
(cond (else (quote woo)))
|
316 | |
===> woo
|
|
215 |
(cond (else "woo"))
|
|
216 |
===> "woo"
|
317 | 217 |
|
318 | 218 |
Functions
|
319 | 219 |
---------
|
320 | 220 |
|
321 | 221 |
You can define functions with `lambda`. They can be anonymous.
|
322 | 222 |
|
323 | |
((lambda (a) a) (quote whee))
|
324 | |
===> whee
|
|
223 |
((lambda (a) a) "whee")
|
|
224 |
===> "whee"
|
325 | 225 |
|
326 | 226 |
Bindings in force when a function is defined will still be in force
|
327 | 227 |
when the function is applied, even if they are not lexically in scope.
|
|
358 | 258 |
|
359 | 259 |
- - - -
|
360 | 260 |
|
|
261 |
Cons Lists
|
|
262 |
----------
|
|
263 |
|
|
264 |
-> Tests for functionality "Interpret Consful Decoy Program"
|
|
265 |
|
|
266 |
`quote` evaluates to literally what is in the head of the tail of
|
|
267 |
the cons cell whose head is `quote`.
|
|
268 |
|
|
269 |
(quote hello)
|
|
270 |
===> hello
|
|
271 |
|
|
272 |
(quote (quote quote))
|
|
273 |
===> (quote quote)
|
|
274 |
|
|
275 |
Atomic symbols may contain letters, `*`s, `?`s, and `-`s.
|
|
276 |
|
|
277 |
(quote abcdef-ghijklm*nopqrst?uvwxyz)
|
|
278 |
===> abcdef-ghijklm*nopqrst?uvwxyz
|
|
279 |
|
|
280 |
`cons` lets you create a list from some thing and another list.
|
|
281 |
|
|
282 |
(cons (quote thing) (quote (rest)))
|
|
283 |
===> (thing rest)
|
|
284 |
|
|
285 |
`cons` can be used to create an improper list.
|
|
286 |
(The `.` syntax for improper lists is not supported in the reader though.)
|
|
287 |
|
|
288 |
(cons (quote thing) (quote rest))
|
|
289 |
===> (thing . rest)
|
|
290 |
|
|
291 |
`car` extracts the head of a list.
|
|
292 |
|
|
293 |
(car (quote (foo bar)))
|
|
294 |
===> foo
|
|
295 |
|
|
296 |
`cdr` extracts the tail of a list.
|
|
297 |
|
|
298 |
(cdr (quote (foo bar)))
|
|
299 |
===> (bar)
|
|
300 |
|
|
301 |
List lists
|
|
302 |
----------
|
|
303 |
|
|
304 |
(if (list 1) "true" "false")
|
|
305 |
===> "true"
|
|
306 |
|
|
307 |
(if (list) "true" "false")
|
|
308 |
===> "true"
|
|
309 |
|
|
310 |
Predicates and Types
|
|
311 |
--------------------
|
|
312 |
|
|
313 |
`equal?` works on symbols.
|
|
314 |
|
|
315 |
(cond (
|
|
316 |
(equal? (quote a) (quote a))
|
|
317 |
(quote true)) (else (quote false)))
|
|
318 |
===> true
|
|
319 |
|
|
320 |
(cond (
|
|
321 |
(equal? (quote a) (quote b))
|
|
322 |
(quote true)) (else (quote false)))
|
|
323 |
===> false
|
|
324 |
|
|
325 |
`equal?` works on lists.
|
|
326 |
|
|
327 |
(cond (
|
|
328 |
(equal? (quote (one (two three)))
|
|
329 |
(cons (quote one) (quote ((two three)))))
|
|
330 |
(quote true)) (else (quote false)))
|
|
331 |
===> true
|
|
332 |
|
|
333 |
A symbol is not a list.
|
|
334 |
|
|
335 |
(cond (
|
|
336 |
(list? (quote a))
|
|
337 |
(quote true)) (else (quote false)))
|
|
338 |
===> false
|
|
339 |
|
|
340 |
A list whose final cons cell's tail contains a null, is a list.
|
|
341 |
|
|
342 |
(cond (
|
|
343 |
(list? (cons (quote a) (quote ())))
|
|
344 |
(quote true)) (else (quote false)))
|
|
345 |
===> true
|
|
346 |
|
|
347 |
(cond (
|
|
348 |
(list? (quote (a b c d e f)))
|
|
349 |
(quote true)) (else (quote false)))
|
|
350 |
===> true
|
|
351 |
|
|
352 |
A pair is not a list.
|
|
353 |
|
|
354 |
Actually, pairs aren't defined at all in Decoy, so I wouldn't
|
|
355 |
blame an implementation for just freaking out at this one.
|
|
356 |
|
|
357 |
(cond (
|
|
358 |
(list? (cons (quote a) (quote b)))
|
|
359 |
(quote true)) (else (quote false)))
|
|
360 |
===> false
|
|
361 |
|
|
362 |
Booleans are not lists.
|
|
363 |
|
|
364 |
(cond (
|
|
365 |
(list? (equal? (quote a) (quote b)))
|
|
366 |
(quote true)) (else (quote false)))
|
|
367 |
===> false
|
|
368 |
|
|
369 |
Lambda functions are not lists.
|
|
370 |
|
|
371 |
(cond (
|
|
372 |
(list? (lambda (x y) (y x)))
|
|
373 |
(quote true)) (else (quote false)))
|
|
374 |
===> false
|
|
375 |
|
|
376 |
But the empty list is a list.
|
|
377 |
|
|
378 |
(cond (
|
|
379 |
(list? (quote ()))
|
|
380 |
(quote true)) (else (quote false)))
|
|
381 |
===> true
|
|
382 |
|
|
383 |
(cond (
|
|
384 |
(list? (cdr (quote (foo))))
|
|
385 |
(quote true)) (else (quote false)))
|
|
386 |
===> true
|
|
387 |
|
|
388 |
The empty list can be expressed as `(quote ())`.
|
|
389 |
|
|
390 |
(cond (
|
|
391 |
(equal? (cdr (quote (foo))) (quote ()))
|
|
392 |
(quote true)) (else (quote false)))
|
|
393 |
===> true
|
|
394 |
|
361 | 395 |
More Types
|
362 | 396 |
----------
|
|
397 |
|
|
398 |
-> Tests for functionality "Interpret Decoy Program"
|
363 | 399 |
|
364 | 400 |
### Strings
|
365 | 401 |
|