Scala collectFirst with return function Option [U]

I had such a situation in the library that I am writing, and I am not very happy with the solutions that I have come up with so far.

Let's say that I have an expensive function f that takes an element of type T and returns a value of type Option [U]. Now suppose I have a collection of type T, and I want to get the first non-None value returned by f when executed through T elements without evaluating f for all T elements if the value is already found.

The only way I came up with is to wrap F in an Extractor object and use it using the scala collectFirst method.

For instance:

object FMatch { def unapply(t : T) = f(t) } collection.collectFirst{ case FMatch(result) => result } 

This seems a little inelegant, and I'm not sure if f is evaluated only once or twice for each result (I have not tested this to find out yet). It seems like it would be useful to have a version of collectFirst that accepts a parameter of type T => Option [U] instead of PartialFunction1 [T].

Is there a more elegant way to do this that I am missing?

+6
source share
3 answers

Use this:

 collection.toIterator.map(f).find(_.isDefined) 
+9
source

Use the collection view, make it lazy and postpone the call to this function until the last possible moment (for example, it will not be called at all for elements that go beyond the first match):

 xs.view map {f(_)} collectFirst {case Some(x) => x} 

or

 xs.view map {f(_)} find {_.isDefined} 

or in the style without dots, in accordance with the answer of Alexei:

 xs.view map {f} find {_.isDefined} 

This, I hope, will give you several alternative ways to think about the problem in more detail :)

+14
source
 @annotation.tailrec def first[A, B](as: Traversable[A], f: A => Option[B]): Option[B] = if (as.isEmpty) None else f(as.head) match { case s @ Some(_) => s case _ => first(as.tail, f) } 
+2
source

Source: https://habr.com/ru/post/896618/


All Articles