2012-01-19 19 views
10

मैं स्कैला के लिए नया हूं और निरंतरता के आसपास अपने सिर को लपेटने की कोशिश कर रहा हूं मैं yield return सी # कथन का पुनरुत्पादन करने की कोशिश कर रहा हूं।निरंतरता और समझ के लिए - असंगतता क्या है?

package com.company.scalatest 

import scala.util.continuations._; 

object GenTest { 

    val gen = new Generator[Int] { 
    def produce = { 
     yieldValue(1) 
     yieldValue(2) 
     yieldValue(3) 
     yieldValue(42) 
    } 
    } 
    // Does not compile :(

    // val gen2 = new Generator[Int] { 
    // def produce = { 
    //  var ints = List(1, 2, 3, 42); 
    // 
    //  ints.foreach((theInt) => yieldValue(theInt)); 
    // } 
    // } 

    // But this works? 
    val gen3 = new Generator[Int] { 
    def produce = { 
     var ints = List(1, 2, 3, 42); 
     var i = 0; 
     while (i < ints.length) { 
     yieldValue(ints(i)); 
     i = i + 1; 
     } 
    } 
    } 

    def main(args: Array[String]): Unit = { 
    gen.foreach(println); 
    // gen2.foreach(println); 
    gen3.foreach(println); 
    } 
} 

abstract class Generator[E] { 

    var loopFn: (E => Unit) = null 

    def produce(): Unit @cps[Unit] 

    def foreach(f: => (E => Unit)): Unit = { 
    loopFn = f 
    reset[Unit, Unit](produce) 
    } 

    def yieldValue(value: E) = 
    shift { genK: (Unit => Unit) => 
     loopFn(value) 
     genK(()) 
    () 
    } 
} 

आप देख सकते हैं, gen2 बाहर टिप्पणी की है के रूप में यह संकलन नहीं करता है:

this post के बाद, मैं निम्नलिखित कोड लिखा है। चूंकि मैं थोड़ी देर लूप का उपयोग करके सूची की सामग्री पर आसानी से पुन: प्रयास कर सकता हूं (gen3 देखें), मुझे उम्मीद थी कि फोरैच लूप भी काम करेगा।

no type parameters for method foreach: (f: Int => B)Unit exist so that 
it can be applied to arguments (Int => Unit @scala.util.continuations.cpsParam[Unit,Unit]) 
--- because --- 
argument expression's type is not compatible with formal parameter type; 
found : Int => Unit @scala.util.continuations.cpsParam[Unit,Unit] 
required: Int => ?B 

क्यों मैं इस त्रुटि मिलती है और वहाँ थोड़ी देर के पाश से क्लीनर कुछ के साथ इस को हल करने के लिए एक रास्ता है है:

संकलन त्रुटि पीछा कर रहा है?

आप

+2

स्केल निरंतरता का उपयोग करके उपज (उपज वापसी) लागू करने के संभावित डुप्लिकेट] (http: // stackoverflow।कॉम/प्रश्न/2201882/कार्यान्वयन-उपज-उपज-वापसी-उपयोग-स्केल-निरंतरता) –

+0

मुझे स्केल निरंतरता का उपयोग करके 'उपज रिटर्न' को पुन: उत्पन्न करने के लिए मुझे एक उत्तर की तलाश नहीं है। मैं इस कारण की तलाश में हूं कि मेरे उदाहरण में 'gen2' क्यों काम नहीं करता है। 'उपज वापसी' केवल वह संदर्भ है जिसमें मुझे इस मुद्दे का सामना करना पड़ा। – GuiSim

+0

आह, क्षमा करें तो। –

उत्तर

4

पहले की क्या यह gen2 संकलित करने के लिए प्राप्त करने के लिए ले जाएगा को देखो धन्यवाद।

object CpsConversions { 

    import scala.collection.IterableLike 
    import scala.util.continuations._ 

    implicit def cpsIterable[A, Repr](xs: IterableLike[A, Repr]) = new { 
    def cps = new { 
     def foreach[B](f: A => [email protected][Unit, Unit]): [email protected][Unit, Unit] = { 
     val it = xs.iterator 
     while(it.hasNext) f(it.next) 
     } 
    } 
    } 
} 

object GenTest { 

    import CpsConversions.cpsIterable 
    val gen2 = new Generator[Int] { 
    def produce = { 
     var ints = List(1, 2, 3, 42) 
     ints.cps.foreach((theInt) => yieldValue(theInt)) 
    } 
    } 

अब देखते हैं कि क्या हो रहा है। मूल gen2 निम्न पंक्ति पर संकलित करने के लिए विफल रहता है:

Int => Unit @cpsParam[Unit,Unit] 
:

ints.foreach((theInt) => yieldValue(theInt)) 

के बाद से yieldValue के प्रकार के एक @cpsParam एनोटेशन भी शामिल है, निरंतरता प्लगइन समारोह प्रकार से एक के लिए foreach विधि के लिए पारित बदल देती है

रास्ता ऊपर List[Int] के पदानुक्रम में, आप foreach देखेंगे के रूप में परिभाषित:

foreach [U] (f: (Int) ⇒ U): Unit 

यह एक समस्या है, क्योंकि प्रकार मेल नहीं खाते हैं और स्कैला को यह नहीं पता कि Int => U से Int => Unit @cpsParam[Unit,Unit] तक कैसे प्राप्त किया जाए। इसे ठीक करने के लिए, मैंने एक अंतर्निहित रूपांतरण में foreach का सीपीएस संस्करण जोड़ा, जिसे आप किसी भी IterableLike पर cps पर कॉल करके एक्सेस कर सकते हैं।

यह बहुत अच्छा है अगर यह अंतर्निहित रूपांतरण स्पष्ट cps कॉल बिना किया जा सकता हो सकता है, लेकिन मुझे लगता है स्काला संकलक इस तरह के एक अंतर्निहित रूपांतरण की प्रयोज्यता पहचान अपनी सूची पर नई foreach दलाल करने के लिए बनाने के लिए एक तरह से नहीं मिला है । यह उस क्रम के साथ करना पड़ सकता है जिसमें संकलक निरंतरता प्लगइन का उपयोग करता है, लेकिन मुझे यह सुनिश्चित करने के लिए इस प्रक्रिया के बारे में बहुत कम पता है।

तो यह foreach के लिए अच्छा और अच्छा है। आपका प्रश्न समझ के लिए उल्लेख करता है, जिसे परिभाषित करने के लिए filter, map, या flatMap की आवश्यकता होगी (समझ के लिए आपके द्वारा क्या चल रहा है) के आधार पर। मैंने इन उपरोक्त टिप्पणी में दिए गए लिंक में इन्हें लागू किया है, जो समझ के लिए सामान्य की अनुमति देने के लिए ऊपर CpsConversions ऑब्जेक्ट बढ़ाता है।

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