tags:

views:

914

answers:

4

An example: val l = List(1,2,3) val t = List(-1,-2,-3)

Can I do something like this?

for (i <- 0 to 10) yield (l(i)) yield (t(i))

Basically I want to yield multiple results for every iteration.

A: 

Apparently not. I get a compile error when I try it.

It looks like for .. yield is an expression. You can't have two yields, since that's not really part of the expression.

If you want to yield multiple values, why not yield them as a tuple or a list?

For example:

for( t <- List(1,2,3); l <- List(-1,-2,-3))
  yield (t, l)
Christopher
A: 

Maybe yield is not the best way to go? Perhaps simple array appending could be used here.

Geo
There is no semantic difference between using yield and using a list. The practical difference involves memory usage, where yield is more efficient for large sets.
Christopher
+2  A: 

No, you can't use multiple yield clauses, but there are work-arounds. For example:

for (i <- 0 to 10;
     r <- List(l(i), t(i)))
yield r

You can nest for-comprehensions, of course, but that would result in a list of lists of elements, which I don't believe is what you want.

Daniel
Warning, this solution is O(n^2)
James Iry
Daniel
Right, for arrays indexed access is O(1) so the solution would be O(n).
James Iry
+5  A: 

It's not clear what you're asking for - what you expect the semantics of multiple yield to be. One thing, though, is that you probably never want to use indexes to navigate a list - each call to t(i) is O(i) to execute.

So here's one possibility that you might be asking for

scala> val l = List(1,2,3); val t = List(-1,-2,-3)
l: List[Int] = List(1, 2, 3)
t: List[Int] = List(-1, -2, -3)

scala> val pairs = l zip t
pairs: List[(Int, Int)] = List((1,-1), (2,-2), (3,-3))

And here's another possibility that you might be asking for

scala> val crossProduct = for (x <- l; y <- t) yield (x,y)
crossProduct: List[(Int, Int)] = List((1,-1), (1,-2), (1,-3), (2,-1), (2,-2), (2,-3), (3,-1), (3,-2), (3,-3))

The later is just syntactic sugar for

scala> val crossProduct2 = l flatMap {x => t map {y => (x,y)}}
crossProduct2: List[(Int, Int)] = List((1,-1), (1,-2), (1,-3), (2,-1), (2,-2), (2,-3), (3,-1), (3,-2), (3,-3))

A third possibility is you want to interleave them

scala> val interleaved = for ((x,y) <- l zip t; r <- List(x,y)) yield r
interleaved: List[Int] = List(1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10)

That's syntax sugar for

scala> val interleaved2 = l zip t flatMap {case (x,y) => List(x,y)}
interleaved2: List[Int] = List(1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10)
James Iry
I think he just wants to interpolate the lists.
Daniel
right, I wanted to interleave them, so both these give the same result:[James]val interleaved = for ((x,y) <- l zip t; r <- List(x,y)) yield r[Daniel]for (i <- 0 to 10; r <- List(l(i), t(i)))yield rI think James' one is more elegant and it also outputs List.Thanks a lot guys.
Monis Iqbal