Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any clean way to combine find and instanceof in Scala?

I want to find in some Iterable some elements that both conform to some given type, and validates a predicate taking that type as an argument.

I wrote this method using imperative-style programming, which seems to conform to my expectations. Is there some way to write this in a more "scalaesque" way?

def findMatch[T](it: Iterable[_], clazz: Class[T], pred: T => Boolean): Option[T] = {
  val itr = it.iterator
  var res: Option[T] = None
  while (res.isEmpty && itr.hasNext) {
    val e = itr.next()
    if (clazz.isInstance(e) && pred(clazz.cast(e))) {
      res = Some(clazz.cast(e))
    }
  }
  res
}
like image 832
scand1sk Avatar asked Nov 30 '22 16:11

scand1sk


2 Answers

You can use collect if you want to find and then map.

scala> val it: Iterable[Any] = List(1,2,3,"4")            
it: Iterable[Any] = List(1, 2, 3, 4)

scala> it.view.collect{case s: String => s}.headOption
res1: Option[String] = Some(4)
like image 167
akihiro4chawon Avatar answered Dec 05 '22 04:12

akihiro4chawon


You can work with an existantial type X forSome{typeX} rather than using _ as type parameter. This then would enable you to write it with the mentioned find method and use the map method on the Option type:

def findMatch[T](it: Iterable[X forSome {type X}], clazz: Class[T], pred: T => Boolean): Option[T] = {
    it.find{ e => clazz.isInstance(e) && pred(clazz.cast(e))}.map{clazz.cast(_)}
}
like image 30
Lutz Avatar answered Dec 05 '22 04:12

Lutz