0

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}
    }
  } 
Rpant
  • 974
  • 2
  • 14
  • 37
  • maybe you're not seeing the errors? I get this error `error: illegal inheritance from sealed class Stream` (you don't describe what you're trying to archive so I'm not sure how to give an answer) – Ossip Oct 10 '17 at 01:39
  • I am trying to define a method cons that takes a stream and an element hd and makes the element the head of the stream. – Rpant Oct 10 '17 at 02:25
  • Your solution doesn't really answer the question. If the Scala worksheet really wasn't working then modifying code in the editor shouldn't have any effect. What did you do to fix the worksheet? If the worksheet was, in fact, working correctly then maybe you should correct the title of your question. Will people searching for help to fix broken worksheets find your question/answer helpful? – jwvh Oct 12 '17 at 00:43
  • I edited the question title. When I posted the question , I actually felt somethings broken with the worksheet because I do not see any compilation error anywhere in eclipse , Just that the worksheet doesn't show any output. – Rpant Oct 12 '17 at 01:37

1 Answers1

2

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
    }
}

inspiration

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
Dennis Tsoi
  • 1,349
  • 2
  • 11
  • 17
  • Thanks. That was helpful. I updated the question above with a solution. Your solution worked too. I realized `[this]` was really required in the private variable. It wouldn't work without [this]. Why is `this` required. Also do you see any advantage in Prof. Odersky approach where he wraps tail in an `Option`. Your approach is clearner. Finally whats the use of = _ in your solution. Sorry am still learning. – Rpant Oct 12 '17 at 00:28
  • 1
    `private[this]` limits the access to the field so no other instances of class can change it. Since it's used as a synchronized state it matters. `var tlVal: Stream[ T ] = _` initializes the `tlVal` to a default value for `Stream[T]` which is basically null. Option is used when the value can be null so it's the safety measure. It doesn't matter in this example but in general it's better to use Option instead of null for more controlled code. – Dennis Tsoi Oct 12 '17 at 07:09