所以,我正在教自己斯卡拉,我一直玩的東西之一是Stream
類。我試圖用classic Haskell version of Dijkstra's solution的天真翻譯海明號問題:模式匹配和無限流
object LazyHammingBad {
private def merge(a: Stream[BigInt], b: Stream[BigInt]): Stream[BigInt] =
(a, b) match {
case (x #:: xs, y #:: ys) =>
if (x < y) x #:: merge(xs, b)
else if (y < x) y #:: merge(a, ys)
else x #:: merge(xs, ys)
}
val numbers: Stream[BigInt] =
1 #:: merge(numbers map { _ * 2 },
merge(numbers map { _ * 3 }, numbers map { _ * 5 }))
}
採取這種在解釋自旋帶隊迅速失望:
scala> LazyHammingBad.numbers.take(10).toList
java.lang.StackOverflowError
我決定去看看,看看其他人已經解決了使用Haskell的方法在Scala中的問題,從羅塞塔代碼改編this solution:
object LazyHammingGood {
private def merge(a: Stream[BigInt], b: Stream[BigInt]): Stream[BigInt] =
if (a.head < b.head) a.head #:: merge(a.tail, b)
else if (b.head < a.head) b.head #:: merge(a, b.tail)
else a.head #:: merge(a.tail, b.tail)
val numbers: Stream[BigInt] =
1 #:: merge(numbers map {_ * 2},
merge(numbers map {_ * 3}, numbers map {_ * 5}))
}
這一個很好地工作,但我仍然想知道我在LazyHammingBad
出錯了。是否使用#::
解構x #:: xs
由於某種原因強制對xs
進行評估?有沒有辦法使用無限流安全模式匹配,或者如果你不想讓事情炸燬,你只需要使用head
和tail
?
我使用'懶惰VAL溶液:列表[移動] = pathsToGoal匹配{ 情況下(_,moveHistory)#:: _ => moveHistory.reverse 情況_ => List.empty [移動] }'和這不會評估尾巴。是因爲我在使用_嗎?在這種情況下,pathsToGoal是一個無限的Stream – himanshu219