कई चर के लिए एक ही मूल्य असाइन करना?


12

कभी-कभी मुझे एक ही मूल्य को कई चरों पर सेट करना पड़ता है।

पायथन में, मैं कर सकता था

f_loc1 = f_loc2 = "/foo/bar"

लेकिन संभ्रांत में, मैं लिख रहा हूं

(setq f_loc1 "/foo/bar" f_loc2 "/foo/bar")

मैं सोच रहा था कि क्या "/foo/bar"केवल एक बार इसका उपयोग करने का कोई तरीका है ?


1
नमस्ते, चिल्लर, क्या आप स्वीकार किए गए के रूप में @tarsius 'उत्तर का चयन कर सकते हैं? मेरा उत्तर उस समाधान को प्रदर्शित करता है जो आपको वह देता है जो आप चाहते हैं, लेकिन जैसा कि मैंने कहा कि यह "एक प्रकार का व्यायाम" है जो इस यकीनन कृत्रिम चुनौती को हल करता है लेकिन व्यवहार में बहुत उपयोगी नहीं है। तारसुइस ने अपने उत्तर में इस स्पष्ट विचार को प्रदर्शित करने में बहुत प्रयास किया है, इसलिए मुझे लगता है कि उसका उत्तर "सही" होने के योग्य है, इसलिए हर कोई फिर से खुश है।
मार्क कारपोव

1
मेरा तर्क है कि एक से अधिक वेरिएबल्स को एक ही मान असाइन करने की आवश्यकता एक डिज़ाइन दोष को इंगित करती है जिसे कवर करने के लिए सिंटैक्टिक शुगर की तलाश के बजाय तय किया जाना चाहिए :)
lunaryorn

1
अगर चाहते हैं निर्धारित करने के लिए @lunaryorn sourceऔर targetशुरुआत में एक ही पथ के लिए और मैं बदल सकता है targetबाद में, उन्हें कैसे तो स्थापित करने के लिए?
चिल्लरअनंद

अधिक कोड दिखाएं, इसलिए हम बता सकते हैं कि आपके उपयोग के मामले में "चर" से आपका क्या मतलब है; यानी, आप किस तरह के वैरिएबल सेट करने की कोशिश कर रहे हैं। @ JordonBiondo के जवाब के लिए मेरी टिप्पणी देखें।
आकर्षित किया

जवाबों:


21

setq मान लौटाता है, ताकि आप बस:

(setq f-loc1 (setq f-loc2 "/foo/bar"))

यदि आप उस पर भरोसा नहीं करना चाहते हैं, तो उपयोग करें:

(setq f-loc1 "/foo/bar" f-loc2 f-loc1)

व्यक्तिगत रूप से मैं बाद वाले से बचूंगा और इसके बजाय लिखूंगा:

(setq f-loc1 "/foo/bar"
      f-loc2 f-loc1)

या और भी

(setq f-loc1 "/foo/bar")
(setq f-loc2 f-loc1)

और बहुत पहले दृष्टिकोण मैं केवल विशेष परिस्थितियों में उपयोग करूंगा जहां यह वास्तव में इरादे पर जोर देता है, या जब विकल्प दूसरे दृष्टिकोण या अन्य का उपयोग करना होगा progn


आप यहाँ पढ़ना बंद कर सकते हैं यदि उपरोक्त आपको खुश करता है। लेकिन मुझे लगता है कि यह आपको और दूसरों को मैक्रों को गाली न देने का एक अच्छा मौका है।


अंत में, जबकि यह setq-every"क्योंकि यह लिस्प है और हम कर सकते हैं" जैसे मैक्रो लिखने के लिए लुभा रहे हैं, मैं ऐसा करने के खिलाफ दृढ़ता से अनुशंसा करूंगा। आप इसे करके बहुत कम लाभ प्राप्त करते हैं:

(setq-every value a b)
   vs
(setq a (setq b value))

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

आप हर बार जब आप देखते हैं setq-everyया आप सिर्फ एक अतिरिक्त चरित्र के साथ रह सकते हैं, तो आप उस मानसिक उपरि से निपट सकते हैं । (कम से कम उस स्थिति में जहां आपको केवल दो चर सेट करने हैं, लेकिन मुझे यह याद नहीं है कि मुझे कभी भी एक ही मूल्य पर दो से अधिक चर सेट करने थे। यदि आपको ऐसा करना है, तो शायद कुछ और है। आपके कोड के साथ।)

दूसरी ओर यदि आप वास्तव में इस मैक्रो का उपयोग शायद आधा दर्जन से अधिक बार करने जा रहे हैं, तो अतिरिक्त अप्रत्यक्ष इसके लायक हो सकता है। उदाहरण के लिए मैं पुस्तकालय --when-letसे मैक्रोज़ का उपयोग करता हूं dash.el। यह उन लोगों के लिए कठिन बना देता है जो पहली बार मेरे कोड में आते हैं, लेकिन यह समझने में कठिनाई पर काबू पाने के लायक है कि इसका उपयोग बहुत कम बार किया जाता है और, कम से कम मेरी राय में, यह कोड को अधिक पठनीय बनाता है ।

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


1
आपके द्वारा एक संस्करण निर्धारित करने के बाद setq, यह नया मान हो सकता है, इसलिए आप इस राक्षसी का भी उपयोग कर सकते हैं: (setq a 10 b a c a d a e a)जो abcd और e को 10. पर सेट करता है
जॉर्डन बियोन्डो

1
@ जोर्डनबियोनडो, हाँ, लेकिन मुझे लगता है कि ओपी का उद्देश्य अपने कोड में पुनरावृत्ति को कम करना है :-)
मार्क कारपोव

3
मैं आपको मैक्रो दुरुपयोग के खिलाफ चेतावनी के लिए +10 देना चाहता हूं!
चंद्रग्रहण 15

बस मैक्रो बेस्ट प्रैक्टिस के बारे में एक खोज बनाई। emacs.stackexchange.com/questions/21015 । आशा है @tarsius और अन्य एक शानदार जवाब देते हैं।
यशी शुजी

13

आप क्या चाहते हैं करने के लिए एक मैक्रो

एक तरह के व्यायाम के रूप में:

(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, जो हमारे स्थूल के लिए सिर्फ प्रतीक हैं।

prognsetqएक में कई रूपों समूह । यह चीज:

(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))))

और समस्या दूर हो गई है।


1
अच्छा होगा यदि आप कुछ स्पष्टीकरण जोड़ सकते हैं कि यह कैसे काम करता है और यह कोड और अधिक विस्तार से क्या कर रहा है, इसलिए अगली बार लोग खुद कुछ ऐसा लिख ​​सकते हैं :)
क्लेमर

आप valueमैक्रो-विस्तार समय पर मूल्यांकन नहीं करना चाहते हैं ।
tarsius

@ टार्सियस, मैं नहीं: (macroexpand '(setq-every user-emacs-directory f-loc1 f-loc2))-> (progn (setq f-loc1 user-emacs-directory) (setq f-loc2 user-emacs-directory))। यदि valueस्थूल विस्तार के समय पर मूल्यांकन किया गया था तो इसे वास्तविक स्ट्रिंग के साथ प्रतिस्थापित किया जाएगा। आप फ़ंक्शन कॉल को साइड इफेक्ट के साथ रख सकते हैं, के स्थान पर value, इसका मूल्यांकन तब तक नहीं किया जाएगा जब तक कि विस्तारित कोड नहीं चलाया जाता है, इसे आज़माएं। valueचूंकि मैक्रो के तर्क का स्वचालित रूप से मूल्यांकन नहीं किया जाता है। असली मुद्दा यह है कि valueकई बार मूल्यांकन किया जाएगा, जो अवांछनीय हो सकता है, once-onlyयहां मदद कर सकता है।
मार्क कार्पोव

1
इसके बजाय mmt-once-only(जिसे बाहरी डिपो की आवश्यकता है), आप उपयोग कर सकते हैं macroexp-let2
यंगफ्रॉग

2
ओह। सवाल यह है कि मैक्रो में setलपेटने के लिए नहीं, इसके साथ पुनरावृत्ति का उपयोग करने के लिए रोता है setq। या सिर्फ setqकई आर्गों के साथ उपयोग करें , जिसमें आर्गन्स की पुनरावृत्ति भी शामिल है।
ड्रू

7

चूंकि आप लिस्प में प्रतीकों का उपयोग और हेरफेर कर सकते हैं, आप बस प्रतीकों और उपयोग की सूची पर लूप कर सकते हैं set

(dolist (var '(foo bar baz)) (set var 10))

(mapc (lambda (var) (set var 10)) '(foo bar baz))

(loop for var in '(foo bar baz) do (set var 11))

(--each '(foo bar baz) (set it 10))

2
हालांकि यह lexically बाध्य चर के लिए काम नहीं करता है
npostavs

@npostavs: सच है, लेकिन यह वही हो सकता है जो ओपी चाहता / चाहती है। यदि वह शाब्दिक चर का उपयोग नहीं कर रहा है, तो यह निश्चित रूप से जाने का रास्ता है। आप सही हैं, हालांकि, यह "चर" अस्पष्ट है, इसलिए सामान्य रूप से प्रश्न का मतलब किसी भी प्रकार का चर हो सकता है। वास्तविक उपयोग के मामले को अच्छी तरह से प्रस्तुत नहीं किया गया है, आईएमओ।
आकर्षित किया
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.