2012-06-28 17 views
5

मुझे एक ऐसे प्रोजेक्ट में कुछ मैक्रोज़ को एकीकृत करना होगा जो केक-पैटर्न का उपयोग कर रहा है। उस पैटर्न ने हमें अन्य फायदों के साथ आयात के ज़िलियन से बचने की इजाजत दी, इसलिए हम इसे रखना चाहते हैं। अब, हम कुछ प्रयोगात्मक मैक्रोज़ के साथ एक समस्या का सामना कर रहे हैं जो हम ट्रंक के बाहर परीक्षण कर रहे हैं। सबसे पहले, के एक डमी प्रणाली केक नामित दिखाते हैं:क्या केक-पैटर्न और मैक्रोज़ को एकीकृत करना संभव है?

trait APiece { 
    class A 
} 

trait BPiece { this: APiece => 
    def aMacro(a: A): Unit =() /* macro ??? */ 
} 

trait CPiece { this: APiece with BPiece => 
    def aMacroInvoker = aMacro(new A) 
} 

class Cake { this: APiece with BPiece with CPiece => } 

प्रत्येक एक वर्ग को परिभाषित करता, BPiece एक मैक्रो जो प्रत्येक परिभाषित वर्ग का उपयोग करता है माना जाता है, और अंत में, CPiece मैक्रो invokes। मैंने कहा कि बीपीस एक मैक्रो होना चाहिए क्योंकि मैं इसके लिए कार्यान्वयन कोड करने में असमर्थ था। मैं कई तरीके की कोशिश की है लेकिन मैं हमेशा निम्न त्रुटि के साथ दुर्घटना:

"macro implementation must be in statically accessible object" 

पढ़ना macros code एक अनुमान लगा सकते हैं कि यह एक स्थिर मॉड्यूल में मैक्रो संलग्न करने की आवश्यक है। क्या सिस्टम संरचनाओं का उपयोग करने वाले मैक्रो को तैनात करने का कोई तरीका है?

उत्तर

4

सौभाग्य से आपकी समस्या का एक आसान समाधान है।

लेकिन सबसे पहले, मुझे कुछ पूर्वदर्शी दें। पहले प्रोटोटाइप में, मैक्रोज़ को इस प्रकार परिभाषित किया गया था: def macro aMacro(a: A): Unit = ...। एसआईपी तैयार करते समय हमने जो बड़ी सफलता हासिल की है, उनमें मैक्रो परिभाषाएं (मैक्रोज़ के सार्वजनिक चेहरे) और मैक्रो कार्यान्वयन (पेड़ ट्रांसफार्मर जो मैक्रो लॉजिक होस्ट करते हैं) को अलग कर रहा है। मुझे थोड़ी देर लग गई कि यह कितना अच्छा है, लेकिन अब जब मैं एक मैक्रो घोषणा लिखता हूं तो मैं खुशी से चमक रहा हूं।

तो, अपने प्रश्न पर वापस जाएं। निश्चित रूप से, मैक्रो कार्यान्वयन स्थिर रूप से सुलभ होना चाहिए (अन्यथा, संकलक संकलन के दौरान उन्हें लोड और इनकार करने में सक्षम नहीं होंगे)। यहां तक ​​कि एक अलग संकलन इकाई में

trait BPiece { this: APiece => 
    def aMacro(a: A): Unit = macro Macros.aMacro 
} 

मैक्रो कार्यान्वयन कि जो कुछ भी वस्तु आप चाहते हैं में रखा जा सकता है परिभाषा से जाना जाता है, हालांकि मैक्रो परिभाषाओं ताकि आप उस तरह परिभाषा लिख ​​सकते हैं इस प्रतिबंध नहीं है, ।

पहेली का एकमात्र गायब टुकड़ा यह है कि हम कार्यान्वयन से A को संदर्भित करने जा रहे हैं, क्योंकि A को केक के अंदर परिभाषित किया गया है। सबसे आसान तरीका aMacro जेनेरिक बनाना होगा और टाइप अनुमान पर भरोसा करना होगा:

(अद्यतन: इस उदाहरण को 2.10.0-एम 7 में काम करने के लिए, आपको c.AbsTypeTag के साथ c.TypeTag को प्रतिस्थापित करने की आवश्यकता है; इस उदाहरण को बनाने के लिए 2.10.0-RC1 में काम करते हैं, c.AbsTypeTag) c.WeakTypeTag के साथ प्रतिस्थापित किया

trait BPiece { this: APiece => 
    def aMacro[A](a: A): Unit = macro Macros.aMacro[A] 
} 

object Macros { 
    def aMacro[A: c.TypeTag](c: Context)(a: c.Expr[A]): c.Expr[Unit] = c.literalUnit 
} 

यह आपको reify का उपयोग, हालांकि, क्योंकि एक मैक्रो कार्यान्वयन A के लिए नहीं दूँगी बिना सिर्फ एक प्रकार पैरामीटर है की जरूरत है कोई सदस्य यदि आप मैक्रो से कुछ केक-विशिष्ट वापस लौटना चाहते हैं तो समस्याएं भी हो रही हैं, लेकिन जब वे उठते हैं तो उनके साथ सौदा करते हैं। कृपया, यदि आपको आवश्यकता हो तो फॉलो-अप प्रश्न सबमिट करें।

+2

मुझे नहीं लगता कि उसकी समस्या हल हो जाती है, और मुझे कुछ भी नहीं लगता है। केक पैटर्न का सार - जैसा कि आपको पता होना चाहिए! :-) - "क्लाइंट" कोड में इच्छित परतों को चुनने में सक्षम है। यदि 'मैक्रोज़ स्थिर है, तो आप इसे इच्छानुसार स्विच नहीं कर सकते हैं। आप स्रोत फ़ाइलों या वर्ग फ़ाइलों को स्विच कर सकते हैं, लेकिन आप कोड लिख नहीं सकते जो कहता है "यह यहां से मैक्रोज़ का उपयोग करेगा, और इससे वहां से मैक्रोज़ का उपयोग किया जाएगा"। –

+0

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

+0

@ डैनियल सी। सोब्राल I हालांकि विचार केक के अंदर एक मैक्रो घोषित करना था। यदि आपके पास अलग-अलग परतें हैं जो विभिन्न मैक्रो कार्यान्वयन का जिक्र करते हुए मैक्रोज़ को परिभाषित करती हैं, तो आप उनके बीच स्विच कर सकते हैं और अलग-अलग व्यवहार प्राप्त कर सकते हैं। –

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