r5rs_pitfall.scm 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. (define-syntax should-be
  2. (syntax-rules ()
  3. ((_ test-id value expression)
  4. (try-catch
  5. (let ((return-value expression))
  6. (if (not (equal? return-value value))
  7. (for-each (lambda (v) (display v))
  8. `("Failure: " test-id ", expected '"
  9. value "', got '" ,return-value "'." #\newline))
  10. (for-each (lambda (v) (display v))
  11. '("Passed: " test-id #\newline))))
  12. (ex <java.lang.Throwable>
  13. (format #t "Failure: ~s - caught exception.~%~!" test-id))))))
  14. (define call/cc call-with-current-continuation)
  15. ;; Section 1: Proper letrec implementation
  16. ;;Credits to Al Petrofsky
  17. ;; In thread:
  18. ;; defines in letrec body
  19. ;; http://groups.google.com/groups?selm=87bsoq0wfk.fsf%40app.dial.idiom.com
  20. (should-be 1.1 0
  21. (let ((cont #f))
  22. (letrec ((x (call-with-current-continuation (lambda (c) (set! cont c) 0)))
  23. (y (call-with-current-continuation (lambda (c) (set! cont c) 0))))
  24. (if cont
  25. (let ((c cont))
  26. (set! cont #f)2
  27. (set! x 1)
  28. (set! y 1)
  29. (c 0))
  30. (+ x y)))))
  31. ;;Credits to Al Petrofsky
  32. ;; In thread:
  33. ;; Widespread bug (arguably) in letrec when an initializer returns twice
  34. ;; http://groups.google.com/groups?selm=87d793aacz.fsf_-_%40app.dial.idiom.com
  35. (should-be 1.2 #t
  36. (letrec ((x (call/cc list)) (y (call/cc list)))
  37. (cond ((procedure? x) (x (pair? y)))
  38. ((procedure? y) (y (pair? x))))
  39. (let ((x (car x)) (y (car y)))
  40. (and (call/cc x) (call/cc y) (call/cc x)))))
  41. ;;Credits to Alan Bawden
  42. ;; In thread:
  43. ;; LETREC + CALL/CC = SET! even in a limited setting
  44. ;; http://groups.google.com/groups?selm=19890302162742.4.ALAN%40PIGPEN.AI.MIT.EDU
  45. (should-be 1.3 #t
  46. (letrec ((x (call-with-current-continuation
  47. (lambda (c)
  48. (list #T c)))))
  49. (if (car x)
  50. ((cadr x) (list #F (lambda () x)))
  51. (eq? x ((cadr x))))))
  52. ;; Section 2: Proper call/cc and procedure application
  53. ;;Credits to Al Petrofsky, (and a wink to Matthias Blume)
  54. ;; In thread:
  55. ;; Widespread bug in handling (call/cc (lambda (c) (0 (c 1)))) => 1
  56. ;; http://groups.google.com/groups?selm=87g00y4b6l.fsf%40radish.petrofsky.org
  57. (should-be 2.1 1
  58. (call/cc (lambda (c) (0 (c 1)))))
  59. ;; Section 3: Hygienic macros
  60. ;; Eli Barzilay
  61. ;; In thread:
  62. ;; R5RS macros...
  63. ;; http://groups.google.com/groups?selm=skitsdqjq3.fsf%40tulare.cs.cornell.edu
  64. (should-be 3.1 4
  65. (let-syntax ((foo
  66. (syntax-rules ()
  67. ((_ expr) (+ expr 1)))))
  68. (let ((+ *))
  69. (foo 3))))
  70. ;; Al Petrofsky again
  71. ;; In thread:
  72. ;; Buggy use of begin in r5rs cond and case macros.
  73. ;; http://groups.google.com/groups?selm=87bse3bznr.fsf%40radish.petrofsky.org
  74. (should-be 3.2 2
  75. (let-syntax ((foo (syntax-rules ()
  76. ((_ var) (define var 1)))))
  77. (let ((x 2))
  78. (begin (define foo +))
  79. (cond (else (foo x)))
  80. x)))
  81. ;;Al Petrofsky
  82. ;; In thread:
  83. ;; An Advanced syntax-rules Primer for the Mildly Insane
  84. ;; http://groups.google.com/groups?selm=87it8db0um.fsf@radish.petrofsky.org
  85. (should-be 3.3 1
  86. (let ((x 1))
  87. (let-syntax
  88. ((foo (syntax-rules ()
  89. ((_ y) (let-syntax
  90. ((bar (syntax-rules ()
  91. ((_) (let ((x 2)) y)))))
  92. (bar))))))
  93. (foo x))))
  94. ;; Al Petrofsky
  95. ;; Contributed directly
  96. (should-be 3.4 1
  97. (let-syntax ((x (syntax-rules ()))) 1))
  98. ;; Setion 4: No identifiers are reserved
  99. ;;(Brian M. Moore)
  100. ;; In thread:
  101. ;; shadowing syntatic keywords, bug in MIT Scheme?
  102. ;; http://groups.google.com/groups?selm=6e6n88%248qf%241%40news.cc.ukans.edu
  103. (should-be 4.1 '(x)
  104. ((lambda lambda lambda) 'x))
  105. (should-be 4.2 '(1 2 3)
  106. ((lambda (begin) (begin 1 2 3)) (lambda lambda lambda)))
  107. (should-be 4.3 #f
  108. (let ((quote -)) (eqv? '1 1)))
  109. ;; Section 5: #f/() distinctness
  110. ;; Scott Miller
  111. (should-be 5.1 #f
  112. (eq? #f '()))
  113. (should-be 5.2 #f
  114. (eqv? #f '()))
  115. (should-be 5.3 #f
  116. (equal? #f '()))
  117. ;; Section 6: string->symbol case sensitivity
  118. ;; Jens Axel S?gaard
  119. ;; In thread:
  120. ;; Symbols in DrScheme - bug?
  121. ;; http://groups.google.com/groups?selm=3be55b4f%240%24358%24edfadb0f%40dspool01.news.tele.dk
  122. (should-be 6.1 #f
  123. (eq? (string->symbol "f") (string->symbol "F")))
  124. ;; Section 7: First class continuations
  125. ;; Scott Miller
  126. ;; No newsgroup posting associated. The jist of this test and 7.2
  127. ;; is that once captured, a continuation should be unmodified by the
  128. ;; invocation of other continuations. This test determines that this is
  129. ;; the case by capturing a continuation and setting it aside in a temporary
  130. ;; variable while it invokes that and another continuation, trying to
  131. ;; side effect the first continuation. This test case was developed when
  132. ;; testing SISC 1.7's lazy CallFrame unzipping code.
  133. (define r #f)
  134. (define a #f)
  135. (define b #f)
  136. (define c #f)
  137. (define i 0)
  138. (should-be 7.1 28
  139. (let ()
  140. (set! r (+ 1 (+ 2 (+ 3 (call/cc (lambda (k) (set! a k) 4))))
  141. (+ 5 (+ 6 (call/cc (lambda (k) (set! b k) 7))))))
  142. (if (not c)
  143. (set! c a))
  144. (set! i (+ i 1))
  145. (case i
  146. ((1) (a 5))
  147. ((2) (b 8))
  148. ((3) (a 6))
  149. ((4) (c 4)))
  150. r))
  151. ;; Same test, but in reverse order
  152. (define r #f)
  153. (define a #f)
  154. (define b #f)
  155. (define c #f)
  156. (define i 0)
  157. (should-be 7.2 28
  158. (let ()
  159. (set! r (+ 1 (+ 2 (+ 3 (call/cc (lambda (k) (set! a k) 4))))
  160. (+ 5 (+ 6 (call/cc (lambda (k) (set! b k) 7))))))
  161. (if (not c)
  162. (set! c a))
  163. (set! i (+ i 1))
  164. (case i
  165. ((1) (b 8))
  166. ((2) (a 5))
  167. ((3) (b 7))
  168. ((4) (c 4)))
  169. r))
  170. ;; Credits to Matthias Radestock
  171. ;; Another test case used to test SISC's lazy CallFrame routines.
  172. (should-be 7.3 '((-1 4 5 3)
  173. (4 -1 5 3)
  174. (-1 5 4 3)
  175. (5 -1 4 3)
  176. (4 5 -1 3)
  177. (5 4 -1 3))
  178. (let ((k1 #f)
  179. (k2 #f)
  180. (k3 #f)
  181. (state 0))
  182. (define (identity x) x)
  183. (define (fn)
  184. ((identity (if (= state 0)
  185. (call/cc (lambda (k) (set! k1 k) +))
  186. +))
  187. (identity (if (= state 0)
  188. (call/cc (lambda (k) (set! k2 k) 1))
  189. 1))
  190. (identity (if (= state 0)
  191. (call/cc (lambda (k) (set! k3 k) 2))
  192. 2))))
  193. (define (check states)
  194. (set! state 0)
  195. (let* ((res '())
  196. (r (fn)))
  197. (set! res (cons r res))
  198. (if (null? states)
  199. res
  200. (begin (set! state (car states))
  201. (set! states (cdr states))
  202. (case state
  203. ((1) (k3 4))
  204. ((2) (k2 2))
  205. ((3) (k1 -)))))))
  206. (map check '((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1)))))
  207. ;; Modification of the yin-yang puzzle so that it terminates and produces
  208. ;; a value as a result. (Scott G. Miller)
  209. (should-be 7.4 '(10 9 8 7 6 5 4 3 2 1 0)
  210. (let ((x '())
  211. (y 0))
  212. (call/cc
  213. (lambda (escape)
  214. (let* ((yin ((lambda (foo)
  215. (set! x (cons y x))
  216. (if (= y 10)
  217. (escape x)
  218. (begin
  219. (set! y 0)
  220. foo)))
  221. (call/cc (lambda (bar) bar))))
  222. (yang ((lambda (foo)
  223. (set! y (+ y 1))
  224. foo)
  225. (call/cc (lambda (baz) baz)))))
  226. (yin yang))))))
  227. ;; Miscellaneous
  228. ;;Al Petrofsky
  229. ;; In thread:
  230. ;; R5RS Implementors Pitfalls
  231. ;; http://groups.google.com/groups?selm=871zemtmd4.fsf@app.dial.idiom.com
  232. (should-be 8.1 -1
  233. (let - ((n (- 1))) n))
  234. (should-be 8.2 '(1 2 3 4 1 2 3 4 5)
  235. (let ((ls (list 1 2 3 4)))
  236. (append ls ls '(5))))
  237. ;;Not really an error to fail this (Matthias Radestock)
  238. ;;If this returns (0 1 0), your map isn't call/cc safe, but is probably
  239. ;;tail-recursive. If its (0 0 0), the opposite is true.
  240. ;(display "Map - failed") (newline)
  241. (should-be 'map #t
  242. (let ((result
  243. (let ()
  244. (define executed-k #f)
  245. (define cont #f)
  246. (define res1 #f)
  247. (define res2 #f)
  248. (set! res1 (map (lambda (x)
  249. (if (= x 0)
  250. (call/cc (lambda (k) (set! cont k) 0))
  251. 0))
  252. '(1 0 2)))
  253. (if (not executed-k)
  254. (begin (set! executed-k #t)
  255. (set! res2 res1)
  256. (cont 1)))
  257. res2)))
  258. (if (equal? result '(0 0 0))
  259. (display "Map is call/cc safe, but probably not tail recursive or inefficient.")
  260. (display "Map is not call/cc safe, but probably tail recursive and efficient."))
  261. (newline)
  262. #t))