PageRenderTime 28ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/stream.coffee

http://github.com/MichaelBlume/coffeestream
CoffeeScript | 153 lines | 147 code | 5 blank | 1 comment | 29 complexity | 4b23158117f8c4addac903ee6fdddc81 MD5 | raw file
Possible License(s): MIT
  1. plus = (a,b) -> a+b
  2. eq = (a,b) -> a==b
  3. mirror = (x) -> x
  4. nonce=[]
  5. class Stream
  6. constructor: (@_head=nonce, @_tail) ->
  7. if not @empty() and not @_tail?
  8. @_tail = new Stream()
  9. @make: (head=nonce, rest...) ->
  10. if head != nonce
  11. new Stream head, -> Stream.make rest...
  12. else
  13. new Stream()
  14. @repeat: (x) ->
  15. s=new Stream x, -> s
  16. @recursive: (f, inits...) ->
  17. n = inits.length
  18. helper = (index) ->
  19. if n > index
  20. new Stream inits[index], -> helper index+1
  21. else
  22. midstreamhelper result
  23. midstreamhelper = (s) ->
  24. next = f(s.take(n).list()...)
  25. new Stream next, -> midstreamhelper s.tail()
  26. result = new Stream inits[0], -> helper 1
  27. @range: (min=1, max='never') ->
  28. if min == max
  29. Stream.make(min)
  30. else new Stream min, -> Stream.range(min+1, max)
  31. empty: -> @_head == nonce
  32. throw_if_empty: ->
  33. if @empty()
  34. throw error: "end of stream"
  35. head: ->
  36. @throw_if_empty()
  37. @_head
  38. tail: ->
  39. @throw_if_empty()
  40. if @_tail not instanceof Stream
  41. @_tail = @_tail()
  42. @_tail
  43. item: (n) -> @skip(n).head()
  44. skip: (n) ->
  45. s = this
  46. while n != 0
  47. n--
  48. s = s.tail()
  49. s
  50. walk: (f) ->
  51. s = this
  52. until s.empty()
  53. f s.head()
  54. s = s.tail()
  55. null
  56. print: -> @walk console.log
  57. force: -> @walk ->
  58. map: (f) ->
  59. if @empty()
  60. new Stream()
  61. else
  62. new Stream f(@head()), => @tail().map f
  63. filter: (f) ->
  64. s = this
  65. until s.empty() or f s.head()
  66. s = s.tail()
  67. return new Stream() if s.empty()
  68. new Stream s.head(), -> s.tail().filter f
  69. any: (f=mirror) -> not @filter(f).empty()
  70. all: (f=mirror) ->
  71. negated = (x) -> not f x
  72. not @any(negated)
  73. take: (n) ->
  74. return new Stream() if n==0
  75. new Stream @head(), =>
  76. return new Stream() if n==1
  77. @tail().take n-1
  78. scale: (factor) ->
  79. scaleone = (n) -> factor*n
  80. @map(scaleone)
  81. zip: (zipper, otherstream) ->
  82. mismatch = -> throw error: "length mismatch"
  83. if @empty()
  84. if otherstream.empty()
  85. new Stream()
  86. else
  87. mismatch()
  88. else if otherstream.empty()
  89. mismatch()
  90. else
  91. new Stream zipper(@head(), otherstream.head()), =>
  92. @tail().zip(zipper, otherstream.tail())
  93. append: (s) ->
  94. if @empty()
  95. s
  96. else
  97. new Stream @head(), => @tail().append(s)
  98. cycle: ->
  99. if @empty()
  100. throw error: "zero times infinity"
  101. s = new Stream @head(), => @tail().append(s)
  102. add: (otherstream) -> @zip plus, otherstream
  103. reduce: (reducer, initial) ->
  104. @walk (element) -> initial = reducer initial, element
  105. initial
  106. sum: -> @reduce(plus, 0)
  107. length: ->
  108. l = 0
  109. @walk -> l++
  110. l
  111. list: ->
  112. out = []
  113. @walk (n) -> out.push n
  114. out
  115. until: (f) ->
  116. return new Stream() if @empty() or f @head()
  117. new Stream @head(), => @tail().until f
  118. up_until: (f) ->
  119. return new Stream() if @empty()
  120. new Stream @head(), =>
  121. if f @head()
  122. new Stream()
  123. else
  124. @tail().up_until f
  125. equal: (s) ->
  126. try
  127. bstream = @zip eq, s
  128. bstream.all()
  129. catch err
  130. if err.error != "length mismatch"
  131. throw err
  132. false
  133. member: (x) -> @any (m) -> m==x
  134. output = exports or window
  135. output.Stream = Stream
  136. primeStream = new Stream 2, ->
  137. Stream.range(3).filter (primeCandidate) ->
  138. primeStream.until((prime)->
  139. prime*prime > primeCandidate
  140. ).all (prime)->
  141. primeCandidate%prime != 0
  142. output.primeStream = primeStream
  143. #in general, it is not possible to tell if a stream is finite.
  144. paradoxicalStream = new Stream 1, ->
  145. if paradoxicalStream.is_finite()
  146. Stream.repeat(1)
  147. else
  148. new Stream()