当前位置: 首页 > 知识库问答 >
问题:

scala中使用异常是一种不好的做法吗?

长孙修远
2023-03-14

我见过很多次scala代码使用Option(对于简单值)或[List[Error],T]来处理错误。

这为这样的代码提供了位置

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语句一发现错误就退出函数可以避免嵌套,但是在scala中也不鼓励使用return...

  • 共有3个答案

    汪典
    2023-03-14

    答案在理想和实际之间有所不同。理想情况下,避免使用异常。实际上,你不能没有他们。

    Scala似乎更喜欢一行程序,v2.10有了新的monad尝试:

    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
    
    詹钊
    2023-03-14

    正如om-nom-nom所说,我问了一个类似的问题:在Scala中抛出异常,什么是“官方规则”

    但这并不是我问的唯一一个你可能感兴趣的问题,因为我曾经用很多样板代码和很多缩进级别进行编码,因为模式匹配等等。。。

    >

  • 您可以检查以下链接:使用以下任一选项处理故障:-

    与错误处理也有点相关,您可能会感兴趣:Scala中的方法参数验证,用于理解和monads,Travis Brown在其中给出了更详细的答案,关于使用应用函子和Scalaz进行快速失败(第一个错误阻止了进程)或收集一组操作的所有错误同样的问题:当返回类型为Option[Error]时处理快速失败

    您可以检查这个使用按名称参数的链接也执行了操作序列。它可能是在a中使用正确投影的一个很好的替代方案,但您无法创建中间结果:(在Scala中使用按名称参数序列进行验证?我不知道它是否可以与您的代码示例一起使用,但我不认为在这种情况下是这样的(假设您的刷新没有副作用并返回新创建的不可变用户实例,而不是修改令牌变量)

  • 宓博实
    2023-03-14

    以下版本利用了< code >要么的右投影是一个单子的事实,并且与您的代码完全等效:

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

    并且在展示<code>或<code>的优点方面做得更好。

    更一般地说,规则与Java中的相同:在异常情况下使用异常。当您以这种方式工作时,您可能会发现您对异常的定义有所改变——例如,无效的用户输入不是真正的异常,超时的网络请求不是真正的异常,等等。

    现在可以省略< code >。右,所以下面的代码从Scala 2.12开始就是等价的:

    def createApplicationToken(accessToken: AccessToken) = for {
       info <- retrieveProviderInfo(accessToken)
       user <- User.findOrCreateFromProviderInfo(info)
       refr <- user.refreshApplicationToken
    } yield refr.token
    
     类似资料:
    • 问题内容: 我正在查看一位同事的代码,但遇到一段类似于以下代码的代码: 我相信没有必要,但我很难证明这一点。如果它更具体(,等等)可能很有意义,但是因为我认为这是不必要的。有人可以给我一些原因,这可能导致什么问题,以及为什么这是不好的做法?还是这个代码可以吗? 问题答案: 该声明是方法合同的一部分。定义合同时,您应始终尽可能 精确 。因此,说是个坏主意。 出于同样的原因,这是不好的做法,因为不好的

    • 我有一个枚举: 在枚举成员之间使用方法检查“层次结构”有什么问题吗?我的意思是-当有人将来可能会意外更改顺序时,使用它排除冗长是否有任何缺点。 还是这样做更好:

    • 我有一个IntentService,它使用TimerTask每隔45秒在OnHandleContent中调用webservice。 我的问题是:我正在调用应用程序启动IntentService,而在OnHandleIntent中,由于TimerTask,任务不断重复。。这样做是一种好做法还是有任何缺点?我应该在我的活动中使用报警管理器每次调用intent service,还是继续使用timer任务

    • 问题内容: 我已经多次听到在HTML 中使用JavaScript事件(例如)是不正确的做法,因为它不利于语义。我想知道不利之处以及如何解决以下代码? 问题答案: 您可能正在谈论简洁的Javascript,看起来像这样: 中央javascript文件中的逻辑如下所示: 优点是 行为(JavaScript)与表示(HTML)分开 没有语言的混合 您正在使用像jQuery这样的javascript框架,

    • 问题内容: 如果使用Sun的专有Java类,则编译器将显示警告。我认为使用这些类通常不是一个好主意。我在某处阅读过。但是,除了警告之外,还有其他根本原因不建议您使用它们? 问题答案: 因为它们是内部API,所以它们可能会以未记录或不受支持的方式进行更改,并且已绑定到特定的JRE / JDK(在您的情况下为Sun),从而限制了程序的可移植性。 尽量避免使用此类API,请始终偏爱公开记录和指定的类。

    • 问题内容: 我已经多次听到在HTML 中使用JavaScript事件(例如)是不正确的做法,因为它不利于语义。我想知道不利之处以及如何解决以下代码? 问题答案: 您可能正在谈论简洁的Javascript,看起来像这样: 中央javascript文件中的逻辑如下所示: 优点是 行为(JavaScript)与表示(HTML)分开 没有语言的混合 您正在使用像jQuery这样的javascript框架,