If I wanted to enumerate the iterations of an inner loop in Scala, how would I approach this in a functional style?
E.g. how would I rewrite the following code:
val documents = List("a" :: "b" :: Nil, "aa" :: "bb" :: Nil, "aaa" :: Nil)
var currentPageNumber = 0
documents.foreach { doc =>
for (page <- doc) {
currentPageNumber += 1
println("%d: %s".format(currentPageNumber.head, page)
// do something with page
}
}
I could get rid of the var by using val currentPageNumber = Iterator.from(0) but this still means that I actually need to declare it outside of the loop.
Is there a trick which would not expose currentPageNumber to the outer scope and – just like the zipWithIndex counter – only exists inside the loop?
Edit:
I’ve also found a version using scanLeft but I think it’s rather confusing. But maybe someone can optimise it somehow.
documents.scanLeft(0) { case (cnt, doc) =>
doc.zip(Iterator.from(cnt + 1).toIterable).map { case(page, cnt) =>
println("%d: %s".format(cnt, page))
cnt
} last
}
Own solution (for now):
Thanks everyone, I think what I had in mind was something like
documents.flatMap{ doc =>
for (page <- doc) yield {
currentPageNumber: Int =>
"%d: %s".format(currentPageNumber, page)
}}.zipWithIndex.map (t => t._1(t._2 + 1)) map(println)
so, the trick is to leave currentPageNumber undecided until one can actually apply zipWithIndex.