【问题标题】:Side effecting function returning disjunction副作用函数返回析取
【发布时间】:2014-07-19 04:21:34
【问题描述】:

我有一个副作用函数,它会改变类变量或在不满足前提条件时抛出异常。添加到类级可变映射后,我想从函数返回一个“布尔值”,表示成功。因此,下面是我正在考虑的内容,但是将布尔值硬编码为“true”感觉不合适,但是当它进入 yield 块时就是这种情况,否则析取的左侧将被异常填充。

def add(e: Entity, value: String): \/[Throwable,Boolean] = {
checkIfFieldIsKey(e.id) match {
  case Some(id) =>
    val validId = validateIdType(..)
    for {
      k <- validId
    } yield { keys += (e -> k); true }
  case None =>
    for {
      r <- validateTypeAndValue(e, value)
    } yield { values += (e -> value); true } 
  }
}

其中 'keys' 和 'values' 是 ConcurrentHashMap 的 'val' 实例。因此,每次“添加”成功时,析取的右侧总是“真”,这意味着布尔值永远不会为假。这看起来合适吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    当副作用方法没有有意义的返回值时,您通常会返回Unit。如果你想捕捉失败的可能性,返回Throwable \/ Unit 是完全合理的,这可能就是我在这里所做的。在任何情况下,我都会说你的直觉是返回 Throwable \/ Boolean 是个坏主意,其中右侧永远不会是任何东西,但 true 是正确的。

    【讨论】:

      【解决方案2】:

      看起来很傻。如果成功,它可以减少到Option[Throwable] -- None,如果不是,则异常。唯一反对它的是None 通常与成功无关。

      作为替代方案,编写您自己的可能 monad,根据情况使用 SuccessFailure(throwable)

      【讨论】:

      • 如果你设计的 API 始终使用Throwable \/ A 来表示失败的可能性,我想说在这里使用Throwable \/ Unit 而不是Option[Throwable] 一点也不傻(即使它们当然是同构的)。
      • @TravisBrown 好点。我没有想到使用 \/ Unit,但如果代码不遵循其他 \/ 用法的路径,我仍然更喜欢自定义 monad。
      猜你喜欢
      • 2011-05-22
      • 1970-01-01
      • 2012-10-03
      • 1970-01-01
      • 1970-01-01
      • 2014-09-08
      • 2011-04-06
      • 2013-11-16
      • 1970-01-01
      相关资源
      最近更新 更多