Scala collectFirst with function returning Option[U] - scala

I've had this situation occur a number of times in the library I'm writing, and I'm not particularly satisfied with the solutions I've come up with so far.
Let's say that I have an expensive function f that takes an item of type T and returns a value of type Option[U]. Now, suppose I have a collection of type T and I want to retrieve the first non-None value returned by f when performed across the elements of T without evaluating f for all elements of T if the value has already been found.
The only way I've come up with to do this is to wrap F into an Extractor Object, and use it with scala's collectFirst method.
For example:
object FMatch { def unapply(t : T) = f(t) }
collection.collectFirst{ case FMatch(result) => result }
This seems a little inelegant, and I'm not certain whether f is evaluated only once or twice for each result (I haven't tested this to find out yet). It seems like it would be useful to have a version of collectFirst that takes a parameter of type T => Option[U] instead of a PartialFunction1[T].
Is there a more elegant way to do this that I'm missing?

Use a view over the collection, to make it lazy and defer invocation of that function until the last possible moment (e.g. it won't be called at all for elements beyond the first match):
xs.view map {f(_)} collectFirst {case Some(x) => x}
or
xs.view map {f(_)} find {_.isDefined}
or in the point-free style, as per Alexey's response:
xs.view map {f} find {_.isDefined}
That should hopefully give you a couple of alternative ways to think about the problem more generally :)

Use this:
collection.toIterator.map(f).find(_.isDefined)

#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)
}

Give a partial functions to collectFirst
collectionT
.collectFirst { t =>
f(t) match {
case Some(u) => u
}

Related

How to implement a custom tail recursive map for lists in Scala

I want to implement a function called map that receives a list and a function and the yields the result of applying the function to each element of the input list.
So I have this so far:
def map(list: List[Int], function: (Int) => Int): List[Int] = {
def loop(list: List[Int], acc: List[Int]): List[Int] = {
list match {
case Nil => acc
case head :: tail => loop(list.tail, function(head) :: acc)
}
}
loop(list.reverse, Nil)
}
This code works and gives me the expected result, but I cannot help thinking there is a more elegant and efficient way that doesn't involve using reverse or another list method that isn't head or tail.
As far as rolling your own implementation of a purely functional map function, without using any mutable state or built-in List higher-order functions, you've done a great job! Having to reverse the list does seem unnecessary, but it's worth it because prepending to a list is a very efficient operation.
As well as the other methods suggested in the comments, you could make acc a scala.collection.mutable.ListBuffer (which supports efficient append and prepend operations), then converting it to a list when you're done. However, the conversion process isn't a great improvement over reverse.
Otherwise, there are a few minor things you can do to improve your map function:
By using curried arguments, you can use map more elegantly.
Functions that need to be tail-recursive should always be decorated with the scala.annotation.tailrec attribute. The Scala compiler then knows your intention, and will issue an error if the function cannot be optimized to use tail recursion.
It's trivial to make this function generic, which will make it far more widely useful.
It's generally more idiomatic to perform the reverse operation on the result. It makes no difference for a map operation, but if you were to write a filter operation, for example, then it would be more efficient to reverse the potentially smaller set of filtered elements.
Here's how that would then look:
import scala.annotation.tailrec
def map[A, B](list: List[A])(function: (A) => B): List[B] = {
#tailrec
def loop(rem: List[A], acc: List[B]): List[B] = rem match {
case Nil => acc.reverse
case head :: tail => loop(tail, function(head) :: acc)
}
loop(list, Nil)
}
Because head :: tail is the most efficient way to deconstruct and reconstruct a List, what you've done is a pretty common pattern. The .reverse is unfortunate but usually amounts to a minor performance penalty.
As mentioned in the comments, map can also be implemented via other Standard Library methods. Here it's done with foldRight:
def map(list :List[Int], function :Int => Int) :List[Int] =
list.foldRight(List.empty[Int])(function(_) :: _)

Is there a concise way to "invert" an Option?

Say I have a function that can take an optional parameter, and I want to return a Some if the argument is None and a None if the argument is Some:
def foo(a: Option[A]): Option[B] = a match {
case Some(_) => None
case None => Some(makeB())
}
So what I want to do is kind of the inverse of map. The variants of orElse are not applicable, because they retain the value of a if it's present.
Is there a more concise way to do this than if (a.isDefined) None else Some(makeB())?
fold is more concise than pattern matching
val op:Option[B] = ...
val inv = op.fold(Option(makeB()))(_ => None)
Overview of this answer:
One-liner solution using fold
Little demo with the fold
Discussion of why the fold-solution could be just as "obvious" as the if-else-solution.
Solution
You can always use fold to transform Option[A] into whatever you want:
a.fold(Option(makeB())){_ => Option.empty[B]}
Demo
Here is a complete runnable example with all the necessary type definitions:
class A
class B
def makeB(): B = new B
def foo(a: Option[A]): Option[B] = a match {
case Some(_) => None
case None => Some(makeB())
}
def foo2(a: Option[A]): Option[B] =
a.fold(Option(makeB())){_ => Option.empty[B]}
println(foo(Some(new A)))
println(foo(None))
println(foo2(Some(new A)))
println(foo2(None))
This outputs:
None
Some(Main$$anon$1$B#5fdef03a)
None
Some(Main$$anon$1$B#48cf768c)
Why fold only seems less intuitive
In the comments, #TheArchetypalPaul has commented that fold seems "lot less obvious" than the if-else solution. I agree, but I still think that it might be interesting to reflect on the reasons why that is.
I think that this is mostly an artifact resulting from the presence of special if-else syntax for booleans.
If there were something like a standard
def ifNone[A, B](opt: Option[A])(e: => B) = new {
def otherwise[C >: B](f: A => C): C = opt.fold((e: C))(f)
}
syntax that can be used like this:
val optStr: Option[String] = Some("hello")
val reversed = ifNone(optStr) {
Some("makeB")
} otherwise {
str => None
}
and, more importantly, if this syntax was mentioned on the first page of every introduction to every programming language invented in the past half-century, then the ifNone-otherwise solution (that is, fold), would look much more natural to most people.
Indeed, the Option.fold method is the eliminator of the Option[T] type: whenever we have an Option[T] and want to get an A out of it, the most obvious thing to expect should be a fold(a)(b) with a: A and b: T => A. In contrast to the special treatment of booleans with the if-else-syntax (which is a mere convention), the fold method is very fundamental, the fact that it must be there can be derived from the first principles.
I've come up with this definition a.map(_ => None).getOrElse(Some(makeB())):
scala> def f[A](a: Option[A]) = a.map(_ => None).getOrElse(Some(makeB()))
f: [A](a: Option[A])Option[makeB]
scala> f(Some(44))
res104: Option[makeB] = None
scala> f(None)
res105: Option[makeB] = Some(makeB())
I think the most concise and clearest might be Option.when(a.isEmpty)(makeB)

Why do I need to use andThen in order to pattern match Futures?

I found out that in order to pattern match Future fur Success/Failure, I need to use andThen (or onComplete, onSuccess...) and cannot use map. Why is that?
What I wanted to do (simplified, I am matching for Success and so on as well):
val f1 = Future(throw new Exception("Oops"))
f1 map { case Failure(e) => ??? }
Gives:
error: constructor cannot be instantiated to expected type;
found : scala.util.Failure[T]
required: Nothing
f1 map { case Failure(e) => ??? }
What I ended up doing:
val f1 = Future(throw new Exception("Oops"))
f1 andThen { case Failure(e) => ??? }
I would like to understand why map cannot be used here.
The answer is in the signature of map: it takes a A => B and returns a Future[B]. If you will, you can look at a Future as follows:
type Future[A] = Async[Either[Throwable, A]]
Future#map, Future#flatMap and Future.apply view this "stack" of types as a single big thing with a hole (Future is basically a special cased monad transformer). When you map/flatMap on a Future, you are only operating on the inner A.
Because the type signature isn't correct. When you want to map over a Future[A], you need to provide a function taking an A and producing a B, which isn't what you seem to be doing. What you're looking for is recover:
f1 recover { case e => // e is already a `Throwable` here ??? }

Explanation of List[_] in pattern matching used in flatten function

I am new to scala and I can not understand the following function
val L = List(List(1, 1), 2, List(3, List(5, 8)))
def flatten(l: List[Any]): List[Any] = l flatMap {
case ms:List[_] => flatten(ms)
case l => List(l)
}
flatten(L) // res2: List[Any] = List(1, 1, 2, 3, 5, 8)
In particular I do not understand the combination of flatMap and pattern matching and also the meaning of the first case ms:List[_]
Can someone explain that and maybe provide a simpler example to clarify the concept?
map and flatMap
First of all flatMap is a higher-order function.
map is also a higher order function which will convert a List to a new List by applying a function on all elements of that List. For example if you have
val l = List(1,2,3)
you can map it to a new list by using
val doubled = l.map(_ * 2) // List(2,4,6)
So what is flatMap? flatMap is useful when your function gets an Int but returns a List[Int]. In this case if you pass this function to map what you get will be a List[List[Int]] but sometimes you want to get a List[Int] instead.
What you can do is to use flatMap instead. Mathematically it is equivalent to first map and then flatten the result but in action it could be the flatten function which is defined based on flatMap not the other way around.
Technical details aside, flatten means that if you have a List[List[List...[Int]]], if you flatten it, you will get a List[Int].
When we look at
def flatten(l: List[Any]): List[Any] = l flatMap {
case ms:List[_] => flatten(ms)
case l => List(l)
}
we first need to know what does this mean. We already know that we have to pass a function to flatMap. In this case the function we are passing is
{
case ms:List[_] => flatten(ms)
case l => List(l)
}
which at first does not seem like a function but it is! It is actually a partial function which you can consider as a function with some nuances!
What is a partial function?
We could achieve (almost) the same result with:
def flatten(l: List[Any]): List[Any] = l flatMap { _ match {
case ms:List[_] => flatten(ms)
case l => List(l)
}
}
The difference between an ordinary function and a partial function is that partial functions may be undefined for some specific inputs. So the compiler will automatically generate a partial function from a body which starts with case keyword (It's not that simple but for the sake of simplicity I skip the details here).
Pattern matching by Type
A pattern like ms:List[_] is called a type pattern. It means that the type of ms will be checked in runtime against the List[_]. _ is a wild card and means any type so ms:List[_] literally means a List of any type (Due to type erasure you can not use a pattern like ms:List[Int], refer to this thread for more info).
So the whole pattern match on this code snippets means that
If ms is a list the result will be flatten(ms), other wise the result will be List(l).
The flatten function defined like this is recursive function which unwraps the lists and do this until there is no more list, then it will wrap the result again in a List! This way List[List[List.......[_]]] will be converted to List[_].
An additional example for type-patterns:
def hello(o: Any) = o match {
case _:Int => "Hi, I am an Int and I'm proud of it!"
case _:List[_] => "I have many things to tell you! I am a list after all!"
case b:Boolean => s"I'm simply a flag and my value is $b"
case _ => "I'm everything else you can imagine :D"
}
Disambiguation
By the way partial function is totally different from partially applied function and partial application!
The concept of partial function in Scala is the same as partial function in mathematics: A function which may be undefined for some of the values of its domain.

Fold collection with None as start value

I want to fold a collection or Y's and return an Option[X]. I want to start with None. Like this...
def f(optX: Option[X], y: Y): Option[X]
val optX = collectionOfY.fold(None) { case (prev, y) => f(prev,y) }
adding unneeded types to make it clearer
val optX: Option[X] = collectionOfY.fold(None) { case (prev: Option[X], y: Y) => f(prev,y) }
However, the compiler can not figure out the type properly and I have to write it like this
val xx: Option[X] = None
val optX = collectionOfY.fold(xx) { case (prev, y) => f(prev,y) }
What is the magic Scala syntax to write this?
Thanks
Peter
Just use foldLeft and any of the following
... foldLeft(Option.empty[X]) ... or ... foldLeft(None: Option[X]) ... or ... foldLeft[Option[X]](None) ...
After all, fold just calls foldLeft. You only really want to use fold when your A1 really is a super-type of A, if that really is the case then you can use fold as above and the compiler will know the type correctly.
For example, Option[List[Int]] <: Option[Seq[Int]] by covariance so we don't get an Any here:
List(Some(List(1,2,3))).fold[Option[Seq[Int]]](None)((_, _) => Some(Seq(1)))
> res2: Option[Seq[Int]] = Some(List(1))
Finally, if you do indeed know Option[X] will be a super-type of Y then say this explicitly in the type declaration of Y - i.e. Y <: Option[X], then you can use fold with the solutions given above.
See When should .empty be used versus the singleton empty instance? for a related discussion.
As was pointed out in the comments above, the preferred solution is change the first parameter passed to Option.fold to avoid the use of None and use Option.empty[X] instead.
val optX = collectionOfY.fold(Option.empty[X]) { case (prev, y) => f(prev,y) }
The Scala compiler accepts this without complaint.
This behavior is logical, because fold is defined as
def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
that means the starting parameter is a supertype of A, but None is's a supertype of Option[T]. If you specify the type directly (like in your second example) then the compiler has enough information to figure out the return type of fold.
One possible workaround is to specify the result of interaction of head of your collection with None as a starting point, and fold it with the rest of the collection (adding a check for Nil):
val optX = collectionOfY.match {
case Nil => None
case x:xs => xs.fold(f(None,x)) {case (prev,y) => f(prev,y) }
}