Question

Is this a bug in indexWhere method, or is there a meaningful explanation for the first four lines in the example bellow?

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, -4)
res0: Int = -2

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, -3)
res1: Int = -1

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, -2)
res2: Int = 0

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, -1)
res3: Int = 1

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, 0)
res4: Int = 2

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, 1)
res5: Int = 2

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, 2)
res6: Int = 2

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, 3)
res7: Int = 3

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, 4)
res8: Int = 4

scala> List(1, 1, 4, 4, 4).indexWhere(_ > 3, 5)
res9: Int = -1
Was it helpful?

Solution 2

Source code looks like this:

override /*SeqLike*/
  def indexWhere(p: A => Boolean, from: Int): Int = {
    var i = from
    var these = this drop from
    while (these.nonEmpty) {
      if (p(these.head))
        return i

      i += 1
      these = these.tail
    }
    -1
  }

So there is no input check, neither zeroing of i variable. I would say it is a bug. If you can, write it on https://groups.google.com/forum/#!forum/scala-language where devs can take a look at it.

OTHER TIPS

I think ideally you'd see an IllegalArgumentException if you passed a negative number as the start index (what's that supposed to mean anyway?), but maybe it was felt that the overhead of a bounds check wasn't worth it. I don't see any specified behaviour in the docs for this, so not sure I'd call it a bug; more a case of "rubbish in, rubbish out".

As a future solution, you might want to implement your own version that does check. You might make it return an Option as well instead of -1, which is also unsafe:

implicit class WithIndexWhereSafe[T](seq: Seq[T]) { 
  def indexWhereSafe(p: T => Boolean, from: Int) = { 
    assert(from >= 0, "from must be >= 0")
    val i = seq.indexWhere(p, from) 
    if (i != -1)
      Some(i)
    else
      None
  }
}


List(1, 1, 4, 4, 4).indexWhereSafe(_ > 3, 2)  // Some(2)
List(1, 1, 4, 4, 4).indexWhereSafe(_ > 3, 5)  // None
List(1, 1, 4, 4, 4).indexWhereSafe(_ > 3, -4) // AssertionError
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top