15

While dealing with Option in Scala what are the things I should be considering to decide whether to map or patten match? For example, if I have Option[MyClass], I can deal with it the following ways:

def getList(myOptionInstance: Option[MyClass]): List[String] =
  myOptionInstance map (...) getOrElse(List.empty[String])

or

def getList(myOptionInstance: Option[MyClass]): List[String] = myOptionInstance match {
  case Some(mySomeInstance) => .....
  case None => List.empty[String]
}

When will I choose one over the other?

Prasanna
  • 3,703
  • 9
  • 46
  • 74
  • 7
    In situations like this I prefer the pattern match because it is generally more readily comprehensible and generates significantly more efficient code (no `Function1`s). – Randall Schulz Feb 21 '14 at 04:40
  • 2
    Other option: `myOptionInstance.toList flatMap (...)` – senia Feb 21 '14 at 07:12

3 Answers3

29

I second @rarry: fold is the preferred way to deal with this.

Some prefer pattern matching because it's "cool" (whatever it means) and sometimes easier to read.

I try to avoid using getOrElse because it does not force you to use the same type for the default value as the type wrapped in your Option:

def getOrElse[B >: A](default: ⇒ B): B

So you can write:

val v = Some(42).getOrElse("FortyTwo")

Here v has type Any. It's very easy to see the problem with such a stupid example but sometimes it's not as obvious and can lead to issues.

While fold:

def fold[B](ifEmpty: ⇒ B)(f: (A) ⇒ B): B

It forces you to return the same type for both branches.

scala> Some(42).fold("fortyTwo")(v => v)
<console>:8: error: type mismatch;
 found   : Int
 required: String
              Some(42).fold("fortyTwo")(v => v)
vptheron
  • 7,426
  • 25
  • 34
  • For some reason this option didn't even occur to me and thanks for pointing out pretty important difference regarding type checks between ```fold``` & ```getOrElse```. – Prasanna Feb 21 '14 at 15:14
  • Option.fold was only added in Scala 2.10, so many people haven't realized it's there yet. Thanks for pointing it out, as well as the great warning about the return types with getOrElse. – Steve May 31 '14 at 12:39
  • BTW: `x => x` is already defined in `Predef` under the name `identity`. – Jörg W Mittag Jun 18 '14 at 17:34
  • 6
    I have to disagree here—in cases where you have a legit default value, `getOrElse(v)` is better than `fold(v)(identity)`. The clarity about intention trumps the possibility of an unwanted lubbing to `Any` (which should quickly and safely crash in any reasonable context, anyway). – Travis Brown Jun 18 '14 at 17:44
  • The question was about mapping on Some or getting a default value for None. Identity was just for my example. – vptheron Jun 18 '14 at 20:49
  • @vptheron: Agreed! If you're mapping (and on 2.10+) you should definitely be using `fold`. But a categorical "don't use `getOrElse`" (which is how I got here) isn't good advice. – Travis Brown Jun 19 '14 at 00:33
  • getOrElse can also be used to throw Exception, when some expected values not provided, when dealing with JSON REST API. – S.Karthik Sep 08 '14 at 07:35
8

Pattern matching is :

Community
  • 1
  • 1
mauhiz
  • 506
  • 5
  • 14
1

I would go for this:

myOptionInstance.fold(Nil: List[String])(...)
rarry
  • 3,553
  • 20
  • 23