आप क्या चाहते हैं करने के लिए एक मैक्रो
एक तरह के व्यायाम के रूप में:
(defmacro setq-every (value &rest vars)
"Set every variable from VARS to value VALUE."
`(progn ,@(mapcar (lambda (x) (list 'setq x value)) vars)))
अब इसे आज़माएँ:
(setq-every "/foo/bar" f-loc1 f-loc2)
यह कैसे काम करता है
चूंकि लोग उत्सुक हैं कि यह कैसे काम करता है (टिप्पणियों के अनुसार), यहां एक स्पष्टीकरण है। वास्तव में यह जानने के लिए कि मैक्रोज़ कैसे लिखें, एक अच्छी कॉमन लिस्प बुक चुनें (हाँ, कॉमन लिस्प, आप Emacs Lisp में वही सामान कर पाएंगे, लेकिन कॉमन लिस्प थोड़ा अधिक शक्तिशाली है और बेहतर किताबें हैं, IMHO)।
मैक्रो कच्चे कोड पर काम करते हैं। मैक्रोज़ अपने तर्कों (कार्यों के विपरीत) का मूल्यांकन नहीं करते हैं। इसलिए हमारे यहां इसका मूल्यांकन value
और संग्रह है vars
, जो हमारे स्थूल के लिए सिर्फ प्रतीक हैं।
progn
setq
एक में कई रूपों समूह । यह चीज:
(mapcar (lambda (x) (list 'setq x value)) vars)
बस setq
प्रपत्रों की एक सूची तैयार करता है , ओपी के उदाहरण का उपयोग करके यह होगा:
((setq f-loc1 "/foo/bar") (setq f-loc2 "/foo/bar"))
आप देखते हैं, प्रपत्र बैकक्वाटर फॉर्म के अंदर है और अल्पविराम के साथ उपसर्ग है
,
। बैकक्लेटेड फ़ॉर्म के अंदर सब कुछ आमतौर पर उद्धृत किया जाता है, लेकिन ,
अस्थायी रूप से "चालू-चालू" मूल्यांकन होता है, इसलिए संपूर्ण mapcar
का मूल्यांकन मैक्रोफैक्टर विस्तार के समय किया जाता है।
अंत में s के @
साथ सूची से बाहरी कोष्ठक निकालता है setq
, इसलिए हम प्राप्त करते हैं:
(progn
(setq f-loc1 "/foo/bar")
(setq f-loc2 "/foo/bar"))
मैक्रो आपके स्रोत कोड को मनमाने ढंग से रूपांतरित कर सकता है, क्या यह महान नहीं है?
एक चेतावनी
यहां एक छोटी सी चेतावनी है, पहले तर्क का मूल्यांकन कई बार किया जाएगा, क्योंकि यह मैक्रो अनिवार्य रूप से निम्नलिखित में फैलता है:
(progn
(setq f-loc1 "/foo/bar")
(setq f-loc2 "/foo/bar"))
आप देखें, यदि आपके पास एक चर या स्ट्रिंग है तो यह ठीक है, लेकिन यदि आप कुछ इस तरह लिखते हैं:
(setq-every (my-function-with-side-effects) f-loc1 f-loc2)
फिर आपके फ़ंक्शन को एक से अधिक बार कॉल किया जाएगा। यह अवांछनीय हो सकता है। यहां बताया गया है कि इसे कैसे ठीक किया जाए once-only
( एमएमटी पैकेज में उपलब्ध
):
(defmacro setq-every (value &rest vars)
"Set every variable from VARS to value VALUE.
VALUE is only evaluated once."
(mmt-once-only (value)
`(progn ,@(mapcar (lambda (x) (list 'setq x value)) vars))))
और समस्या दूर हो गई है।