एक लिस्प की तरह सिंटैक्स एक्सटेंशन तंत्र के साथ प्रोग्रामिंग भाषाओं [बंद]


20

मुझे केवल लिस्प का सीमित ज्ञान है (अपने खाली समय में थोड़ा सीखने की कोशिश करना) लेकिन जहाँ तक मैं समझता हूँ लिस्प मैक्रोज़ को लिस्प में ही वर्णन करके नई भाषा निर्माण और वाक्य रचना शुरू करने की अनुमति है। इसका मतलब है कि एक नया निर्माण पुस्तकालय के रूप में जोड़ा जा सकता है, बिना लिस्प कंपाइलर / इंटरप्रेटर को बदले।

यह दृष्टिकोण अन्य प्रोग्रामिंग भाषाओं से बहुत अलग है। उदाहरण के लिए, यदि मैं पास्कल को एक नए प्रकार के लूप या कुछ विशेष मुहावरों के साथ विस्तारित करना चाहता था, तो मुझे भाषा के वाक्यविन्यास और शब्दार्थ का विस्तार करना होगा और फिर संकलक में उस नई सुविधा को लागू करना होगा।

क्या लिस्प परिवार के बाहर अन्य प्रोग्रामिंग भाषाएं हैं (यानी कॉमन लिस्प, स्कीम, क्लोजर (?), रैकेट (?), इत्यादि) जो भाषा के भीतर ही भाषा का विस्तार करने की समान संभावना प्रदान करती हैं?

संपादित करें

कृपया, विस्तारित चर्चा से बचें और अपने उत्तरों में विशिष्ट बनें। प्रोग्रामिंग भाषाओं की एक लंबी सूची के बजाय जिसे किसी तरह या किसी अन्य तरीके से बढ़ाया जा सकता है, मैं एक वैचारिक दृष्टिकोण से समझना चाहूंगा कि लिस्प मैक्रो के लिए एक विस्तार तंत्र के रूप में क्या विशिष्ट है, और कौन सी गैर-लिस्प प्रोग्रामिंग भाषाएं कुछ अवधारणा पेश करती हैं उनके करीब है।


6
लिस्प के पास नियमित मैक्रोज़ के अलावा एक और चाल है। "रीडर मैक्रोज़" पार्सर सिंटैक्स को रनटाइम पर कैप्चर करने और विस्तारित करने की अनुमति देता है, इसलिए भाषा का मूल टोकन संरचना भी नियंत्रण में है।
ddyer

@ddyer: धन्यवाद, मुझे इस बारे में नहीं पता था: मेरी पढ़ने की सूची में जोड़ा जाने वाला एक और विषय।
जियोर्जियो

मैं रूबी metaprogramming दांव लगाना चाहते हैं यह पूरा कर सकते हैं।
ऋग्वेद

1
आपका सवाल विरोधाभासी है, पहले आप एक सूची मांगते हैं, फिर आप वैचारिक जानकारी मांगते हैं, यह कौन है ???

मैं एक सूची के लिए कह रहा हूं, लेकिन एक सामान्य नहीं (केवल किसी भी प्रोग्रामिंग भाषा को नहीं बढ़ाया जा सकता है), क्योंकि यह बहुत सामान्य होगा। मैं उन भाषाओं के बारे में जानना चाहूंगा जिन्हें लिस्प के समान विस्तारित किया जा सकता है (विस्तार को उसी भाषा का उपयोग करके परिभाषित किया गया है जो इसे विस्तारित करती है, किसी प्रकार की मेटा-भाषा नहीं)। Péter Török, Thomas Eding, SK-Logic और मैकेनिकल घोंघा के उत्तर मुझे जो मन में आया, उसके सबसे करीब लगते हैं। मुझे अभी भी सभी उत्तर को ध्यान से पढ़ना है।
जियोर्जियो

जवाबों:


19

स्काला इसे भी संभव बनाता है (वास्तव में यह जानबूझकर नए भाषा निर्माणों और यहां तक ​​कि पूर्ण डीएसएल की परिभाषा का समर्थन करने के लिए डिज़ाइन किया गया था)।

उच्च-क्रम के कार्यों के अलावा, लंबदा और करी, जो कार्यात्मक भाषाओं में आम हैं, इस * को सक्षम करने के लिए यहां कुछ विशेष भाषा विशेषताएं हैं: *

  • कोई ऑपरेटर नहीं - सब कुछ एक फ़ंक्शन है, लेकिन फ़ंक्शन नाम में '+', '-' या 'जैसे विशेष वर्ण शामिल हो सकते हैं:'
  • डॉट्स और ब्रेसिज़ को एकल-पैरामीटर विधि कॉल के लिए छोड़ा जा सकता है, अर्थात इनफ़िक्स फ़ॉर्म के a.and(b)बराबर हैa and b
  • एकल-पैरामीटर फ़ंक्शन कॉल के लिए आप सामान्य ब्रेसिज़ के बजाय घुंघराले ब्रैकेट का उपयोग कर सकते हैं - यह (साथ में क्यूरिंग) आपको इस तरह लिखने की अनुमति देता है

    val file = new File("example.txt")
    
    withPrintWriter(file) {
      writer => writer.println("this line is a function call parameter")
    }
    

    जहां withPrintWriterदो पैरामीटर सूचियों के साथ एक सादा तरीका है, दोनों में एक एकल पैरामीटर है

  • नाम के मापदंडों से आप लंबोदा में खाली पैरामीटर सूची को छोड़ सकते हैं, जिससे आप myAssert(() => x > 3)कम रूप में कॉल लिख सकते हैंmyAssert(x > 3)

एक उदाहरण डीएसएल के निर्माण के बारे में अध्याय 11 में विस्तार से चर्चा की गई है । नि: शुल्क पुस्तक प्रोग्रामिंग स्काला के स्काला में डोमेन-विशिष्ट भाषाएं

* मेरा मतलब यह नहीं है कि ये स्काला के लिए अद्वितीय हैं, लेकिन कम से कम वे बहुत सामान्य नहीं लगते हैं। मैं हालांकि कार्यात्मक भाषाओं का विशेषज्ञ नहीं हूं।


1
+1: दिलचस्प है। क्या इसका मतलब यह है कि सिंटैक्स का विस्तार करने के लिए मैं नई कक्षाओं को परिभाषित कर सकता हूं और उस पद्धति पर हस्ताक्षर नए सिंटैक्स को उप-उत्पाद के रूप में प्रदान करेंगे?
जियोर्जियो

@ जियोर्जियो, मूल रूप से हाँ।
पीटर टॉपर

लिंक अब काम नहीं करते।
नैट ग्लेन

13

पर्ल अपनी भाषा के पूर्व-प्रसंस्करण के लिए अनुमति देता है। हालांकि यह अक्सर भाषा में वाक्यविन्यास को मौलिक रूप से बदलने की हद तक उपयोग नहीं किया जाता है, यह कुछ में देखा जा सकता है ... विषम मॉड्यूल:

  • एक्मे :: वास्तव में साफ कोड के लिए ब्लीच
  • एक्मे :: मोर्स कोड में लिखने के लिए मोर्स
  • लिंग :: रोमाना :: लैटिन में लिखने के लिए पर्लीगाटा (उदाहरण के लिए, संज्ञाएं चर और संख्या, केस और डिक्लेरेशन हैं और संज्ञा का प्रकार बदल जाता है अगला ==> $ अगला, अगला ==> @next)

वहाँ भी एक मॉड्यूल मौजूद है जो पर्ल को कोड चलाने की अनुमति देता है जो दिखता है कि यह पायथन में लिखा गया था।

पर्ल के भीतर इसके लिए एक और आधुनिक दृष्टिकोण फ़िल्टर :: सरल (पर्ल 5 में मुख्य मॉड्यूल में से एक) का उपयोग करना होगा ।

ध्यान दें कि उन सभी उदाहरणों में डेमियन कॉनवे शामिल है जिन्हें "मैड डॉक्टर ऑफ पर्ल" के रूप में संदर्भित किया गया है। इसकी अभी भी एक आश्चर्यजनक शक्तिशाली क्षमता है जो भाषा को मोड़ना चाहती है कि वह कैसे चाहता है।

इस और अन्य विकल्पों के लिए अधिक दस्तावेज perlfilter में मौजूद हैं ।


13

हास्केल

हास्केल में "टेम्पलेट हास्केल" के साथ-साथ "क्वासिकोटेशन" भी है:

http://www.haskell.org/haskellwiki/Template_Haskell

http://www.haskell.org/haskellwiki/Quasiquotation

ये सुविधाएँ उपयोगकर्ताओं को नाटकीय रूप से सामान्य साधनों के बाहर भाषा के वाक्य विन्यास में जोड़ने की अनुमति देती हैं। इन्हें संकलन समय पर भी हल किया जाता है, जो मुझे लगता है कि एक बड़ी अवश्य है (संकलित भाषाओं के लिए कम से कम) [1]।

मैंने सी-लाइक भाषा पर एक उन्नत पैटर्न माचिस बनाने से पहले हास्केल में एक बार क्वासिकोटेशन का उपयोग किया है:

moveSegment :: [Token] -> Maybe (SegPath, SegPath, [Token])
moveSegment [hc| HC_Move_Segment(@s, @s); | s1 s2 ts |] = Just (mkPath s1, mkPath s2, ts)
moveSegment _ = Nothing

[1] निम्नलिखित को सिंटैक्स एक्सटेंशन के रूप में उत्तीर्ण करता है:, runFeature "some complicated grammar enclosed in a string to be evaluated at runtime"जो निश्चित रूप से बकवास का भार है।


3
हास्केल की अन्य विशेषताएं भी हैं जो अनिवार्य रूप से कस्टम सिंटैक्स के लिए अनुमति देती हैं, जैसे कि अपना खुद का ऑपरेटर बनाना या लैंबडा फ़ंक्शन के साथ युग्मित स्वचालित करीकरण (उदाहरण के विशिष्ट उपयोग पर विचार करें forM)।
जिओन

मुझे ईमानदारी से लगता है कि करी और कस्टम ऑपरेटर योग्य नहीं हैं। वे एक भाषा का बड़े करीने से उपयोग करने की अनुमति देते हैं, लेकिन वे आपको भाषा में नई / कार्यक्षमता जोड़ने की अनुमति नहीं देते हैं। TH और QQ करते हैं। एक सख्त अर्थ में, न तो TH और QQ इस अर्थ में है कि वे वही करते हैं जो वे करने के लिए डिज़ाइन किए गए हैं, लेकिन वे आपको संकलन समय पर "भाषा से बाहर" जाने की अनुमति देते हैं।
थॉमस ईडिंग सेप

1
"निम्न को सिंटैक्स एक्सटेंशन के रूप में उत्तीर्ण करता है ...": बहुत अच्छा बिंदु।
जियोर्जियो

12

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

proc loopCard23 {cardinalVar squareVar cubeVar body} {
    upvar 1 $cardinalVar cardinal $squareVar square $cubeVar cube

    # We borrow a 'for' loop for the implementation...
    for {set cardinal 0} true {incr cardinal} {
        set square [expr {$cardinal ** 2}]
        set cube [expr {$cardinal ** 3}]

        uplevel 1 $body
    }
}

तब इसका उपयोग इस तरह किया जाएगा:

loopCard23 a b c {
    puts "got triplet: $a, $b, $c"
    if {$c > 400} {
        break
    }
}

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

हालाँकि, यह केवल एक अंश है जो किया जाता है। एम्बेडेड भाषा को Tcl होने की भी आवश्यकता नहीं है; यह वस्तुतः कुछ भी हो सकता है (जब तक यह अपने ब्रेसिज़ को संतुलित करता है - अगर चीजें सही नहीं हैं तो चीजें बहुत भयानक हो जाती हैं - जो कि कार्यक्रमों का सबसे बड़ा हिस्सा है) और Tcl बस आवश्यक रूप से एम्बेडेड विदेशी भाषा को भेज सकती है। ऐसा करने के उदाहरणों में TCL आदेशों को लागू करने के लिए C को एम्बेड करना और फोरट्रान के साथ समतुल्य शामिल हैं। (तर्क से, सभी Tcl की अंतर्निहित कमांड इस तरह से की जाती हैं, कि वे वास्तव में सिर्फ एक मानक पुस्तकालय हैं न कि स्वयं भाषा।)


10

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

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

महत्वपूर्ण सामान्य विशेषता यह है कि वे आपको भाषा के निर्माण को परिभाषित करते हैं जो भाषाओं के संपर्क में आने वाली सुविधाओं का उपयोग करते हुए अंतर्निहित कार्यों के साथ-साथ काम करते हैं। इस सुविधा के लिए समर्थन की डिग्री बदलती है:

  • कई पुराने भाषाओं में निर्मित बशर्ते जैसे कार्यों sin(), round()आदि, अपने खुद के लागू करने के लिए किसी भी तरह से बिना।
  • सी ++ सीमित समर्थन प्रदान करता है। उदाहरण के लिए कुछ बिल्ट-इन डाले जैसे कीवर्ड ( static_cast<target_type>(input), dynamic_cast<>(), const_cast<>(), reinterpret_cast<>()) टेम्पलेट काम करता है, के लिए जो बूस्ट का उपयोग करता है का उपयोग कर नकल करते किया जा सकता है lexical_cast<>(), polymorphic_cast<>(), any_cast<>(), ....
  • जावा (अंतर्निहित नियंत्रण संरचनाओं for(;;){}, while(){}, if(){}else{}, do{}while(), synchronized(){}, strictfp{}) और नहीं करता है आप अपने खुद के परिभाषित करते हैं। स्काला इसके बजाय एक सार सिंटैक्स को परिभाषित करता है जो आपको एक सुविधाजनक नियंत्रण-संरचना-जैसे सिंटैक्स का उपयोग करके फ़ंक्शन को कॉल करने देता है, और लाइब्रेरीज़ नए नियंत्रण संरचनाओं (जैसे react{}एक्टर्स लाइब्रेरी) को प्रभावी ढंग से परिभाषित करने के लिए इसका उपयोग करते हैं ।

इसके अलावा, आप नोटेशन पैकेज में Mathematica की कस्टम सिंटैक्स कार्यक्षमता को देख सकते हैं । (तकनीकी रूप से यह लिस्प परिवार में है, लेकिन कुछ एक्स्टेंसिबिलिटी फीचर्स अलग तरह से किए गए हैं, साथ ही साथ सामान्य लिस्पेबिलिटी भी है।)


2
गलत। लिस्प है वास्तव में आप एक नया वाक्य रचना की पूरी तरह से किसी भी प्रकार जोड़ने के लिए अनुमति देते हैं। जैसे इस उदाहरण में: meta-alternative.net/pfront.pdf - यह एक लिस्प मैक्रो के अलावा कुछ भी नहीं है।
एसके-लॉजिक

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

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

और, योजना आम लिस्प से अलग नहीं है, आर 6 आरएस से आधिकारिक तौर पर शुरू होती है, और अनौपचारिक रूप से उम्र के लिए, क्योंकि यह एक (define-macro ...)समकक्ष प्रदान करता है , जो बदले में आंतरिक रूप से किसी भी प्रकार के पार्सिंग का उपयोग कर सकता है।
एसके-लॉजिक

8

Rebol लगभग वही लगता है जो आप वर्णन कर रहे हैं, लेकिन थोड़ा बग़ल में।

विशिष्ट सिंटैक्स को परिभाषित करने के बजाय, रेबोल में सब कुछ एक फ़ंक्शन कॉल है - कोई कीवर्ड नहीं हैं। (हां, आप फिर से परिभाषित कर सकते हैं ifऔर whileयदि आप वास्तव में चाहते हैं)। उदाहरण के लिए, यह एक ifबयान है:

if now/time < 12:00 [print "Morning"]

ifएक फ़ंक्शन है जो 2 तर्क लेता है: एक शर्त और एक ब्लॉक। यदि स्थिति सही है, तो ब्लॉक का मूल्यांकन किया जाता है। अधिकांश भाषाओं की तरह लगता है, है ना? खैर, ब्लॉक एक डेटा संरचना है, यह कोड तक ही सीमित नहीं है - यह ब्लॉक का एक ब्लॉक है, उदाहरण के लिए, और "कोड के लचीलेपन का एक त्वरित उदाहरण डेटा है":

SomeArray: [ [foo "One"] [bar "Two"] [baz "Three"] ]
foreach action SomeArray [action/1: 'print] ; Change the data
if now/time < 12:00 SomeArray/2 ; Use the data as code - right now, if now/time < 12:00 [print "Two"]

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


7

रूबी के पास काफी लचीला वाक्यविन्यास है, मुझे लगता है कि यह "भाषा के भीतर ही भाषा का विस्तार करें" का एक तरीका है।

एक उदाहरण रेक है । यह रूबी में लिखा है, यह रूबी है, लेकिन यह मेक की तरह दिखता है ।

कुछ संभावनाओं की जांच करने के लिए आप रूबी और मेटाप्रोग्रामिंग कीवर्ड की तलाश कर सकते हैं ।


13
"लचीला सिंटैक्स" "एक्सटेन्सिबल सिंटैक्स" से बहुत अलग है। रूबी में प्रोग्राम किए हुए एक लंबा समय हो गया है, लेकिन रेक सिर्फ बिल्ट-इन सिंटैक्स के एक अच्छी तरह से डिज़ाइन किए गए उपयोग की तरह दिखता है। दूसरे शब्दों में, यह एक गैर-उदाहरण है।
थॉमस एडिंग

2
क्या यह डिग्री का मामला नहीं है? आप एक "एक्स्टेंसिबल सिंटैक्स" भाषा के बीच अंतर कैसे करेंगे जो इसके सिंटैक्स के कुछ पहलुओं को बढ़ा सकती है, लेकिन दूसरों को नहीं, और "लचीली सिंटैक्स" भाषा को?
21

1
यदि लाइन धुंधली है, तो चलो लाइन को पीछे धकेलें ताकि C को एक्स्टेंसिबल सिंटैक्स का समर्थन करने के लिए माना जाए।
थॉमस ईडिंग सेप

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

किसी भी ट्यूरिंग पूरी भाषा को मेक फाइल्स को प्रोसेस करने में सक्षम होना चाहिए। सिंटैक्स की लचीलेपन से परे एक कारक नहीं है कि यह कितनी चुनौती होगी।
ऋग्वेद

7

सिंटैक्स को जिस तरह से आप के बारे में बात कर रहे हैं उसे बढ़ाने से आप डोमेन विशिष्ट भाषाओं को बनाने की अनुमति देते हैं। तो शायद आपके प्रश्न को फिर से समझने का सबसे उपयोगी तरीका है, डोमेन विशिष्ट भाषाओं के लिए अन्य भाषाओं का क्या अच्छा समर्थन है?

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

आर, सांख्यिकीय कंप्यूटिंग के लिए भाषा, कार्यों को उनके तर्कों को बिना शर्त प्राप्त करने की अनुमति देता है। यह प्रतिगमन फॉर्मूला निर्दिष्ट करने के लिए एक डीएसएल बनाने के लिए इसका उपयोग करता है। उदाहरण के लिए:

y ~ a + b

का अर्थ है "y में मूल्यों के लिए k0 + k1 * a + k2 * b के रूप में एक पंक्ति फिट करें।"

y ~ a * b

का अर्थ है "y में मानों के लिए k0 + k1 * a + k2 * b + k3 * a * फॉर्म की एक पंक्ति को फिट करें।"

और इसी तरह।


2
ग्रूवी के एएसटी ट्रांसफॉर्मेस लिस्प या क्लोझर मैक्रोज़ की तुलना में बहुत क्रियात्मक हैं। उदाहरण के लिए groovy.codehaus.org/Global+AST+Transformations पर 20+ लाइन ग्रूवी उदाहरण क्लोजर में एक छोटी लाइन के रूप में फिर से लिखा जा सकता है, जैसे `(यह (प्रिंट्ल ~ संदेश))। इतना ही नहीं बल्कि आपको जार को संकलित करने के लिए, मेटाडेटा, या उस ग्रूव पृष्ठ पर किसी भी अन्य सामान को लिखना नहीं होगा।
Vorg van Geir

7

एकाग्र एक और एक गैर lispy metaprogramming भाषा है। और, कुछ हद तक, C ++ भी योग्य है।

यकीनन, मेटाक्लेमल लिस्प से काफी दूर है। वाक्यविन्यास विलुप्त होने की एक पूरी तरह से अलग शैली के लिए, लेकिन अभी तक काफी शक्तिशाली है, CamlP4 पर एक नज़र डालें

निम्फेल एक अन्य विलुप्त होने वाली भाषा है जिसमें लिस्प-शैली मेटाप्रोग्रामिंग है, हालांकि यह स्काला जैसी भाषाओं के करीब है।

और, स्काला खुद भी जल्द ही ऐसी भाषा बन जाएगी

संपादित करें: मैं सबसे दिलचस्प उदाहरण के बारे में भूल गया - JetBrains MPS । यह केवल लिस्पिश से बहुत दूर नहीं है, यह एक गैर-पाठीय प्रोग्रामिंग प्रणाली भी है, जिसमें संपादक एक एएसटी स्तर पर सीधे काम करता है।

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


आपका स्काला लिंक स्पष्ट रूप से कहता है कि प्रस्तावित मैक्रोज़ "स्काला का सिंटैक्स नहीं बदल सकता है"। (दिलचस्प है, यह इसे उस प्रस्ताव और C / C ++ प्रीप्रोसेसर मैक्रोज़ के बीच अंतर के रूप में सूचीबद्ध करता है!)
ruakh

@ruakh, हाँ, यह Converge और Template Haskell के समान ही है - मैक्रो एप्लिकेशन स्पष्ट रूप से चिह्नित है और इसे "सामान्य" सिंटैक्स के साथ नहीं मिलाया जा सकता है। लेकिन, आपके अंदर कोई भी वाक्यविन्यास आपको पसंद आ सकता है, इसलिए यकीनन यह एक एक्स्टेंसिबल सिंटैक्स है। "गैर-लिस्प" आवश्यकता, दुर्भाग्य से, इस तरह से भाषाओं के लिए आपके विकल्पों को सीमित करती है।
SK-

"मैंने इसे सादे सी के साथ भी किया है": यह कैसे संभव है?
जियोर्जियो

@Giorgio, निश्चित रूप से मैंने एक संकलक (जोड़ा मैक्रोज़ और एक वृद्धिशील मॉड्यूल संकलन) को संशोधित किया है, जो वास्तव में सी के लिए काफी स्वाभाविक है)।
एसके-तर्क

एएसटी तक पहुंच क्यों आवश्यक है?
इलियट गोरोखोवस्की

6

प्रोलॉग नए ऑपरेटरों को परिभाषित करने की अनुमति देता है जो उसी नाम के यौगिक शब्दों में अनुवादित होते हैं। उदाहरण के लिए, यह एक has_catऑपरेटर को परिभाषित करता है और यह जाँचने के लिए एक विधेय के रूप में परिभाषित करता है कि क्या किसी सूची में परमाणु है cat:

:- op(500, xf, has_cat).
X has_cat :- member(cat, X).

?- [apple, cat, orange] has_cat.
true ;
false.

xfका मतलब है कि has_catएक पोस्टफ़िक्स ऑपरेटर है, का उपयोग करते हुए fxयह एक उपसर्ग ऑपरेटर xfxबना देगा , और इसे दो तर्क लेते हुए एक इन्फिक्स ऑपरेटर बना देगा। चेक इस लिंक Prolog में ऑपरेटरों को परिभाषित करने के बारे में अधिक जानकारी के लिए।


5

TeX पूरी तरह से सूची से गायब है। आप सभी इसे जानते हैं, है ना? यह कुछ इस तरह दिखता है:

Some {\it ``interesting''} example.

... सिवाय इसके कि आप प्रतिबंधों के बिना वाक्यविन्यास को फिर से परिभाषित कर सकते हैं। भाषा में प्रत्येक (!) टोकन को एक नया अर्थ सौंपा जा सकता है। कॉनटेक्स एक मैक्रो पैकेज है, जिसने चौकोर ब्रेसेस के साथ घुंघराले ब्रेसिज़ को बदल दिया है:

Some \it[``interesting''] example.

अधिक सामान्य मैक्रो पैकेज LaTeX भी अपने उद्देश्यों के लिए भाषा को फिर से परिभाषित करता है, जैसे \begin{environment}…\end{environment}वाक्य रचना को जोड़ना ।

लेकिन यह वहाँ बंद नहीं करता है। तकनीकी रूप से, आप निम्न को पार्स करने के लिए टोकन को फिर से परिभाषित कर सकते हैं:

Some <it>“interesting”</it> example.

हाँ, बिलकुल संभव है। कुछ पैकेज छोटे डोमेन-विशिष्ट भाषाओं को परिभाषित करने के लिए इसका उपयोग करते हैं। उदाहरण के लिए, TikZ पैकेज तकनीकी ड्राइंग के लिए एक संक्षिप्त सिंटैक्स को परिभाषित करता है, जो निम्नलिखित की अनुमति देता है:

\foreach \angle in {0, 30, ..., 330} 
  \draw[line width=1pt] (\angle:0.82cm) -- (\angle:1cm);

इसके अलावा, TeX पूरा हो रहा है ताकि आप सचमुच इसके साथ सब कुछ कर सकें। मैंने इसे अपनी पूरी क्षमता के लिए कभी नहीं देखा है क्योंकि यह बहुत व्यर्थ और बहुत जटिल होगा लेकिन यह पूरी तरह से निम्न कोड को केवल टोकन को फिर से परिभाषित करने के लिए संभव बनाने के लिए संभव है (लेकिन यह संभवतः पार्सर की भौतिक सीमाओं के कारण जाएगा, जिस तरह से इसे बनाया गया है):

for word in [Some interesting example.]:
    if word == interesting:
        it(word)
    else:
        word

5

बू आपको सिंटैक्टिक मैक्रोज़ के माध्यम से संकलन-समय पर भारी भाषा को अनुकूलित करने देता है।

बू में "एक्स्टेंसिबल कम्पाइलर पाइपलाइन" है। इसका मतलब है कि कंपाइलर पाइपलाइन के दौरान किसी भी बिंदु पर एएसटी रूपांतरण करने के लिए आपके कोड को कॉल कर सकता है। जैसा कि आप जानते हैं, जावा की जेनेरिक या सी # लाइनक जैसी चीजें संकलन समय पर सिर्फ वाक्यविन्यास रूपांतरण हैं, इसलिए यह है काफी शक्तिशाली है।

लिस्प की तुलना में, मुख्य लाभ यह है कि यह किसी भी प्रकार के सिंटैक्स के साथ काम करता है। बू एक पायथन से प्रेरित वाक्यविन्यास का उपयोग कर रहा है, लेकिन आप शायद C या Pascal वाक्यविन्यास के साथ एक एक्स्टेंसिबल कंपाइलर लिख सकते हैं। और चूंकि मैक्रो का संकलन समय पर मूल्यांकन किया गया है, इसलिए कोई प्रदर्शन जुर्माना नहीं है।

लिस्प की तुलना में डाउनसाइड्स हैं:

  • एएसटी के साथ काम करना एस-भावों के साथ काम करने के रूप में सुरुचिपूर्ण नहीं है
  • चूंकि मैक्रो का संकलन समय पर किया जाता है, इसलिए इसमें रनटाइम डेटा तक पहुंच नहीं होती है।

उदाहरण के लिए, यह है कि आप एक नई नियंत्रण संरचना कैसे लागू कर सकते हैं:

macro repeatLines(repeatCount as int, lines as string*):
    for line in lines:
        yield [| print $line * $repeatCount |]

उपयोग:

repeatLines 2, "foo", "bar"

जो तब संकलित समय पर, कुछ इस तरह से अनुवादित हो जाता है:

print "foo" * 2
print "bar" * 2

(दुर्भाग्य से, बू का ऑनलाइन प्रलेखन हमेशा पुराना है और इस तरह से उन्नत सामान को कवर भी नहीं करता है। मुझे पता है कि भाषा के लिए सबसे अच्छा दस्तावेज यह पुस्तक है: http://www.manning.com/rahien/ )


1
इस सुविधा के लिए वेब दस्तावेज़ वर्तमान में टूट गया है, और मैं खुद Boo नहीं लिखता, लेकिन मुझे लगा कि अगर इसे अनदेखा किया गया तो यह एक दया होगी। मैं मॉड फीडबैक की सराहना करता हूं और इस पर पुनर्विचार करूंगा कि कैसे मैं अपने खाली समय में मुफ्त जानकारी देने में योगदान देता हूं।
दान

4

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

fuzzy[a_ && b_]      := Min[fuzzy[a], fuzzy[b]]
fuzzy[a_ || b_]      := Max[fuzzy[a], fuzzy[b]]
fuzzy[!a_]           := 1-fuzzy[a]
If[fuzzy[a_], b_,c_] := fuzzy[a] * fuzzy[b] + fuzzy[!a] * fuzzy[c]

यह पूर्वनिर्धारित तार्किक संचालकों के मूल्यांकन को ओवरराइड करता है &&, || और अंतर्निर्मितIf खंड।

आप इन परिभाषाओं को फ़ंक्शन परिभाषाओं की तरह पढ़ सकते हैं, लेकिन वास्तविक अर्थ यह है: यदि कोई अभिव्यक्ति बाईं ओर वर्णित पैटर्न से मेल खाती है, तो इसे सही पक्ष पर अभिव्यक्ति के साथ बदल दिया जाता है। आप इस तरह से अपने स्वयं के खंड को परिभाषित कर सकते हैं:

myIf[True, then_, else_] := then
myIf[False, then_, else_] := else
SetAttributes[myIf, HoldRest]

SetAttributes[..., HoldRest] मूल्यांकनकर्ता को बताता है कि उसे पैटर्न के मिलान से पहले पहले तर्क का मूल्यांकन करना चाहिए, लेकिन पैटर्न के मिलान और प्रतिस्थापित होने के बाद बाकी के लिए मूल्यांकन को पकड़ें।

यह बड़े पैमाने पर Mathematica मानक पुस्तकालयों के अंदर प्रयोग किया जाता है जैसे Dकि एक फ़ंक्शन को परिभाषित करने के लिए जो एक अभिव्यक्ति लेता है और इसके प्रतीकात्मक व्युत्पन्न का मूल्यांकन करता है।


3

मेटलुआ एक भाषा और एक संकलक है जो लुआ के साथ संगत है जो इसे प्रदान करता है।

  • लुआ 5.1 स्रोतों और बाइटकोड के साथ पूर्ण संगतता: स्वच्छ, सुरुचिपूर्ण शब्दार्थ और वाक्यविन्यास, अद्भुत अभिव्यंजक शक्ति, अच्छा प्रदर्शन, लगभग-सार्वभौमिक पोर्टेबिलिटी। - एक पूर्ण मैक्रो सिस्टम, जो कि लिस्प बोलियों या टेम्प्लेट हास्केल द्वारा की गई शक्ति के समान है; हेरफेर किए गए कार्यक्रमों
    को स्रोत कोड के रूप में देखा जा सकता है , सार सिंटैक्स पेड़ों के रूप में, या
    इसके मनमाने मिश्रण के रूप में , जो भी इस कार्य को बेहतर तरीके से सूट करता है।
  • एक गतिशील रूप से एक्स्टेंसिबल पार्सर, जो आपको अपने मैक्रोज़ को एक सिंटैक्स के साथ समर्थन करने देता है जो बाकी भाषा के साथ अच्छी तरह से मिश्रण करता है।

  • भाषा एक्सटेंशन का एक सेट, सभी को नियमित रूप से मेटलुआ मैक्रोज़ के रूप में लागू किया गया है।

लिस्प के साथ अंतर:

  • जब वे एक नहीं लिख रहे हों तो मैक्रो के साथ डेवलपर्स को परेशान न करें: जब हम मैक्रोज़ नहीं लिख रहे हैं, तो भाषा का वाक्यविन्यास और शब्दार्थ उन 95% के लिए सबसे उपयुक्त होना चाहिए।
  • डेवलपर्स को भाषा के सम्मेलनों का पालन करने के लिए प्रोत्साहित करें: न केवल "सर्वोत्तम प्रथाओं के साथ किराए पर" कोई भी नहीं सुनता है, लेकिन एक एपीआई की पेशकश करके जो धातुआ वे को लिखने के लिए आसान बनाता है। साथी डेवलपर्स द्वारा पठनीयता संकलनकर्ताओं द्वारा पठनीयता की तुलना में अधिक महत्वपूर्ण और अधिक कठिन है, और इसके लिए, सम्मानित सम्मेलनों का एक सामान्य सेट होने से बहुत मदद मिलती है।
  • फिर भी सभी सत्ता को संभालने के लिए तैयार हैं। न तो लुआ और न ही मेटलुआ अनिवार्य बंधन और अनुशासन में हैं, इसलिए यदि आप जानते हैं कि आप क्या कर रहे हैं, तो भाषा आपके रास्ते में नहीं आएगी।
  • यह स्पष्ट करें जब कुछ दिलचस्प होता है: सभी मेटा-ऑपरेशन + {...} और - {...} के बीच होते हैं, और नेत्रहीन नियमित कोड से बाहर रहते हैं।

आवेदन का एक उदाहरण एमएल-जैसे पैटर्न मिलान का कार्यान्वयन है।

इसे भी देखें: http://lua-users.org/wiki/MetaLua


यद्यपि लुआ वास्तव में एक लिस्प नहीं है, लेकिन "अंतर" की आपकी सूची काफी संदिग्ध है (केवल प्रासंगिक आइटम अंतिम एक है)। और, ज़ाहिर है, लिस्प समुदाय एक शेख़ी से सहमत नहीं होगा कि किसी को 95% मैक्रोज़ लिखना / उपयोग नहीं करना चाहिए - लिस्प रास्ता मैक्रो के ऊपर, डीएसएल का उपयोग करने और लिखने के समय की 95% की तरह कुछ की ओर झुकता है, निश्चित रूप से पाठ्यक्रम।
एसके-लॉजिक

2

यदि आप ऐसी भाषाओं की तलाश कर रहे हैं जो विस्तार योग्य हैं, तो आपको स्मॉलटाक पर एक नज़र डालनी चाहिए।

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

आप Smalltalk में स्टैंड-अलोन एप्लिकेशन नहीं लिखते हैं, आप इसके बजाय भाषा-परिवेश का विस्तार करते हैं।

की जाँच करें http://www.world.st/ संसाधनों और सूचना के एक मुट्ठी भर के लिए।

मैं छोटी सी दुनिया में प्रवेश की बोली के रूप में फारो की सिफारिश करना चाहता हूं: http://pharo-project.org

आशा है कि यह मदद की!


1
दिलचस्प लगता है।
थॉमस एडिंग

1

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

इसलिए, भाषा X का व्याकरण लेना संभव होगा, भाषा X का व्याकरण परिभाषित करें '(X आपके कस्टम एक्सटेंशन के साथ) और परिवर्तन X' → X, और Spoofax एक संकलक X '→ X उत्पन्न करेगा।

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


1

फोर्थ एक और भाषा है जो अत्यधिक विस्तार योग्य है। कई फोर्थ कार्यान्वयन में कोडांतरक या C में लिखे गए छोटे कर्नेल होते हैं, फिर शेष भाषा फोर्थ में ही लिखी जाती है।

कई स्टैक-आधारित भाषाएं भी हैं जो फोर्थ से प्रेरित हैं और इस सुविधा को साझा करती हैं, जैसे कि फैक्टर


0

Funge-98

फ़ंज -98 की फ़िंगरप्रिंट सुविधा से भाषा के संपूर्ण सिंटैक्स और शब्दार्थ के पूर्ण पुनर्गठन की अनुमति दी जा सकती है। लेकिन केवल अगर कार्यान्वयनकर्ता एक फिंगरप्रिंट तंत्र की आपूर्ति करता है, जो उपयोगकर्ता को लैंगॉएज को प्रोग्रामेटिक रूप से बदलने की अनुमति देता है (यह सैद्धांतिक रूप से सामान्य फ़ंज -98 सिंटैक्स और शब्दार्थ के भीतर लागू करना संभव है)। यदि ऐसा है, तो कोई शाब्दिक रूप से शेष फ़ाइल (या फ़ाइल के कुछ हिस्से) C ++ या लिस्प (या जो कुछ भी चाहता है) के रूप में कार्य कर सकता है।

http://quadium.net/funge/spec98.html#Fingerprints


आपने अपने पिछले उत्तर में जोड़ने के बजाय इसे अलग से क्यों पोस्ट किया ?
gnat

1
क्योंकि फन्गे का हास्केल से कोई लेना-देना नहीं है।
थॉमस एडिंग

-1

आप जो ढूंढ रहे हैं उसे पाने के लिए वास्तव में उन कोष्ठकों और वाक्यविन्यास की कमी की आवश्यकता होती है। कुछ वाक्यविन्यास-आधारित भाषाएँ करीब आ सकती हैं, लेकिन यह एक सच्चे मैक्रो के रूप में एक ही बात नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.