तो, मैं खुद को स्कैला सिखाने के लिए काम कर रहा हूं, और जिन चीजों के साथ मैं खेल रहा हूं उनमें से एक Stream
वर्ग है।पैटर्न मिलान और अनंत स्ट्रीम
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
मैं यह देखने के लिए देखने का फैसला किया मैं आलोचनात्मक संख्या समस्या का classic Haskell version of Dijkstra's solution की एक सीधी सादी अनुवाद का उपयोग करने की कोशिश की अन्य लोगों हास्केल दृष्टिकोण का उपयोग कर स्काला में समस्या हल हो गया था, और Rosetta कोड से 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
का उपयोग करना है यदि आप चीजों को उड़ाना नहीं चाहते हैं?
मैं 'उपयोग कर रहा हूँ आलसी वैल समाधान: सूची [ले जाएँ] = pathsToGoal मैच { मामले (_, moveHistory) # :: _ => moveHistory.reverse मामले _ => List.empty [ले जाएँ] }' और यह पूंछ का मूल्यांकन नहीं करता है। क्या ऐसा इसलिए है क्योंकि मैं _ का उपयोग कर रहा हूं? यहां इस मामले में पथ टोज़ल एक अनंत स्ट्रीम है – himanshu219