स्काला 2.8 की नई विशेषताओं में से एक संदर्भ सीमाएं हैं। एक संदर्भ बाध्य क्या है और यह कहां उपयोगी है?
बेशक मैं पहली बार खोजा गया (और उदाहरण के लिए मिला इस ), लेकिन मैं किसी भी वास्तव में स्पष्ट और विस्तृत जानकारी नहीं मिल सका।
स्काला 2.8 की नई विशेषताओं में से एक संदर्भ सीमाएं हैं। एक संदर्भ बाध्य क्या है और यह कहां उपयोगी है?
बेशक मैं पहली बार खोजा गया (और उदाहरण के लिए मिला इस ), लेकिन मैं किसी भी वास्तव में स्पष्ट और विस्तृत जानकारी नहीं मिल सका।
जवाबों:
क्या आपको यह लेख मिला ? यह सरणी सुधार के संदर्भ में नई संदर्भ बाध्य सुविधा को शामिल करता है।
आम तौर पर, एक संदर्भ बाउंड के साथ एक प्रकार का पैरामीटर फॉर्म का होता है [T: Bound]
; यह एक प्रकार के T
अंतर्निहित पैरामीटर के साथ सादे प्रकार के पैरामीटर में विस्तारित होता है Bound[T]
।
उस विधि पर विचार करें tabulate
जो किसी दिए गए फ़ंक्शन को लागू करने के परिणामों से लेकर संख्याओं की एक सीमा पर 0 से लेकर जब तक कि दी गई लंबाई तक एक सरणी बनाती है। स्केल 2.7 तक, सारणी निम्नानुसार लिखी जा सकती है:
def tabulate[T](len: Int, f: Int => T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
स्केल 2.8 में यह अब संभव नहीं है, क्योंकि रनटाइम की जानकारी सही प्रतिनिधित्व बनाने के लिए आवश्यक है Array[T]
। एक ClassManifest[T]
अंतर्निहित पैरामीटर के रूप में विधि में पारित करके इस जानकारी को प्रदान करने की आवश्यकता है :
def tabulate[T](len: Int, f: Int => T)(implicit m: ClassManifest[T]) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
शॉर्टहैंड फ़ॉर्म के रूप में, एक संदर्भ बाउंड का उपयोग T
इसके बजाय टाइप पैरामीटर पर किया जा सकता है :
def tabulate[T: ClassManifest](len: Int, f: Int => T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
रॉबर्ट का जवाब कॉन्टेक्ट बाउंड्स के तकनीकी विवरण को कवर करता है। मैं आपको उनके अर्थ की अपनी व्याख्या दूंगा।
स्काला में एक व्यू बाउंड ( A <% B
) 'के रूप में देखा जा सकता है' की अवधारणा को कैप्चर करता है (जबकि एक ऊपरी बाउंड <:
'एक है' की अवधारणा को पकड़ता है)। एक संदर्भ बाउंड ( A : C
) कहता है 'में' एक प्रकार के बारे में है। आप कई उदाहरणों के बारे में पढ़ सकते हैं जैसे " T
एक है Manifest
"। आप के बारे में Ordered
बनाम से जुड़ा उदाहरण Ordering
अंतर दिखाता है। एक विधी
def example[T <% Ordered[T]](param: T)
कहते हैं कि पैरामीटर को एक के रूप में देखा जा सकता है Ordered
। तुलना करना
def example[T : Ordering](param: T)
जो कहता है कि पैरामीटर में एक संबद्धता है Ordering
।
उपयोग के संदर्भ में, सम्मेलनों को स्थापित करने में कुछ समय लगा, लेकिन संदर्भ सीमा को सीमा से अधिक पसंद किया जाता है ( देखें सीमाएं अब पदावनत हो गई हैं )। एक सुझाव यह है कि जब आप सीधे इसे संदर्भित करने की आवश्यकता के बिना एक दायरे से दूसरे दायरे में एक अंतर्निहित परिभाषा को स्थानांतरित करने की आवश्यकता होती है, तो एक संदर्भ बाध्य पसंद किया जाता है (यह निश्चित रूप से ClassManifest
एक सरणी बनाने के लिए उपयोग किए जाने के लिए मामला है )।
दृश्य सीमा और संदर्भ सीमा के बारे में सोचने का एक और तरीका यह है कि पहले स्थानान्तरण कॉलर के दायरे से रूपांतरण करता है। दूसरे स्थानान्तरण से कॉलर के दायरे से वस्तुएं निकलती हैं।
has a
मेरे लिए और अधिक समझ में आता है]
(यह एक पैतृक नोट है। पहले अन्य उत्तरों को पढ़ें और समझें।)
संदर्भ सीमाएं वास्तव में देखें सीमा को सामान्य करती हैं।
इसलिए, इस कोड को व्यू बाउंड के साथ व्यक्त किया गया है:
scala> implicit def int2str(i: Int): String = i.toString
int2str: (i: Int)String
scala> def f1[T <% String](t: T) = 0
f1: [T](t: T)(implicit evidence$1: (T) => String)Int
यह एक प्रकार के उपनाम के साथ भी व्यक्त किया जा सकता है, एक प्रकार के उपनाम की मदद से प्रकार से कार्यों का प्रतिनिधित्व F
करने वाला T
।
scala> trait To[T] { type From[F] = F => T }
defined trait To
scala> def f2[T : To[String]#From](t: T) = 0
f2: [T](t: T)(implicit evidence$1: (T) => java.lang.String)Int
scala> f2(1)
res1: Int = 0
एक संदर्भ बाउंड का उपयोग एक प्रकार के प्रकार के साथ किया जाना चाहिए * => *
। हालाँकि टाइप कंस्ट्रक्टर Function1
दयालु होता है (*, *) => *
। अलियास प्रकार का उपयोग आंशिक रूप से दूसरे प्रकार के पैरामीटर के साथ लागू होता है String
, एक संदर्भ बाउंड के रूप में उपयोग के लिए सही प्रकार का एक प्रकार का निर्माण।
एक निशान के अंदर अन्य प्रकार के उपयोग के बिना, आपको सीधे स्काला में आंशिक रूप से लागू प्रकारों को व्यक्त करने की अनुमति देने का एक प्रस्ताव है। आप तब लिख सकते हैं:
def f3[T : [X](X => String)](t: T) = 0
From
प्रकार के To[String]
। हम एक प्रकार का तर्क प्रदान नहीं करते हैं From
, इसलिए हम टाइप निर्माता का उल्लेख करते हैं, एक प्रकार का नहीं। इस प्रकार का निर्माण एक संदर्भ बाउंड के रूप में उपयोग किए जाने वाले सही प्रकार का है - * -> *
। यह प्रकार के T
अनुमानित पैरामीटर की आवश्यकता से टाइप पैरामीटर को बांधता है To[String]#From[T]
। प्रकार के उपनाम और वॉइला का विस्तार करें, आप साथ रह गए हैं Function1[String, T]
।
यह एक और पैतृक नोट है।
जैसा कि बेन ने बताया , एक संदर्भ बाउंड एक प्रकार के पैरामीटर और एक प्रकार के वर्ग के बीच एक "है-ए" बाधा का प्रतिनिधित्व करता है। एक और तरीका रखो, यह एक बाधा का प्रतिनिधित्व करता है कि एक विशेष प्रकार के वर्ग का एक निहित मूल्य मौजूद है।
जब एक संदर्भ बाध्य का उपयोग करते हैं, तो एक को अक्सर उस निहित मूल्य को सतह पर लाने की आवश्यकता होती है। उदाहरण के लिए, बाधा को देखते हुए T : Ordering
, किसी को अक्सर उस उदाहरण की आवश्यकता होगी Ordering[T]
जो बाधा को संतुष्ट करता है। जैसा कि यहां दिखाया गया है , implicitly
विधि या थोड़ी अधिक उपयोगी context
विधि का उपयोग करके निहित मूल्य तक पहुंचना संभव है :
def **[T : Numeric](xs: Iterable[T], ys: Iterable[T]) =
xs zip ys map { t => implicitly[Numeric[T]].times(t._1, t._2) }
या
def **[T : Numeric](xs: Iterable[T], ys: Iterable[T]) =
xs zip ys map { t => context[T]().times(t._1, t._2) }