0

In Scala, what if I have a nested for loop, and I want to execute different things on each one.

for (int i = 0; i<5; i++) {
   System.out.println(i);       //do something for just i
   for(int j = 0; j<5; j++) {
      System.out.println(i+j);  //do something for both i and j
   }
}

But the scala code:

for {i<-0  to 5 
     j<- 0 to 5} yield { print(i); print(i+j)} 

gives the output:

    0
(0,0)
0
(0,1)
0
(0,2)
0
(0,3)
0
(0,4)
0
(0,5)

but I want it to be:

0
(0,0)
(0,1)
(0,2)
(0,3)
(0,4)
(0,5)

Is there a way to only print i for each i, and i+j for each i and j in ONE for loop?

3
  • if (j == 0) print(i); print(i+j); .. not very clean, as side-effects. Why not just a nested loop? You can still use the "x <- a to b" syntax for the range. Commented Sep 1, 2017 at 0:27
  • This is an abstract representation of my problem. Basically I want to iterate through two things, do something on the outer loop and something on the inner loop.@user2864740 Commented Sep 1, 2017 at 0:36
  • 2
    Just use two for-loops. Also, for{...} {...} is for-loop. for{...} yield {...} is for-comprehension. They are very different things. Commented Sep 1, 2017 at 1:49

3 Answers 3

3

The compiler rewrites for comprehensions into their constituent map(), flatMap(), foreach(), and withFilter() parts. That's why some of the normal rules of Scala syntax don't apply inside sequence comprehension expressions. They get mangled in the rewriting process.

There are a few tricks to get around the problem.

for {
  i <- 0 to 5
  _ = println(i)
  j <- 0 to 5
} yield // do stuff with i and j

It really depends on what you need to do with the i value. It could be that a for comprehension is not the best tool for the job.

Sign up to request clarification or add additional context in comments.

2 Comments

If it's for side effects, like in OP's case, it's probably better to remove yield.
@user2864740; I wrote that "some of the normal rules" don't apply. Here are 2 examples: 1) can't place a println() statement (without the trick shown in the above answer). 2) can't create variables in the normal way. (e.g. val x = 5 won't compile but x = 5 will) I wasn't trying to say that the OP's code wouldn't execute. It works just fine. But what the OP wants to do, putting code between 2 generators, is tricky at best, and seldom advisable.
1

Alternative way of doing the same would be to use map function as following

val loop = 0 to 5
loop.map(i => {
  println(i) // do your stuffs as you did for i
  loop.map(j => {
    println(i, j) //do your stuffs as you did for i, j 
  })
})

Comments

1

I think this will do the trick:

(0 to 5).zip(0 to 5).foreach{case (i, j) => 
    //do stuff to i an dj
}

1 Comment

This has the same "problem" as the original if the "stuff" is print(i); print(i+j).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.