2012-10-22 46 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

相关问题