Scala Language
स्ट्रीम
खोज…
टिप्पणियों
धाराओं का आलसी रूप से मूल्यांकन किया जाता है, जिसका अर्थ है कि उनका उपयोग जनरेटर को लागू करने के लिए किया जा सकता है, जो तथ्य के बजाय निर्दिष्ट प्रकार की ऑन-डिमांड का एक नया आइटम प्रदान या 'उत्पन्न' करेगा। यह सुनिश्चित करता है कि केवल आवश्यक गणना की जाती है।
एक यादृच्छिक अनुक्रम उत्पन्न करने के लिए एक स्ट्रीम का उपयोग करना
genRandom
यादृच्छिक संख्याओं की एक धारा बनाता है जिसमें हर बार इसे समाप्त करने के चार अवसरों में से एक होता है।
def genRandom: Stream[String] = {
val random = scala.util.Random.nextFloat()
println(s"Random value is: $random")
if (random < 0.25) {
Stream.empty[String]
} else {
("%.3f : A random number" format random) #:: genRandom
}
}
lazy val randos = genRandom // getRandom is lazily evaluated as randos is iterated through
for {
x <- randos
} println(x) // The number of times this prints is effectively randomized.
#::
निर्माण पर ध्यान दें, जो आलसी पुनरावृत्ति करता है : क्योंकि यह एक धारा में वर्तमान यादृच्छिक संख्या को पूर्वनिर्मित कर रहा है, यह तब तक धारा के शेष का मूल्यांकन नहीं करता है जब तक कि इसके माध्यम से पुनरावृत्ति न हो।
रिकर्सन के माध्यम से अनंत धाराएँ
धाराओं का निर्माण किया जा सकता है जो स्वयं को संदर्भित करते हैं और इस प्रकार असीम रूप से पुनरावर्ती बन जाते हैं।
// factorial
val fact: Stream[BigInt] = 1 #:: fact.zipWithIndex.map{case (p,x)=>p*(x+1)}
fact.take(10) // (1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880)
fact(24) // 620448401733239439360000
// the Fibonacci series
val fib: Stream[BigInt] = 0 #:: fib.scan(1:BigInt)(_+_)
fib.take(10) // (0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
fib(124) // 36726740705505779255899443
// random Ints between 10 and 99 (inclusive)
def rndInt: Stream[Int] = (util.Random.nextInt(90)+10) #:: rndInt
rndInt.take(10) // (20, 95, 14, 44, 42, 78, 85, 24, 99, 85)
इस संदर्भ में वर, वल और डिफ के बीच अंतर दिलचस्प है। एक के रूप में def
प्रत्येक तत्व हर बार यह संदर्भित है पुनर्गणना की जाती है। एक val
रूप में प्रत्येक तत्व की गणना की जाती है और इसका पुन: उपयोग किया जाता है। यह प्रत्येक गणना के साथ एक साइड-इफ़ेक्ट बनाकर प्रदर्शित किया जा सकता है।
// def with extra output per calculation
def fact: Stream[Int] = 1 #:: fact.zipWithIndex.map{case (p,x)=>print("!");p*(x+1)}
fact(5) // !!!!!!!!!!!!!!! 120
fact(4) // !!!!!!!!!! 24
fact(7) // !!!!!!!!!!!!!!!!!!!!!!!!!!!! 5040
// now as val
val fact: Stream[Int] = 1 #:: fact.zipWithIndex.map{case (p,x)=>print("!");p*(x+1)}
fact(5) // !!!!! 120
fact(4) // 24
fact(7) // !! 5040
यह भी बताता है कि यादृच्छिक संख्या Stream
val
रूप में काम क्यों नहीं करती है।
val rndInt: Stream[Int] = (util.Random.nextInt(90)+10) #:: rndInt
rndInt.take(5) // (79, 79, 79, 79, 79)
अनंत आत्म-संदर्भ धारा
// Generate stream that references itself in its evaluation lazy val primes: Stream[Int] = 2 #:: Stream.from(3, 2) .filter { i => primes.takeWhile(p => p * p <= i).forall(i % _ != 0) } .takeWhile(_ > 0) // prevent overflowing // Get list of 10 primes assert(primes.take(10).toList == List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29)) // Previously calculated values were memoized, as shown by toString assert(primes.toString == "Stream(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, ?)")