2012-07-26 19 views
5

में लेबलडिफ का उपयोग करके मैं स्कैला 2.10 मैक्रो सुविधाओं के साथ प्रयोग कर रहा हूं। मुझे कुछ मामलों में लेबलडिफ का उपयोग करने में परेशानी है। कुछ हद तक मैंने कंपाइलर के कोड में देखा, Miguel Garcia's papers के अंश पढ़ें लेकिन मैं अभी भी अटक गया हूं।
स्कैला मैक्रोज़ (2.10)

तो मेरी समझ सही है, एक छद्म परिभाषा होगा:
LabelDef(labelName, listOfParameters, stmsAndApply) जहां 3 तर्क पेड़ हैं और:
- labelName लेबल $ एल के पहचानकर्ता
परिभाषित किया जा रहा है - listOfParameters जब label- लागू होता है, में $ एल के रूप में तर्क पारित कर दिया के अनुरूप (A1, ..., एक), और खाली
हो सकता है - stmsAndApply ब्लॉक से मेल खाती है बयान (संभवतः कोई नहीं) और अंतिम के लागू -expression
अर्थ लेबल से लागू अधिक या कम एक लेबल

उदाहरण के लिए करने के लिए एक गोटो, एक साधारण पाश के मामले में, एक LabelDef कर सकते हैं अंत में ही लागू:
LabelDef($L,(), {...; $L()})

अब, अगर मैं 2 LabelDef कि एक दूसरे के लिए कूद परिभाषित करना चाहते हैं:

... 
LabelDef($L1,(), $L2()) 
... 
LabelDef($L2,(), $L1()) 
... 

दूसरा लेबलडिफ ठीक है, लेकिन कंपाइलर पहले पर एक त्रुटि आउटपुट करता है, "नहीं मिला: मान $ L2"। मुझे लगता है कि ऐसा इसलिए है क्योंकि $ L2 अभी तक परिभाषित नहीं किया गया है जबकि इसे लागू करने का प्रयास किया गया है। यह एक पेड़ बनाया जा रहा है जिससे मुझे समझ में आ जाए। क्या मेरी समझ अब तक सही है? क्योंकि अगर कोई त्रुटि अपेक्षित नहीं है, तो इसका मतलब है कि मेरा मैक्रो कार्यान्वयन शायद छोटी है।

वैसे भी, मेरा मानना ​​है कि वहाँ (अर्थात $ एल 2 के लिए कूदते) $ एल 1 से, $ एल 2 लागू करने के लिए किसी भी तरह एक तरह से होना चाहिए, लेकिन मैं तो बस कोई सुराग नहीं है कि यह कैसे करना है। क्या किसी के पास ऐसा करने का कोई उदाहरण है, या कोई सूचक?


अन्य अस्पष्ट अंक (लेकिन अभी का कोई खास महत्व) मैक्रो में LabelDef उपयोग के बारे में कर रहे हैं:
-क्या 2 तर्क वस्तुतः, है, यह जब गैर खाली किया जाता है? दूसरे शब्दों में, पैरामीटर के साथ एक लेबल-तंत्र के तंत्र क्या हैं?
- क्या यह लेबल के लागू होने के अलावा तीसरे तर्क की अंतिम अभिव्यक्ति में कुछ भी वैध है? (ऐसा नहीं है कि मैं कोशिश नहीं कर सकता, लेकिन मैक्रोज़ अभी भी प्रयोगात्मक हैं)
-क्या एक फ़ॉरवर्डिंग लेबल निष्पादित करना संभव है-लेबलडिफ़ के बाहर लागू करें? (शायद यह एक अनावश्यक सवाल है)

उत्तर में कोई भी मैक्रो कार्यान्वयन उदाहरण निश्चित रूप से बहुत स्वागत है!
चीयर्स,

+0

यह मैं अंत में संबंधित * स्केला को पढ़ने के लिए था http://groups.google.com/group/scala-internals –

+0

@Eugene पर इस पूछने के लिए एक अच्छा विचार हो सकता है - आंतरिक * धागे। हालांकि ऐसा लगता है कि स्कैला 2.11 से 'लेबलडिफ' छोड़ना पहले ही तय किया जा चुका है (और कार्यान्वित)। जबकि मैं एक आंतरिक दृष्टिकोण से प्रेरणा को समझता हूं, 'लेबल' के आधार पर 'गोटो' -श सुविधाओं के साथ डीएसएल प्रभावित होंगे, मुझे विश्वास है (उदा। जेएमवी 'गोटो 'निर्देश के बजाय, वर्कअराउंड निर्देशों का एक समूह)। क्या आपके पास कोई इनपुट है? – eruve

+0

यह निश्चित रूप से अभी तक लागू नहीं हुआ है, क्योंकि लेबलडिफ अभी भी 2.11 शाखा में हैं: https://github.com/scala/scala/blob/master/src/reflect/scala/reflect/internal/Trees.scala। मैंने http://groups.google.com/group/scala-internals/browse_thread/thread/50c8643af1fe0973 पर एक प्रश्न पूछा है - कृपया, अपनी चिंताओं में शामिल हों और साझा करें। –

उत्तर

1

क्योंकि अगर कोई त्रुटि अपेक्षित नहीं है, तो इसका मतलब है कि मेरा मैक्रो कार्यान्वयन संभवतः छोटी है।
हां, ऐसा लगता है कि यह एक बग था (^^; हालांकि मुझे यकीन नहीं है कि ब्लॉक/लेबलडिफ संयोजन के साथ सीमा उद्देश्य पर मौजूद है या नहीं।

def EVIL_LABELS_MACRO = macro EVIL_LABELS_MACRO_impl 
def EVIL_LABELS_MACRO_impl(c:Context):c.Expr[Unit] = { // fails to expand 
    import c.universe._ 
    val lt1 = newTermName("$L1"); val lt2 = newTermName("$L2") 
    val ld1 = LabelDef(lt1, Nil, Block(c.reify{println("$L1")}.tree, Apply(Ident(lt2), Nil))) 
    val ld2 = LabelDef(lt2, Nil, Block(c.reify{println("$L2")}.tree, Apply(Ident(lt1), Nil))) 
    c.Expr(Block(ld1, c.reify{println("ignored")}.tree, ld2)) 
} 

def FINE_LABELS_MACRO = macro FINE_LABELS_MACRO_impl 
def FINE_LABELS_MACRO_impl(c:Context):c.Expr[Unit] = { // The End isn't near 
    import c.universe._ 
    val lt1 = newTermName("$L1"); val lt2 = newTermName("$L2") 
    val ld1 = LabelDef(lt1, Nil, Block(c.reify{println("$L1")}.tree, Apply(Ident(lt2), Nil))) 
    val ld2 = LabelDef(lt2, Nil, Block(c.reify{println("$L2")}.tree, Apply(Ident(lt1), Nil))) 
    c.Expr(Block(ld1, c.reify{println("ignored")}.tree, ld2, c.reify{println("The End")}.tree)) 
} 

मुझे लगता है कि एक ब्लॉक को {स्टेटमेंट में पार्स किया गया है; अभिव्यक्ति} इस प्रकार अंतिम तर्क अभिव्यक्ति है। यदि लेबलडिफ अभिव्यक्ति पर "गिरता है", उदा। EVIL_LABELS_MACRO पैटर्न, इसका विस्तार कथन में दिखाई नहीं देगा; इसलिए त्रुटि "नहीं मिली: मान $ L2"।

तो यह सुनिश्चित करना बेहतर है कि सभी लेबलडिफ स्टेटमेंट पर "पतन" करें। FINE_LABELS_MACRO करता है और फैलता है करने के लिए:

{ 
    $L1(){ 
    scala.this.Predef.println("$L1"); 
    $L2() 
    }; 
    scala.this.Predef.println("ignored"); 
    $L2(){ 
    scala.this.Predef.println("$L2"); 
    $L1() 
    }; 
    scala.this.Predef.println("The End") 
} 
+0

क्या यह 'एम्प्टी ट्री' के साथ समाप्त हो सकता है? –

+0

मुझे लगता है कि 'एम्प्टी ट्री' में कोई प्रकार संलग्न नहीं है, _even not_ 'scala.Nothing', इस प्रकार _expression_ पर लागू नहीं है। मेरे उदाहरण में अंत कभी नहीं पहुंचता है, लेकिन 'सी.एक्सप्र' का 'ब्लॉक' 'लिटल (कॉन्सटेंट (())) के साथ समाप्त हो सकता है, क्योंकि मैक्रो को 'यूनिट' प्राप्त करना होगा। – eruve

+0

@ डैनियल: यदि आपका मतलब 'लेबलडिफ' था, तो मैं _believe_ तीसरे तर्क के पेड़ के साथ-साथ _expression_ उत्पन्न करना चाहिए, इसलिए कोई 'खाली नहीं'। मुझे नहीं पता कि भविष्य में वह _valid_ रहेगा, लेकिन तीसरा तर्क अनिवार्य रूप से _label-apply_ आवश्यक नहीं है। – eruve

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