2009-11-12 14 views
26

एक और सवाल मैंने पूछा से जारी रखते हुए, Scala 2.8 breakout, मैं स्काला विधि TraversableLike[A].map जिनके हस्ताक्षर निम्नानुसार बारे में कुछ और समझने के लिए करना चाहता था :स्काला 2.8 CanBuildFrom

  • यह में प्रत्येक A को घुमाने में एक फ़ंक्शन लेता है।
  • यह That देता है और CanBuildFrom[Repr, B, That] टाइप का एक निहित तर्क लेता है।

मैं इस रूप में निम्नानुसार कॉल कर सकते हैं:

> val s: Set[Int] = List("Paris", "London").map(_.length) 
s: Set[Int] Set(5,6) 

क्या मैं काफी समझ नहीं कर सकते कैसे तथ्य That है कि बाध्यB को (जो है, यह बी के कुछ संग्रह है) संकलक द्वारा लागू किया जा रहा है। प्रकार पैरामीटर के ऊपर और विशेषता CanBuildFrom खुद के हस्ताक्षर के दोनों हस्ताक्षर से स्वतंत्र होने के लिए लग रही है:

trait CanBuildFrom[-From, -Elem, +To] 

स्काला संकलक कैसे सुनिश्चित किया जाता है कि That नहीं किया जा सकता जो कुछ मतलब नहीं है के लिए मजबूर?

> val s: Set[String] = List("Paris", "London").map(_.length) //will not compile 

संकलक कैसे तय करता है क्या निहित CanBuildFrom वस्तुओं कॉल के लिए दायरे में कर रहे हैं?

+0

यहाँ एक काफी अच्छा स्पष्टीकरण http://blog.bruchez.name/2012/08/getting-to-know-canbuildfrom-without-phd.html –

+0

रिकॉर्ड के लिए साथ पोस्ट है, इस तरह के उपयोग है एक वैचारिक नाम: वापसी प्रकार polymorphism। – lcn

उत्तर

29

ध्यान दें कि map पर दूसरा तर्क एक निहित तर्क है। उपयुक्त प्रकारों के दायरे में एक निहित होना चाहिए, या अन्यथा, आप इस तरह के तर्क को पास करना होगा।

अपने उदाहरण में, ThatSet[String] होना चाहिए, बी Int होना चाहिए और ReprList[String] होना चाहिए। इसलिए, कि संकलित करने के लिए के लिए आप दायरे में निम्नलिखित अंतर्निहित वस्तु की जरूरत है:

implicit object X: CanBuildFrom[List[String], Int, Set[String]] 

दायरे में जैसी कोई चीज नहीं है। इसके अलावा, breakOut इसे प्रदान नहीं कर सकता है, क्योंकि इसे स्वयं को CanBuildFrom की आवश्यकता होती है, जिसका पहला प्रकार किसी भी वर्ग (Nothing का एक कॉन्ट्रैक्ट-वेरिएंट वंश) हो सकता है, लेकिन अन्यथा अन्य प्रकारों द्वारा प्रतिबंधित है।

एक नज़र, उदाहरण के लिए, List का साथी वस्तु से ले लो CanBuildFrom कारखाने पर: क्योंकि यह A के माध्यम से दूसरे और तीसरे पैरामीटर बांधता

implicit def canBuildFrom [A] : CanBuildFrom[List, A, List[A]] 

, प्रश्न में निहित काम नहीं करेगा।

तो, इस तरह के निहितार्थों के बारे में, किसी को कैसे पता चल सकता है? सबसे पहले, स्कैला कुछ चीजों को सभी क्षेत्रों में आयात करता है।अभी, मैं निम्नलिखित आयात याद कर सकते हैं:

import scala.package._ // Package object 
import scala.Predef._ // Object 
// import scala.LowPriorityImplicits, class inherited by Predef 
import scala.runtime._ // Package 

जब से हम implicits बारे में चिंतित हैं, ध्यान रखें कि जब आप संकुल से बातें आयात करते हैं, तभी संभव implicits एकमात्र कर रहे हैं। जब आप ऑब्जेक्ट्स (सिंगलेट्स) से चीजें आयात करते हैं, तो दूसरी तरफ, आप निहित परिभाषाएं, मूल्य और सिंगलेट्स ले सकते हैं।

अभी Predef और LowPriorityImplicits के अंदर implicits हैं, जो स्ट्रिंग से संबंधित हैं। वे हमें "this is a string" map (_.toInt) लिखने में सक्षम करते हैं।

तो, इन स्वचालित आयातों को छोड़कर, और आपके द्वारा किए गए स्पष्ट आयात, जहां कोई अंतर्निहित पाया जा सकता है? एक स्थान: उदाहरण के साथी वस्तुएं जिस पर विधि लागू की जा रही है।

मैं कहता साथी वस्तु रों, बहुवचन में, क्योंकि सभी लक्षण और वर्गों के साथी वस्तुओं प्रश्न में उदाहरण के वर्ग द्वारा विरासत में मिली प्रासंगिक implicits हो सकती है। मुझे यकीन नहीं है कि उदाहरण में स्वयं एक अंतर्निहित हो सकता है। ईमानदार होने के लिए, मैं अभी इसे पुन: पेश नहीं कर सकता, इसलिए मैं निश्चित रूप से यहां किसी तरह की गलती कर रहा हूं।

किसी भी दर पर, साथी वस्तुओं के अंदर देखो।

+0

डैनियल - मुझे कैसे पता चलेगा कि मेरे कोड में किसी दिए गए बिंदु पर 'अंतर्निहित' वस्तुएं क्या हैं? सवाल यह है कि सवाल उठता है, मुझे एहसास है। यह कहां निर्दिष्ट है? इसके अलावा, इस प्रश्न का 'ब्रेकऑट' से कोई लेना देना नहीं है। –

+0

ऑब्जेक्ट स्कैला में अंतर्निहित रूपांतरणों के अलावा। प्रीफिफ़, आपको या तो एक या एक संलग्न क्षेत्र में अंतर्निहित परिभाषित करना होगा या आपको उस अंतर्निहित रूप से स्पष्ट रूप से आयात करना होगा। –

+0

"जब आप संकुल से चीजें आयात करते हैं, तो केवल एकमात्र निहितार्थ सिंगलेट्स हैं" क्या यह अभी भी स्कैला 2.8 पैकेज ऑब्जेक्ट्स के साथ सच है? वे भी अंतर्निहित defs और vals हो सकता है। –

0
object ArrayBuffer extends SeqFactory[ArrayBuffer] { 
    /** $genericCanBuildFromInfo */ 
    implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ArrayBuffer[A]] = new GenericCanBuildFrom[A] 
    def newBuilder[A]: Builder[A, ArrayBuffer[A]] = new ArrayBuffer[A] 
}