私はScalaを教えるために働いています。私が使ってきたことの1つは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のアプローチを使用してスカラ座での問題を解決し、そしてロゼッタコードから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}))
}
この1うまくいきましたが、私はまだLazyHammingBad
に間違っていたのでしょうか?何らかの理由でを使用してx #:: xs
を強制的に使用してxs
の評価を行っていますか?無限のストリームでパターンマッチングを安全に使用する方法はありますか?物事を爆破したくない場合は、head
とtail
を使用するだけですか?
Iは '遅延ヴァル溶液使用しています:' [移動] = pathsToGoal一致{ 場合(_、moveHistory)#:: _ => moveHistory.reverse 場合_ => List.empty [移動] }リストとこれはテールを評価しません。私は_を使っているからですか?ここでは、pathsToGoalは無限のストリームです – himanshu219