stream.scm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. (library (stream)
  2. (export make-stream
  3. stream-value
  4. stream-index
  5. stream-next-proc
  6. stream-next
  7. stream-get-nth-value
  8. stream-map
  9. stream-pos
  10. stream->list)
  11. (import
  12. (except (rnrs base) let-values map)
  13. (only (guile)
  14. lambda* λ)
  15. ;; structs
  16. (srfi srfi-9)
  17. ;; for functional structs (not part of srfi-9 directly)
  18. (srfi srfi-9 gnu))
  19. (define-immutable-record-type <stream>
  20. (make-stream val
  21. index
  22. previous-input
  23. next-input
  24. next-output)
  25. stream?
  26. ;; val is the value of the last application of the next
  27. ;; procedure.
  28. (val stream-value)
  29. ;; index is the current index in the stream.
  30. (index stream-index)
  31. ;; Store the previous input, to enable things like
  32. ;; counting up, regardless of what the output value is
  33. ;; and basing the next output value on another value
  34. ;; than the output value. For example one might want to
  35. ;; output all square numbers.
  36. (previous-input stream-previous-input)
  37. ;; next-input is the procedure, which gets the next
  38. ;; input value for next-proc.
  39. (next-input stream-next-input-proc)
  40. ;; next-proc is the procedure, which calculates the next
  41. ;; value.
  42. (next-output stream-next-output-proc))
  43. (define stream-next
  44. (λ (stream)
  45. (let ([val (stream-value stream)]
  46. [index (stream-index stream)]
  47. [previous-input (stream-previous-input stream)]
  48. [next-input-proc (stream-next-input-proc stream)]
  49. [next-output-proc (stream-next-output-proc stream)])
  50. (make-stream
  51. ;; The output of the stream is based on the input,
  52. ;; ...
  53. (next-output-proc
  54. ;; ... which is calculated using the previous
  55. ;; input, the previous output value, or the index
  56. ;; of the stream.
  57. (next-input-proc val index previous-input))
  58. (+ index 1)
  59. (next-input-proc val index previous-input)
  60. next-input-proc
  61. next-output-proc))))
  62. (define stream-get-nth-value
  63. (λ (stream n)
  64. (cond
  65. [(= n 0)
  66. (stream-value stream)]
  67. [else
  68. (stream-get-nth-value (stream-next stream)
  69. (- n 1))])))
  70. (define stream-map
  71. (λ (proc base)
  72. (make-stream
  73. ;; make sure proc is already mapped to the first
  74. ;; value
  75. (proc (stream-value base))
  76. ;; index of the new stream starts at zero
  77. 0
  78. (stream-previous-input base)
  79. (stream-next-input-proc base)
  80. ;; Wrap the base stream's function for calculating
  81. ;; an output value using the provided mapped proc,
  82. ;; effectively applying proc to every value the
  83. ;; base stream would produce.
  84. (λ (input)
  85. (proc
  86. ((stream-next-output-proc base) input))))))
  87. (define stream-pos
  88. (λ (elem a-stream)
  89. (let iter ([stream a-stream] [n 0])
  90. (cond
  91. [(equal? (stream-value stream) elem) n]
  92. [else
  93. (iter (stream-next stream)
  94. (+ n 1))]))))
  95. (define stream->list
  96. (λ (stream max-num-elems)
  97. (cond
  98. [(= max-num-elems 0) '()]
  99. [else
  100. (cons (stream-value stream)
  101. (stream->list (stream-next stream) (- max-num-elems 1)))]))))