我有这种方法,给定一系列工具,它查询网络服务以获得旧价格和新价格。然后它将使用一个函数来查看价格差异是否显着。它将返回具有显着价格差异的第一台仪器。 现在,我的问题是它总是返回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
}
答案 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