2010-05-14 6 views
6

स्कैला में, क्या स्ट्रीम में वर्तमान में मूल्यांकन किए गए आइटम प्राप्त करने का कोई तरीका है? स्ट्रीम में उदाहरण के लिएस्कैला में, क्या स्ट्रीम में वर्तमान में मूल्यांकन किए गए आइटम प्राप्त करने का कोई तरीका है?

val s: Stream[Int] = Stream.cons(1, Stream.cons(2, Stream.cons(3, s.map(_+1)))) 

विधि केवल List(1,2,3) लौटना चाहिए।

उत्तर

7

2.8 में, tailDefined नामक एक संरक्षित विधि है जो स्ट्रीम में उस बिंदु तक पहुंचने पर झूठी वापसी करेगी जिसका मूल्यांकन अभी तक नहीं किया गया है।

यह बहुत उपयोगी नहीं है (जब तक कि आप अपना खुद का Stream वर्ग नहीं लिखना चाहते हैं) सिवाय इसके कि Cons स्वयं विधि को सार्वजनिक बनाता है। मुझे यकीन नहीं है कि यह स्ट्रीम में क्यों संरक्षित है और विपक्ष में नहीं - मुझे लगता है कि एक या दूसरा एक बग हो सकता है। लेकिन अब के लिए, कम से कम, आप लिख सकते हैं तो तरह एक विधि (एक कार्यात्मक समकक्ष लेखन पाठक के लिए एक व्यायाम के रूप में छोड़ दिया जाता है):

def streamEvalLen[T](s: Stream[T]) = { 
    if (s.isEmpty) 0 
    else { 
    var i = 1 
    var t = s 
    while (t match { 
     case c: Stream.Cons[_] => c.tailDefined 
     case _ => false 
    }) { 
     i += 1 
     t = t.tail 
    } 
    i 
    } 
} 

यहाँ आप कार्रवाई में इसे देख सकते हैं:

scala> val s = Stream.iterate(0)(_+1) 
s: scala.collection.immutable.Stream[Int] = Stream(0, ?) 

scala> streamEvalLen(s) 
res0: Int = 1 

scala> s.take(3).toList 
res1: List[Int] = List(0, 1, 2) 

scala> s 
res2: scala.collection.immutable.Stream[Int] = Stream(0, 1, 2, ?) 

scala> streamEvalLen(s) 
res3: Int = 3 
+0

विधि 'पूंछ परिभाषित' दोनों 'विपक्ष' और 'खाली' दोनों में सार्वजनिक है इसलिए मुझे नहीं लगता कि यह एक बग है। मैंने पहले यह नहीं देखा था। मैं अपनी समस्या को हल करने के लिए अपने समाधान को अनुकूलित कर सकता हूं। –

3

उस कथन को इंटरैक्टिव शैल में टाइप करें और आप देखेंगे कि यह s: Stream[Int] = Stream(1, ?) पर मूल्यांकन करता है। तो, वास्तव में, 2 और 3 के अन्य दो तत्व अभी तक ज्ञात नहीं हैं।

जैसे ही आप आगे के तत्वों तक पहुंचते हैं, स्ट्रीम की अधिक गणना की जाती है। तो, अब s(3) को खोल में डालें, जो res0: Int = 2 लौटाएगा। अब खोल में s डालें और आपको नया मान res1: Stream[Int] = Stream(1, 2, 3, 2, ?) दिखाई देगा।

एकमात्र तरीका जो मैं पा सकता हूं उसमें वह जानकारी शामिल थी जो आप चाहते थे, दुर्भाग्यवश, s.toString। कुछ पार्सिंग के साथ आप तत्वों को स्ट्रिंग से वापस प्राप्त कर पाएंगे। यह केवल स्याही के साथ एक मुश्किल स्वीकार्य समाधान है और मैं स्ट्रिंग पार्सिंग विचार का उपयोग कर किसी भी सामान्य समाधान की कल्पना नहीं कर सका।

5

समाधान Rex's answer के आधार पर:

def evaluatedItems[T](stream: => Stream[T]): List[T] = { 
    @tailrec 
    def inner(s: => Stream[T], acc: List[T]): List[T] = s match { 
    case Empty => acc 
    case c: Cons[T] => if (c.tailDefined) { 
     inner(c.tail, acC++ List(c.head)) 
    } else { acC++ List(c.head) } 
    } 
    inner(stream, List()) 
} 
0

scanLeft

lazy val s: Stream[Int] = 1 #:: s.scanLeft(2) { case (a, _) => 1 + a } 
का उपयोग करना
संबंधित मुद्दे

 संबंधित मुद्दे