I have am trying something in scala worksheet in eclipse. This is not showing any output , and doesn't show any error or warning either.
object stream {
println("Welcome to the Scala worksheet")
def cons[T](hd: T, t1: => Stream[T]): Stream[T] = new Stream[T] {
def head = hd
private var t1Opt: Option[Stream[T]] = None
def tail: Stream[T] = t1Opt match {
case Some(x) => x
case None => t1Opt = Some(t1); tail
}
}
def streamIncrementedby2(x: Int): Stream[Int] = x #:: streamIncrementedby2(x + 2)
val x = this.cons(-1, this.streamIncrementedby2(5))
println(x.head)
}
I am trying out the example in the courera odersky course: scala functional design week3 video. Interestingly in the above example, if I remove everything below the first println statement, I see an evaluated output.
******* Update ******** To help other readers , I am posting corrected version of the above program , inspired by the answer.
def cons[T](hd: T, t1: => Stream[T]) = new Stream[T] {
override def head = hd
override def isEmpty = false
private[ this ] var t1Opt: Option[Stream[T]] = None
def tailDefined: Boolean = true
override def tail: Stream[T] = t1Opt match {
case Some(x) => x
case None => {t1Opt = Some(t1); tail}
}
}
If you just want to make a generic element head of a Stream, you can use existing method in Stream package called cons
def streamIncrementedby2( x: Int ): Stream[ Int ] = x #:: streamIncrementedby2( x + 2 )
val x = Stream.cons( -1, this.streamIncrementedby2( 5 ) )
println( x.head )
It works fine. However, if you want to make your own version you have to dig deeper. By using the following function definition you are making the constructor, not the ordinary function
def cons[T](hd: T, t1: => Stream[T]): Stream[T] = new Stream[T] { ...
Key thing here is = new Stream[T]
. Therefore you have to provide a lot of stuff that a proper constructor needs: overriding abstract functions like head
, tail
and isEmpty
and providing necessary function tailDefined
.
def classCons[ T ]( hd: T, t1: => Stream[ T ] ): Stream[ T ] = new Stream[ T ] {
override def isEmpty = false
override def head = hd
private[ this ] var tlVal: Stream[ T ] = _
def tailDefined: Boolean = tlVal ne null
override def tail: Stream[T] = {
if ( !tailDefined )
synchronized {
if ( !tailDefined )
tlVal = t1
}
tlVal
}
}
You can also make your cons
function a normal function ang get the same result without messing around constructors.
def funcCons[ T ]( hd: T, t1: => Stream[ T ] ): Stream[ T ] = {
if ( t1.isEmpty )
Stream( hd )
else
hd #:: t1.tail
}
results are the same:
val ccStream = classCons( -1, this.streamIncrementedby2( 5 ) )
val ffStream = funcCons( -1, this.streamIncrementedby2( 5 ) )
println( ccStream.head )
println( ffStream.head )
// Result => -1
// Result => -1