gpt4 book ai didi

scala - 处理多个选项并记录未找到的情况

转载 作者:行者123 更新时间:2023-12-04 01:51:08 27 4
gpt4 key购买 nike

当我有多个选项并且只有当所有选项都有值时我才需要处理某些内容时,for comprehension 提供了一种编写代码的好方法

for {
a <- aOption
b <- bOption
c <- cOption
d <- dOption
} yield {...process...}

虽然这是一种非常有用且优雅简洁的代码编写方式,但我错过了如果说“cOption”的值为 none 时的日志记录功能,因此处理没有发生。

上面的代码中是否有一个很好的方法,能够在不求助于嵌套 ifs 的情况下记录缺失值。

最佳答案

您可以编写一个简单的函数,但它只会记录 Option 中第一次缺少值的情况。 (由于 for-comprehension 的顺序性质):

def logEmpty[T](opt: Option[T], msgIfNone: String) = {
if (opt.isEmpty) println(msgIfNone) //or something like logger.warn
opt
}

用法:

for {
a <- logEmpty(aOption, "Sorry no a")
b <- logEmpty(bOption, "Sorry no b")
c <- logEmpty(cOption, "Sorry no c")
d <- logEmpty(dOption, "Sorry no d")
} yield {...process...}

类 DSL:

implicit class LogEmpty[T](opt: Option[T]) {
def reportEmpty(msg: String) = {
if (opt.isEmpty) println(msg)
opt
}
}

用法:

for {
a <- aOption reportEmpty "Sorry no a"
b <- bOption reportEmpty "Sorry no b"
c <- cOption reportEmpty "Sorry no c"
d <- dOption reportEmpty "Sorry no d"
} yield {a + b + c + d}

例子:

scala> for {
| a <- Some("a") reportEmpty "Sorry no a"
| b <- None reportEmpty "Sorry no b"
| c <- Some("c") reportEmpty "Sorry no c"
| d <- None reportEmpty "Sorry no d"
| } yield {a + b + c + d}
Sorry no b
res19: Option[String] = None

如果您需要报告更多 - 最好的方法是使用 Validation来自 scalaz 或 Validated来自 cats ,所以你关于缺席的消息将被表示为 Validated 的无效状态.您可以随时转换 ValidatedOption .

解决方法:

import cats._
import cats.data.Validated
import cats.data.Validated._
import cats.implicits._

implicit class RichOption[T](opt: Option[T]) {
def validOr(msg: String) =
opt.map(Valid(_)).getOrElse(Invalid(msg)).toValidatedNel

}

例子:

val aOption = Some("a")
val bOption: Option[String] = None
val cOption: Option[String] = None

scala> aOption.validOr("no a") |+| bOption.validOr("no b") |+| cOption.validOr("no c")
res12: cats.data.Validated[cats.data.NonEmptyList[String],String] = Invalid(NonEmptyList(no b, no c))

scala> aOption.validateOr("no a") |+| aOption.validateOr("no a again")
res13: cats.data.Validated[cats.data.NonEmptyList[String],String] = Valid(aa)

我用了|+|运算符假设串联,但您也可以使用应用程序构建器(或仅 zip ),以便对选项的内容实现其他操作:

scala> (aOption.validOr("no a") |@| aOption.validOr("no a again")) map {_ + "!" + _}
res18: cats.data.Validated[cats.data.NonEmptyList[String],String] = Valid(a!a)

scala> (aOption.validOr("no a") |@| bOption.validOr("no b") |@| cOption.validOr("no c")) map {_ + _ + _}
res27: cats.data.Validated[cats.data.NonEmptyList[String],String] = Invalid(NonEmptyList(no b, no c))

两只猫的XorValidated是 scala 的 Either 的变体, 但 Xor 之间的区别和 Validated是那个Xor (和 Either )与 Validated 相比,更多地被用于“快速失败”的单子(monad)方法(对于理解也称为做符号)这是使用应用方法(允许 |@|zip )。 flatMap被视为顺序运算符,|@|/zip被视为并行运算符(不要与执行模型混淆 - 它与运算符的性质正交)。您可以在猫文档中阅读更多内容:Validated , Xor .

关于scala - 处理多个选项并记录未找到的情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40066242/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com