Given a collection in Scala, I'd like to traverse this collection and for each object I'd like to emit (yield) from 0 to multiple elements that should be joined together into a new collection.
For example, I expect something like this:
val input = Range(0, 15)
val output = input.somefancymapfunction((x) => {
if (x % 3 == 0)
yield(s"${x}/3")
if (x % 5 == 0)
yield(s"${x}/5")
})
to build an output collection that will contain
(0/3, 0/5, 3/3, 5/5, 6/3, 9/3, 10/5, 12/3)
Basically, I want a superset of what filter (1 → 0..1) and map (1 → 1) allows to do: mapping (1 → 0..n).
Solutions I've tried
Imperative solutions
Obviously, it's possible to do so in non-functional maneer, like:
var output = mutable.ListBuffer()
input.foreach((x) => {
if (x % 3 == 0)
output += s"${x}/3"
if (x % 5 == 0)
output += s"${x}/5"
})
Flatmap solutions
I know of flatMap, but it again, either:
1) becomes really ugly if we're talking about arbitrary number of output elements:
val output = input.flatMap((x) => {
val v1 = if (x % 3 == 0) {
Some(s"${x}/3")
} else {
None
}
val v2 = if (x % 5 == 0) {
Some(s"${x}/5")
} else {
None
}
List(v1, v2).flatten
})
2) requires usage of mutable collections inside it:
val output = input.flatMap((x) => {
val r = ListBuffer[String]()
if (x % 3 == 0)
r += s"${x}/3"
if (x % 5 == 0)
r += s"${x}/5"
r
})
which is actually even worse that using mutable collection from the very beginning, or
3) requires major logic overhaul:
val output = input.flatMap((x) => {
if (x % 3 == 0) {
if (x % 5 == 0) {
List(s"${x}/3", s"${x}/5")
} else {
List(s"${x}/3")
}
} else if (x % 5 == 0) {
List(s"${x}/5")
} else {
List()
}
})
which is, IMHO, also looks ugly and requires duplicating the generating code.
Roll-your-own-map-function
Last, but not least, I can roll my own function of that kind:
def myMultiOutputMap[T, R](coll: TraversableOnce[T], func: (T, ListBuffer[R]) => Unit): List[R] = {
val out = ListBuffer[R]()
coll.foreach((x) => func.apply(x, out))
out.toList
}
which can be used almost like I want:
val output = myMultiOutputMap[Int, String](input, (x, out) => {
if (x % 3 == 0)
out += s"${x}/3"
if (x % 5 == 0)
out += s"${x}/5"
})
Am I really overlooking something and there's no such functionality in standard Scala collection libraries?
Similar questions
This question bears some similarity to Can I yield or map one element into many in Scala? — but that question discusses 1 element → 3 elements mapping, and I want 1 element → arbitrary number of elements mapping.
Final note
Please note that this is not the question about division / divisors, such conditions are included purely for illustrative purposes.
Rather than having a separate case for each divisor, put them in a container and iterate over them in a for comprehension:
val output = for {
n <- input
d <- Seq(3, 5)
if n % d == 0
} yield s"$n/$d"
Or equivalently in a collect nested in a flatMap:
val output = input.flatMap { n =>
Seq(3, 5).collect {
case d if n % d == 0 => s"$n/$d"
}
}
In the more general case where the different cases may have different logic, you can put each case in a separate partial function and iterate over the partial functions:
val output = for {
n <- input
f <- Seq[PartialFunction[Int, String]](
{case x if x % 3 == 0 => s"$x/3"},
{case x if x % 5 == 0 => s"$x/5"})
if f.isDefinedAt(n)
} yield f(n)
You can also use some functional library (e.g. scalaz) to express this:
import scalaz._, Scalaz._
def divisibleBy(byWhat: Int)(what: Int): List[String] =
(what % byWhat == 0).option(s"$what/$byWhat").toList
(0 to 15) flatMap (divisibleBy(3) _ |+| divisibleBy(5))
This uses the semigroup append operation |+|. For Lists this operation means a simple list concatenation. So for functions Int => List[String], this append operation will produce a function that runs both functions and appends their results.
If you have complex computation, during which you should sometimes add some elements to operation global accumulator, you can use popular approach named Writer Monad
Preparation in scala is somewhat bulky but results are extremely composable thanks to Monad interface
import scalaz.Writer
import scalaz.syntax.writer._
import scalaz.syntax.monad._
import scalaz.std.vector._
import scalaz.syntax.traverse._
type Messages[T] = Writer[Vector[String], T]
def yieldW(a: String): Messages[Unit] = Vector(a).tell
val output = Vector.range(0, 15).traverse { n =>
yieldW(s"$n / 3").whenM(n % 3 == 0) >>
yieldW(s"$n / 5").whenM(n % 5 == 0)
}.run._1
Here is my proposition for a custom function, might be better with pimp my library pattern
def fancyMap[A, B](list: TraversableOnce[A])(fs: (A => Boolean, A => B)*) = {
def valuesForElement(elem: A) = fs collect { case (predicate, mapper) if predicate(elem) => mapper(elem) }
list flatMap valuesForElement
}
fancyMap[Int, String](0 to 15)((_ % 3 == 0, _ + "/3"), (_ % 5 == 0, _ + "/5"))
You can try collect:
val input = Range(0,15)
val output = input.flatMap { x =>
List(3,5) collect { case n if (x%n == 0) => s"${x}/${n}" }
}
System.out.println(output)
I would us a fold:
val input = Range(0, 15)
val output = input.foldLeft(List[String]()) {
case (acc, value) =>
val acc1 = if (value % 3 == 0) s"$value/3" :: acc else acc
val acc2 = if (value % 5 == 0) s"$value/5" :: acc1 else acc1
acc2
}.reverse
output contains
List(0/3, 0/5, 3/3, 5/5, 6/3, 9/3, 10/5, 12/3)
A fold takes an accumumlator (acc), a collection, and a function. The function is called with the initial value of the accumumator, in this case an empty List[String], and each value of the collection. The function should return an updated collection.
On each iteration, we take the growing accumulator and, if the inside if statements are true, prepend the calculation to the new accumulator. The function finally returns the updated accumulator.
When the fold is done, it returns the final accumulator, but unfortunately, it is in reverse order. We simply reverse the accumulator with .reverse.
There is a nice paper on folds: A tutorial on the universality and expressiveness of fold, by Graham Hutton.
def QuickSort(arr:Array[Int],first:Int,last:Int): List[Int] = {
var pivot:Int = 0
var temp:Int = 0
if (first < last) {
pivot = first
var i:Int = first
var j:Int = last;
while(i<j){
while(arr(i) <= arr(pivot) && i < last)
i=i+1
while(arr(j) > arr(pivot))
j=j+1
if(i<j)
{
temp = arr(i)
arr(i) = arr(j)
arr(j) = temp
}
}
temp = arr(pivot)
arr(pivot) = arr(j)
arr(j) = temp
QuickSort(arr, first, j-1)
QuickSort(arr, j+1, last)
}
arr.toList
}
Hello I m new to scala and trying to implement quick sort. Program is working correctly but I want to remove the while loop since I read that while and do while are not recommended in scala because they do not return any value.
Is there any way to remove while loop in above code.
The classic quicksort algorithm, as you've coded here, requires a mutable collection (like Array) and the swapping of element values, which requires mutable variables (i.e. var). These things are discouraged in functional programming and aren't held in high esteem in the Scala community.
Here's a similar approach that is a little more in keeping to the spirit of the FP ethic.
// pseudo-quicksort -- from Array[Int] to List[Int]
def pqs(arr:Array[Int]): List[Int] = arr match {
case Array() => List()
case Array(x) => List(x)
case Array(x,y) => if (x < y) List(x,y) else List(y,x)
case _ => val (below, above) = arr.partition(_ < arr(0))
pqs(below) ++ List(arr(0)) ++ pqs(above.tail)
}
Better yet is to use one of the sort methods (sortBy, sortWith, sorted) as offered in the standard library.
Not so elegant, but without while:
def QuickSort(l: List[Int]) : List[Int] = {
if( l.length == 0) return Nil
if( l.length == 1 ) return arr
val pivot = arr(arr.length / 2)
val lesserThanPivot = l.filter( _ < pivot)
val equalToPivot = l.filter( _ == pivot)
val biggerThanPivot = l.filter( _ > pivot)
QuickSort( lesserThanPivot ) ++ equalToPivot.tail ++ List(pivot) ++ QuickSort(biggerThanPivot)
}
Below is an example of code which will generate Correlation Matrix but I need to add column header and row header in front and top of matrix.
For example in the above matrix amber coloured objects are the labels which i need to add to the blue coloured data generated by Correlation matrix whose code i have attached below.
In Scala breeze is there a way to add labels to matrix ? The problem is DenseMatrix is Double and labels are character so i am not able to add any char label to matrix object.
def getCorMatrix(c :String,d :String,n :Int) :breeze.linalg.DenseMatrix[Double] = {
CorMatrixlogger.info("Inside generating Correlation Matrix")
val query = MongoDBObject("RunDate" -> d) ++ ("Country" -> c)
CorMatrixlogger.info("Query Object created for {}", c)
val dbObject = for (d <- price.find(query)) yield(d)
val objectReader = (dbObject map {x => objectRead(x)}).toList
val fetchAssetData = objectReader map {x => x.Symbol} map { x=> assetStats(x,n) } filterNot {x => x.length < n-1}
CorMatrixlogger.info("Asset Data fetched")
val excessReturnMatrix = DenseMatrix((for(i <- fetchAssetData) yield i.excessReturn).map(_.toArray):_*)
CorMatrixlogger.info("Excess Return matrix generated")
val transposeExcessreturnMatrix = excessReturnMatrix.t
val vcvMatrix = breeze.numerics.rint(((excessReturnMatrix * transposeExcessreturnMatrix):/ (n-1).toDouble ) :* 1000000.0) :/ 1000000.0
CorMatrixlogger.info("VcV Matrix Generated")
val transposeStDevVector = DenseMatrix(for (i <- fetchAssetData ) yield i.sigma)
val stDevVector = transposeStDevVector.t
val stDevMatrix = breeze.numerics.rint(( stDevVector * transposeStDevVector) :* 1000000.0) :/ 1000000.0
CorMatrixlogger.info("Correlation Matrix Generated")
lowerTriangular(breeze.numerics.rint((vcvMatrix :/ stDevMatrix) :* 10000.0) :/ 10000.0)
}
Edit
Thanks David. Your solution really worked well for me.
val ma = DenseMatrix((1.0,2.0,3.0), (3.0,4.0,5.0),(6.0,7.0,8.0))
val im = DenseMatrix.tabulate(ma.rows,ma.cols)(ma(_,_).toString)
val head = DenseVector("a","b","c")
val thead = head.t
val withHeader:DenseMatrix[String] = DenseMatrix.tabulate(im.rows+1, im.cols+1) { (i, j) =>
if (i == 0 && j == 0) " "
else if (i == 0) head(j -1)
else if (j == 0 ) thead (i -1)
else im(i-1,j-1)
} //> withHeader : breeze.linalg.DenseMatrix[String] = a b c
//| a 1.0 2.0 3.0
//| b 3.0 4.0 5.0
//| c 6.0 7.0 8.0
There's nothing built in, sadly. You could do something like
val withHeader:DenseMatrix[Any] = DenseMatrix.tabulate(n+1, m+1){ (i, j) =>
if (i == 0 && j == 0) ""
else if (i == 0) colHeaders(j - 1)
else if (j == 0) rowHeaders(i - 1)
else orig(i - 1, j - 1)
}
You lose all typing information that way, of course, but if you just need to toString something, it's probably the quickest way in current Breeze.
I have just started learning Scala and sideways I am doing some algorithms also. Below is an implementation of merge sort in Scala. I know it isn't very "scala" in nature, and some might even reckon that I have tried to write java in scala. I am not totally familiar with scala, i just know some basic syntax and i keep googling if i need something more. So please give me some pointers on to what can i do in this code to make it more functional and in accord with scala conventions and best practices. Please dont just give correct/optimized code, i will like to do it myself. Any suggestions are welcomed !
def mergeSort(list: Array[Int]): Array[Int] = {
val len = list.length
if (len == 1) list
else {
var x, y = new Array[Int](len / 2)
val z = new Array[Int](len)
Array.copy(list, 0, x, 0, len / 2)
Array.copy(list, len / 2, y, 0, len / 2)
x = mergeSort(x)
y = mergeSort(y)
var i, j = 0
for (k <- 0 until len) {
if (j >= y.length || (i < x.length && x(i) < y(j))) {
z(k) = x(i)
i = i + 1
} else {
z(k) = y(j)
j = j + 1
}
}
z
}
}
[EDIT]
This code works fine and I have assumed for now that input array will always be of even length.
UPDATE
Removed vars x and y
def mergeSort(list: Array[Int]): Array[Int] = {
val len = list.length
if (len == 1) list
else {
val z = new Array[Int](len)
val x = mergeSort(list.dropRight(len/2))
val y = mergeSort(list.drop(len/2))
var i, j = 0
for (k <- 0 until len) {
if (j >= y.length || (i < x.length && x(i) < y(j))) {
z(k) = x(i)
i = i + 1
} else {
z(k) = y(j)
j = j + 1
}
}
z
}
}
Removing the var x,y = ... would be a good start to being functional. Prefer immutability to mutable datasets.
HINT: a method swap that takes two values and returns them ordered using a predicate
Also consider removing the for loop(or comprehension).
How do I break out a loop?
var largest=0
for(i<-999 to 1 by -1) {
for (j<-i to 1 by -1) {
val product=i*j
if (largest>product)
// I want to break out here
else
if(product.toString.equals(product.toString.reverse))
largest=largest max product
}
}
How do I turn nested for loops into tail recursion?
From Scala Talk at FOSDEM 2009 http://www.slideshare.net/Odersky/fosdem-2009-1013261
on the 22nd page:
Break and continue
Scala does not have them. Why?
They are a bit imperative; better use many smaller functions
Issue how to interact with closures.
They are not needed!
What is the explanation?
You have three (or so) options to break out of loops.
Suppose you want to sum numbers until the total is greater than 1000. You try
var sum = 0
for (i <- 0 to 1000) sum += i
except you want to stop when (sum > 1000).
What to do? There are several options.
(1a) Use some construct that includes a conditional that you test.
var sum = 0
(0 to 1000).iterator.takeWhile(_ => sum < 1000).foreach(i => sum+=i)
(warning--this depends on details of how the takeWhile test and the foreach are interleaved during evaluation, and probably shouldn't be used in practice!).
(1b) Use tail recursion instead of a for loop, taking advantage of how easy it is to write a new method in Scala:
var sum = 0
def addTo(i: Int, max: Int) {
sum += i; if (sum < max) addTo(i+1,max)
}
addTo(0,1000)
(1c) Fall back to using a while loop
var sum = 0
var i = 0
while (i <= 1000 && sum <= 1000) { sum += 1; i += 1 }
(2) Throw an exception.
object AllDone extends Exception { }
var sum = 0
try {
for (i <- 0 to 1000) { sum += i; if (sum>=1000) throw AllDone }
} catch {
case AllDone =>
}
(2a) In Scala 2.8+ this is already pre-packaged in scala.util.control.Breaks using syntax that looks a lot like your familiar old break from C/Java:
import scala.util.control.Breaks._
var sum = 0
breakable { for (i <- 0 to 1000) {
sum += i
if (sum >= 1000) break
} }
(3) Put the code into a method and use return.
var sum = 0
def findSum { for (i <- 0 to 1000) { sum += i; if (sum>=1000) return } }
findSum
This is intentionally made not-too-easy for at least three reasons I can think of. First, in large code blocks, it's easy to overlook "continue" and "break" statements, or to think you're breaking out of more or less than you really are, or to need to break two loops which you can't do easily anyway--so the standard usage, while handy, has its problems, and thus you should try to structure your code a different way. Second, Scala has all sorts of nestings that you probably don't even notice, so if you could break out of things, you'd probably be surprised by where the code flow ended up (especially with closures). Third, most of Scala's "loops" aren't actually normal loops--they're method calls that have their own loop, or they are recursion which may or may not actually be a loop--and although they act looplike, it's hard to come up with a consistent way to know what "break" and the like should do. So, to be consistent, the wiser thing to do is not to have a "break" at all.
Note: There are functional equivalents of all of these where you return the value of sum rather than mutate it in place. These are more idiomatic Scala. However, the logic remains the same. (return becomes return x, etc.).
This has changed in Scala 2.8 which has a mechanism for using breaks. You can now do the following:
import scala.util.control.Breaks._
var largest = 0
// pass a function to the breakable method
breakable {
for (i<-999 to 1 by -1; j <- i to 1 by -1) {
val product = i * j
if (largest > product) {
break // BREAK!!
}
else if (product.toString.equals(product.toString.reverse)) {
largest = largest max product
}
}
}
It is never a good idea to break out of a for-loop. If you are using a for-loop it means that you know how many times you want to iterate. Use a while-loop with 2 conditions.
for example
var done = false
while (i <= length && !done) {
if (sum > 1000) {
done = true
}
}
To add Rex Kerr answer another way:
(1c) You can also use a guard in your loop:
var sum = 0
for (i <- 0 to 1000 ; if sum<1000) sum += i
Simply We can do in scala is
scala> import util.control.Breaks._
scala> object TestBreak {
def main(args : Array[String]) {
breakable {
for (i <- 1 to 10) {
println(i)
if (i == 5)
break;
} } } }
output :
scala> TestBreak.main(Array())
1
2
3
4
5
Since there is no break in Scala yet, you could try to solve this problem with using a return-statement. Therefore you need to put your inner loop into a function, otherwise the return would skip the whole loop.
Scala 2.8 however includes a way to break
http://www.scala-lang.org/api/rc/scala/util/control/Breaks.html
An approach that generates the values over a range as we iterate, up to a breaking condition, instead of generating first a whole range and then iterating over it, using Iterator, (inspired in #RexKerr use of Stream)
var sum = 0
for ( i <- Iterator.from(1).takeWhile( _ => sum < 1000) ) sum += i
// import following package
import scala.util.control._
// create a Breaks object as follows
val loop = new Breaks;
// Keep the loop inside breakable as follows
loop.breakable{
// Loop will go here
for(...){
....
// Break will go here
loop.break;
}
}
use Break module
http://www.tutorialspoint.com/scala/scala_break_statement.htm
Just use a while loop:
var (i, sum) = (0, 0)
while (sum < 1000) {
sum += i
i += 1
}
Here is a tail recursive version. Compared to the for-comprehensions it is a bit cryptic, admittedly, but I'd say its functional :)
def run(start:Int) = {
#tailrec
def tr(i:Int, largest:Int):Int = tr1(i, i, largest) match {
case x if i > 1 => tr(i-1, x)
case _ => largest
}
#tailrec
def tr1(i:Int,j:Int, largest:Int):Int = i*j match {
case x if x < largest || j < 2 => largest
case x if x.toString.equals(x.toString.reverse) => tr1(i, j-1, x)
case _ => tr1(i, j-1, largest)
}
tr(start, 0)
}
As you can see, the tr function is the counterpart of the outer for-comprehensions, and tr1 of the inner one. You're welcome if you know a way to optimize my version.
Close to your solution would be this:
var largest = 0
for (i <- 999 to 1 by -1;
j <- i to 1 by -1;
product = i * j;
if (largest <= product && product.toString.reverse.equals (product.toString.reverse.reverse)))
largest = product
println (largest)
The j-iteration is made without a new scope, and the product-generation as well as the condition are done in the for-statement (not a good expression - I don't find a better one). The condition is reversed which is pretty fast for that problem size - maybe you gain something with a break for larger loops.
String.reverse implicitly converts to RichString, which is why I do 2 extra reverses. :) A more mathematical approach might be more elegant.
I am new to Scala, but how about this to avoid throwing exceptions and repeating methods:
object awhile {
def apply(condition: () => Boolean, action: () => breakwhen): Unit = {
while (condition()) {
action() match {
case breakwhen(true) => return ;
case _ => { };
}
}
}
case class breakwhen(break:Boolean);
use it like this:
var i = 0
awhile(() => i < 20, () => {
i = i + 1
breakwhen(i == 5)
});
println(i)
if you don’t want to break:
awhile(() => i < 20, () => {
i = i + 1
breakwhen(false)
});
The third-party breakable package is one possible alternative
https://github.com/erikerlandson/breakable
Example code:
scala> import com.manyangled.breakable._
import com.manyangled.breakable._
scala> val bkb2 = for {
| (x, xLab) <- Stream.from(0).breakable // create breakable sequence with a method
| (y, yLab) <- breakable(Stream.from(0)) // create with a function
| if (x % 2 == 1) continue(xLab) // continue to next in outer "x" loop
| if (y % 2 == 0) continue(yLab) // continue to next in inner "y" loop
| if (x > 10) break(xLab) // break the outer "x" loop
| if (y > x) break(yLab) // break the inner "y" loop
| } yield (x, y)
bkb2: com.manyangled.breakable.Breakable[(Int, Int)] = com.manyangled.breakable.Breakable#34dc53d2
scala> bkb2.toVector
res0: Vector[(Int, Int)] = Vector((2,1), (4,1), (4,3), (6,1), (6,3), (6,5), (8,1), (8,3), (8,5), (8,7), (10,1), (10,3), (10,5), (10,7), (10,9))
import scala.util.control._
object demo_brk_963
{
def main(args: Array[String])
{
var a = 0;
var b = 0;
val numList1 = List(1,2,3,4,5,6,7,8,9,10);
val numList2 = List(11,12,13);
val outer = new Breaks; //object for break
val inner = new Breaks; //object for break
outer.breakable // Outer Block
{
for( a <- numList1)
{
println( "Value of a: " + a);
inner.breakable // Inner Block
{
for( b <- numList2)
{
println( "Value of b: " + b);
if( b == 12 )
{
println( "break-INNER;");
inner.break;
}
}
} // inner breakable
if( a == 6 )
{
println( "break-OUTER;");
outer.break;
}
}
} // outer breakable.
}
}
Basic method to break the loop, using Breaks class.
By declaring the loop as breakable.
Ironically the Scala break in scala.util.control.Breaks is an exception:
def break(): Nothing = { throw breakException }
The best advice is: DO NOT use break, continue and goto! IMO they are the same, bad practice and an evil source of all kind of problems (and hot discussions) and finally "considered be harmful". Code block structured, also in this example breaks are superfluous.
Our Edsger W. Dijkstra† wrote:
The quality of programmers is a decreasing function of the density of go to statements in the programs they produce.
I got a situation like the code below
for(id<-0 to 99) {
try {
var symbol = ctx.read("$.stocks[" + id + "].symbol").toString
var name = ctx.read("$.stocks[" + id + "].name").toString
stocklist(symbol) = name
}catch {
case ex: com.jayway.jsonpath.PathNotFoundException=>{break}
}
}
I am using a java lib and the mechanism is that ctx.read throw a Exception when it can find nothing.
I was trapped in the situation that :I have to break the loop when a Exception was thrown, but scala.util.control.Breaks.break using Exception to break the loop ,and it was in the catch block thus it was caught.
I got ugly way to solve this: do the loop for the first time and get the count of the real length.
and use it for the second loop.
take out break from Scala is not that good,when you are using some java libs.
Clever use of find method for collection will do the trick for you.
var largest = 0
lazy val ij =
for (i <- 999 to 1 by -1; j <- i to 1 by -1) yield (i, j)
val largest_ij = ij.find { case(i,j) =>
val product = i * j
if (product.toString == product.toString.reverse)
largest = largest max product
largest > product
}
println(largest_ij.get)
println(largest)
Below is code to break a loop in a simple way
import scala.util.control.Breaks.break
object RecurringCharacter {
def main(args: Array[String]) {
val str = "nileshshinde";
for (i <- 0 to str.length() - 1) {
for (j <- i + 1 to str.length() - 1) {
if (str(i) == str(j)) {
println("First Repeted Character " + str(i))
break() //break method will exit the loop with an Exception "Exception in thread "main" scala.util.control.BreakControl"
}
}
}
}
}
I don't know how much Scala style has changed in the past 9 years, but I found it interesting that most of the existing answers use vars, or hard to read recursion. The key to exiting early is to use a lazy collection to generate your possible candidates, then check for the condition separately. To generate the products:
val products = for {
i <- (999 to 1 by -1).view
j <- (i to 1 by -1).view
} yield (i*j)
Then to find the first palindrome from that view without generating every combination:
val palindromes = products filter {p => p.toString == p.toString.reverse}
palindromes.head
To find the largest palindrome (although the laziness doesn't buy you much because you have to check the entire list anyway):
palindromes.max
Your original code is actually checking for the first palindrome that is larger than a subsequent product, which is the same as checking for the first palindrome except in a weird boundary condition which I don't think you intended. The products are not strictly monotonically decreasing. For example, 998*998 is greater than 999*997, but appears much later in the loops.
Anyway, the advantage of the separated lazy generation and condition check is you write it pretty much like it is using the entire list, but it only generates as much as you need. You sort of get the best of both worlds.