如何避免scala中的显式返回

时间:2017-05-17 19:26:43

标签: scala

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

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

在什么情况下我们无法避免使用明确的return语句?

// 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
}

3 个答案:

答案 0 :(得分:3)

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

  • 第一个是for表达式,其类型为Unit:表示没有yield的for表达式的返回类型(它被解释为致电Seq.foreach并返回Unit
  • 第二个只是None

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

添加return语句会导致方法在到达此表达式之前返回(在某些情况下),因此&#34;更正&#34;结果

你可以使用更简洁的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)
  })
}

答案 1 :(得分: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)
}

答案 2 :(得分:1)

一般技术是简单地定义您对整个集合的操作,并使用懒惰来完成获得结果所需的大量工作。

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

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