स्काला में "संदर्भ बाउंड" क्या है?


115

स्काला 2.8 की नई विशेषताओं में से एक संदर्भ सीमाएं हैं। एक संदर्भ बाध्य क्या है और यह कहां उपयोगी है?

बेशक मैं पहली बार खोजा गया (और उदाहरण के लिए मिला इस ), लेकिन मैं किसी भी वास्तव में स्पष्ट और विस्तृत जानकारी नहीं मिल सका।


8
: भी इस सीमा के सभी प्रकार के एक दौरे के लिए बाहर की जाँच gist.github.com/257758/47f06f2f3ca47702b3a86c76a5479d096cb8c7ec
अर्जन Blokzijl

2
यह उत्कृष्ट उत्तर तुलना / विरोधाभासी संदर्भ सीमा और दृश्य सीमा की तुलना करता है: stackoverflow.com/questions/4465948/…
हारून नोवस्त्रुप

यह एक बहुत अच्छा जवाब है stackoverflow.com/a/25250693/1586965
samthebest

जवाबों:


107

क्या आपको यह लेख मिला ? यह सरणी सुधार के संदर्भ में नई संदर्भ बाध्य सुविधा को शामिल करता है।

आम तौर पर, एक संदर्भ बाउंड के साथ एक प्रकार का पैरामीटर फॉर्म का होता है [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
}

145

रॉबर्ट का जवाब कॉन्टेक्ट बाउंड्स के तकनीकी विवरण को कवर करता है। मैं आपको उनके अर्थ की अपनी व्याख्या दूंगा।

स्काला में एक व्यू बाउंड ( A <% B) 'के रूप में देखा जा सकता है' की अवधारणा को कैप्चर करता है (जबकि एक ऊपरी बाउंड <:'एक है' की अवधारणा को पकड़ता है)। एक संदर्भ बाउंड ( A : C) कहता है 'में' एक प्रकार के बारे में है। आप कई उदाहरणों के बारे में पढ़ सकते हैं जैसे " Tएक है Manifest"। आप के बारे में Orderedबनाम से जुड़ा उदाहरण Orderingअंतर दिखाता है। एक विधी

def example[T <% Ordered[T]](param: T)

कहते हैं कि पैरामीटर को एक के रूप में देखा जा सकता है Ordered। तुलना करना

def example[T : Ordering](param: T)

जो कहता है कि पैरामीटर में एक संबद्धता है Ordering

उपयोग के संदर्भ में, सम्मेलनों को स्थापित करने में कुछ समय लगा, लेकिन संदर्भ सीमा को सीमा से अधिक पसंद किया जाता है ( देखें सीमाएं अब पदावनत हो गई हैं )। एक सुझाव यह है कि जब आप सीधे इसे संदर्भित करने की आवश्यकता के बिना एक दायरे से दूसरे दायरे में एक अंतर्निहित परिभाषा को स्थानांतरित करने की आवश्यकता होती है, तो एक संदर्भ बाध्य पसंद किया जाता है (यह निश्चित रूप से ClassManifestएक सरणी बनाने के लिए उपयोग किए जाने के लिए मामला है )।

दृश्य सीमा और संदर्भ सीमा के बारे में सोचने का एक और तरीका यह है कि पहले स्थानान्तरण कॉलर के दायरे से रूपांतरण करता है। दूसरे स्थानान्तरण से कॉलर के दायरे से वस्तुएं निकलती हैं।


2
"मेरे पास" के बजाय "एक" या "के रूप में देखा गया" मेरे लिए महत्वपूर्ण अंतर्दृष्टि था - किसी अन्य स्पष्टीकरण में इसे नहीं देखा गया। अन्यथा थोड़े से गूढ़ संचालकों / कार्यों का एक सादा अंग्रेजी संस्करण होने से इसे अवशोषित करना बहुत आसान हो जाता है - धन्यवाद!
डीएनए

1
@Ben Lings क्या मतलब है आपके पास .... 'में' एक प्रकार के बारे में है ...? एक प्रकार के बारे में क्या है ?
जहीदुस

1
@ ज़ेगेदस यहाँ मेरा पार्सिंग है: "एक प्रकार के बारे में" का अर्थ है कि ए एक प्रकार को संदर्भित करता है। वाक्यांश "ए" का उपयोग अक्सर ऑब्जेक्ट रिलेशनशिप का वर्णन करने के लिए ऑब्जेक्ट-ओरिएंटेड डिज़ाइन में किया जाता है (उदाहरण के लिए ग्राहक का "पता")। लेकिन यहाँ "संबंध" एक प्रकार के बीच है, वस्तुओं के बीच नहीं। यह एक ढीला सादृश्य है क्योंकि "एक" संबंध निहित या सार्वभौमिक नहीं है जिस तरह से यह ओओ डिजाइन में है; एक ग्राहक के पास हमेशा एक पता होता है, लेकिन संदर्भ के लिए बाध्य A में हमेशा C. C नहीं होता है, लेकिन संदर्भ बाध्यता निर्दिष्ट करती है कि C [A] का उदाहरण अंतर्निहित रूप से प्रदान किया जाना चाहिए।
जॉयलर

मैं एक महीने के लिए स्काला सीख रहा हूं, और यह इस महीने में मैंने देखा सबसे अच्छा विवरण है! शुक्रिया @Ben!
लिफू हुआंग

@ बिंग रिंग्स: धन्यवाद, समझने के लिए इतना लंबा समय बिताने के बाद क्या संदर्भ बाध्य है, आपका उत्तर बहुत मददगार है। [ has aमेरे लिए और अधिक समझ में आता है]
शंकर

39

(यह एक पैतृक नोट है। पहले अन्य उत्तरों को पढ़ें और समझें।)

संदर्भ सीमाएं वास्तव में देखें सीमा को सामान्य करती हैं।

इसलिए, इस कोड को व्यू बाउंड के साथ व्यक्त किया गया है:

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 

क्या आप f2 की परिभाषा में #From का अर्थ समझा सकते हैं? मुझे यकीन नहीं है कि जहां एफ का निर्माण हो रहा है (क्या मैंने इसे सही तरीके से कहा है?)
कोलिन

1
यह एक प्रकार का प्रक्षेपण कहा जाता है, एक प्रकार सदस्य को संदर्भित Fromप्रकार के To[String]। हम एक प्रकार का तर्क प्रदान नहीं करते हैं From, इसलिए हम टाइप निर्माता का उल्लेख करते हैं, एक प्रकार का नहीं। इस प्रकार का निर्माण एक संदर्भ बाउंड के रूप में उपयोग किए जाने वाले सही प्रकार का है - * -> *। यह प्रकार के Tअनुमानित पैरामीटर की आवश्यकता से टाइप पैरामीटर को बांधता है To[String]#From[T]। प्रकार के उपनाम और वॉइला का विस्तार करें, आप साथ रह गए हैं Function1[String, T]
रेट्रो

क्या यह फ़ंक्शन 1 [टी, स्ट्रिंग] होना चाहिए?
ssanj

18

यह एक और पैतृक नोट है।

जैसा कि बेन ने बताया , एक संदर्भ बाउंड एक प्रकार के पैरामीटर और एक प्रकार के वर्ग के बीच एक "है-ए" बाधा का प्रतिनिधित्व करता है। एक और तरीका रखो, यह एक बाधा का प्रतिनिधित्व करता है कि एक विशेष प्रकार के वर्ग का एक निहित मूल्य मौजूद है।

जब एक संदर्भ बाध्य का उपयोग करते हैं, तो एक को अक्सर उस निहित मूल्य को सतह पर लाने की आवश्यकता होती है। उदाहरण के लिए, बाधा को देखते हुए 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) }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.