       stream = stream.rest()
     results
 
-  toString: ->
-    this.toArray().join(', ')
+  toString: -> @toArray().join(', ')
 
 Stream.iterate = (start, step) ->
   new Stream(start, -> Stream.iterate(step(start), step))

suspend = (code) ->
  cache = {
    force: ->
      val = code()
      this.force = () -> val
      val
  }
  -> cache.force()


class Stream
  constructor: (@first, rest) ->
    @rest = if rest? then suspend(rest) else -> null

  take_while: (pred) ->
    if pred(@first)

    new Stream(op(this.first, other.first), =>
      this.rest().combine(other.rest(), op) if this.rest() and other.rest())

  plus:  (other) -> @combine(other, (a,b) -> a + b)
  minus: (other) -> @combine(other, (a,b) -> a - b)
  times: (other) -> @combine(other, (a,b) -> a * b)
  by:    (other) -> @combine(other, (a,b) -> a / b)

  accumulate: (start, op) ->
    new_start = op(start, @first)
    new Stream(new_start, => @rest().accumulate(new_start, op) if @rest())

  sums:     -> @accumulate(0, (a,b) -> a + b)
  products: -> @accumulate(1, (a,b) -> a * b)

  merge: (other) -> new Stream(@first, => other.merge(@rest()) if other)

