2014-02-21 7 views
11

Имея дело с Option в Scala, что я должен рассмотреть, чтобы решить, следует ли сопоставлять или паттен? Например, если у меня есть Option[MyClass], я могу справиться с этим следующими способами:Scala Опция: map vs Pattern Matching

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

или

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

Когда я выбираю один над другим?

+6

В ситуациях l Подобным образом я предпочитаю совпадение шаблонов, потому что он, как правило, более понятен и генерирует значительно более эффективный код (без 'Function1's '). –

+2

Другая опция: 'myOptionInstance.toList flatMap (...)' – senia

ответ

24

Я второй @rarry: fold является предпочтительным способом борьбы с этим.

Некоторые предпочитают совпадение шаблонов, потому что это «круто» (что бы это ни значило), а иногда и легче читать.

Я стараюсь избегать использования getOrElse, потому что это не заставит вас использовать тот же тип для значения по умолчанию, как тип завернутые в вашем Option:

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

Таким образом, вы можете написать:

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

Здесь v имеет тип Any. Это очень легко увидеть проблему с таким глупым примером, но иногда это не так очевидно и может привести к проблемам.

Хотя fold:

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

Это заставляет вас возвращаться один и тот же тип для обеих ветвей.

scala> Some(42).fold("fortyTwo")(v => v) 
<console>:8: error: type mismatch; 
found : Int 
required: String 
       Some(42).fold("fortyTwo")(v => v) 
+0

По какой-то причине этот вариант мне даже не пригодился, и спасибо за то, что он указал на довольно важное различие в проверках типов между '' 'fold''' &' ' 'getOrElse'''. – Prasanna

+0

Option.fold был добавлен только в Scala 2.10, поэтому многие люди еще не поняли, что он еще есть. Спасибо, что указали это, а также большое предупреждение о типах возврата с getOrElse. – Steve

+0

BTW: 'x => x' уже определен в' Predef' под именем 'identity'. –

1

Я хотел бы пойти на это:

myOptionInstance.fold(Nil: List[String])(...) 
3

соответствие Паттерн:

  • немного более эффективный
  • не анальный о подтипах (в данном случае @rarry пришлось добавить тип подсказку)
  • легче читать
  • одобрил Мартин Одерки: https://stackoverflow.com/a/5332657/578101