1

I've been trying out Scala in a pet project recently and noticed that the following code snippet was eating up memory (I call this method a lot):

private[this] def isConsistent(startLang2: Int, lengthLang2: Int, 
    startLang1: Int, lengthLang1: Int,
    lang2FinalAlignments: ArrayBuffer[ArrayBuffer[Int]]): Boolean = {

    (startLang2 to (startLang2 + lengthLang2)) foreach {
      i =>
        val valueSeq = lang2FinalAlignments(i)
        if (valueSeq.size == 0 || valueSeq.exists { value => value < startLang1 || value > (startLang1 + lengthLang1) })
          false
    }
    true
}

When I changed the 'false' to 'return false' the situation seems to have resolved itself:

private[this] def isConsistent(startLang2: Int, lengthLang2: Int, 
    startLang1: Int, lengthLang1: Int,
    lang2FinalAlignments: ArrayBuffer[ArrayBuffer[Int]]): Boolean = {

    (startLang2 to (startLang2 + lengthLang2)) foreach {
      i =>
        val valueSeq = lang2FinalAlignments(i)
        if (valueSeq.size == 0 || valueSeq.exists { value => value < startLang1 || value > (startLang1 + lengthLang1) })
          return false
    }
    true
}

When I think about it snippet #2 makes sense with regards to how I expect/want the method to work. Could someone please explain to me what the first snippet is doing?

Royston Pinto
  • 6,681
  • 2
  • 28
  • 46

1 Answers1

2

Let's see what foreach does:

def foreach[U](f: Elem => U): Unit

So it runs f on every element of the collection and discards its result - it doesn't care about the return type of f.

In your case when you call

... foreach {
  i => {
    ...
    if (...)
      false
  }
true

the body of the function return false if the condition is satisfied and Unit otherwise. Their common supertype is Any, so the function passed to foreach is of type Int => Any. It's result is discarded and you traverse the whole collection. (Try giving an explicit type such as foreach[Any] or foreach[Boolean].)

In the second snippet the situation is very different:

... foreach {
  i => {
    ...
    if (...)
      return false
  }
true

Here foreach traverses the range only until the condition is satisfied and then return escapes the foreach execution and makes the main function exit.

Petr
  • 62,528
  • 13
  • 153
  • 317