मैक्रो का उपयोग करने के लिए या उपयोग नहीं करने के लिए [बंद]


12

मुझे अपने कार्यक्रम में मैक्रो का उपयोग कब करना चाहिए या नहीं करना चाहिए?

यह प्रश्न @tarsius द्वारा एक जानकारीपूर्ण उत्तर से प्रेरित है। मेरा मानना ​​है कि कई लोगों के पास दूसरों को साझा करने के लिए बहुत अच्छे अनुभव हैं। मुझे उम्मीद है कि यह सवाल ग्रेट सब्जेक्टिव प्रश्नों में से एक बन गया है और Emacs प्रोग्रामर की मदद करता है।

जवाबों:


13

अंगूठे का नियम

सिंटैक्स के लिए मैक्रोज़ का उपयोग करें , लेकिन शब्दार्थ के लिए कभी नहीं

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

क्यों?

मैक्रोज़ में बहुत कमियां हैं:

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

1
लेक्सिकल बाइंडिंग बनाम मैक्रो विस्तार पर नोट्स विशेष रूप से दिलचस्प हैं; धन्यवाद चंद्रगुप्त (मैं कभी नहीं सक्रिय कर दिया है किसी भी कोड मैं लिखा है के लिए शाब्दिक बाध्यकारी, तो यह एक संघर्ष है कि मैंने कभी के बारे में सोचा था नहीं है।)
फिल्स

6

मेरे पढ़ने, डिबगिंग और मेरे और दूसरों के संभावित कोड को संशोधित करने के अनुभव से मैं यथासंभव मैक्रोज़ से बचने का सुझाव दूंगा।

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

यह नुकसान कार्यों पर लागू नहीं होता है: फ़ंक्शन कॉल से पहले सभी आर्गनों का मूल्यांकन किया जाता है। जिसका अर्थ है कि आप एक अज्ञात डिबगिंग स्थिति में विकसित हो सकते हैं। आप सीधे तौर पर आपके लिए अनजान कार्यों की परिभाषा को भी सीधे छोड़ सकते हैं, जब तक कि वे सीधा डेटा वापस नहीं करते हैं, और आप मानते हैं कि वे वैश्विक स्थिति को नहीं छूते हैं।

इसे दूसरे तरीके से तैयार करने के लिए, मैक्रोज़ भाषा का हिस्सा बन जाता है। यदि आप अज्ञात मैक्रोज़ के साथ एक कोड पढ़ रहे हैं, तो आप लगभग एक ऐसी भाषा में एक कोड पढ़ रहे हैं जिसे आप नहीं जानते हैं।

उपरोक्त आरक्षण के अपवाद:

मानक मैक्रो चाहते push, pop, dolistवास्तव में आप के लिए बहुत कुछ करते हैं, और अन्य प्रोग्रामर के लिए जाना जाता है। वे मूल रूप से भाषा युक्ति का हिस्सा हैं। लेकिन अपने स्वयं के मैक्रो को मानकीकृत करना व्यावहारिक रूप से असंभव है। न केवल उपरोक्त उदाहरणों की तरह कुछ सरल और उपयोगी के साथ आना मुश्किल है, बल्कि इसे सीखने के लिए हर प्रोग्रामर को आश्वस्त करना भी कठिन है।

इसके अलावा, मुझे मैक्रोज़ से कोई आपत्ति नहीं है save-selected-window: वे स्टोर करते हैं और राज्य को पुनर्स्थापित करते हैं और अपने आर्ग्स का मूल्यांकन उसी तरह prognकरते हैं। बहुत सीधा, वास्तव में कोड को सरल बनाता है।

ओके मैक्रोज़ का एक और उदाहरण सामान की तरह defhydraया हो सकता है use-package। ये मैक्रोज़ मूल रूप से अपनी खुद की मिनी-भाषा के साथ आते हैं। और वे अभी भी सरल डेटा का इलाज करते हैं, या जैसे कार्य करते हैं progn। इसके अलावा वे आम तौर पर शीर्ष स्तर पर होते हैं, इसलिए मैक्रो तर्कों पर निर्भर होने के लिए कॉल स्टैक पर कोई चर नहीं हैं, जिससे यह थोड़ा सरल हो जाता है।

मेरी राय में magit-section-actionऔर magit-section-caseमैगिट में एक खराब मैक्रो का एक उदाहरण है । पहला वाला पहले ही हटा दिया गया था, लेकिन दूसरा अभी भी बना हुआ है।


4

मैं कुंद हो जाऊंगा: मुझे समझ नहीं आ रहा है कि "सिंटैक्स के लिए क्या उपयोग किया जाए, न कि शब्दार्थ के लिए"। यही कारण है कि इस उत्तर का हिस्सा चंद्र के उत्तर से निपटेगा , और दूसरा भाग मूल प्रश्न का उत्तर देने का मेरा प्रयास होगा।

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

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

  1. defun और दोस्तों, जो भाषा का एक अनिवार्य हिस्सा हैं उन्हीं शब्दों में वर्णित नहीं किया जा सकता है, जिन्हें आप फ़ंक्शन कॉल का वर्णन करेंगे।

  2. setfअभिव्यक्ति के प्रभावों का वर्णन करने के लिए कार्य कैसे कार्य करते हैं, यह वर्णन अपर्याप्त है (setf (aref x y) z)

  3. with-output-to-stringमैक्रो के अंदर कोड के शब्दार्थ को भी बदलता है। इसी तरह, with-current-bufferऔर अन्य with-मैक्रोज़ का एक गुच्छा ।

  4. dotimes और इसी तरह के कार्यों के संदर्भ में वर्णित नहीं किया जा सकता है।

  5. ignore-errors कोड के शब्दार्थ को बदल देता है।

  6. cl-libपैकेज, eieioपैकेज और कुछ अन्य लगभग सर्वव्यापी लाइब्रेरी में परिभाषित मैक्रोज़ का एक पूरा गुच्छा है जो Emacs Lisp में उपयोग किया जाता है, जबकि ऐसा लग सकता है कि फ़ंक्शन रूपों की अलग-अलग व्याख्याएं हैं।

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


जब मैं मैक्रोज़ का उपयोग नहीं करूंगा:

  1. जब वे किसी भी नए निर्माण का परिचय नहीं देते हैं, तो नए शब्दार्थ के साथ (जैसे कि फ़ंक्शन अच्छा काम करेगा)।

  2. जब यह सिर्फ एक प्रकार की सुविधा है (अर्थात एक मैक्रो बनाने का नाम है mvbजो cl-multiple-value-bindकेवल इसे छोटा बनाने के लिए फैलता है )।

  3. जब मैं मैक्रो द्वारा छिपे हुए त्रुटि हैंडलिंग कोड की बहुत उम्मीद करता हूं (जैसा कि नोट किया गया है, मैक्रोज़ डिबग करना मुश्किल है)।


जब मैं दृढ़ता से कार्यों पर मैक्रोज़ पसंद करूंगा:

  1. जब डोमेन-विशिष्ट अवधारणाओं को फ़ंक्शन कॉल द्वारा अस्पष्ट किया जाता है। उदाहरण के लिए, यदि किसी को उसी contextतर्क को कार्यों के एक समूह में पारित करने की आवश्यकता होती है जिसे उत्तराधिकार में बुलाया जाना चाहिए, तो मैं उन्हें एक मैक्रो में लपेटना पसंद करूंगा, जहां contextतर्क छिपा हुआ है।

  2. जब फ़ंक्शन रूप में सामान्य कोड अत्यधिक क्रिया है (Emacs में नंगे पुनरावृत्ति निर्माण लिस्प मेरे स्वाद के लिए बहुत क्रियात्मक हैं और अनावश्यक रूप से प्रोग्रामर को निम्न-स्तरीय कार्यान्वयन विवरण में उजागर करते हैं)।


चित्रण

नीचे दिया गया संस्करण नीचे दिया गया है, जिसका अर्थ है कि कंप्यूटर विज्ञान में शब्दार्थ से एक अंतर्ज्ञान देना।

मान लीजिए कि आपके पास इन सिंटैक्स नियमों के साथ एक अत्यंत सरल प्रोग्रामिंग भाषा है:

variable := 1 | 0
operation := +
expression := variable | (expression operation expression)

इस भाषा के साथ हम जैसे "कार्यक्रमों" का निर्माण कर सकते (1+0)+1या 0या ((0+0))आदि

लेकिन जब तक हम शब्दार्थ नियम प्रदान नहीं करते, ये "कार्यक्रम" निरर्थक हैं।

मान लीजिए कि अब हम अपनी भाषा को (शब्दार्थ) नियमों से लैस करते हैं:

0+0  0+1  1+0  1+1  (exp)
---, ---, ---, ---, -----
 0   1+0   1    0    exp

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

जब हम भाषाओं के लिस्प परिवार के बारे में बात करते हैं, तो फ़ंक्शन मूल्यांकन के बुनियादी शब्दार्थ नियम मोटे तौर पर लंबो-कैलकुलस के होते हैं:

(f x)  (lambda x y)   x
-----, ------------, ---
 fx        ^x.y       x

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

(a . b)
-------
(cons a b)

यह वास्तव में Emacs लिस्प में एक मैक्रो नहीं है, लेकिन यह हो सकता था। मैंने केवल सादगी के लिए चुना। ध्यान दें कि ऊपर परिभाषित कोई भी नियम इस मामले पर लागू नहीं होगा क्योंकि निकटतम उम्मीदवार एक फ़ंक्शन के रूप में (f x)व्याख्या fकरता है, जबकि aआवश्यक रूप से एक फ़ंक्शन नहीं है।


1
"Syntactic चीनी" वास्तव में कंप्यूटर विज्ञान में एक शब्द नहीं है। यह विभिन्न चीजों का मतलब करने के लिए इंजीनियरों द्वारा उपयोग किया जाता है। तो मेरे पास कोई निश्चित जवाब नहीं है। चूंकि हम शब्दार्थ के बारे में बात कर रहे हैं, तो, फॉर्म के सिंटैक्स की व्याख्या करने के लिए नियम: (x y)मोटे तौर पर "y का मूल्यांकन करें, फिर पिछले मूल्यांकन के परिणाम के साथ x कॉल करें"। जब आप लिखते हैं (defun x y), तो y का मूल्यांकन नहीं किया जाता है और न ही x है। चाहे आप अलग-अलग शब्दार्थों का उपयोग करके समान प्रभाव वाला एक कोड लिख सकते हैं, लेकिन स्वयं के शब्दार्थ वाले कोड के इस टुकड़े को अस्वीकार नहीं करता है।
wvxvw

1
पुन: आपकी दूसरी टिप्पणी: क्या आप कृपया मुझे उस मैक्रो की परिभाषा का उल्लेख कर सकते हैं जिसका आप उपयोग कर रहे हैं जो कहती है कि आप क्या दावा करते हैं? मैंने आपको केवल एक उदाहरण दिया है जहाँ एक स्थूल के माध्यम से नया शब्दार्थ नियम प्रस्तुत किया गया है। कम से कम सीएस के सटीक अर्थों में। मुझे नहीं लगता कि परिभाषाओं के बारे में बहस करना उत्पादक है, और मुझे यह भी लगता है कि सीएस में इस्तेमाल की जाने वाली परिभाषाएं इस चर्चा के लिए सबसे अच्छा मेल हैं।
wvxvw

1
ठीक है ... आपको अपना स्वयं का विचार है कि "शब्दार्थ" शब्द का क्या अर्थ है, जो विडंबना की तरह है, अगर आप इसके बारे में सोचते हैं :) लेकिन वास्तव में, इन चीजों की बहुत सटीक परिभाषाएं हैं, आप बस, अच्छी तरह से .. उन पर ध्यान न दें। उत्तर में जो पुस्तक मैंने लिंक की है वह सीमैटिक्स पर एक मानक पाठ्यपुस्तक है जैसा कि सीएस में पाठ्यक्रम में पढ़ाया गया है। यदि आप सिर्फ विकी के संबंधित लेख को पढ़ते हैं: en.wikipedia.org/wiki/Semantics_%28computer_science%29 आप देखेंगे कि यह वास्तव में क्या है। उदाहरण (defun x y)फ़ंक्शन फ़ंक्शन की व्याख्या करने के लिए नियम है ।
wvxvw

ओह ठीक है, मुझे नहीं लगता कि यह चर्चा करने का मेरा तरीका है। यह भी एक कोशिश और एक शुरुआत करने के लिए एक गलती थी; मैंने अपनी टिप्पणियों को हटा दिया, इस सब का कोई मतलब नहीं है। मुझे आपका समय बर्बाद करने के लिए खेद है।
22
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.