shift-reset.scm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Olivier Danvy, Richard Kelsey, Jonathan Rees
  3. ; ,open signals escapes
  4. ; Changes by jar:
  5. ; Added Uses of Scheme 48's WITH-CONTINUATION primitive, so that unreachable
  6. ; continuations can be reclaimed by the GC.
  7. ;
  8. ; Renamed reset-thunk -> *reset
  9. ; call/ct -> *shift
  10. ;
  11. ; Note: the meta-continuation ought to be thread-specific.
  12. ; Alternatively, the threads package could be defined in terms of
  13. ; shift and reset. This would have the advantage of making the threads
  14. ; package itself re-entrant. It would be nice to rehabilitate the
  15. ; runnable-threads queue, currently a piece of global state, as local
  16. ; to a particular invocation of WITH-MULTITASKING.
  17. ;Date: Wed, 29 Dec 1993 13:54:52 +0100
  18. ;From: Olivier Danvy <danvy@daimi.aau.dk>
  19. ;To: jar@martigny.ai.mit.edu
  20. ;Subject: little Christmas gift
  21. ;Reply-To: danvy@daimi.aau.dk
  22. ;
  23. ;Hi again:
  24. ;
  25. ;Here is a contribution for the Scheme48 library: the shift and reset
  26. ;operators from "Abstracting Control" (LFP90) and "Representing Control"
  27. ;(MSCS92). In his POPL94 paper, Andrzej Filinski observed that since the
  28. ;meta-continuation is single-threaded, it can be globalized in a
  29. ;register. Andrzej has programmed this both in SML and in Scheme. I
  30. ;only have prettified the Scheme definition a wee bit.
  31. (define-syntax reset
  32. (syntax-rules ()
  33. ((_ ?e) (*reset (lambda () ?e)))))
  34. (define-syntax shift
  35. (syntax-rules ()
  36. ((_ ?k ?e) (*shift (lambda (?k) ?e)))))
  37. (define *meta-continuation*
  38. (lambda (v)
  39. (assertion-violation 'shift "You forgot the top-level reset...")))
  40. (define *abort
  41. (lambda (thunk)
  42. (with-continuation null-continuation ;JAR hack
  43. (lambda ()
  44. (let ((val (thunk)))
  45. (*meta-continuation* val))))))
  46. (define null-continuation #f)
  47. (define *reset
  48. (lambda (thunk)
  49. (let ((mc *meta-continuation*))
  50. (call-with-current-continuation
  51. (lambda (k)
  52. (begin
  53. (set! *meta-continuation*
  54. (lambda (v)
  55. (set! *meta-continuation* mc)
  56. (k v)))
  57. (*abort thunk)))))))
  58. (define *shift
  59. (lambda (f)
  60. (call-with-current-continuation
  61. (lambda (k)
  62. (*abort (lambda ()
  63. (f (lambda (v)
  64. (reset (k v))))))))))
  65. ;----------
  66. ;
  67. ;Reminder: reset specifies a control delimiter. shift grabs the current
  68. ;continuation up to the current control delimiter, and reifies it as a
  69. ;composable procedure. If the procedure is not used, shift has the
  70. ;effect of aborting up to the current control delimiter.
  71. ;
  72. ;Examples:
  73. ;
  74. ;(+ 10 (reset (+ 2 3)))
  75. ;-->
  76. ;15
  77. ;
  78. ;(+ 10 (reset (+ 2 (shift k 3))))
  79. ;-->
  80. ;13
  81. ;
  82. ;(+ 10 (reset (+ 2 (shift k (k 3)))))
  83. ;-->
  84. ;15
  85. ;
  86. ;(+ 10 (reset (+ 2 (shift k (+ 100 (k 3))))))
  87. ;-->
  88. ;115
  89. ;
  90. ;(+ 10 (reset (+ 2 (shift k (+ 100 (k (k 3)))))))
  91. ;-->
  92. ;117
  93. ;
  94. ;
  95. ;Other reminder: shift and reset are weaker than Matthias's control and
  96. ;prompt, in that they can be CPS-transformed.
  97. ;
  98. ;Have a happy holiday,
  99. ;
  100. ;-- Olivier
  101. ;
  102. ;PS: This definition is not unlike David Espinoza's implementation of monadic
  103. ;effects, ie, it has no interpretive or translation overhead.
  104. ; JAR's notes:
  105. ;
  106. ; ; CWCC defined in terms of SHIFT
  107. ;
  108. ; (define cwcc
  109. ; (lambda (p)
  110. ; (shift k (k (p (lambda (x)
  111. ; (shift k1 (k x))))))))
  112. ;
  113. ; ; Monads from shift and reset (from Filinski, POPL '94)
  114. ;
  115. ; (define (reflect meaning)
  116. ; (shift k (extend k meaning)))
  117. ;
  118. ; (define (reify thunk)
  119. ; (reset (eta (thunk))))
  120. ;
  121. ; Example: nondeterminism monad.
  122. ;
  123. ; > (define (eta x) (list x))
  124. ; > (define (extend f l) (apply append (map f l)))
  125. ; >
  126. ; > (define-syntax amb
  127. ; (syntax-rules () ((amb ?x ?y) (*amb (lambda () ?x) (lambda () ?y)))))
  128. ;
  129. ; > (define (*amb t1 t2)
  130. ; (reflect (append (reify t1) (reify t2))))
  131. ; >
  132. ; > (reify (lambda () (amb 1 2)))
  133. ; '(1 2)
  134. ; > (reify (lambda () (+ (amb 1 2) 3)))
  135. ; '(4 5)
  136. ; >
  137. ; > (define cwcc call-with-current-continuation)
  138. ; > (reify (lambda ()
  139. ; (+ 1 (cwcc (lambda (k)
  140. ; (* 10 (amb 3 (k 4))))))))
  141. ; '(31 51)
  142. ; >