8

値が Some(...) の場合に副作用を実行し、値が None の場合に別の副作用を実行する最も慣用的な方法は何ですか。私が現在書きがちなことは次のとおりです。

def doSideEffectA(value: Int) {
  // ...
}

def doSideEffectB() {
  // ...
}

def doSideEffect(valueOption: Option[Int]) {
  valueOption map { value =>
    doSideEffectA(value)
  } getOrElse {
    doSideEffectB()
  }
}

私の問題は、valueOption が None の場合に何もする必要がない場合、次のように書くことです。

def doSideEffectNothingIfNone(valueOption: Option[Int]) {
  valueOption foreach { value =>
    doSideEffectA(value)
  }
}

map/getOrElse は通常、副作用のコンテキストでは使用されませんが、foreach は使用されます。ValueOption map { ... } getOrElse { ... } が Unit を返すことにあまり慣れていません。Option[Int] から何も「取得」しないからです。

4

6 に答える 6

13

Kim Stebel の言葉: パターン マッチングはシンプルなソリューションです。

valueOption match {
  case Some(value) => doSideEffectA(value)
  case None => doSideEffectB()
}
于 2012-11-07T10:51:29.653 に答える
9

Scala 2.10には、両方が必要で、同じタイプ(を含む)に解決する場合に適したfoldメソッドが含まれています。OptionNoneSomeUnit

scala> Option("salmon").fold(println("No fish")){f => println(s"I like $f")}
I like salmon
于 2012-11-07T14:11:41.470 に答える
4

Scalazには がありcata、次のように記述できます。

valueOption.cata(doSideEffectA, doSideEffectB)

使用したことはありませんが、かなり便利で読みやすいようです。実装方法は次のとおりです。

  /**
   * Catamorphism over the option. Returns the provided function `some` applied to item contained in the Option
   * if it is defined, otherwise, the provided value `none`.
   */
  def cata[X](some: A => X, none: => X): X = value match {
    case None => none
    case Some(a) => some(a)
  }
于 2012-11-07T11:37:35.717 に答える
4

scalaz を使用すると、foldメソッド onを取得できます。このメソッドは 2 つの関数を取り、 aまたは aOptionがあるかどうかに応じてそのうちの 1 つを実行します。SomeNone

scala> some(3).fold({ x => println(x) }, println("FOO"))
3

scala> none[String].fold({ x => println(x) }, println("FOO"))
FOO
于 2012-11-07T11:13:14.870 に答える
3

私は今でもパターン マッチングが最も読みやすいオプションだと考えていますが、それを自分のやり方でOption行い、暗黙的な変換を使用してラッパーを定義することもできます。

class Else(doit:Boolean) {
  def orDoThis[A](f: =>A) {
    if (doit) f
  }
}

class OptionWrapper[A](o:Option[A]) {
  def each[B](f: A=>B):Else = o match {
    case Some(v) => f(v); new Else(false)
    case None => new Else(true)
  }
}

implicit def wrapOption[A](o:Option[A]):OptionWrapper[A] = new OptionWrapper(o)

次に、たとえば次のように記述できます。

Some(1) each println orDoThis println("nothing there")
于 2012-11-07T11:11:41.863 に答える
1

最も慣用的な方法は実際にはパターンマッチングです。それ以外の場合は、目的のメソッドを提供する暗黙のラッパーを作成できます。

class RichOption[T](o: Option[T]) {
  def ifEmpty(action: => Unit) { if (o.isEmpty) action }
}

object RichOption {
  implicit def enrich(o: Option[T]) = return new RichOption(o)
}

編集:@KimStebelの回答にあるものは、目的の使用法によりよく一致します。

于 2012-11-07T11:02:22.657 に答える