2012-05-26 20 views
6

के लिए इंटरमीडिएट प्रतिनिधित्व मैं क्लोजर में एक डीएसएल डिजाइन कर रहा हूं जिसका उपयोग कोड जेनरेटर (इस मामले में प्रक्रियात्मक छवि संश्लेषण के लिए - clisk) के लिए किया जाता है और मुझे मध्यवर्ती मूल्यों के लिए सर्वोत्तम प्रतिनिधित्व करने में परेशानी हो रही है ।लिस्प/क्लोजर डीएसएल

मूल रूप से डीएसएल में ऐसे कार्यों शामिल थे जो एक या अधिक रूपों को लौटाते थे, उदा। (चित्रकारी)

(v+ 1.0 [1.0 'y]) 
=> ['(+ 1.0 1.0) '(+ 1.0 y)] 

इन कार्यों को कोड के बड़े ब्लॉक बनाने के लिए बनाया जा सकता है।

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

मुझे यकीन है कि यह लिस्प दुनिया में एक हल समस्या है - आमतौर पर इस तरह के डीएसएल के लिए सबसे अच्छा मध्यवर्ती प्रतिनिधित्व क्या होगा?

उत्तर

7

कभी भी आपको मध्यवर्ती प्रतिनिधित्व की आवश्यकता होती है जिसका उपयोग कोड उत्पन्न करने के लिए किया जाएगा, मेरे दिमाग में सबसे स्पष्ट चीज एक सार वाक्यविन्यास पेड़ (एएसटी) है। आपका उदाहरण प्रतिनिधित्व सूचियां है, जो मेरे अनुभव में एक रूप के रूप में लचीला नहीं है। छोटी सी चीज पीढ़ी से ज्यादा किसी चीज के लिए, मैं झाड़ी के चारों ओर नहीं मारूंगा, और बस एक पूर्ण उड़ा हुआ एएसटी प्रतिनिधित्व के साथ जाऊंगा। सूचियों का उपयोग करके, आप पीढ़ी के पक्ष में अधिक प्रकार के काम को पुश करने के लिए और जैसे पहले आइटम का अर्थ विश्लेषण करते हैं। एएसटी प्रतिनिधित्व में जाने से आपको अधिक लचीलापन मिल जाएगा और पार्सिंग साइड से अधिक काम की लागत (या फॉर्म उत्पन्न करने वाले कार्यों से अधिक काम) की लागत पर, सिस्टम के अधिक से अधिक decouples। पीढ़ी की ओर से और भी काम कर रहे हैं, लेकिन उन घटकों में से कई को डीकॉप्लेड किया जा सकता है क्योंकि उनके इनपुट अधिक संरचित होंगे।

क्या एएसटी देखो की तरह, मैं या तो क्रिस्टोफ़ ग्रांड के लू ए, नकल हैं चाहिए जहां वह {:tag <tag name> :attrs <map of attrs> :content <some collection>}

का उपयोग करता है या क्या clojure स्क्रिप्ट का उपयोग करता है, {:op <some operator> :children <some collection>} के संदर्भ में।

यह जब से तुम मनमाना वॉकर कि :children में झांक सकते हैं परिभाषित कर सकते हैं और क्या :op की या :tag के बारे में वास्तव में जानने के बिना किसी भी संरचना पार कर सकते हैं यह काफी सामान्य बनाता है।

फिर परमाणु घटकों के लिए, आप इसे मानचित्र में लपेट सकते हैं और इसे कुछ प्रकार की जानकारी (अपने डीएसएल के अर्थशास्त्र के संबंध में) दे सकते हैं जो वस्तु के वास्तविक प्रकार से स्वतंत्र है। {:atom <the object> :type :background-image}

कोड जनरेशन पक्ष पर, जब परमाणु का सामना करना पड़ता है, तो आपका कोड :type पर प्रेषित कर सकता है, और फिर, यदि आप चाहते हैं, तो ऑब्जेक्ट के वास्तविक प्रकार पर आगे प्रेषण करें। संग्रह रूपों से जनरेशन भी आसान है, प्रेषण: op /: टैग, और फिर बच्चों के साथ दोबारा शुरू करें। बच्चों के लिए किस संग्रह का उपयोग करना है, मैं Google समूहों पर चर्चा पर और अधिक पढ़ूंगा। उनके निष्कर्ष मेरे लिए प्रबुद्ध थे।

https://groups.google.com/forum/#!topic/clojure-dev/vZLVKmKX0oc/discussion

इस तरह के एक अगर बयान में के रूप में बच्चों के लिए संक्षेप में, है, अगर वहाँ अर्थ आदेश महत्व थे, तो एक नक्शा {:conditional z :then y :else x} का उपयोग करें। अगर यह सिर्फ एक तर्क सूची थी, तो आप एक वेक्टर का उपयोग कर सकते हैं।

+0

बहुत धन्यवाद - बस अंतर्दृष्टि की तरह मैं ढूंढ रहा था! – mikera

1

मुझे लगता है कि मुझे समझ में नहीं आता है। मैं सिर्फ सूचियों या संरचनाओं का उपयोग करता हूं।

लिस्प में, सूचियों में कुछ भी शामिल हो सकता है। मुझे कहना चाहिए, एक कंस सेल कुछ भी इंगित कर सकता है और इस प्रकार सूची में कुछ भी शामिल हो सकता है। तो बहुत अधिक डेटा संरचना (संरचनाएं, सरणी, मानचित्र, आदि) बहुत अधिक कर सकते हैं।

अब, ये संरचनाएं प्रिंटर द्वारा प्रस्तुत करने योग्य नहीं हैं, या कुछ पठनीय (रीड द्वारा) में प्रस्तुत की जाती हैं, लेकिन इसका मतलब यह नहीं है कि उन्हें संग्रहीत और कुशलता से नहीं बदला जा सकता है।

क्या कोई कारण है कि आपको इस प्रतिनिधित्व को बाहरी करने की आवश्यकता है?

+0

आखिरकार मैं फॉर्म का उपयोग करके फॉर्म को संकलित करना चाहता हूं उदा। '(eval \' (fn [xyz] ~ form-to-compile) जैसे कुछ का उपयोग करना) - यह एम्बेडेड ऑब्जेक्ट्स के साथ काम नहीं करता है (देखें http://stackoverflow.com/questions/10735701/embedding-arbitrary- ऑब्जेक्ट-इन-क्लोजर-कोड) – mikera

1

वास्तव में कोई जवाब नहीं है, क्योंकि मुझे नहीं पता कि क्लोजर इस संबंध में कैसे काम करता है, लेकिन सीएल में पाठक मैक्रोज़ विशेष रूप से इस मामले के लिए डिज़ाइन किए गए हैं: यानी आप अनपेक्षित वस्तुओं को प्रिंट करने के लिए अपने फ़ंक्शन को परिभाषित करेंगे + एक पाठक मैक्रो जो उन्हें मुद्रित करने के तरीके से पढ़ता है। वस्तुओं को मुद्रित करने के तरीके को परिभाषित करने के लिए आप एक नई विधि print-object परिभाषित करेंगे जो आपको आवश्यक वस्तु के प्रकार और set-macro-character पर रीडटेबल में फ़ंक्शन जोड़ने के लिए माहिर है जो जानता है कि आपके डिज़ाइन की ऑब्जेक्ट को कैसे पढ़ा जाए।

कई चीजों के बारे में पता होना चाहिए, लेकिन आमतौर पर टाइमर बम की तरह कार्य करने वाले कुछ मामले होते हैं, जब ऑब्जेक्ट्स को खुद को संदर्भित करने की अनुमति दी जाती है, इस मामले में प्रिंटिंग को पहले मुद्रित वस्तुओं पर विचार करने की आवश्यकता होती है।