I am trying to implement an iterable for a linked list. But this implementation throws stack overflow error. What am I doing wrong here?
The iterable implementation throws error, even before I call any function on the class.
I initially thought, it could be because of using def instead of val for the nodeValue and tailList. But that didnt solve the problem.
I tried to change the iterator to loop over Int instead of LinkedList. I still get the same error. Thanks in advance!!
trait LinkedList extends Iterable[LinkedList]{
def nodeValue: Int
def tailList: LinkedList
}
class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
override def iterator: Iterator[LinkedList] = Iterator
.iterate(this: LinkedList)(_.tailList)
.takeWhile(_ != Nil)
}
object Nil extends LinkedList {
def nodeValue= throw new IllegalAccessException("head of Nil")
def tailList = throw new IllegalAccessException("tail of Nil")
override def iterator: Iterator[LinkedList] = Iterator.empty
}
val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)
//Printing this first Time
//chainedLinkedList.foreach(println)
Output:
java.lang.StackOverflowError
at scala.collection.AbstractIterable.<init>(LinkedListIterable.sc:50)
at scala.collection.AbstractSeq.<init>(LinkedListIterable.sc:37)
at scala.collection.mutable.AbstractSeq.<init>(LinkedListIterable.sc:44)
at scala.collection.mutable.StringBuilder.<init>(LinkedListIterable.sc:28)
at scala.collection.mutable.StringBuilder.<init>(LinkedListIterable.sc:45)
at scala.collection.mutable.StringBuilder.<init>(LinkedListIterable.sc:50)
at scala.collection.TraversableOnce.mkString(LinkedListIterable.sc:319)
at scala.collection.TraversableOnce.mkString$(LinkedListIterable.sc:318)
at #worksheet#.Node.mkString(LinkedListIterable.sc:6)
at scala.collection.TraversableLike.toString(LinkedListIterable.sc:596)
at scala.collection.TraversableLike.toString$(LinkedListIterable.sc:596)
at #worksheet#.Node.toString(LinkedListIterable.sc:6)
at java.lang.String.valueOf(LinkedListIterable.sc:2990)
at scala.collection.mutable.StringBuilder.append(LinkedListIterable.sc:196)
at scala.collection.TraversableOnce.$anonfun$addString$1(LinkedListIterable.sc:355)
at scala.collection.Iterator.foreach(LinkedListIterable.sc:925)
at scala.collection.Iterator.foreach$(LinkedListIterable.sc:925)
at scala.collection.AbstractIterator.foreach(LinkedListIterable.sc:1413)
at scala.collection.IterableLike.foreach(LinkedListIterable.sc:67)
at scala.collection.IterableLike.foreach$(LinkedListIterable.sc:66)
at #worksheet#.Node.foreach(LinkedListIterable.sc:6)
at scala.collection.TraversableOnce.addString(LinkedListIterable.sc:353)
at scala.collection.TraversableOnce.addString$(LinkedListIterable.sc:349)
at #worksheet#.Node.addString(LinkedListIterable.sc:6)
at scala.collection.TraversableOnce.mkString(LinkedListIterable.sc:319)
at scala.collection.TraversableOnce.mkString$(LinkedListIterable.sc:318)
at #worksheet#.Node.mkString(LinkedListIterable.sc:6)
at scala.collection.TraversableLike.toString(LinkedListIterable.sc:596)
at scala.collection.TraversableLike.toString$(LinkedListIterable.sc:596)
at #worksheet#.Node.toString(LinkedListIterable.sc:6)
at java.lang.String.valueOf(LinkedListIterable.sc:2990)
at scala.collection.mutable.StringBuilder.append(LinkedListIterable.sc:196)
at scala.collection.TraversableOnce.$anonfun$addString$1(LinkedListIterable.sc:355)
at scala.collection.Iterator.foreach(LinkedListIterable.sc:925)
Output exceeds cutoff limit.
Update:
The problem is as mentioned by @Dima, Iterator, iterates through some value in container and not the container itself. Once that was clear, I modified the code, which ran fine as below.
trait LinkedList extends Iterable[Int]{
val nodeValue: Int
val tailList: LinkedList
override def toString(): String = this.mkString(" -> ")
}
class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
override def iterator: Iterator[Int] = Iterator
.iterate(this: LinkedList)(_.tailList)
.takeWhile(_ != Nil)
.map(_.nodeValue)
}
object Nil extends LinkedList {
lazy val nodeValue= throw new IllegalAccessException("head of Nil")
lazy val tailList = throw new IllegalAccessException("tail of Nil")
override def iterator: Iterator[Int] = Iterator.empty
}
val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)
//Printing this first Time
chainedLinkedList.foreach(println)