Note that there are some explanatory texts on larger screens.

plurals
  1. PONested iteration over infinite streams in Scala
    primarykey
    data
    text
    <p>I sometimes find myself wanting to perform nested iterations over infinite streams in Scala <strong>for</strong> comprehensions, but specifying the loop termination condition can be a little tricky. Is there a better way of doing this kind of thing?</p> <p>The use case I have in mind is where I don't necessarily know up front how many elements will be needed from each of the infinite streams I'm iterating over (but obviously I know it's not going to be an infinite number). Assume the termination condition for each stream might depend on the values of other elements in the for expression in some complicated way. </p> <p>The initial thought is to try to write the stream termination condition as an <strong>if</strong> filter clause in the <strong>for</strong> expression, however this runs into trouble when looping over nested infinite streams, because there's no way of short-circuiting the iteration over the first infinite stream, which ultimately leads to an OutOfMemoryError. I understand why this is the case, given how <strong>for</strong> expressions map to <strong>map</strong>, <strong>flatMap</strong> and <strong>withFilter</strong> method calls - my question is whether there's a better idiom for doing this kind of thing (perhaps not involving <strong>for</strong> comprehensions at all).</p> <p>To give a somewhat contrived example to illustrate the issue just described, consider the following (very naive) code to generate all pairings of the numbers 1 and 2:</p> <pre><code>val pairs = for { i &lt;- Stream.from(1) if i &lt; 3 j &lt;- Stream.from(1) if j &lt; 3 } yield (i, j) pairs.take(2).toList // result: List[(Int, Int)] = List((1,1), (1,2)) pairs.take(4).toList // 'hoped for' result: List[(Int, Int)] = List((1,1), (1,2), (2,1), (2,2)) // actual result: // java.lang.OutOfMemoryError: Java heap space // at scala.collection.immutable.Stream$.from(Stream.scala:1105) </code></pre> <p>Obviously, in this simple example, the problem could easily be averted by moving the <strong>if</strong> filters into <strong>takeWhile</strong> method calls on the original streams, as follows:</p> <pre><code>val pairs = for { i &lt;- Stream.from(1).takeWhile(_ &lt; 3) j &lt;- Stream.from(1).takeWhile(_ &lt; 3) } yield (i, j) </code></pre> <p>but for the purposes of the question imagine a more complex use case where the stream termination condition can't easily be moved onto the stream expression itself.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload