Rudziankoŭ
Rudziankoŭ

Reputation: 11251

Nested loops in scala

I noticed that scala loops differs from java loops:

//java:
for(int i = 0; i < 2; i ++){
     System.out.println("1loop");
     for(int i = 0; i < 2; i ++){
         System.out.println("2loop");     
     }
}
// output:
1loop
2loop
2loop
...

And in Scala:

ranges.foreach{ range_line =>
      print("1")
      transactions.foreach{ transaction_line =>
        print("2")       
      }
    }
//output 
111...22

Why it happening so? How to rearrange this nested loop to more scala-like style?

val ranges = scala.io.Source.fromInputStream(getClass.getResourceAsStream("/ranges.tsv")).getLines
val transactions = scala.io.Source.fromInputStream(getClass.getResourceAsStream("/transactions.tsv")).getLines

Upvotes: 1

Views: 948

Answers (2)

Dylan
Dylan

Reputation: 13859

My guess is that transactions is not a regular collection like a List or Array - it is probably a representation of some future computation, e.g. a Future or some kind of stream.

If so, the function you pass to transactions.foreach is likely to be running asynchronously (i.e. later on, sometimes on a different thread, typically not blocking the calling thread).

Following this assumption, your call to transactions.foreach is causing some work to happen "in the background", but the ranges.foreach is continuing on, uninterrupted. ranges.foreach could potentially finish, then the work triggered by transactions.foreach finally gets around to running, so you get all of the 2's at the end.


That said, this appears to be an abnormal case. If ranges and transactions were regular collections like a List, you'd see the same looping behavior as you would with a regular Java collection.

Upvotes: 4

4lex1v
4lex1v

Reputation: 21547

There's definitely some issue with your definitions for ranges and transactions, please do not that foreach call is not equivalent to Java's for-loop, foreach intends to iterate over the collection. If you try to following snippet, which in some sense equivalent to the for-loop of your, then you'll see the desired result:

    scala> 

    (1 to 2).foreach { i1 =>
      println("1loop")
      (1 to 2).foreach { i2 =>
        println("2loop")
      }
    }

    1loop
    2loop
    2loop
    1loop
    2loop
    2loop

Hope it helps

Upvotes: 1

Related Questions