2013-09-01 3 views
8

Quasiquotes आश्चर्यजनक हैं- वे स्कैला में बहुत कम दर्दनाक लिखने वाले मैक्रोज़ बनाते हैं, और मेरे अनुभव में वे लगभग हमेशा ठीक उसी तरह काम करते हैं जैसा मैं अपेक्षा करता हूं। और सबसे अच्छा, अब वे स्केल 2.10 में as a plugin उपलब्ध हैं।एकाधिक पैरामीटर और पैरामीटर सूचियों के लिए Quasiquotes

यह प्रश्न this blog post लिखते समय एक छोटी सी समस्या के बारे में है। जब मैं कुछ मिनट पा सकता हूं, तो यह मेरी सामग्री की सूची में है, लेकिन मुझे लगा कि मैं इसे यहां पोस्ट करूंगा यदि कोई और मुझे मार सकता है, और अन्य लोगों की मदद करने के लिए जो एक ही प्रश्न में चल रहे हैं।

मान लीजिए मैं नाम-प्रकार जोड़े की सूची की एक सूची है:

def foo(x: Int, y: Char)(z: String) = ??? 

निम्नलिखित काम करता है ठीक:

val pss = List(
    List(newTermName("x") -> typeOf[Int], newTermName("y") -> typeOf[Char]), 
    List(newTermName("z") -> typeOf[String]) 
) 

मैं एक पेड़ है कि इस तरह दिखता है में इन चालू करना चाहते हैं:

q"def bar(${pss.head.head._1}: ${pss.head.head._2}) = ???" 

है यही कारण है कि, यह निम्न पेड़ बनाता है:

def bar(x: Int) = ??? 

कौन सा पता चलता है कि मैं कुछ इस तरह लिखने के लिए सक्षम होना चाहिए:

q"def baz(..${quoted.head}) = ???" 

न तो काम करता है: एक एकल पैरामीटर सूची में

val quoted = pss.map(_.map { case (n, t) => q"$n: $t" }) 

q"def foo..${quoted.map(ps => q"($ps)")} = 1" 

या एक छोटे से अधिक बस, कई मापदंडों के साथ मुझे इस तरह की त्रुटियां मिलती हैं:

<console>:28: error: type mismatch; 
found : List[c.universe.Typed] 
required: List[c.universe.ValDef] 
      q"def baz(..${quoted.head}) = ???" 
           ^

पर्याप्त मेला- मैं कर सकता हूँ और यह quasiquoter को कैसे देखेंगे जैसे कि मैं quoted में पैरामीटर को परिभाषित करने के बजाय टाइप किए गए अभिव्यक्तियों का निर्माण कर रहा हूं। काम करने की कोशिश करने के लिए मुझे लगता है कि कोई भी स्पष्ट चीज नहीं है (= _ जोड़कर, स्पष्ट रूप से ValDef आदि के रूप में quasiquote टाइप करना)।

मुझे पता है कि मैं मैन्युअल पैरामीटर परिभाषाओं का निर्माण कर सकते हैं:

val valDefs = pss.map(
    _.map { 
    case (n, t) => ValDef(Modifiers(Flag.PARAM), n, TypeTree(t), EmptyTree) 
    } 
) 

और अब baz संस्करण (एक पैरामीटर सूची के साथ) काम करता है:

q"def baz(..${valDefs.head}) = ???" 

लेकिन नहीं foo संस्करण (एक एकाधिक पैरामीटर सूचियों के साथ)।

तो यहां दो प्रश्न हैं। सबसे पहले, मैं उद्धृत पैरामीटर सूची के संदर्भ के बाहर नाम-प्रकार जोड़ी को पैरामीटर ValDef में बदलने के लिए quasiquotes का उपयोग कैसे कर सकता हूं? और दूसरा, मैं एकाधिक पैरामीटर सूचियों में पैरामीटर परिभाषाओं की सूचियों की सूची कैसे बदल सकता हूं?

पूरे डॉन चीज के लिए मैन्युअल एएसटी निर्माण में वापस आने के लिए काफी आसान है (उदाहरण के लिए my post देखें), लेकिन मैं इसके बजाय quasiquotes का उपयोग करने में सक्षम होना चाहता हूं।

val pss = List(
    List(newTermName("x") -> typeOf[Int], newTermName("y") -> typeOf[Char]), 
    List(newTermName("z") -> typeOf[String]) 
) 
val vparamss: List[List[ValDef]] = pss.map { _.map { case (name, tpe) => q"val $name: $tpe" } } 
q"def foo(...$vparamss)" 

आप विशेष देख सकते हैं ... $ जोड़ आप एक से अधिक तर्क सूची के साथ एक समारोह परिभाषित करने देता है:

+2

1) मेरा मानना ​​है कि q "वैल $ n: $ टी" 2 काम करेंगे) का प्रयोग करें ... $ सूचियों –

+0

की सूची ब्याह करने के लिए 'वैल' पूरी तरह से यहां काम करता है-धन्यवाद! '... उद्धृत किया गया है, हालांकि, मुझे लगता है कि आंतरिक सूचियों को स्वचालित रूप से पैरामीटर सूचियों में नहीं हटाया जाता है? –

उत्तर

4

यहाँ आपकी समस्या का त्वरित समाधान है। फ़ंक्शन तर्क स्वयं को नियमित रूप से वैसे ही दर्शाए जाते हैं।

एक अन्य उदाहरण है जहां ... $ यह उपयोगी हो सकता है:

val xy = List(List(q"x"), List(q"y")) 
q"f(...$xy)" // same as q"f(x)(y)" 
+0

पूरी तरह से काम करता है, धन्यवाद! मैंने पैरामीटर में पैरामीटर सूचियों की सूची डालने का प्रयास नहीं किया था, लेकिन मैं देख सकता हूं कि इसका उपयोग सिंटैक्स के रूप में करने के लिए समझ में आता है। –

संबंधित मुद्दे