你不能實現這個摺疊。摺疊循環遍及集合的每個元素,而tryOld
有時會提前終止。你可以利用Stream
的懶惰和在collectFirst
和Try
方面實現:
import scala.util.Try
def tryOld(string: String, original: Exception, zomOldList: List[String => Double]): Double =
zomOldList.toStream.map(x => Try(x(string))) collectFirst {
case Success(x) => x
} getOrElse (throw original)
但你原來的遞歸實現更清晰和更高性能。
編輯:
如果斯卡拉曾與同懶惰屬性Haskell的foldr
一個foldRight
,那麼這可能是在來定義的foldRight
:
implicit class GiveStreamAWorkingFoldRight[A](val s: Stream[A]) extends AnyVal {
def lazyFoldRight[B](z: => B)(f: (A,() => B) => B): B =
if (s.isEmpty) z else f(s.head,() => s.tail.lazyFoldRight(z)(f))
}
def tryOld(string: String, original: Exception, zomOldList: List[String => Double]): Double =
zomOldList.toStream.lazyFoldRight(throw original) { (a, b:() => Double) =>
try {
a(string)
} catch {
case ex: Exception => b()
}
}
然而,Scala的缺乏真正的尾巴優化意味着每次調用b
都會引入一個新的堆棧幀,可能導致堆棧溢出。
遞歸有什麼問題呢?遞歸非常適合解決遞歸問題。 –
遞歸可以工作,只需從另一個角度查看解決方案。我回答了一個帖子,下面有一個函數拋出異常可能是一個不好的做法。使用Try [Double]使用fold應該可以工作。 – ferk86