Scala异常作为函数参数设计模式

rir*_*iri 1 types scala exception

我正在编写一个Web应用程序,其中异常用于处理错误情况.通常,我发现自己写这样的帮手:

def someHelper(...) : Boolean {...}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

if (!someHelper(...)){
    throw new SomeException()
}
Run Code Online (Sandbox Code Playgroud)

这些异常表示无效参数之类的事情,并且在处理时它们向用户发送有用的错误消息,例如

try {
     ...
} catch {
    case e: SomeException => "Bad user!"
}
Run Code Online (Sandbox Code Playgroud)

这是一种合理的方法吗?我怎么能将异常传递给辅助函数并将其抛出?我在为这样的函数构造类型时遇到了麻烦.

Rex*_*err 6

Either大部分时间都在使用,而不是例外.我通常使用异常,就像你已经完成的或类似的方式,当控制流程必须走的时候,回到某个遥远的点,否则没有什么明智的事情可做.但是,当异常可以在本地处理时,我会改为

def myMethod(...): Either[String,ValidatedInputForm] = {
  ...
  if (!someHelper(...)) Left("Agree button not checked")
  else Right(whateverForm)
}
Run Code Online (Sandbox Code Playgroud)

然后当我称这种方法时,我可以

myMethod(blah).fold({ err =>
  doSomething(err)
  saneReturnValue
}, { form =>
  foo(form)
  form.usefulField
})
Run Code Online (Sandbox Code Playgroud)

或匹配Left(err)vs Right(form)或其他各种事物.

如果我不想在那里处理错误,而是想要处理返回值,我

myMethod(blah).right.map{ form =>
  foo(form)
  bar(form)
}
Run Code Online (Sandbox Code Playgroud)

我会得到一个Either与错误消息不变的Left,如果它是一个错误信息,或与的结果{ foo(form); bar(form) }Right,如果它是好的.你也可以使用链接你的错误处理flatMap,例如,如果你想对迄今为止正确的值进行额外检查并拒绝其中一些,你可以

myMethod(blah).right.flatMap{ form =>
  if (!checkSomething(form)) Left("Something didn't check out.")
  else Right(form)
}
Run Code Online (Sandbox Code Playgroud)

正是这种处理使得使用Either更方便(并且通常表现更好,如果例外是常见的)比异常,这就是我使用它们的原因.

(事实上,在很多情况下,我不关心为什么出事了,只有它出了问题,在这种情况下,我只使用一个Option.)