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)
Related
I'm trying to understand particular use of underscore in Scala. And following piece of code I cannot understand
class Test[T, S] {
def f1(f: T => S): Unit = f2(_ map f)
def f2(f: Try[T] => Try[S]): Unit = {}
}
How is the _ treated in this case? How is the T=>S becomes Try[T]=>Try[S]?
It seems you are reading it wrongly. Look at the type of f2(Try[T] => Try[S]):Unit.
Then looking into f1 we have f: T => S.
The _ in value position desugars to f2(g => g map f).
Let's see what we know so far:
f2(Try[T] => Try[S]):Unit
f: T => S
f2(g => g map f)
Give 1. and 3. we can infer that the type of g has to be Try[T]. map over Try[T] takes T => Something, in case f which is T => S, in which case Something is S.
It may seem a bit hard to read now, but once you learn to distinguish between type and value position readin this type of code becomes trivial.
Another thing to notice def f2(f: Try[T] => Try[S]): Unit = {} is quite uninteresting and may be a bit detrimental in solving your particular question.
I'd try to solve this like that: first forget the class you created. Now implement this (replace the ??? with a useful implementation):
object P1 {
def fmap[A, B](A => B): Try[A] => Try[B] = ???
}
For bonus points use the _ as the first char in your implementation.
Given a List[Foo], I apply a function f.
def f(foo: Foo): Option[Boolean]
I wrote this function body to see if any Foo evaluates to Some(true).
val optFalse: Option[Boolean] = Some(false)
val foos: List[Foo] = ...
foos.foldLeft(optFalse){
(acc: Option[Boolean], elem: Foo) => {
val isMatch: Option[Boolean] = f(elem)
optionOr(acc)(match) // takes 2 Option[Boolean] and `or`'s them.
}
}
However, the f method could be an expensive operation. I'd prefer to "short-circuit":
foos.foldLeft(optFalse){
(acc: Option[Boolean], elem: Foo) => {
if( isTrueOption(acc) ) acc
else {
val isMatch: Option[Boolean] = f(elem)
isMatch
}
}
}
Is there a non-strict way to fold over the entire List[Foo], but stop evaluation once one of the Option[Boolean] equals Some(true) without my changed code? Perhaps using the => operator?
If so, I'm thinking that there's a "space" cost, but I'm not entirely understanding it. Please include that topic as well in your answer (if there is one).
It's unclear what role Option is playing in your code. If you just want to find out whether there's any value for which f returns Some(true), that sounds like a good use case for exists, which is short-circuit:
foos.exists{x => Some(true) == f(x)}
If you need to know whether any f returns None, then clearly you'll need to evaluate the whole list (at least in the case where they're actually all Some, which is presumably the interesting case).
If it has to be a fold, then fold is strict (it would be possible to write a non-strict fold, but that wouldn't be the standard fold). You could use #Peter's solution in a more structured way by using breakable.
Is this what you are looking for?
foos.reduce {
case (Some(true), _)=> Some(true)
case (_, x) => f(x)
}
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) }
}
Extractors can be an incredibly useful way to reduce duplication in pattern matching code, however, often the logic contained in them is just a simple one-line pattern that needed to be DRYed out from the code, for example, I had a recurring pattern of Person(_, _, Some(Position(_, Some(company)))), so I came up with this extractor:
object EmployedAt {
def unapply(x: Person): Option[Company] = x match {
case Person(_, _, Some(Position(_, company))) => company
case _ => None
}
}
which I could then use like this:
val companies = people.collect { case EmployedAt(c) => c }.distinct
def numEmployees(company: Company) =
people.collect { case EmployedAt(`company`) => }.size
people.collect { case p # EmployedAt(c) if numEmployees(c) >= 2 => (p, c) }
etc — all very nice, concise and readable... except for the extractor implementation itself. The problem I'm seeing is that, ultimately, the extractor just boils down to the 1st case statement, and the rest is just boilerplate. Instead, I think the following would be much more desirable for defining simple (possibly one-off or twice-off) extractors:
def EmployedAt(x: Person): Company = {
case Person(_, _, Some(Position(_, Some(company)))) => company
}
...which is 2 full lines instead of 4.
— how would I go about DRYing up the boilerplate to come to something as concise as the above?
I immediately started playing around with potential solutions and I think I've come to quite a nice one, which, in addition to allowing the definition of extractors without the object+unapply+Option[T]+case _ => None boilerplate, also makes it immediately obvious to the reader that a given function is an extractor, as well as statically marking it as an Extractor:
trait Extractor[T, U] { def unapply(x: T): Option[U] }
object Extractor {
def apply[T, U](f: PartialFunction[T, U]) = new Extractor[T, U] {
def unapply(x: T) = f.lift(x)
}
}
val EmployedAt = Extractor[Person, Company] {
case Person(_, _, Some(Position(_, Some(company)))) => company
}
I did not have the intention to immediately answer my own question but this is how it turned out. I'm still open to criticism and other suggestions from potentially more competent Scala community members! :)
What I'm looking for is this function:
def maybe[A, B](a: Option[A])(f: A => B)(g: () => B): B = a match
{
case Some(x) => f(x)
case None => g()
}
It's in the Haskell prelude so I'm thinking it might be in the Scala standard library somewhere and I've just missed it. I hate having to recode it in projects so I'm wondering if anyone knows where it is, or if it's definitively not there. Or is there a better method for getting this functionality?
Other answers have given the map + getOrElse composition. Just for the record, you can "add" a maybe function to Option in the following way:
implicit def optionWithMaybe[A](opt: Option[A]) = new {
def maybe[B](f: A=>B)(g: =>B) = opt map f getOrElse g
}
It's worth noting that the syntax of higher-order functions in Scala is usually nicer when the function parameter comes last. Thus, a better way to organize maybe would be as follows:
def maybe[B](g: =>B)(f: A=>B) = opt map f getOrElse g
This could be used as follows:
val opt: Option[String] = ...
opt.maybe("") { _.toUpperCase }
You could do
val opt:Option[A] = // ...
val result:B = opt.map(f).getOrElse(g());
getOrElse takes a by-name parameter, so g will only be evaluated if opt is None.
The method would be called fold if it were to adhere to convention (see Either.fold which is the catamorphism for Either).
You can use scalaz, and then you have an implicit conversion to OptionW which has fold, or you can use Scala 2.10.0-M3 and use the builtin Option.fold
scala> Some(1).fold(5)(_ * 2)
res5: Int = 2
scala> (None: Option[Int]).fold(5)(_ * 2)
res7: Int = 5
Note that the scalaz fold signature is fold[X](some: A => X, none: => X), while the builtin seems to be fold[X](none: => X)(some: A => X).
I don't think there is. The best I could come up with is to chain Option's "map" and "getOrElse" together:
scala> var a: Option[String] = Some("hello")
a: Option[String] = Some(hello)
scala> a.map(_.toUpperCase).getOrElse("empty")
res19: java.lang.String = HELLO
scala> a = None
a: Option[String] = None
scala> a.map(_.toUpperCase).getOrElse("empty")
res21: java.lang.String = empty
I don't think there is. However, I'd write it to take g by name:
def maybe[A, B](a: Option[A])(f: A => B)(g: => B): B = a.map(f).getOrElse(g)
This is more Scala- and Haskell-like and a bit nicer to use.
I'd use Option.fold for this:
opt.fold(g)(f)
Note that g is by-name, just like getOrElse. Also note the inversion of the cases.