chapter-08-lambda-the-ultimate.scm 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. (use-modules (srfi srfi-64))
  2. ;; needed for the books code
  3. (define (atom? sth)
  4. (and (not (pair? sth))
  5. (not (null? sth))))
  6. ;; ====================================
  7. ;; Exercises and Solutions of Chapter 8
  8. ;; ====================================
  9. (define rember-f
  10. (λ (test? a lst)
  11. (cond [(null? lst) '()]
  12. [(test? a (car lst))
  13. (rember-f test? a (cdr lst))]
  14. [else (cons (car lst)
  15. (rember-f test?
  16. a
  17. (cdr lst)))])))
  18. (test-begin "rember-f-test")
  19. (test-group "rember-f-test"
  20. (test-equal (rember-f eq? 'a '(a b c a d e)) '(b c d e))
  21. (test-equal (rember-f eq? 'a '(h b c k d e)) '(h b c k d e))
  22. (test-equal (rember-f eq? 'tuna '(tuna salad is good)) '(salad is good)))
  23. (test-end "rember-f-test")
  24. (define rember-f-2
  25. (λ (test?)
  26. (λ (a lst)
  27. (cond [(null? lst) '()]
  28. [(test? a (car lst)) ((rember-f-2 test?) a (cdr lst))]
  29. [else (cons (car lst)
  30. ((rember-f-2 test?) a (cdr lst)))]))))
  31. (test-begin "rember-f-2-test")
  32. (test-group "rember-f-2-test"
  33. (test-equal ((rember-f-2 eq?) 'a '(a b c a d e))
  34. '(b c d e))
  35. (test-equal ((rember-f-2 eq?) 'a '(h b c k d e))
  36. '(h b c k d e))
  37. (test-equal ((rember-f-2 eq?) 'tuna '(shrimp salad and tuna salad))
  38. '(shrimp salad and salad)))
  39. (test-end "rember-f-2-test")
  40. (define insertL
  41. (λ (insertion right lst)
  42. (cond [(null? lst) '()]
  43. [(eq? (car lst) right) (cons insertion
  44. (cons right
  45. (insertL insertion right (cdr lst))))]
  46. [else (cons (car lst)
  47. (insertL insertion
  48. right
  49. (cdr lst)))])))
  50. (test-begin "insertL-test")
  51. (test-group "insertL-test"
  52. (test-equal (insertL 'ins 'a '(c b a g d e)) '(c b ins a g d e))
  53. (test-equal (insertL 'ins 'a '(c b g d e)) '(c b g d e)))
  54. (test-end "insertL-test")
  55. (define insertR
  56. (λ (insertion left lst)
  57. (cond [(null? lst) '()]
  58. [(eq? (car lst) left)
  59. (cons left
  60. (cons insertion
  61. (insertR insertion left (cdr lst))))]
  62. [else (cons (car lst)
  63. (insertR insertion
  64. left
  65. (cdr lst)))])))
  66. (test-begin "insertR-test")
  67. (test-group "insertR-test"
  68. (test-equal (insertR 'ins 'a '(c b a g d e))
  69. '(c b a ins g d e))
  70. (test-equal (insertR 'ins 'a '(c b g d e))
  71. '(c b g d e)))
  72. (test-end "insertR-test")
  73. (define insertL-f
  74. (λ (test?)
  75. (λ (insertion right lst)
  76. (cond [(null? lst) '()]
  77. [(test? (car lst) right)
  78. (cons insertion
  79. (cons (car lst)
  80. ((insertL-f test?)
  81. insertion
  82. right
  83. (cdr lst))))]
  84. [else
  85. (cons (car lst)
  86. ((insertL-f test?)
  87. insertion
  88. right
  89. (cdr lst)))]))))
  90. (test-begin "insertL-f-test")
  91. (test-group "insertL-f-test"
  92. (test-equal ((insertL-f eq?) 'ins 'a '(c b a g d e))
  93. '(c b ins a g d e))
  94. (test-equal ((insertL-f eq?) 'ins 'a '(c b g d e))
  95. '(c b g d e))
  96. (test-equal ((insertL-f (λ (first second)
  97. (not (eq? first second))))
  98. 'ins
  99. 'elem-to-find
  100. '(c b g d e))
  101. '(ins c ins b ins g ins d ins e)))
  102. (test-end "insertL-f-test")
  103. (define insertR-f
  104. (λ (test?)
  105. (λ (insertion left lst)
  106. #;(display (simple-format #f "called with: ~a ~a ~a\n" insertion left lst))
  107. (cond [(null? lst) '()]
  108. [(test? (car lst) left)
  109. #;(display (simple-format #f "res: ~a\n"
  110. (cons (car lst)
  111. (cons insertion
  112. 'REST))))
  113. (cons (car lst)
  114. (cons insertion
  115. ((insertR-f test?) insertion left (cdr lst))))]
  116. [else (cons (car lst)
  117. ((insertR-f test?) insertion left (cdr lst)))]))))
  118. (test-begin "insertR-f-test")
  119. (test-group "insertR-f-test"
  120. (test-equal ((insertR-f eq?) 'ins 'a '(c b a g d e))
  121. '(c b a ins g d e))
  122. (test-equal ((insertR-f eq?) 'ins 'a '(c b g d e))
  123. '(c b g d e))
  124. (test-equal ((insertR-f (λ (first second) (not (eq? first second))))
  125. 'ins
  126. 'a
  127. '(c b g d e))
  128. '(c ins b ins g ins d ins e ins)))
  129. (test-end "insertR-f-test")
  130. (define insert-g-attempt
  131. (λ (test?)
  132. (λ (insertion elem-to-find lst)
  133. (cond [(null? lst) '()]
  134. [(test? (car lst) elem-to-find)
  135. (cons (car lst)
  136. (cons insertion
  137. ((insert-g-attempt test?) insertion elem-to-find (cdr lst))))]
  138. [else (cons insertion
  139. (cons (car lst)
  140. ((insert-g-attempt test?) insertion elem-to-find (cdr lst))))]))))
  141. (test-begin "insert-g-attempt-test")
  142. (test-group "insert-g-attempt-test"
  143. (test-equal ((insert-g-attempt eq?) 'ins 'a '(c b a g d e))
  144. '(ins c ins b a ins ins g ins d ins e))
  145. (test-equal ((insert-g-attempt eq?) 'ins 'a '(c b g d e))
  146. '(ins c ins b ins g ins d ins e))
  147. (test-equal ((insert-g-attempt (λ (first second)
  148. (not (eq? first second))))
  149. 'ins
  150. 'a
  151. '(c b g d e))
  152. '(c ins b ins g ins d ins e ins)))
  153. (test-end "insert-g-attempt-test")
  154. (define seqL
  155. (λ (insertion right lst)
  156. (cons insertion (cons right lst))))
  157. (test-begin "seqL-test")
  158. (test-group "seqL-test"
  159. (test-equal (seqL 'a 'b '(c d))
  160. '(a b c d)))
  161. (test-end "seqL-test")
  162. (define seqR
  163. (λ (insertion left lst)
  164. (cons left (cons insertion lst))))
  165. (test-begin "seqR-test")
  166. (test-group "seqR-test"
  167. (test-equal (seqR 'a 'b '(c d))
  168. '(b a c d)))
  169. (test-end "seqR-test")
  170. ;; Now define insertL and insertR in terms of a modified insert-g, which takes a function as a parameter, which determins how to insert.
  171. (define make-inserter-with-sequencer
  172. (λ (sequencer)
  173. (λ (insertion to-find lst)
  174. (cond [(null? lst) '()]
  175. [(eq? (car lst) to-find)
  176. (sequencer insertion
  177. to-find
  178. ((make-inserter-with-sequencer sequencer)
  179. insertion
  180. to-find
  181. (cdr lst)))]
  182. [else (cons (car lst)
  183. ((make-inserter-with-sequencer sequencer)
  184. insertion
  185. to-find
  186. (cdr lst)))]))))
  187. (test-begin "make-inserter-with-sequencer-test")
  188. (test-group "make-inserter-with-sequencer-test"
  189. (let ([insertion 'ins]
  190. [to-find 'a]
  191. [left-inserter (make-inserter-with-sequencer seqL)]
  192. [right-inserter (make-inserter-with-sequencer seqR)]
  193. [left-inserter-with-lambda
  194. (make-inserter-with-sequencer
  195. (λ (insertion right lst)
  196. (cons insertion (cons right lst))))]
  197. [right-inserter-with-lambda
  198. (make-inserter-with-sequencer
  199. (λ (insertion left lst)
  200. (cons left (cons insertion lst))))])
  201. (test-equal (left-inserter insertion
  202. to-find
  203. '(c d))
  204. '(c d))
  205. (test-equal (left-inserter insertion
  206. to-find
  207. '(a c d))
  208. '(ins a c d))
  209. (test-equal (left-inserter insertion
  210. to-find
  211. '(a c a d))
  212. '(ins a c ins a d))
  213. (test-equal (right-inserter insertion
  214. to-find
  215. '(a c d))
  216. '(a ins c d))
  217. (test-equal (right-inserter insertion
  218. to-find
  219. '(a c a d))
  220. '(a ins c a ins d))
  221. (test-equal (left-inserter-with-lambda insertion
  222. to-find
  223. '(a c d))
  224. '(ins a c d))
  225. (test-equal (right-inserter-with-lambda insertion
  226. to-find
  227. '(a c d))
  228. '(a ins c d))
  229. (test-equal (left-inserter insertion to-find '(c d))
  230. (right-inserter insertion to-find '(c d)))))
  231. (test-end "make-inserter-with-sequencer-test")
  232. (define substitute
  233. (make-inserter-with-sequencer
  234. (λ (insertion to-find lst)
  235. (cons insertion lst))))
  236. (test-begin "substitute-test")
  237. (test-group "substitute-test"
  238. (test-equal (substitute 'a 'c '(c d)) '(a d))
  239. (test-equal (substitute 'sub 'a '(c a a d)) '(c sub sub d)))
  240. (test-end "substitute-test")
  241. (define rember
  242. (make-inserter-with-sequencer
  243. (λ (insertion to-find lst) lst)))
  244. (test-begin "rember-test")
  245. (test-group "rember-test"
  246. (test-equal (rember #f 'c '(c d)) '(d))
  247. (test-equal (rember #f 'a '(c a a d)) '(c d))
  248. (test-equal (rember #f 'sausage '(pizza with sausage and bacon)) '(pizza with and bacon)))
  249. (test-end "rember-test")
  250. ;; =======================
  251. ;; after ninth commandment
  252. ;; =======================
  253. ;; Write something similar for the `value` function.
  254. ;; Here is the value function from chapter 6.
  255. ;; It relies on previously defined functions.
  256. (define value
  257. (λ (nexp)
  258. (cond [(atom? nexp) nexp]
  259. [(eq? (operator nexp) '+)
  260. (plus (value (1st-sub-expr nexp))
  261. (value (2nd-sub-expr nexp)))]
  262. [(eq? (operator nexp) '*)
  263. (mult (value (1st-sub-expr nexp))
  264. (value (2nd-sub-expr nexp)))]
  265. [else
  266. (pow (value (1st-sub-expr nexp))
  267. (value (2nd-sub-expr nexp)))])))
  268. (define (1st-sub-expr aexp)
  269. (cadr aexp))
  270. (define (2nd-sub-expr aexp)
  271. (caddr aexp))
  272. (define (operator aexp)
  273. (car aexp))
  274. (define (plus num1 num2)
  275. (define (iter res to-add)
  276. (cond [(or (< res 0) (< to-add 0))
  277. (throw 'failed-contract "number is negative - we only deal with positive numbers")]
  278. [(zero? to-add) res]
  279. [else (iter (addo1 res) (subo1 to-add))]))
  280. (iter num1 num2))
  281. (define (mult summand times-to-add)
  282. (define (iter res times-to-add)
  283. (cond [(or (< res 0) (< times-to-add 0))
  284. (throw 'failed-contract "number is negative - we only deal with positive numbers")]
  285. [(zero? times-to-add) res]
  286. [else (iter (plus res summand)
  287. (subo1 times-to-add))]))
  288. (iter 0 times-to-add))
  289. (define (pow base exponent)
  290. (cond
  291. [(zero? exponent) 1]
  292. [(zero? base) 0]
  293. [else (mult base
  294. (pow base (subo1 exponent)))]))
  295. (define (subo1 num)
  296. (cond [(< num 1)
  297. (throw 'failed-contract "number is negative - we only deal with positive numbers")]
  298. [else (- num 1)]))
  299. (define (addo1 num)
  300. (cond [(< num 0)
  301. (throw 'failed-contract "number is negative - we only deal with positive numbers")]
  302. [else (+ num 1)]))
  303. ;; Now we define the abstraction to get the repeating code outside of value.
  304. (define atom-to-function
  305. (λ (a)
  306. (cond [(eq? a '+) plus]
  307. [(eq? a '*) mult]
  308. [else pow])))
  309. ;; Rewrite `value` using `atom-to-function` so that it has only 2 cond branches.
  310. (define value-2
  311. (λ (nexp)
  312. (cond [(atom? nexp) nexp]
  313. [else
  314. ((atom-to-function (operator nexp))
  315. (value-2 (1st-sub-expr nexp))
  316. (value-2 (2nd-sub-expr nexp)))])))
  317. ;; Rewrite multirember to take the test? function as an argument.
  318. (define (multirember a lat)
  319. (cond [(null? lat) '()]
  320. [(eq? a (car lat)) (multirember a (cdr lat))]
  321. [else (cons (car lat)
  322. (rember a (cdr lat)))]))
  323. (define multirember-f
  324. (λ (test?)
  325. (λ (a lat)
  326. (cond [(null? lat) '()]
  327. [(test? a (car lat))
  328. ((multirember-f test?) a (cdr lat))]
  329. [else
  330. (cons (car lat)
  331. ((multirember-f test?) a (cdr lat)))]))))
  332. (define multirember&co
  333. (λ (a lat col)
  334. (cond
  335. [(null? lat)
  336. (col '() '())]
  337. [(eq? (car lat) a)
  338. (multirember&co a
  339. (cdr lat)
  340. ;; construct a lambda which takes the final 2 arguments
  341. ;; delaying evaluation by using a lambda
  342. (λ (newlat seen)
  343. ;; call previous lambda (named col)
  344. ;; Why name it "newlat"?
  345. ;; Because it is the list,
  346. ;; that would be without the a, which is removed.
  347. (col newlat
  348. ;; but append the car of lat to the "seen"
  349. ;; equal elements
  350. (cons (car lat) seen))))]
  351. [else
  352. (multirember&co a
  353. (cdr lat)
  354. (λ (newlat seen)
  355. ;; the other way around,
  356. ;; consing to the other elements
  357. (col (cons (car lat) newlat)
  358. seen)))])))
  359. (define a-friend
  360. (λ (x y)
  361. (null? y)))
  362. ;; The book gives the following repetition of code for easier reading.
  363. (define (multiinsertL elem right lat)
  364. (cond [(null? lat) '()]
  365. [(eq? right (car lat))
  366. (cons elem
  367. (cons (car lat)
  368. (multiinsertL elem
  369. right
  370. (cdr lat))))]
  371. [else
  372. (cons (car lat)
  373. (multiinsertL elem right (cdr lat)))]))
  374. (define (multiinsertR elem left lat)
  375. (cond [(null? lat) '()]
  376. [(eq? left (car lat))
  377. (cons left
  378. (cons elem
  379. (multiinsertR elem
  380. left
  381. (cdr lat))))]
  382. [else
  383. (cons (car lat)
  384. (multiinsertR elem left (cdr lat)))]))
  385. (define (multiinsertLR elem left right lat)
  386. (cond [(null? lat) '()]
  387. [(eq? (car lat) right)
  388. (cons elem
  389. (cons right
  390. (multiinsertLR elem
  391. left
  392. right
  393. (cdr lat))))]
  394. [(eq? (car lat) left)
  395. (cons left
  396. (cons elem
  397. (multiinsertLR elem
  398. left
  399. right
  400. (cdr lat))))]
  401. [else
  402. (cons (car lat)
  403. (multiinsertLR elem
  404. left
  405. right
  406. (cdr lat)))]))
  407. ;; Write multiinsertLR&co.
  408. ;; The final result depends on the given continuation col, for it will
  409. ;; be called in the newly made lambdas, that are passed on as new
  410. ;; continuations. It will be called as a very last step, when the list
  411. ;; is empty. In other cases it merely be "wrapped" in new
  412. ;; lambdas. Those new lambdas or new continuation will finally be
  413. ;; evaluated when the base case of multiinsertLR&co happens and the
  414. ;; then wrapped continuation is called.
  415. (define (multiinsertLR&co inserted left right lat col)
  416. (cond [(null? lat)
  417. ;; empty list will be consed to whatever col builds.
  418. ;; zeros will be added to the counts col already accumulated.
  419. (col '() 0 0)]
  420. [(eq? (car lat) right)
  421. ;; recur
  422. (multiinsertLR&co inserted
  423. left
  424. right
  425. ;; search rest of list
  426. (cdr lat)
  427. ;; build new continuation to wrap previous continuation
  428. (λ (newlat left-count right-count)
  429. ;; call to the previous col, which will
  430. ;; be evaluated later, when this lambda
  431. ;; is evaluated
  432. (col
  433. ;; build the new list - do what you would
  434. ;; normally do in multiinsertLR for the
  435. ;; list of atoms.
  436. ;; newlat will be given later, by outer
  437. ;; wrapping lambdas and finally by the
  438. ;; call to col, which will be the empty
  439. ;; list to make a proper list.
  440. (cons inserted (cons right newlat))
  441. ;; not a left but a right insertedent was found, so left-count stays the same.
  442. left-count
  443. ;; a right element was found, so right-count is increased by one.
  444. (+ right-count 1))))]
  445. [(eq? (car lat) left)
  446. ;; recur
  447. (multiinsertLR&co inserted
  448. left
  449. right
  450. ;; search rest of list
  451. (cdr lat)
  452. ;; build new continuation to wrap previous continuation
  453. (λ (newlat left-count right-count)
  454. ;; call to the previous col, which will
  455. ;; be evaluated later, when this lambda
  456. ;; is evaluated
  457. (col
  458. ;; build the new list - do what you would
  459. ;; normally do in multiinsertLR for the
  460. ;; list of atoms.
  461. ;; newlat will be given later, by outer
  462. ;; wrapping lambdas and finally by the
  463. ;; call to col, which will be the empty
  464. ;; list to make a proper list.
  465. (cons left (cons inserted newlat))
  466. ;; a left element was found, so left-count is increased by one.
  467. (+ left-count 1)
  468. ;; not a right but a left element was found, so right-count stays the same.
  469. right-count)))]
  470. [else
  471. ;; recur
  472. (multiinsertLR&co inserted
  473. left
  474. right
  475. ;; search the rest of the list
  476. (cdr lat)
  477. ;; build new continuation to wrap previous continuation
  478. (λ (newlat left-count right-count)
  479. ;; call to the previous col, which will
  480. ;; be evaluated later, when this lambda
  481. ;; is evaluated
  482. (col
  483. ;; build the new list - do what you would
  484. ;; normally do in multiinsertLR for the
  485. ;; list of atoms.
  486. ;; newlat will be given later, by outer
  487. ;; wrapping lambdas and finally by the
  488. ;; call to col, which will be the empty
  489. ;; list to make a proper list.
  490. ;; neither left nor right has been
  491. ;; found, so we do not insert anything.
  492. (cons (car lat) newlat)
  493. ;; a left element was found, so left-count is increased by one.
  494. left-count
  495. ;; not a right but a left element was found, so right-count stays the same.
  496. right-count)))]))
  497. ;; TASK: Write evens-only*.
  498. (define even?
  499. (lambda (num)
  500. (= (remainder num 2)
  501. 0)))
  502. (define evens-only*
  503. (lambda (lst)
  504. (cond [(null? lst) '()]
  505. [(atom? (car lst))
  506. (cond [(even? (car lst))
  507. (cons (car lst) (evens-only* (cdr lst)))]
  508. [else (evens-only* (cdr lst))])]
  509. [else
  510. (cons (evens-only* (car lst))
  511. (evens-only* (cdr lst)))])))
  512. (test-begin "evens-only-asterisk-test")
  513. (test-group "evens-only-asterisk-test"
  514. (test-equal
  515. '(2 4)
  516. (evens-only* '(1 2 3 4)))
  517. (test-equal
  518. '((2) 4)
  519. (evens-only* '(1 (2 3) 4))))
  520. (test-end "evens-only-asterisk-test")
  521. ;; TASK: Write evens-only*&co.
  522. (define evens-only*&co
  523. (lambda (lst col)
  524. (cond [(null? lst)
  525. ;; Finish the list with the empty list and use the neutral elements of multiplication
  526. ;; (one) and addition (zero).
  527. (col '() 1 0)]
  528. [(atom? (car lst))
  529. (cond [(even? (car lst))
  530. ;; In case of an even number we need to multiply it with the product of factors
  531. ;; yet to be visited.
  532. (evens-only*&co (cdr lst)
  533. (lambda (new-lst factor addend)
  534. (col (cons (car lst) new-lst)
  535. (* (car lst) factor)
  536. addend)))]
  537. [else
  538. ;; In case of an odd number, we need to add it to the sum of odd numbers in the
  539. ;; continuation.
  540. (evens-only*&co (cdr lst)
  541. (lambda (new-lst factor addend)
  542. (col new-lst
  543. factor
  544. (+ (car lst) addend))))])]
  545. [else
  546. ;; In case car is a list, it is more complicated. The idea is to first calculate the
  547. ;; result for the car and at the same time build up the continuation for the cdr of the
  548. ;; list. The continuation however, needs to to apply evens-only*&co to the cdr at some
  549. ;; point. This is why we call it and only then give an updated continuation to it as an
  550. ;; argument.
  551. (evens-only*&co (car lst)
  552. ;; Build the continuation for the application to cdr of the list. The
  553. ;; signature must still match though!
  554. (lambda (new-lst-from-car factor-from-car addend-from-car)
  555. ;; Apply evens-only*&co also to the cdr of the list.
  556. (evens-only*&co (cdr lst)
  557. ;; Give it the updated continuation.
  558. (lambda (new-lst-from-cdr factor-from-cdr addend-from-cdr)
  559. ;; The original list consisted of a list in car and a
  560. ;; list in cdr. This means the new list needs to have
  561. ;; the same nesting structure. We cons the new list
  562. ;; produced from the call of evens-only*&co for the
  563. ;; car to the new list produced from the call to
  564. ;; evens-only*&co for the cdr.
  565. ;; Here we rely on the evens-only*&co call for cdr
  566. ;; again giving us the appropriate arguments and take
  567. ;; the other used values from the outer scope, which
  568. ;; is a continuation for the call of evens-only*&co
  569. ;; for the car of the list.
  570. (col (cons new-lst-from-car new-lst-from-cdr)
  571. ;; Also we need to multiply the factor from the
  572. ;; car and the factor from cdr.
  573. (* factor-from-car factor-from-cdr)
  574. ;; And the addends of car and cdr.X
  575. (+ addend-from-car addend-from-cdr))))))])))
  576. ;; NOTE:
  577. ;; This function is an example for building a continuation, which handles the cdr (or tail or right
  578. ;; or left part) to do tail call elimination when traversing a tree. Instead of "forking" into two
  579. ;; recursive calls, only the call for the car (or head or left or right part) is made and the call
  580. ;; for the cdr is put into the newly built continuation instead of being at the "same level".
  581. (test-begin "evens-only-asterisk-and-co")
  582. (test-group "evens-only-asterisk-and-co"
  583. (test-equal
  584. '((2 4) 8 4)
  585. (evens-only*&co '(1 2 3 4)
  586. (lambda (new-lst prod sum)
  587. (list new-lst prod sum)))))
  588. (test-end "evens-only-asterisk-and-co")