Опция Scala - избавление от if (opt.isDefined) {} - PullRequest
27 голосов
/ 08 декабря 2011

Мой код становится замусоренным следующим шаблоном кода:

val opt = somethingReturningAnOpt
if (opt.isDefinedAt) {
    val actualThingIWant = opt.get
}

Есть ли способ упростить это?(это кажется излишне сложным и пахнет кодом).В идеале это было бы что-то вроде:

if (Some(actualThingIWant) = somethingReturningAnOpt) {
   doSomethingWith(actualThingIWant)
}

Возможно ли что-нибудь подобное?

Ответы [ 4 ]

33 голосов
/ 08 декабря 2011

Может быть что-то вроде этого:

somethingReturningAnOpt match {
  case Some(actualThingIWant) => doSomethingWith(actualThingIWant)
  case None =>
}

или, как подсказывает pst:

somethingReturningAnOpt.foreach { actualThingIWant =>
  doSomethingWith(actualThingIWant)
}

// or...

for (actualThingIWant <- somethingReturningAnOpt) {
  doSomethingWith(actualThingIWant)
}
30 голосов
/ 08 декабря 2011

каноническое руководство к Варианту споров принадлежит Тони Моррису.

10 голосов
/ 08 декабря 2011

Или:

somethingReturningAnOpt.map(doSomethingWith(_))

Как в:

val str = Some("foo")
str.map(_.toUpperCase)

... и использовать flatMap, когда результатом doSomethingWith является сама опция.

val index = Option(Map("foo" -> "bar"))
index.flatMap(_.get("whatever"))        // Returns None :-)
index.map(_.get("whatever"))            // Returns Some(None) :-(
5 голосов
/ 08 декабря 2011

Следующий код не может сделать что-то полезное, так как после if, actualThingIWant не всегда определяется и, следовательно, этот код не будет компилироваться, если вы попытаетесь использовать actualThingIWant позже.

val opt = somethingReturningAnOpt
if (opt.isDefinedAt) {
    val actualThingIWant = opt.get
}

Итак, вы должны указать значение по умолчанию.Это может быть достигнуто с помощью getOrElse:

val thingIWant = opt.getOrElse(myDefaultValue)

Или если вы не хотите иметь actualThingIWant после тела if, что означает, что вы хотите вызвать только некоторые побочные эффектыесли опция определена, вы можете написать:

opt.foreach{ thingIWant => 
  println(thingIWant)
}

или чуть короче

opt.foreach(println)
...