0

From Here we get to know that an expression like:

for( i <- 1 to 10 ) yield i + 1

will expand into

( 1 to 10 ).map( _+1 )

But what does the following expression expand to?

for( i <- 1 to 50  j <- i to 50 ) yield List(1,i,j)

Is this correct?

( 1 to 50 ).map( x => (1 to 50 ).map(List(1,x,_))

I'm interested in this problem because I'd like to make a function which performs multiple Xi <- Xi-1 to 50 operations, as shown below:

for( X1 <- 1 to 50  X2 <- X1 to 50  X3 <- X2 to 50 ..... Xn <- Xn-1 to 50 ) 
    yield List(1,X1,X2,X3,.....,Xn)

The function has one parameter: dimension which denotes the n in the above expression.
Its return type is IndexSeq[List[Int]]

How can I achieve that?

Thank you for answering (:

Community
  • 1
  • 1
Yun-Chih Chen
  • 543
  • 6
  • 18

2 Answers2

6

It's well explained in a relevant doc. In particular:

for(x <- c1; y <- c2; z <- c3) yield {...}

will be translated into

c1.flatMap(x => c2.flatMap(y => c3.map(z => {...})))

I don't think there is a way to abstract over arbitrary nested comprehension (unless you're using voodoo magic, like macros)

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
0

See om-nom-nom's answer for an explanation of what the for loops expand to. I'd like to answer the second part of the opening question, how to implement a function that can do:

for( X1 <- 1 to 50  X2 <- X1 to 50  X3 <- X2 to 50 ..... Xn <- Xn to 50 ) 
    yield List(1,X1,X2,X3,.....,Xn)

You can use:

def upto50(dimension: Int) = {
  def loop(n: Int, start: Int): IndexedSeq[List[Int]] = {
    if (n > dimension)
      IndexedSeq(List())
    else {
      (n to 50).flatMap(x => loop(n + 1, x).map(x :: _))
    }
  }
  loop(1, 1)
}

We compute each of the loops recursively, working inside-out, starting with Xn to 50 and building up the solution.

Solutions for the more general case of:

for( X1 <- S1  X2 <- S2  X3 <- S3 ..... Xn <- Sn ) 
    yield List(1,X1,X2,X3,.....,Xn)

Where S1..Sn are arbitraray sequences or monads are also possible. See this gist for the necessary wall of code.

wingedsubmariner
  • 13,350
  • 1
  • 27
  • 52
  • I understand that `Vector` is a subtype of `Indexseq`, but why don't you just use `Indexseq` here? – Yun-Chih Chen Jul 02 '14 at 01:11
  • Thanks for answering, but the output of `upto50` is not incremental as required. Is it possible to modify it so that it produce "strictly incremental sequence"? Again, thanks for answering (: – Yun-Chih Chen Jul 02 '14 at 02:40
  • Oops, I missed that each loop starts from the value of the previous loop. And you're right, `IndexedSeq` makes more sense. Edited. – wingedsubmariner Jul 02 '14 at 03:57