 
 puts = (s) -> print (if s? then s else '') + "\n"
 
-puts "new Stream(1, -> new Stream(2)):"
+puts "A stream with just the numbers 1 and 2:"
 puts new Stream(1, -> new Stream(2))
 puts()
 


puts "The squares of the number from 101 to 110:"
puts Stream.from(1).drop(100).map((n) -> n * n).take(10)
puts

  map: (func) ->
    new Stream(func(@first), => @rest().map(func) if @rest())

  select: (pred) ->
    if pred(@first)
      new Stream(@first, => @rest().select(pred) if @rest())
    else if @rest()
      @rest().select(pred)

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

  plus:  (other) -> this.combine(other, (a,b) -> a + b)
  minus: (other) -> this.combine(other, (a,b) -> a - b)
  times: (other) -> this.combine(other, (a,b) -> a * b)
  by:    (other) -> this.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:     -> this.accumulate(0, (a,b) -> a + b)
  products: -> this.accumulate(1, (a,b) -> a * b)

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

  concat: (other) ->
    new Stream(@first, => if @rest() then @rest().concat(other) else other)

  # CAUTION: don't call the following methods on an infinite stream.
  last: ->
    stream = this
    while stream.rest()
      stream = stream.rest()
    stream.first

  toArray: ->
    stream = this
