Iterator.continually: special proccessing for the first element

Viewed 162

I have an Iterator based on a repeatedly function calls:

anObject.synchronized {
    Iterator.continually { 
        anObject.wait()      // skip this call for the 1st iteration
        Try(anObject.foo()) 
    }.dropWhile(_.isFailure).next()
    anObject.notifyAll()
}

I would like to make first iteration without calling anObject.wait(). Certainly, I could make something like the following:

anObject.synchronized {
    if (Try(anObject.foo()).isFailure) {
        Iterator.continually { 
            anObject.wait()
            Try(anObject.foo()) 
        }.dropWhile(_.isFailure).next()
    }
    anObject.notifyAll()
}

Is there more elegant or standard approach to obtain same purpose (skip function call on first iteration)

PS Similar task arises when it is needed to print a list with delimiters:

scala> List("a", "b", "c").mkString(", ")
res1: String = a, b, c

So, I hope there is some approach for my question too

2 Answers

Perhaps create a new iterator which check for the first element

def continually[A](firstElem: => A)(elem: => A): Iterator[A] = new AbstractIterator[A] {
    var isFirst = true
    def hasNext = true
    def next(): A = if (isFirst) { isFirst = false; firstElem } else elem
  }

continually("a")("b").take(3).foreach(print)
// abb

You could change .continually to .tabulate as long as 2,147,483,647 wouldn't be a meaningful limitation on the number of iterations.

anObject.synchronized {
    Iterator.tabulate { n => 
        if (n != 0) anObject.wait()  // skip 1st iteration
        Try(anObject.foo()) 
    }.dropWhile(_.isFailure).next()
    anObject.notifyAll()
}
Related