2012-10-22 112 views
22

我已經看過許多使用Option(對於簡單值)或者[List [Error],T]來處理錯誤的scala代碼片斷。在scala中使用異常是一個糟糕的做法嗎?

這給地方像這樣的代碼

def createApplicationToken(accessToken: AccessToken): Either[List[Error], ApplicationToken] = { 

// go to social info provider and fetch information 
retrieveProviderInfo(accessToken).fold(
    errors => Left(errors), 
    info => { 
    // try to find user using the info from the provider 
    // if it's not there, create user 
    User.findOrCreateFromProviderInfo(info).fold(
     errors => Left(errors), 
     user => { 
     // try to create a fresh token and save it to the user 
     user.refreshApplicationToken.fold(
      errors => Left(errors), 
      user => Right(user.token) 
     ) 
     } 
    ) 
    } 
) 

其產生的不那麼漂亮的代碼嵌套,迫使你處理故障的每一個步驟,同時也迫使你把所有的函數返回一個要麼[ ...]

所以我想知道,如果

  • 異常的使用Scala中(或一般函數式編程)氣餒

  • 有使用它們(關於不變性或代碼併發)

  • 例外是某種方式與原則或衝突功能的編程

  • 你能想到的一個更好的方式來編寫的任何缺點給出的例子

-

人們可以通過退出本功能避免嵌套離子一旦發現使用return語句的錯誤,但使用返回也不鼓勵在標量...

+3

相關http://stackoverflow.com/questions/12886285/throwing-exceptions-in-scala-what-is-the-official-rule的鏈接 –

+0

感謝... – opensas

+3

平面圖,狗屎 –

回答

21

以下版本使用的事實是Either的正確投影是monad,並且完全等價於您的代碼:

def createApplicationToken(accessToken: AccessToken) = for { 
    info <- retrieveProviderInfo(accessToken).right 
    user <- User.findOrCreateFromProviderInfo(info).right 
    refr <- user.refreshApplicationToken.right 
} yield refr.token 

而且確實呈現出Either優勢掉一個更好的工作。

更一般地說,規則與Java相同:在特殊情況下使用異常。您可能會發現,當您以這種風格工作時,您會改變例外的定義 - 例如,無效的用戶輸入並不是非常特殊,超時的網絡請求並不是特例,等等。

+1

什麼是例外?因爲你提供了一些不是的例子,所以一些特殊的例子會很好。 – pedrofurla

+0

在我的示例中,每一步都可能失敗,從twitter | facebook獲取信息,從twitter信息創建用戶,並創建一個新的令牌並將其保存到用戶......您會認爲它們是特殊的嗎?好的答案,BTW – opensas

+0

@opensas:我並沒有聲稱這裏有一條強硬的路線,但是沒有 - 我會用'Either'(或者Scalaz的'Validation')模擬所有這些失敗。 –

3

作爲OM-NOM-NOM說,我問了一個類似的問題: Throwing exceptions in Scala, what is the "official rule"

但它不是唯一的一個,我問您可能會感興趣,因爲我用了大量的樣板代碼和大量的代碼由於模式匹配等縮進級別...


+0

感謝您的鏈接,我有幾個關於我的更多問題自己:http://stackoverflow.com/questions/12067296/scala-how-to-handle-validations-in-a-functional-way?rq=1,http://stackoverflow.com/questions/12547419/scala-習慣性和功能性的方式,以添加錯誤的錯誤列表?rq = 1 – opensas

+0

很好:) thx將檢查 –

2

答案之間有什麼理想,什麼是實際的變化。理想的情況下,應避免使用例外,實際上,你不能沒有他們的生活

斯卡拉似乎贊成單線和沿着這些線路v2.10有新的莫納d 嘗試

import scala.util.Try 

def percentCompleted(total:Int, done:Int): Int = Try (done * 100/total) getOrElse 100 

percentCompleted(0, 10) // Catches divide-by-zero and returns 100% instead 
+0

+1爲「實際上,你不能沒有他們的生活「。 – opensas

相關問題