gpt4 book ai didi

scala - 表达这个 Scala 的更惯用(单子(monad)?)方式

转载 作者:行者123 更新时间:2023-12-04 13:17:12 24 4
gpt4 key购买 nike

我有几个遵循这种模式的代码块:

// Dummy function defs.
def result(i : Int, d : Double, b : Boolean) = {
if (b) d else i
}

def fA(s : String) = {7}
def fB(s : String, i : Int) = {1.0}
def fC(s : String, i : Int, d : Double) = {true}

// Actual code.
def test(s : String) : Double = {
try {
val a = fA(s)
try {
val b = fB(s, a)
try {
val c = fC(s, a, b)
result(a, b, c)
} catch {
case _ => result(a, b, false)
}

} catch {
case _ => result(a, 0.0, false)
}
} catch {
case _ => result(0, 0.0, false)
}
}

其中 a、b 和 c 由相应的函数依次计算,然后将值传递给结果函数。如果在任何阶段发生异常,则使用默认值代替其余变量。

有没有更惯用的方式来表达这段代码。它让我想起了 Monads,因为它是一系列链式计算,如果任何计算失败,它们会立即退出。

最佳答案

我通常使用 map + recover 的组合来解决大多数 try-catch 问题。或 flatMap + recoverWith .
一般来说,我更喜欢链接而不是嵌套
给猫剥皮的方法有很多种。这里有3个:
我认为 fA、fB 和 fC 是更复杂逻辑的人为示例。如果他们确实像示例一样点头,那么选项 3 是最简单的。

  • 这是我的首选方式。这里的可读性比嵌套的 flatMaps 好很多
  • def test(s: String): Double =
    (for {
    a <- Try(fA(s)).recover { case _ => 0 }
    b <- Try(fB(s, a)) recover { case _ => 0.0 }
    c <- Try(result(a, b, fC(s, a, b))) recover { case _ => result(a, b, false) }
    } yield c).get
  • 在将 for 表达式去糖化为 flatMaps 之后,这个与前一个相同,尽管它看起来比链式更嵌套。
  • def test(s: String): Double =
    Try(fA(s)).recover { case _ => 0 }
    .flatMap(a =>
    (Try(fB(s, a)) recover { case _ => 0.0 })
    .flatMap(b =>
    Try(result(a, b, fC(s, a, b)))
    recover { case _ => result(a, b, false) }
    )
    ).get

    可读性不是很好,因为 flatMap 中的 args 是作为匿名函数编写的。如果我在不使用匿名函数的情况下重写它,那么我有:
    def test(s: String): Double = {
    val evalA = Try(fA(s)).recover { case _ => 0 }
    val evalB: Int => Try[Double] = a =>
    Try(fB(s, a)) recover { case _ => 0.0 }
    val evalC: (Int, Double) => Try[Double] = (a,b) =>
    Try(result(a, b, fC(s, a, b))) recover { case _ => result(a, b, false) }

    evalA.flatMap(a =>
    evalB(a).flatMap(b =>
    evalC(a, b))
    ).get
    }
  • 您可以使用 getOrElse()如果不需要其他副作用。
  • def test(s: String) = {
    val evalA = Try(fA(s)).getOrElse(0)
    val evalB = Try(fB(s, evalA)).getOrElse(0.0)
    val evalC = Try(fC(s, evalA, evalB)).getOrElse(false)

    result(evalA, evalB, evalC)
    }

    关于scala - 表达这个 Scala 的更惯用(单子(monad)?)方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11219986/

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