【问题标题】:How to avoid explicit return in scala [duplicate]如何避免在scala中显式返回[重复]
【发布时间】:2017-10-17 09:52:12
【问题描述】:

我有这种方法,给定一系列工具,它会查询 Web 服务以获取旧价格和新价格。然后它将使用一个函数来查看价格差异是否显着。它将返回第一个具有显着价格差异的工具。 现在,我的问题是它总是返回 None ,除非我添加如下明确的 return 语句。

我了解 scala 返回要评估的最后一个表达式。有没有办法重构此代码以避免显式返回。

在什么情况下我们不能避免显式的返回语句?

// without explicit return

def findEquty[A](instruments: Seq[A], change: (Double, Double) => Boolean): Option[A] = {
  for (instrument <- instruments) {
    val oldPrice = getOldPrice(instrument)
    val newPrice = getNewPrice(instrument)
    if (change(oldPrice, newPrice)) Some(instrument)
  }
  None
}

// with explicit return

def findEquty[A](instruments: Seq[A], change: (Double, Double) => Boolean): Option[A] = {
  for (instrument <- instruments) {
    val oldPrice = getOldPrice(instrument)
    val newPrice = getNewPrice(instrument)
    if (change(oldPrice, newPrice)) return Some(instrument)
  }
  None
}

【问题讨论】:

    标签: scala


    【解决方案1】:

    您的实现(没有return 语句)包含两个表达式

    • 第一个是for 表达式,它的类型为Unit:这是没有yield 的for 表达式的返回类型(它被解释为对Seq.foreach 的调用,它返回Unit)李>
    • 第二个就是None

    Scala 中的每个代码块都计算为该块中的 last 表达式;因此,在这种情况下,整个方法体必然求值为None

    添加return 语句会导致方法在到达此表达式之前返回(在某些情况下),因此是“正确”的结果。

    您可以通过使用更简洁的find 来解决这个问题,它完全符合您的需要 - 找到与给定谓词匹配的第一个元素,如果没有找到则 None

    def findEquty[A](instruments: Seq[A], change: (Double, Double) => Boolean): Option[A] = {
      instruments.find(instrument => {
        val oldPrice = getOldPrice(instrument)
        val newPrice = getNewPrice(instrument)
        change(oldPrice, newPrice)
      })
    }
    

    【讨论】:

      【解决方案2】:

      For 循环返回一个Unit,这意味着它们只针对它们的副作用而执行,这就是为什么它不会返回一个值,除非你明确地这样做。

      您应该使用find method,它返回一个选项,其中第一个元素与给定的谓词匹配:

      def findEquty[A](instruments: Seq[A], change: (Double, Double) => Boolean): Option[A] = 
        instruments.find {
          val oldPrice = getOldPrice(instrument)
          val newPrice = getNewPrice(instrument)
          change(oldPrice, newPrice)
      }
      

      【讨论】:

        【解决方案3】:

        一种通用技术是简单地定义对整个集合的操作,并使用惰性来只做获得结果所需的工作量。

        您可以过滤并获取结果的第一个元素。如果您使用 Iterator,或者可能是 Stream,则可以防止做太多工作。

        instruments.iterator.filter { instrument =>
          val oldPrice = getOldPrice(instrument)
          val newPrice = getNewPrice(instrument)
          change(oldPrice, newPrice)
        }.buffered.headOption
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-03
          • 2020-10-25
          • 1970-01-01
          • 1970-01-01
          • 2021-09-03
          • 1970-01-01
          • 1970-01-01
          • 2019-08-15
          相关资源
          最近更新 更多