Guest User

Untitled

a guest
Jul 21st, 2018
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.52 KB | None | 0 0
  1. ;; Deriving something like generators, but I didn't really feel like doing that exactly.
  2.  
  3. ;; This applys a function across a range from 0 to x.
  4. (define (apply-to-range f x)
  5. (let loop ((i 0))
  6. (if (< i x)
  7. (begin
  8. (f i)
  9. (loop (+ 1 i))))))
  10.  
  11. ;; (apply-to-range display 10) => #unspecified, but prints 0123456789
  12.  
  13. ;; At each step, it essentially does this.
  14. ;; Pass it a new value for i and apply the function `f'
  15. (define (apply-to-range f x)
  16. (lambda (i)
  17. (if (< i x)
  18. (f i))))
  19.  
  20. ;; Essentially, here, we've separated the core logic from the
  21. ;; iteration. Big woop.
  22.  
  23.  
  24. ;; Let's keep out the iteration but add the state back.
  25. (define (apply-to-range f x)
  26. (lambda (i)
  27. (lambda ()
  28. (if (< i x)
  29. (begin
  30. (f i)
  31. (set! i (+ 1 i)))))))
  32.  
  33. ;; Now, we get to say:
  34. ;; (define counter ((apply-to-range display 10) 1) ; 1 represents the starting value.
  35. ;; (counter) => #unspecified, but it outputs 1.
  36. ;; (counter) => #unspecified, but it outputs 2.
  37. ;; ...
  38.  
  39. ;; We can create a factory for this.
  40. (define (apply-to-range-factory f i x)
  41. ((apply-to-range x) 1))
  42.  
  43. ;; but, now we've got an extra function,
  44. ;; and we've completely lost the spirit of the original intention,
  45. ;; which the first one showed. (i.e. the structure of the code is gone)
  46.  
  47.  
  48. ;; What if we could automatically replace the running function with a new
  49. ;; one right before we return at each iteration?
  50.  
  51. ;; how do we break out of the loop early?
  52. (define (apply-to-range f x)
  53. (call-with-current-continuation
  54. (lambda (bail)
  55. (let loop ((i 0))
  56. (if (< i x)
  57. (begin
  58. (f i)
  59. (bail)
  60. (loop (+ 1 i)))))))
  61. ;; calling `bail' puts us here
  62. )
  63.  
  64. ;; So, now, we didn't end up looping and instead bailed out after
  65. ;; calling the `f' once.
  66.  
  67. ;; What if we were able to save our spot where we exited and come
  68. ;; back to it later?
  69.  
  70. ;; The `bail' function represented the exit point of the function
  71. ;; `apply-to-range', can we represent the point in the program
  72. ;; where `bail' was called?
  73.  
  74. ;; Sure! But, let's go one step further. Let's REPLACE the
  75. ;; `main-logic' function with that new frame of reference.
  76. (define (apply-to-range f x)
  77. (define (main-logic exit-function)
  78. (let loop ((i 0))
  79. (if (< i x)
  80. (begin
  81. (f i)
  82. (call-with-current-continuation
  83. (lambda (new-bail)
  84. (set! main-logic new-bail)
  85. (exit-function)))
  86. (display "continuing...")
  87. (newline)
  88. (loop (+ 1 i))))))
  89. (lambda ()
  90. (call-with-current-continuation
  91. (lambda (exit-function)
  92. (main-logic exit-function)))))
  93.  
  94. ;; (define counter (apply-to-range display 10))
  95. ;; (counter) => #unspecified, but it outputs 0
  96. ;; (counter) => #unspecified, but it outputs "continuing...\n1"
  97. ;; (counter) => #unspecified, but it outputs "continuing...\n2"
  98. ;; (counter) => #unspecified, but it outputs "continuing...\n3"
  99. ;; (counter) => #unspecified, but it outputs "continuing...\n4"
  100.  
  101. ;; So, the state is there, we can temporarily exit, and when we
  102. ;; continue go right back to where we left off... but it's ugly!
  103.  
  104. ;; Let's give the save point a nice name, call it 'suspend'
  105. (define (apply-to-range f x)
  106. (define (main-logic exit-function)
  107. (letrec ((suspend (lambda ()
  108. (call-with-current-continuation
  109. (lambda (new-bail)
  110. (set! main-logic new-bail)
  111. (exit-function))))))
  112. (let loop ((i 0))
  113. (if (< i x)
  114. (begin
  115. (f i)
  116. (suspend)
  117. (display "continuing...")
  118. (newline)
  119. (loop (+ 1 i)))))))
  120. (lambda ()
  121. (call-with-current-continuation
  122. (lambda (exit-function)
  123. (main-logic exit-function)))))
  124.  
  125. ;; Looks a bit nicer, still works the same way.
  126. ;; (define counter (apply-to-range display 10))
  127. ;; (counter) => #unspecified, but it outputs 0
  128. ;; (counter) => #unspecified, but it outputs "continuing...\n1"
  129. ;; (counter) => #unspecified, but it outputs "continuing...\n2"
  130. ;; (counter) => #unspecified, but it outputs "continuing...\n3"
  131. ;; (counter) => #unspecified, but it outputs "continuing...\n4"
  132.  
  133.  
  134. ;; But damn, that's a lot of code to get the desired effect...
  135. ;; We've created a sort of framework, which we can "template"
  136. ;; in the form of a macro
  137.  
  138. (define-syntax def-generator
  139. (syntax-rules ()
  140. ((_ (name arg1 ...) suspend-name body1 ...)
  141. (define (name arg1 ...)
  142. (define (main-logic exit-function)
  143. (letrec ((suspend-name (lambda ()
  144. (call-with-current-continuation
  145. (lambda (new-bail)
  146. (set! main-logic new-bail)
  147. (exit-function))))))
  148. (let name ((arg1 arg1) ...)
  149. body1 ...)))
  150. (lambda ()
  151. (call-with-current-continuation
  152. (lambda (exit-function)
  153. (main-logic exit-function))))))))
  154.  
  155.  
  156. (def-generator (apply-to-range f i x) suspend
  157. (if (< i x)
  158. (begin
  159. (f i)
  160. (suspend)
  161. (display "continuing...")
  162. (newline)
  163. (apply-to-range f (+ i 1) x))))
  164.  
  165. ;; Looks a bit nicer, still works the same way.
  166. ;; (define counter (apply-to-range display 1 10))
  167. ;; (counter) => #unspecified, but it outputs 0
  168. ;; (counter) => #unspecified, but it outputs "continuing...\n1"
  169. ;; (counter) => #unspecified, but it outputs "continuing...\n2"
  170. ;; (counter) => #unspecified, but it outputs "continuing...\n3"
  171. ;; (counter) => #unspecified, but it outputs "continuing...\n4"
Add Comment
Please, Sign In to add comment