स्काला में एक घोषणापत्र क्या है और आपको इसकी आवश्यकता कब है?


132

स्केल 2.7.2 के बाद से Manifestजावा के प्रकार के विलोपन के लिए वर्कअराउंड कहा जाता है। लेकिन Manifestवास्तव में कैसे काम करता है और क्यों / कब आपको इसका उपयोग करने की आवश्यकता है?

ब्लॉग पोस्ट मैनिफ़ेस्ट्स: रीफ़ाइंड टाइप्स द्वारा जॉर्ज ऑर्टिज़ इसके बारे में कुछ समझाता है, लेकिन यह यह नहीं समझाता है कि इसे संदर्भ सीमा के साथ कैसे उपयोग किया जाए ।

इसके अलावा, क्या है ClassManifest, क्या अंतर है Manifest?

मेरे पास कुछ कोड हैं (एक बड़े कार्यक्रम का हिस्सा, इसे आसानी से यहां शामिल नहीं किया जा सकता है) जिसमें टाइप एरासुर के संबंध में कुछ चेतावनी है; मुझे संदेह है कि मैं मैनिफ़ेस्ट का उपयोग करके इन्हें हल कर सकता हूं, लेकिन मुझे यकीन नहीं है कि कैसे।


2
मैनिफेस्ट / क्लासमैनफैस्ट अंतर के बारे में मेलिंग सूची पर चर्चा हुई है, देखें scala-programming-language.1934581.n4.nabble.com/…
Arjan Blokzijl

जवाबों:


197

कंपाइलर जानता है कि जेवीएम रनटाइम आसानी से प्रतिनिधित्व कर सकता है। एक मैनिफेस्ट संकलक के लिए एक अंतर-आयामी संदेश को रनटाइम पर कोड को उस प्रकार की जानकारी के बारे में भेजने का एक तरीका है जो खो गया था।

यह उसी तरह है जैसे क्लेप्टोनियन ने जीवाश्म रिकॉर्ड और मानव के "जंक" डीएनए में एन्कोडेड संदेशों को छोड़ दिया है। लाइटस्पेड और गुरुत्वाकर्षण अनुनाद क्षेत्रों की सीमाओं के कारण, वे सीधे संवाद करने में असमर्थ हैं। लेकिन, यदि आप जानते हैं कि उनके सिग्नल को कैसे ट्यून किया जाए, तो आप उन तरीकों से लाभ उठा सकते हैं जिनकी आप कल्पना नहीं कर सकते हैं, यह तय करने से कि लंच के लिए क्या खाना चाहिए या कौन सा लोट्टो नंबर खेलना है।

यह स्पष्ट नहीं है कि एक मैनिफेस्ट आपको उन त्रुटियों से लाभान्वित करेगा जिन्हें आप अधिक विस्तार से जाने बिना देख रहे हैं।

मैनिफ़ेस्ट का एक सामान्य उपयोग यह है कि आपका कोड किसी संग्रह के स्थिर प्रकार के आधार पर भिन्न व्यवहार करता है। उदाहरण के लिए, यदि आप किसी सूची [स्ट्रिंग] को अन्य प्रकार की सूची से अलग करना चाहते हैं, तो क्या होगा:

 def foo[T](x: List[T])(implicit m: Manifest[T]) = {
    if (m <:< manifest[String])
      println("Hey, this list is full of strings")
    else
      println("Non-stringy list")
  }

  foo(List("one", "two")) // Hey, this list is full of strings
  foo(List(1, 2)) // Non-stringy list
  foo(List("one", 2)) // Non-stringy list

इसका प्रतिबिंब आधारित समाधान संभवतः सूची के प्रत्येक तत्व का निरीक्षण करना शामिल होगा।

एक संदर्भ बाउंड स्केला में टाइप-क्लास का उपयोग करने के लिए सबसे अनुकूल लगता है, और देबाशीष घोष द्वारा यहां अच्छी तरह से समझाया गया है: http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html

संदर्भ सीमाएं भी विधि हस्ताक्षरों को अधिक पठनीय बना सकती हैं। उदाहरण के लिए, उपरोक्त फ़ंक्शन को संदर्भ सीमा जैसे उपयोग करके फिर से लिखा जा सकता है:

  def foo[T: Manifest](x: List[T]) = {
    if (manifest[T] <:< manifest[String])
      println("Hey, this list is full of strings")
    else
      println("Non-stringy list")
  }

25

एक पूर्ण उत्तर नहीं है, लेकिन Manifestऔर के बीच के अंतर के बारे में ClassManifest, आप स्काला 2.8 Arrayपेपर में एक उदाहरण पा सकते हैं :

एकमात्र शेष प्रश्न यह है कि जेनेरिक सरणी निर्माण को कैसे लागू किया जाए। जावा के विपरीत, स्काला एक इंस्टेंस क्रिएशन को अनुमति देता है Array[T]जहाँ Tएक प्रकार का पैरामीटर होता है। यह कैसे लागू किया जा सकता है, इस तथ्य को देखते हुए कि जावा में एक समान सरणी प्रतिनिधित्व मौजूद नहीं है?

ऐसा करने का एकमात्र तरीका अतिरिक्त रनटाइम जानकारी की आवश्यकता है जो प्रकार का वर्णन करता है T। स्केल 2.8 में इसके लिए एक नया तंत्र है, जिसे एक घोषणापत्र कहा जाता है । प्रकार की एक वस्तु प्रकार के Manifest[T]बारे में पूरी जानकारी प्रदान करती है T
Manifestमान आमतौर पर निहित मापदंडों में पारित किए जाते हैं; और संकलक जानता है कि उन्हें सांख्यिकीय रूप से ज्ञात प्रकारों के लिए कैसे बनाना हैT

इसमें एक कमजोर रूप भी मौजूद है, जिसका ClassManifestनिर्माण किसी प्रकार के शीर्ष स्तर के वर्ग को जानने से किया जा सकता है, बिना इसके सभी तर्क प्रकारों को जानना
यह इस प्रकार की रनटाइम जानकारी है जो सरणी निर्माण के लिए आवश्यक है।

उदाहरण:

एक 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 
} 

शॉर्टहैंड फ़ॉर्म के रूप में, एक संदर्भ बाउंड 1 का उपयोग Tइसके बजाय टाइप पैरामीटर पर किया जा सकता है ,

( चित्रण के लिए यह SO प्रश्न देखें )

, दे रहा है:

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 
} 

जब एक प्रकार जैसे कि Int, या String, पर सारणीबद्ध करते हैं List[T], तो स्केल संकलक, सारणीबद्ध करने के लिए अंतर्निहित तर्क के रूप में पारित करने के लिए एक वर्ग प्रकट बना सकता है।


25

एक घोषणापत्र का मकसद जेवीएम (जो जेनेरिक का समर्थन नहीं करता है) पर चलने के लिए टाइप-मिटाने वाले जेनेरिक प्रकारों का पुनरीक्षण करना था। हालांकि, उनके पास कुछ गंभीर मुद्दे थे: वे बहुत सरल थे, और स्काला के प्रकार प्रणाली का पूरी तरह से समर्थन करने में असमर्थ थे। इस प्रकार वे स्केल 2.10 में पदावनत हो गए , और उन्हें TypeTagएस के साथ बदल दिया गया (जो अनिवार्य रूप से स्काला संकलक स्वयं प्रकारों का प्रतिनिधित्व करने के लिए उपयोग करता है, और इसलिए पूरी तरह से स्काला प्रकारों का समर्थन करता है)। अंतर पर अधिक जानकारी के लिए, देखें:

दूसरे शब्दों में

आपको इसकी आवश्यकता कब होती है?

2013-01-04 से पहले, जब स्कला 2.10 जारी किया गया था


यह अभी तक वंचित नहीं है (लेकिन होगा), क्योंकि 2.10 में स्काला प्रतिबिंब अभी भी प्रयोगात्मक है।
केरोस

2013-01-04 से पहले, या यदि आप एक एपीआई का उपयोग कर रहे हैं जो उस पर निर्भर है।
डेविड मोल्स

1

आइए सूत्रों manifestमें भी बताएं scala( Manifest.scala), हम देखते हैं:

Manifest.scala:
def manifest[T](implicit m: Manifest[T])           = m

तो निम्नलिखित उदाहरण कोड के संबंध में:

def foo[A](somelist: List[A])(implicit m: Manifest[A]): String = {
  if (m <:< manifest[String]) {
    "its a string"
  } else {
    "its not a string"
  }
}

हम देख सकते हैं कि manifest functionएक निहितार्थ की खोज m: Manifest[T]जो आपको संतुष्ट करती type parameterहै हमारे उदाहरण कोड में यह प्रदान करती है manifest[String]। तो जब आप कुछ कहते हैं:

if (m <:< manifest[String]) {

यदि implicit mआप अपने फ़ंक्शन में परिभाषित किया गया है , तो आप जाँच कर रहे हैं कि यह किस प्रकार का है manifest[String]और जैसा कि यह एक विशेष manifestप्रकार की manifest[T]खोज है manifest[String]और यह पता चलता है कि क्या ऐसा कोई निहित है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.