भाषा को होमोसेक्सुअल कैसे बनाया जाए


16

इस लेख के अनुसार लिस्प कोड की निम्न पंक्ति "हैलो वर्ल्ड" को मानक आउटपुट में प्रिंट करती है।

(format t "hello, world")

लिस्प, जो एक होमोसेक्सुअल भाषा है , इस तरह से डेटा के रूप में कोड का इलाज कर सकता है:

अब कल्पना करें कि हमने निम्नलिखित मैक्रो लिखा है:

(defmacro backwards (expr) (reverse expr))

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

(backwards ("hello, world" t format))

जब लिस्प कंपाइलर कोड की उस लाइन को देखता है, तो यह सूची में पहले परमाणु ( backwards) को देखता है, और नोटिस करता है कि यह एक मैक्रो का नाम देता है। यह ("hello, world" t format)मैक्रो को अनवील किए गए सूची को पास करता है , जो सूची को फिर से व्यवस्थित करता है (format t "hello, world")। परिणामी सूची मैक्रो अभिव्यक्ति को बदल देती है, और यह वह है जो रन-टाइम पर मूल्यांकन किया जाएगा। लिस्प वातावरण देखेगा कि इसका पहला परमाणु ( format) एक फ़ंक्शन है, और इसका मूल्यांकन करें, इसे बाकी तर्कों को पारित करते हुए।

लिस्प में इस कार्य को प्राप्त करना आसान है (मुझे गलत होने पर सही करें) क्योंकि कोड को सूची ( एस-एक्सप्रेशंस ?) के रूप में लागू किया गया है ।

अब इस OCaml (जो एक होमोसेक्सुअल भाषा नहीं है) पर एक नज़र डालें:

let print () =
    let message = "Hello world" in
    print_endline message
;;

कल्पना करें कि आप OCaml में समरूपता जोड़ना चाहते हैं, जो लिस्प की तुलना में बहुत अधिक जटिल वाक्यविन्यास का उपयोग करता है। आप वह कैसे करेंगें? क्या भाषा को समरूपता प्राप्त करने के लिए विशेष रूप से आसान वाक्यविन्यास करना पड़ता है?

EDIT : इस विषय से मुझे होमोसेक्सुअलिटी को प्राप्त करने का एक और तरीका मिला जो लिस्प से अलग है: io भाषा में लागू किया गया । यह आंशिक रूप से इस प्रश्न का उत्तर दे सकता है।

यहाँ, चलो एक साधारण ब्लॉक से शुरू करते हैं:

Io> plus := block(a, b, a + b)
==> method(a, b, 
        a + b
    )
Io> plus call(2, 3)
==> 5

ठीक है, इसलिए ब्लॉक काम करता है। प्लस ब्लॉक ने दो नंबर जोड़े।

अब इस छोटे से साथी पर कुछ आत्मनिरीक्षण करें।

Io> plus argumentNames
==> list("a", "b")
Io> plus code
==> block(a, b, a +(b))
Io> plus message name
==> a
Io> plus message next
==> +(b)
Io> plus message next name
==> +

गर्म पवित्र ठंडा सांचा। न केवल आप ब्लॉक के नाम पा सकते हैं। और न केवल आप ब्लॉक के पूर्ण स्रोत कोड की एक स्ट्रिंग प्राप्त कर सकते हैं। आप कोड में चुपके और संदेशों को अंदर ले जा सकते हैं। और सभी का सबसे अद्भुत: यह भयानक आसान और प्राकृतिक है। आईओ की खोज के लिए सही है। रूबी के दर्पण में से कोई भी नहीं देख सकता है।

लेकिन, जो वाह, हे, अब उस डायल को मत छुओ।

Io> plus message next setName("-")
==> -(b)
Io> plus
==> method(a, b, 
        a - b
    )
Io> plus call(2, 3)
==> -1

1
आप देखना चाहते हैं कि स्काला ने
मैक्रों

1
@Bergi Scala के पास मैक्रोज़ के लिए एक नया तरीका है: scala.meta
मार्टिन बर्गर

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

@PeriataBreatta आप सही हैं, लेकिन सांसद का मुख्य लाभ यह है कि सांसद रन-टाइम जुर्माना के बिना अमूर्तता को सक्षम बनाता है । इस प्रकार सांसद बढ़ती भाषा की जटिलता की कीमत पर अमूर्तता और प्रदर्शन के बीच तनाव को हल करता है। यह इसके लायक है? मैं इस तथ्य को कहूंगा कि सभी प्रमुख पीएल में एमपी एक्सटेंशन हैं, यह दर्शाता है कि बहुत से कार्यशील प्रोग्रामर व्यापार-ऑफ एमपी को उपयोगी प्रदान करते हैं।
मार्टिन बर्गर

जवाबों:


10

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

लिस्प के पास इसके आसान सिंटैक्स के कारण जल्दी था, लेकिन डब्ल्यू ताहा के मेटाएमएल परिवार की भाषाओं ने दिखाया कि किसी भी भाषा के लिए ऐसा करना संभव है।

पूरी प्रक्रिया को मॉडलिंग सजातीय सामान्य मेटा-प्रोग्रामिंग में उल्लिखित किया गया है । उसी सामग्री का अधिक हल्का परिचय यहां दिया गया है


1
यदि मैं गलत हूं तो मुझे सही करों। "मिररिंग" प्रश्न के दूसरे भाग (io lang में समरूपता) से संबंधित है, है ना?
incud

@ मुझे यकीन नहीं है कि मैं आपकी टिप्पणी को पूरी तरह से समझ सकता हूं। समरूपता का उद्देश्य डेटा के रूप में कोड के उपचार को सक्षम करना है। अर्थात किसी भी प्रकार के कोड में डेटा के रूप में एक प्रतिनिधित्व होना चाहिए। इसे करने के कई तरीके हैं (जैसे एएसटी क्वैसी-कोट्स, डेटा से कोड को अलग-अलग करने के लिए जैसे कि लाइट-वेट मॉड्यूलर स्टेजिंग अप्रोच द्वारा किया जाता है), लेकिन सभी को किसी न किसी रूप में भाषा सिंटैक्स के दोहरीकरण / मिररिंग की आवश्यकता होती है।
मार्टिन बर्जर

मुझे लगता है कि MetaOCaml को देखकर @Ignus को फायदा होगा? क्या "होमोसेक्सुअल" होने का मतलब सिर्फ उद्धृत करना है? मेरा मानना ​​है कि मेटामाएल और मेटाओक्लेम जैसी मल्टी-स्टेज लैंग्वेज आगे बढ़ती हैं?
स्टीवन शॉ

1
@StevenShaw MetaOCaml बहुत दिलचस्प है, विशेष रूप से ओलेग के नए BER MetaOCaml । हालांकि, यह कुछ हद तक प्रतिबंधित है कि यह केवल रन-टाइम मेटा-प्रोग्रामिंग करता है, और केवल क्वैसी-कोट्स के माध्यम से कोड का प्रतिनिधित्व करता है जो एएसटी के रूप में अभिव्यंजक नहीं है।
मार्टिन बर्जर

7

Ocaml कंपाइलर Ocaml में ही लिखा गया है, इसलिए निश्चित रूप से Ocaml में Ocaml ASTs में हेरफेर करने का एक तरीका है।

कोई एक निर्मित प्रकार ocaml_syntaxको भाषा में जोड़ने की कल्पना कर सकता है , और एक defmacroअंतर्निहित फ़ंक्शन में, जो कि एक प्रकार का इनपुट लेता है, कहते हैं

f : ocaml_syntax -> ocaml_syntax

अब किस प्रकार का है defmacro? ठीक है कि वास्तव में इनपुट पर निर्भर करता है, जैसे कि fपहचान समारोह है, कोड के परिणामस्वरूप टुकड़े का प्रकार में पारित सिंटैक्स के टुकड़े पर निर्भर है।

यह समस्या लिस्प में उत्पन्न नहीं होती है, क्योंकि भाषा गतिशील रूप से टाइप की जाती है, और संकलन के समय किसी भी प्रकार को मैक्रो में स्वयं को निर्दिष्ट करने की आवश्यकता नहीं होती है। एक समाधान होगा

defmacro : (ocaml_syntax -> ocaml_syntax) -> 'a

जो किसी भी संदर्भ में मैक्रो का उपयोग करने की अनुमति देगा । लेकिन यह असुरक्षित है, निश्चित रूप से, यह एक boolका उपयोग करने की अनुमति देगा string, रन-टाइम पर प्रोग्राम को क्रैश कर सकता है।

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

निष्कर्ष में: जटिल वाक्यविन्यास होना कोई समस्या नहीं है, क्योंकि भाषा के अंदर वाक्यविन्यास का प्रतिनिधित्व करने के कई तरीके हैं, और संभवतः quoteआंतरिक में "सरल" वाक्यविन्यास को एम्बेड करने के लिए ऑपरेशन जैसे मेटा-प्रोग्रामिंग का उपयोग करते हैं ocaml_syntax

समस्या यह अच्छी तरह से टाइप कर रही है, विशेष रूप से एक रन-टाइम मैक्रो तंत्र है जो टाइप त्रुटियों के लिए अनुमति नहीं देता है।

एक संकलन-समय रहा OCaml तरह एक भाषा में मैक्रो के लिए तंत्र निश्चित रूप से संभव है, उदाहरण के लिए देख MetaOcaml

इसके अलावा संभवतः उपयोगी: Ocaml में मेटा-प्रोग्रामिंग पर जेन स्ट्रीट


2
मेटाओक्लेम में रनटाइम-मेटा-प्रोग्रामिंग है, न कि संकलन-समय मेटा-प्रोग्रामिंग। इसके अलावा मेटाकार्ल के टाइपिंग सिस्टम पर निर्भर प्रकार नहीं हैं। (MetaOCaml को टाइप-अनसाउंड भी पाया गया!) टेम्पलेट हास्केल में एक दिलचस्प मध्यवर्ती दृष्टिकोण है: प्रत्येक चरण टाइप-सुरक्षित है, लेकिन एक नए चरण में प्रवेश करते समय, हमें टाइप-चेकिंग फिर से करना चाहिए। यह मेरे अनुभव में वास्तव में अच्छी तरह से काम करता है, और आप अंतिम (रन-टाइम) चरण में टाइप-सुरक्षा के लाभों को ढीला नहीं करते हैं।
मार्टिन बर्जर

@ क्या यह संभव है कि एक्सटेंशन पॉइंट्स के साथ OCaml में मेटाप्रोग्रामिंग भी हो , है ना?
incud

@ इग्नस मैं डरता हूं कि मैं एक्सटेंशन पॉइंट्स के बारे में ज्यादा नहीं जानता, हालांकि मैं जेन स्ट्रीट ब्लॉग के लिंक में इसका संदर्भ देता हूं।
कोड़ी

1
मेरा सी संकलक सी में लिखा है, लेकिन इसका मतलब यह नहीं है कि आप सी में एएसटी में हेरफेर कर सकते हैं ...
ब्लूराजा - डैनी पफ्लुगुफ्ट

2
@ मिनीबिस: जाहिर है, लेकिन अगर उसका यही मतलब है तो वह कथन दोनों ही सवाल से खाली और असंबंधित है ...
BlueRaja - Danny Pflughoeft

1

एक उदाहरण के रूप में F # (OCaml पर आधारित) पर विचार करें। एफ # पूरी तरह से होमोसेक्सुअल नहीं है, लेकिन कुछ परिस्थितियों में एएसटी के रूप में एक फ़ंक्शन का कोड प्राप्त करने का समर्थन करता है।

F # में, आपका printप्रतिनिधित्व Exprउस के रूप में किया जाएगा जो इस प्रकार मुद्रित होता है:

Let (message, Value ("Hello world"), Call (None, print_endline, [message]))

संरचना को बेहतर ढंग से उजागर करने के लिए, यहां एक वैकल्पिक तरीका है कि आप इसे कैसे बना सकते हैं Expr:

let messageVar = Var("message", typeof<string>)
let expr = Expr.Let(messageVar,
                    Expr.Value("Hello world"),
                    Expr.Call(print_endline_method, [Expr.Var(messageVar)]))

मुझे यह समझ नहीं आया। आपका मतलब है कि F # आपको अभिव्यक्ति के एएसटी का "निर्माण" करने देता है और फिर इसे निष्पादित करता है? यदि हां, तो उन भाषाओं के साथ क्या अंतर है जो आपको eval(<string>)फ़ंक्शन का उपयोग करने देती हैं? ( कई संसाधनों के अनुसार, निष्कासन कार्य होमोसेक्सुअलिटी होने से अलग है - क्या यही कारण है कि आपने कहा कि F # पूरी तरह से होमोसेक्सुअल नहीं है?)
incud

@ इग्नस आप एएसटी का निर्माण खुद कर सकते हैं, या आप कंपाइलर को कर सकते हैं। Homoiconicity "भाषा के सभी कोड को डेटा के रूप में एक्सेस और ट्रांसफ़ॉर्म करने की अनुमति देता है" । F # में, आप कुछ कोड को डेटा के रूप में एक्सेस कर सकते हैं । (उदाहरण के लिए, आपको विशेषता के printसाथ चिह्नित करने की आवश्यकता है [<ReflectedDefinition>]।)
svick
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.