12.body.scm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. (define (for-effect-only item-ignored)
  2. "unspecified value")
  3. (define invalid-method-name-indicator "unknown")
  4. (define (box-maker init-value)
  5. (let ((contents init-value))
  6. (lambda msg
  7. (case (first msg)
  8. ((type) "box")
  9. ((show) contents)
  10. ((update!)
  11. (for-effect-only (set! contents (second msg))))
  12. ((swap!)
  13. (let ((ans contents))
  14. (set! contents (second msg))
  15. ans))
  16. ((reset!)
  17. (for-effect-only (set! contents init-value)))
  18. (else (delegate base-object msg))))))
  19. (define (delegate obj msg)
  20. (apply obj msg))
  21. (define base-object
  22. (lambda msg
  23. (case (first msg)
  24. ((type) "base-object")
  25. (else invalid-method-name-indicator))))
  26. (define (send . args)
  27. (let* ((object (car args))
  28. (message (cdr args))
  29. (try (apply object message)))
  30. (if (eq? invalid-method-name-indicator try)
  31. (error "Bad method name:" (car message)
  32. "sent to object of"
  33. (object 'type)
  34. "type.")
  35. try)))
  36. (define (counter-maker init-value unary-proc)
  37. (let ((total (box-maker init-value)))
  38. (lambda msg
  39. (case (first msg)
  40. ((type) "counter")
  41. ((update!)
  42. (let ((result (unary-proc (send total 'show))))
  43. (send total 'update! result)))
  44. ((show reset!) (delegate total msg))
  45. (else (delegate base-object msg))))))
  46. (define (accumulator-maker init-value binary-proc)
  47. (let ((total (box-maker init-value)))
  48. (lambda msg
  49. (case (first msg)
  50. ((type "accumulator"))
  51. ((update!)
  52. (send total 'update!
  53. (binary-proc (send total 'show)
  54. (second msg))))
  55. ((show reset!) (delegate total msg))
  56. (else (delegate base-object msg))))))
  57. (define (gauge-maker init-value unary-proc-up unary-proc-down)
  58. (let ((total (box-maker init-value)))
  59. (lambda msg
  60. (case (first msg)
  61. ((type) "gauge")
  62. ((up!)
  63. (send total 'update!
  64. (unary-proc-up (send total 'show))))
  65. ((down!)
  66. (send total 'update!
  67. (unary-proc-down (send total 'show))))
  68. ((show reset!) (delegate total msg))
  69. (else (delegate base-object msg))))))
  70. (define (stack-maker)
  71. (let ((stk '()))
  72. (lambda msg
  73. (case (first msg)
  74. ((type) "stack")
  75. ((empty?) (null? stk))
  76. ((push!)
  77. (for-effect-only
  78. (set! stk (cons (second msg) stk))))
  79. ((top)
  80. (if (null? stk)
  81. (error "top: The stack is empty.")
  82. (car stk)))
  83. ((pop!)
  84. (for-effect-only
  85. (if (null? stk)
  86. (error "pop!: The stack is empty.")
  87. (set! stk (cdr stk)))))
  88. ((size) (length stk))
  89. ((print)
  90. (display "TOP: ")
  91. (for-each
  92. (lambda (x)
  93. (display x)
  94. (display " "))
  95. stk)
  96. (newline))
  97. (else (delegate base-object msg))))))
  98. (define (queue-maker)
  99. (let ((q '()))
  100. (lambda msg
  101. (case (first msg)
  102. ((type) "queue")
  103. ((empty?) (null? q))
  104. ((enqueue!)
  105. (for-effect-only
  106. (let ((list-of-item (cons (second msg) '())))
  107. (if (null? q)
  108. (set! q list-of-item)
  109. (append! q list-of-item)))))
  110. ((front)
  111. (if (null? q)
  112. (error "front: The queue is empty.")
  113. (car q)))
  114. ((dequeue!)
  115. (for-effect-only
  116. (if (null? q)
  117. (error "dequeue!: The queue is empty.")
  118. (set! q (cdr q)))))
  119. ((size) (length q))
  120. ((print)
  121. (display "FRONT: ")
  122. (for-each
  123. (lambda (x) (display x) (display " "))
  124. q)
  125. (newline))
  126. (else (delegate base-object msg))))))
  127. (define (bucket-maker)
  128. (let ((table '()))
  129. (lambda msg
  130. (case (first msg)
  131. ((type) "bucket")
  132. ((lookup)
  133. (let ((key (second msg))
  134. (succ (third msg))
  135. (fail (fourth msg)))
  136. (lookup key table (lambda (pr) (succ (cdr pr))) fail)))
  137. ((update!)
  138. (for-effect-only
  139. (let ((key (second msg))
  140. (updater (third msg))
  141. (initializer (fourth msg)))
  142. (lookup key table
  143. (lambda (pr)
  144. (set-cdr! pr (updater (cdr pr))))
  145. (lambda ()
  146. (let ((pr (cons key (initializer key))))
  147. (set! table (cons pr table))))))))
  148. (else (delegate base-object msg))))))
  149. (define (memoize proc)
  150. (let ((bucket (bucket-maker)))
  151. (lambda (arg)
  152. (send bucket 'update! arg (lambda (val) val) proc)
  153. (send bucket 'lookup arg
  154. (lambda (val) val) (lambda () #f)))))
  155. (define (hash-table-maker size hash-fn)
  156. (let ((v ((vector-generator (lambda (i) (bucket-maker))) size)))
  157. (lambda msg
  158. (case (first msg)
  159. ((type) "hash table")
  160. (else
  161. (delegate (vector-ref v (hash-fn (second msg))) msg))))))