I want to generate a combination of some values as in the code below:
object ContinueGenerate {
val foods = List("A", "B", "C")
val places = List("P1", "P2", "P3")
val communities = List("C1", "C2", "C3", "C4")
case class Combination(food: String, place: String, community: String)
def allCombinations() = {
for {
food <- foods; place <- places; community <- communities
} yield Combination(food, place, community)
}
def main(args: Array[String]) {
allCombinations foreach println
}
}
However the problem with this approach is that, all the data is generated at once. This is big problem when the size of foods
, places
and communities
becomes very large. Also there could be other parameters other than these three.
So I want to be able generate combinations, in a continuation style, such that a combination is generated only when it is requested.
What would be an idiomatic Scala way of doing that ?
You use streams:
object ContinueGenerate {
val foods = Stream("A", "B", "C")
val places = Stream("P1", "P2", "P3")
val communities = Stream("C1", "C2", "C3", "C4")
case class Combination(food: String, place: String, community: String)
def allCombinations() = {
for {
food <- foods; place <- places; community <- communities
} yield Combination(food, place, community)
}
def main(args: Array[String]) {
allCombinations foreach println
}
}
A Stream
caches all the data. If you only want to iterate once, use Iterator
instead, which should garbage-collect already traversed elements.
You can do this by using a View
over each list. In the code below I've added a side effect so it is visible when the yield
gets called for each element.
val foods = List("A", "B", "C")
val places = List("P1", "P2", "P3")
val communities = List("C1", "C2", "C3", "C4")
case class Combination(food: String, place: String, community: String)
def allCombinations() =
for {
food <- foods; place <- places; community <- communities
} yield {
val comb = Combination(food, place, community)
println(comb)
comb
}
//Prints all items
val combinations = allCombinations()
def allCombinationsView() =
for {
//Use a view of each list
food <- foods.view; place <- places.view; community <- communities.view
} yield {
val comb = Combination(food, place, community)
println(comb)
comb
}
//Prints nothing
val combinationsView = allCombinationsView()
//Prints 5 items
val five = combinationsView.take(5).toList
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With