Scala:orElse返回值的组件

时间:2011-09-16 18:13:29

标签: scala

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

def doSomething = f(x) orElse g(x,y,z) orElse h(p,q,r) orElse default

其中每个都返回一个选项。新代码应返回(Option,Audit。)元组

我已将其实现为

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{

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

2 个答案:

答案 0 :(得分:8)

您可以使用Monads撰写留下审计跟踪的转换。您可以在Monad内部进行审核。有关详细信息,请查看this answer

我试着为你制作一个例子。我不知道如何处理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)

输出

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

安全

使用flatMap处理该值会强制执行审核。如果您没有提供map并限制如何从monad中提取值(如果这样做,可能会写一个日志输出),您可以非常安全地假设将记录值的每个转换。获得该值后,您将在日志中获得一个条目。

答案 1 :(得分:2)

您是否只审核fg等的成功执行?

如果是这样,我会让doSomething返回Option[(YourData, Audit)](而不是(Option[YourData], Audit))。然后你可以组成这样的函数:

def doSomething = (f(x) andThen (t => (t, audit_f(x)))) orElse
                  (g(x, y, z) andThen (t => (t, audit_g(x, y, z)))) orElse
                  ... etc.