object Test extends Application
{
    def factorial(number : Int) : BigInt = factorials(number)(number-1)
    
    def factorials(number : Int) : Stream[BigInt] =
    {
      import Stream.{cons,empty,range}
      
      if(number < 0) 
        empty
      else
      {
        var steps = range(2,number+1)
        var next  = 1

        def loop : Stream[BigInt] =
        {
            if(steps.isEmpty) return empty
            
            next = next * steps.head
            steps = steps.tail
            cons (next, loop) 
        }
        cons (next, loop)
      }
    }

    // use a single factorial
    def usage1 
    {
      println ( factorial(10)  )
    }

    // use a all factorials up to a single one
    def usage2
    {
      for (x <- factorials (10) )
        println ( x )
    }

    // re-use the sequence without re-computation
    def usage3
    {
      val factorials1to10 = factorials (10) toArray
            
      for (x <- factorials1to10 )
        println ( x )
        
      for (x <- factorials1to10 reverse )
        println ( x )        
    }
}
