स्काला में `: _ *` (कोलन अंडरस्कोर स्टार) क्या करता है?


195

मेरे पास इस प्रश्न से निम्नलिखित कोड है :

def addChild(n: Node, newChild: Node) = n match {
  case Elem(prefix, label, attribs, scope, child @ _*) => Elem(prefix, label, attribs, scope, child ++ newChild : _*)
  case _ => error("Can only add children to elements!")
}

इस टुकड़े को छोड़कर इसमें सब कुछ बहुत स्पष्ट है: child ++ newChild : _*

यह क्या करता है?

मैं समझता हूं कि Seq[Node]दूसरे के साथ सहमति है Nodeऔर फिर? क्या करता : _*है?


70
शीर्षक में (कोलन अंडरस्कोर स्टार) जोड़ने के लिए बहुत बहुत धन्यवाद!
गैल

जवाबों:


151

यह "स्पैट्स" 1 अनुक्रम।

कंस्ट्रक्टर के हस्ताक्षर को देखें

new Elem(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding,
         child: Node*)

जिसे कहा जाता है

new Elem(prefix, label, attributes, scope,
         child1, child2, ... childN)

लेकिन यहां केवल एक अनुक्रम है, नहीं child1, child2आदि। इसलिए यह परिणाम अनुक्रम को निर्माता के इनपुट के रूप में उपयोग करने की अनुमति देता है।

खुश कोडिंग।


1 इसमें SLS में एक cutesy-name नहीं है, लेकिन यहाँ विवरण हैं। प्राप्त करने के लिए महत्वपूर्ण बात यह है कि यह बदल जाता है कि स्केल कैसे तर्कों को दोहराए गए मापदंडों के साथ बांधता है (जैसा कि Node*ऊपर से दर्शाया गया है)।

_*प्रकार एनोटेशन एसएलएस के "4.6.2 दोहराया पैरामीटर" में शामिल है।

एक पैरामीटर सेक्शन का अंतिम मान पैरामीटर "*", उदाहरण के लिए (..., x: T *) द्वारा suf a xed हो सकता है। विधि के अंदर इस तरह के दोहराया पैरामीटर का प्रकार फिर अनुक्रम प्रकार scala.Seq [T] है। दोहराया मापदंडों के साथ तरीके टी * प्रकार टी के तर्कों की एक चर संख्या लेते हैं। यही है, अगर एक विधि m प्रकार के साथ (p1: T1,।, Pn: Tn, ps: S *) U को तर्कों (e1,,।, Ek) पर लागू किया जाता है, जहाँ k> = n, तो m होता है। उस एप्लिकेशन में टाइप करने के लिए लिया गया (p1: T1।,। pn: Tn, ps: S।,।, ps0S) U, k ¡n घटनाओं के प्रकार के साथ S, जहां ps से परे कोई भी पैरामीटर नाम ताजा है।इस नियम का एकमात्र अपवाद यह है कि अंतिम तर्क को _ * प्रकार के एनोटेशन के माध्यम से अनुक्रम तर्क के रूप में चिह्नित किया गया है। यदि उपरोक्त m को तर्कों (e1,।, En, e0: _ *) पर लागू किया जाता है, तो उस अनुप्रयोग में m का प्रकार (p1: T1,।,।, Pn: Tn, ps, scala) लिया जाता है। .Seq [एस])


5
हम इसे "स्मूच ऑपरेटर" कहना पसंद करते हैं, भले ही यह वास्तव में एक ऑपरेटर न हो :)
हेनरिक गुस्ताफ्सन

1
पायथन में इसे
अनपैकिंग

क्या कोई सीमा है कि अनुक्रम कितने समय तक हो सकता है, जैसे कि जावा वेरगेज के साथ है?
qwwqqq

95
  • child ++ newChild - अनुक्रम
  • : - टाइप एस्क्रिप्शन, एक संकेत जो समझने में कंपाइलर की मदद करता है, उस एक्सप्रेशन का क्या प्रकार है
  • _* - प्लेसहोल्डर किसी भी मूल्य + वैरग ऑपरेटर को स्वीकार करता है

child ++ newChild : _*विस्तार Seq[Node]करता है Node*(संकलक को बताता है कि हम एक अनुक्रम से एक varargs के साथ काम कर रहे हैं)। विशेष रूप से उन विधियों के लिए उपयोगी है जो केवल varargs स्वीकार कर सकते हैं।


1
क्या आप "टाइप एस्क्रिप्शन" के बारे में अधिक लिख सकते हैं? यह क्या है और यह कैसे काम करता है?
एमफोरिस


24

उपरोक्त सभी उत्तर बहुत अच्छे लगते हैं, लेकिन इसे समझाने के लिए बस एक नमूने की आवश्यकता है। यह रहा :

val x : Seq[Seq[Int]] = Seq(Seq(1),Seq(2))

def f(arg: Seq[Any]*) : Int = {
 arg.length
}
f(x) //1 as x is taken as single arg
f(x:_*)  // 2 as x is "unpacked" as a Seq[Any]*

तो अब हम जानते हैं कि :_*संकलक को क्या करना है: कृपया इस तर्क को अनपैक करें और उन तत्वों को फ़ंक्शन तर्क कॉल में varar पैरामीटर से बाँधें, बजाय x को एक तर्क के रूप में लें।

तो संक्षेप में, :_*जब तर्क को vargg पैरामीटर को पास करना अस्पष्टता को दूर करना है।


5

मेरे जैसे कुछ आलसी लोगों के लिए, यह बस Seq को varArgs में बदल देता है!

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