Scala:orElse返回值的组件

whe*_*ies 2 scala

我的任务是将审计跟踪附加到一堆计算之后用于重构值(即具有业务领域知识的人来解读出错的地方.)当前代码看起来像这样:

def doSomething = f(x) orElse g(x,y,z) orElse h(p,q,r) orElse default
Run Code Online (Sandbox Code Playgroud)

其中每个都返回一个选项.新代码应返回(选项,审计)元组.

我已经实现了它

def doSomething = f(x) match{
  case None => g_prime(x,y,z)
  case x @ Some(_) => (x, SomeAuditObject)
}
//and taking some liberties with the actual signature...
def g_prime(x,y,z) = g(x,y,z) match{
Run Code Online (Sandbox Code Playgroud)

依此类推,直至"默认".每个函数链接到下一个和下一个,依此类推.我不喜欢它.感觉太必要了.我错过了什么.有一些思考这个问题的方法,我只是没有看到.除了将返回值包装到另一个选项中之外,它是什么?

zig*_*tar 8

您可以使用Monads组成留下审计跟踪的转换.您可以在Monad内部进行审核.有关详细信息,请查看此答案.

我试着为你制作一个例子.我不知道如何处理for-comprehension的最后一步,这是一个map并且不提供审计跟踪.如果您不允许使用,map则不能使用for-comprehensions但必须使用普通调用flatMap.

case class WithAudit[A](value: A, audit: String){
  def flatMap[B](f: A => WithAudit[B]): WithAudit[B] = {
    val bWithAudit = f(value)
    WithAudit(bWithAudit.value, audit + ":" + bWithAudit.audit)
  }
  def map[B](f: A => B): WithAudit[B] = {
    WithAudit(f(value), audit +  ":applied unknown function")
  }
}

def doSomething(in: Option[Int]): WithAudit[Option[Int]] = WithAudit(
    in.map(x => x - 23),
    "substract 23"
)

def somethingElse(in: Int): WithAudit[String] = WithAudit(
  in.toString, 
  "convert to String"
)


val processed = for(
    v <- WithAudit(Some(42), "input Some(42)");
    proc <- doSomething(v);
    intVal <- WithAudit(proc.getOrElse(0), "if invalid, insert default 0");
    asString <- somethingElse(intVal)
) yield asString

println(processed)
Run Code Online (Sandbox Code Playgroud)

输出将是

WithAudit(
  19,
  input Some(42)
    :substract 23
    :if invalid, insert default 0
    :convert to String
    :applied unknown function
)
Run Code Online (Sandbox Code Playgroud)

安全

使用flatMap处理值强制审计的规定.如果你不提供map和限制如何从monad中提取值(如果你这样做可能写一个日志输出),你可以非常安全地假设值的每个转换都会被记录.获得该值后,您将在日志中获得一个条目.