Pracuję więc, aby nauczyć się Scala, a jedną z rzeczy, z którymi się bawiłem jest klasa Stream
. Próbowałem użyć tłumaczenia naiwne z classic Haskell version of Dijkstra's solution problemu numer Hamminga:Dopasowywanie wzorców i nieskończone strumienie
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 }))
}
Biorąc to dla korkociągu w tłumacza doprowadziły szybko do rozczarowania:
scala> LazyHammingBad.numbers.take(10).toList
java.lang.StackOverflowError
postanowiłem sprawdź, czy inni ludzie nie rozwiązało problemu w Scala stosując podejście Haskell i dostosowane this solution z kodeksem Rosetta:
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}))
}
ten jeden działało ładnie, ale wciąż zastanawiam się, jak poszło nie tak w LazyHammingBad
. Czy użycie #::
do zniszczenia x #:: xs
wymusza na sobie ocenę xs
z jakiegoś powodu? Czy istnieje sposób na bezpieczne dopasowanie wzorca z nieskończonymi strumieniami, czy po prostu trzeba użyć head
i tail
, jeśli nie chcesz, aby coś się wysadziło?
używam 'lazy rozwiązanie Val: Lista [Move] = pathsToGoal mecz { przypadek (_, moveHistory) # :: _ => moveHistory.reverse sprawa _ => List.empty [Move] }' a to nie ocenia ogona. Czy to dlatego, że używam _? Tutaj w tym przypadku pathsToGoal jest nieskończonym strumieniem – himanshu219