Monday 15 July 2013

scala - Macro access to members of object where macro is defined -


मेरे पास एक विशेषता है Foo जो कि मैं एक प्रारंभिक मान i < कोड>

  val foo = new Foo (6) // class Foo (i: Int)   

और मैं बाद में एक secondMethod < / Code> बदले में कॉल myMacro

  foo.secondMethod (7) // def secondMethod (j: int) = macro myMacro   

फिर, myMacro को i (6) का प्रारंभिक मान कैसे खोज सकता हूँ?

मैं सामान्य संकलन प्रतिबिंब के साथ सफल नहीं हुआ c.prefix , c.eval (...) आदि लेकिन इसके बजाय एक 2-परियोजना समाधान मिला:

प्रोजेक्ट बी:

  ऑब्जेक्ट संकलन B {def resultB (x: int, y: int) = मैक्रो परिणाम B_impl def resultB_impl (c: context) (x: c.Expr [int], y: c.exp [int]) = C.universe.reify (x.splice * y.splice)}   

परियोजना ए (परियोजना बी पर निर्भर करता है):

  गुण फू {val i : Int // पास के माध्यम से 'i` के संकलन को B: def लागू (y: int) = Compilati OnB.resultB (i, y)} वस्तु संकलन A {def makeFoo (x: int): Foo = macro makeFoo_impl def makeFoo_impl (c: context) (x: c.Expr [int]): c.Expr [Foo] = c .universe.reify (new foo {val i = x.splice}}}   

हम एक Foo बना सकते हैं और i मूल्य सामान्य तात्कालिकता के साथ या makeFoo जैसे मैक्रो के साथ। दूसरा दृष्टिकोण हमें पहले संकलन में समय संकलित करने पर Foo को कस्टमाइज़ करने की अनुमति देता है और फिर दूसरे संकलन में इनपुट ( i इस मामले में) की प्रतिक्रिया को और भी अनुकूलित करता है! किसी भी तरह से हमें "मेटा-मेटा" क्षमताओं (या "पैतृक़ीय" -कपनीयताएं) मिलती हैं- आमतौर पर हमें i को आत्मसात करने के लिए क्षेत्र में फू होना पड़ता है (साथ में उदाहरण सी। एवल (...))। लेकिन i वस्तु को Foo ऑब्जेक्ट के अंदर सहेज कर हम इसे किसी भी समय एक्सेस कर सकते हैं और हम Foo कहीं भी इन्स्तांत कर सकते हैं:

  ऑब्जेक्ट टेस्ट ऐप {import CompilationA._ // सामान्य प्रारम्भिक वाल foo1 = नया फू {val i = 7} val r1 = foo1 (6) // मेक्रो इंस्टीटियंस वैल foo2 = मेकफू (7) val r2 = foo2 ( 6) // "करीड" अभिवादन वैल आर 3 = मेकफू (6) (7) प्रिंट्लएन ("परिणाम 1 2 3: $ आर 1 $ आर 2 $ आर 3") जोर देकर ((आर 1, आर 2, आर 3) == (42, 42) , मेरे उदाहरण के मैक्रो के अंदर इस डबल के बिना मुझे  i  मिल सकता है, 42))}   

मेरा प्रश्न

Foo के सदस्यों तक पहुंचना आसान हो गया है।

डबल संकलन का सहारा लेने के बिना मैक्रो के अंदर। यहां हमारा उदाहरण मैक्रो i के मूल्य तक पहुंच सकता है:

  val i = c.Expr [int] (चयन करें (c.prefix.tree, TermName ( "I"))) को संशोधित करें (i.splice * j.splice)   

सटीक होना, i वास्तव में एक एक्सप्र हम एक मूल्य के रूप में एक संख्या मान के रूप में reify

के साथ काम कर सकते हैं और काम कर सकते हैं। हाँ, यह एक मैक्रो ( प्रक्रिया ) के अंदर संभव है ऑब्जेक्ट ( Foo ) का मैसेज ( i ) का उपयोग सदस्यों को एक संकलन के भीतर परिभाषित किया गया है ( Foo ) ("परिभाषित" I इसका अर्थ है कि मैं मैक्रो कीवर्ड का उपयोग करता हूं):

  वस्तु संकलन {def makeFoo (x: int): Foo = macro makeFoo_impl def makeFoo_impl (c: context) (x : C.Expr [Int]): सी। एक्सप्र [Foo] = c.universe.reify (नया Foo {val i = x.splice}) def प्रक्रिया (c: context) (j: c.exp [int]) : C.Expr [Int] = {import c.universe._ // Foo.i मैक्रो वैल I = c.Expr [Int] के अंदर पहुँचा (चयन करें (c.prefix.tree, TermName ("i")) संशोधित करें (I.splice * j.splice)}} गुण Foo {val I: Int def apply (j: int) = मैक्रो संकलन। प्रोजेक्ट} ऑब्जेक्ट टेस्ट में एप {आयात संकलन। _ Val foo1 = new Foo {val i = 6} कंसोल println foo1 (7) // 42 val foo2 विस्तारित करता है = मेकफू (6) कंसोल प्रिंट्लान फू 2 (7) // 42 कंसोल प्रिंटलेन मेकफू (6) (7) // 42}   

मुझे फ़्रांसको बेलोमी द्वारा एक प्रश्न / उत्तर के लिए यह समाधान देना है / यूजीन बर्माको जो स्कैला-उपयोगकर्ता सूची में मिलीं।

एक तरफ नोट के रूप में, हमें जरूरी नहीं कि c.eval (...) का उपयोग करने की ज़रूरत नहीं है वास्तविक मूल्य से एक Expr से कुछ untyped [यह कहना सही है?] पेड़ ज्यादातर मामलों में हमें एक एक्सप्र में लिप होने वाला मान प्राप्त करना चाहिए, क्योंकि हम उसे उस महत्व को संशोधित करने के द्वारा उस मूल्य को जैसा मान का उपयोग कर सकते हैं (ब्याह-) मूल्य के साथ हमारे सभी गणना करते हैं!

No comments:

Post a Comment