6

यदि आप मेरे जैसे हैं, तो आप कभी-कभी स्कैला संग्रह या अनुक्रमों के लिए उन्नत विधियां लिखना चाहते हैं, लेकिन आप संग्रह प्रकार के साथ-साथ तत्व प्रकार को बाध्य करना चाहते हैं, न कि केवल Seq [T] तक।आप जेनेरिक स्कैला एन्हांसमेंट विधियों को कैसे लिख सकते हैं जो संग्रहण प्रकार के साथ-साथ तत्व प्रकार को बाध्य करते हैं?

उत्तर

7

यह करने के लिए एक तरीका होता है, और यह इस तरह काम करता है:

object enhance { 
    import scala.language.higherKinds 
    import scala.language.implicitConversions 
    import scala.collection.SeqLike 
    import scala.collection.generic.CanBuildFrom 

    implicit class Enhance[T, S[E] <: SeqLike[E, S[E]]](seq: S[T]) { 
    def first3(implicit cbf: CanBuildFrom[S[T], T, S[T]]) = seq.take(3) 
    def foo = seq.iterator 
    def goo(implicit cbf: CanBuildFrom[Nothing, T, S[T]]) = foo.take(3).to[S] 
    def moo[U](f: T => U)(implicit cbf: CanBuildFrom[S[T], U, S[U]]) = seq.map(f) 
    } 
} 

ऊपर प्रकार हस्ताक्षर पैटर्न का उपयोग करना, बढ़ाया तरीकों दोनों तत्व प्रकार के बारे में पता कर रहे हैं T (Int जैसे या String) और उच्च-प्रकार वाले अनुक्रम प्रकार S (उदाहरण के लिए List या Vector) और इसलिए यह ठीक उसी अनुक्रम प्रकार को वापस कर सकता है जिसे इसे कॉल किया गया था।

कई अनुक्रम विधियों को CanBuildFrom प्रत्यारोपण की आवश्यकता हो सकती है, जो Enhance विधियों को अंतर्निहित पैरामीटर के रूप में जोड़ा जाता है, जहां उन्हें ऊपर दिए गए उदाहरणों में आवश्यकता होती है।

के बाद, एक नमूना रन है वांछित उच्च kinded संग्रह वापसी प्रकार दिखा:

scala> import enhance._ 
import enhance._ 

scala> (1 to 10).toList.first3 
res0: List[Int] = List(1, 2, 3) 

scala> (1 to 10).toVector.first3 
res1: Vector[Int] = Vector(1, 2, 3) 

scala> (1 to 10).toList.goo 
res2: List[Int] = List(1, 2, 3) 

scala> (1 to 10).toVector.goo 
res3: Vector[Int] = Vector(1, 2, 3) 

scala> (1 to 10).toList.moo(_.toDouble) 
res4: List[Double] = List(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) 

scala> (1 to 10).toVector.moo(_.toDouble) 
res5: Vector[Double] = Vector(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) 
+4

इसके अलावा, आप 'के रूप में निहित वर्ग संशोधन [टी, एस [ई] <वर्ग को परिभाषित कर सकते हैं: IterableLike [ई, एस [ई]]] (सीईसी: एस [टी]) {'और फिर आपको 'asInstanceOf' –

+3

की आवश्यकता नहीं होगी यदि आप' मानचित्र 'या किसी अन्य विधि का उपयोग करते हैं जो नई विधि में' CanBuildFrom' लेता है तो यह काम नहीं करेगा कार्यान्वयन। नतीजा सिर्फ 'सेक' के रूप में सामने आएगा। आपको 'Enhance' कक्षा या विधि में प्रासंगिक अंतर्निहित' CanBuildFrom' पास करने की आवश्यकता होगी। – Kolmar

+1

धन्यवाद @ НиколайМитропольский और कोलमार, दोनों संशोधन बहुत उपयोगी हैं! मैंने उन्हें अपने मूल जवाब को क्रिया में दिखाने के लिए फिर से काम किया। – eje

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