why does GenSeqLike.indexWhere return Int rather than Option[Int]?

260 views
Skip to first unread message

Damian Helme

unread,
Nov 22, 2012, 7:43:41 AM11/22/12
to scala...@googlegroups.com
I was wondering why GenSeqLike.indexWhere(p: (A) => Boolean) : Int returns an Int, with '-1' meaning that no elements in the seq satisfied the predicate.

It would feel more 'Scala-like' to me to return an Option[Int], with None for when the predicate doesn't match.

Am I missing something?

Thanks

Damian.

Matthew Pocock

unread,
Nov 22, 2012, 2:34:33 PM11/22/12
to Damian Helme, scala...@googlegroups.com
Hi,

These kind of operations tend to be called inside tight loops. The overhead of boxing the jvm int to an Integer and then wrapping it in a newly-created Option would be prohibitive. You may be able to get rid of the Integer boxing if Option is specialized correctly and if indexWhere takes advantage of this.

There is the obvious correspondence between i >=0 and Some(i), i < 0 and None, and with enough compiler magic, perhaps Option[Int with NonNegative] could be convinced to be represented like this. But, this isn't something that I would know how do do.

Or you could build a type today using 'tagged types' that is the disjoint union of non-negative integers and -1, but these things aren't part of the standard lib as they where 'discovered' since the library was written.

Matthew
--
Dr Matthew Pocock
Integrative Bioinformatics Group, School of Computing Science, Newcastle University
skype: matthew.pocock
tel: (0191) 2566550

Damian Helme

unread,
Nov 25, 2012, 12:57:47 PM11/25/12
to scala...@googlegroups.com, Damian Helme
Matthew - thanks for your thoughts.

I've got so used to running for-comprehensions over the return from function values that it seems a bit anachronistic to have to do something like:

val idx = x.indexWhere( p ) 
if ( idx == -1 ) 
  // handle error
else {
  // use idx ....

Som Snytt

unread,
Nov 25, 2012, 3:37:15 PM11/25/12
to Damian Helme, scala...@googlegroups.com
As a neophyte (or dumb person), I'm always impressed when people use zipWithIndex to operate on data and do something useful with indices.  Then collectFirst gives you the Option you seek.  If you're not inside a tight loop.

The extra zip seems impossibly wasteful at first glance, but one coder's waste is another coder's haste.


On Sun, Nov 25, 2012 at 9:57 AM, Damian Helme <damia...@gmail.com> wrote:

I've got so used to running for-comprehensions over the return from function values that it seems a bit anachronistic to have to do something like:

val idx = x.indexWhere( p ) 
if ( idx == -1 ) 
  // handle error
else {
  // use idx ....
}

On Thursday, November 22, 2012 7:34:38 PM UTC, Matthew Pocock wrote:

These kind of operations tend to be called inside tight loops.

object Test extends App {
  val data = List("cat","dog","rat")
  val ats = data.zipWithIndex collect { case (s,i) if s endsWith "at" => i }
  val nonat = data.zipWithIndex collectFirst { case (s,i) if !(s endsWith "at") => i }
  println(ats)
  println(nonat)
}
 

Naftoli Gugenheim

unread,
Nov 25, 2012, 11:01:08 PM11/25/12
to Som Snytt, Damian Helme, scala-user
Why not just
Some(x.indexWhere(p)) filterNot -1.==

Som Snytt

unread,
Nov 26, 2012, 1:42:24 AM11/26/12
to Naftoli Gugenheim, Damian Helme, scala-user
On Sun, Nov 25, 2012 at 8:01 PM, Naftoli Gugenheim <nafto...@gmail.com> wrote:
Why not just
Some(x.indexWhere(p)) filterNot -1.==

Similarly,

  import scala.util.Try
  println(Try(data indexWhere (_ endsWith "it")) filter (-1).<)
  println(Try(data indexWhere (_ endsWith "at")) filter (_ >= 0))

Reply all
Reply to author
Forward
0 new messages