2014-10-31 25 views
0

這是我以前的question的後續處理。假設我有以下功能:使用Scala處理任何錯誤

type Result[A] = Either[String, A] // left is an error message 

def f1(a: A): Result[B] = ... 
def f2(b: B): Result[C] = ... 
def f3(c: C): Result[D] = ... 

def f(a: A): Result[D] = for { 
    b <- f1(a).right 
    c <- f2(b).right 
    d <- f3(c).right 
} yield d; 

假如我也想更多信息添加到錯誤消息。

def f(a: A): Result[D] = for { 
    b <- { val r = f1(a); r.left.map(_ + s"failed with $a"); r.right } 
    c <- { val r = f2(b); r.left.map(_ + s"failed with $a and $b"); r.right } 
    d <- { val r = f3(c); r.left.map(_ + s"failed with $a, $b, and $c"); r.right } 
} yield d; 

該代碼看起來很醜。你會如何改進代碼?

+5

爲什麼不'F1(A).left.map(_ + s 「用$失敗」)right'? – 2014-10-31 17:03:41

+0

謝謝。你是對的。 – Michael 2014-10-31 17:08:13

+0

是否有任何理由不將函數f1,f2,f3中的參數附加到錯誤消息中? – lea 2014-10-31 20:23:25

回答

1

該代碼看起來很醜,因爲你在重複自己。

改寫一個方法!或者一個擴展方法。其中的一個,也許是:

implicit class StringEitherCanAdd[A](private val e: Either[String, A]) extends AnyVal { 
    def info(s: String): Either[String, A] = e.left.map(_ + s) 
    def failed(a: Any*): Either[String, A] = 
    if (a.length == 0) e 
    else if (a.length == 1) e.left.map(_ + s"failed with ${a(0)}") 
    else if (a.length == 2) e.left.map(_ + s"failed with ${a(0)} and ${a(1)}") 
    else e.left.map(_ + s"failed with ${a.init.mkString(", ")}, and ${a.last}") 
} 

現在你只

f1(a).info(s"failed with $a").right 
f2(b).failed(a,b).right