2012-09-17 20 views
13

के साथ संगतता Emacs 24 स्थानीय चर के लिए वैकल्पिक शब्दावली बाइंडिंग जोड़ा। XEmacs और पिछले Emacs संस्करणों के साथ संगतता बनाए रखते हुए, मैं अपने मॉड्यूल में इस कार्यक्षमता का उपयोग करना चाहता हूं।Emacs में लेक्सिकल स्कोप: पुराने Emacsen

Emacs 24 से पहले, lexical-letcl-macs में परिभाषित फॉर्म का उपयोग करके बंद करने का सबसे आसान तरीका था, जो कुछ चालाक मैक्रो चालबाजी के साथ अक्षीय दायरे को अनुकरण करता था। हालांकि इस elisp प्रोग्रामर के बीच बेहद लोकप्रिय कभी नहीं था, यह काम किया है, वास्तविक और कुशल बंद बनाने, जब तक कि आप इस स्यूडोकोड में के रूप में उन्हें lexical-let में रैप करने के लिए याद किया,:

(defun foo-open-tag (tag data) 
    "Maybe open TAG and return a function that closes it." 
    ... do the work here, initializing state ... 
    ;; return a closure that explicitly captures internal state 
    (lexical-let ((var1 var1) (var2 var2) ...) 
    (lambda() 
     ... use the captured vars without exposing them to the caller ... 
    ))) 

सवाल यह है: क्या है Emacs 23 और XEmacs के लिए समर्थन बनाए रखते हुए, नई शब्दावली बाइंडिंग का उपयोग करने का सबसे अच्छा तरीका है? वर्तमान में मैं यह एक पैकेज विशेष मैक्रो फैलता को परिभाषित द्वारा हल lexical-let में या साधारण let कि क्या lexical-binding बाध्य और सच है पर निर्भर करता है में:

(defmacro foo-lexlet (&rest letforms) 
    (if (and (boundp 'lexical-binding) 
      lexical-binding) 
     `(let ,@letforms) 
    `(lexical-let ,@letforms))) 
(put 'foo-lexlet 'lisp-indent-function 1) 

... at the end of file, turn on lexical binding if available: 
;; Local Variables: 
;; lexical-binding: t 
;; End: 

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


होशियार (जरूरी अच्छा नहीं) समाधान है कि कोड को बंद बनाने के लिए मानक रूपों का उपयोग कर जारी रखने की अनुमति के लिए संपादित करें विचारों का

दो उदाहरण:

  • एक सलाह का प्रयोग करें या lexical-let के तहत lexical-let के तहत lexical-let को केवल उन प्रतीकों को असाइन किया गया है जो किसी भी तरह से लंबवत रूप से स्कॉप्ड किए गए हैं। यह सलाह केवल foo.el के बाइट-संकलन के दौरान अस्थायी रूप से सक्रिय की जाएगी, ताकि lexical-let का अर्थ शेष Emacs के लिए अपरिवर्तित बनी रहे।

  • पुराने Emacsen के तहत lexical-let पर गैर-प्रीफ़िक्स्ड प्रतीकों के let संकलित करने के लिए एक मैक्रो/कोड-वॉकर सुविधा का उपयोग करें। यह फिर से केवल foo.el के बाइट-संकलन के दौरान लागू होगा।

चिंतित मत हो, तो इन विचारों overengineering की गंध: मैं के रूप में है उन्हें इस्तेमाल करने का प्रस्ताव नहीं कर रहा हूँ। मुझे उपरोक्त मैक्रो के विकल्पों में दिलचस्पी है जहां पैकेज को लोडिंग/संकलन की कुछ अतिरिक्त जटिलताओं की कीमत के बंद होने के लिए निकर्स पोर्टेबल उपयोग का लाभ मिलता है।


संपादित 2

के रूप में कोई भी एक समाधान है कि मॉड्यूल उन्हें Emacs के आराम के लिए तोड़ने के बिना let या lexical-let का उपयोग कर रखने के लिए, मैं स्टीफन के जवाब को स्वीकार कर रहा हूँ की अनुमति होगी के साथ कदम रखा है, जो बताता है कि उपरोक्त मैक्रो ऐसा करने का तरीका है। इसके अलावा, उत्तर bound-and-true-p का उपयोग करके और एडबग और लिस्प-इंडेंट के लिए एक सुंदर घोषणा जोड़कर मेरे कोड पर सुधार करता है।

अगर किसी के पास इस संगतता परत के लिए वैकल्पिक प्रस्ताव है, या उपर्युक्त विचारों का एक सुंदर कार्यान्वयन है, तो मैं उन्हें उत्तर देने के लिए प्रोत्साहित करता हूं।

+0

यदि मैं सामान्य लिस्प में इस मैक्रो रैपर को लिख रहा था, तो शायद मैं यहां एक ही मूल दृष्टिकोण का उपयोग करूंगा। सिवाय इसके कि मैं शीर्ष स्तर पर एक एकल डिफैमक्रो ब्लै-लेक्सलेट रखकर, नील 'eval, और उसके बाद एक संकलन समय है अगर यह निर्धारित करता है कि कोड का विस्तार करने के लिए कौन सा रूप है (चलो या लेक्सिकल- इस मामले में चलो)। मैं इसे उत्तर के रूप में नहीं डाल रहा हूं b/c यह एक सामान्य लिस्पे दृष्टिकोण है, और आपके द्वारा उपयोग किए जाने वाले वही मूल दृष्टिकोण है। –

+0

अच्छा बिंदु, मैंने अब 'if' macroexpansion-time को स्थानांतरित करने के लिए उदाहरण को संशोधित किया है। हालांकि, प्रश्न में बताए गए 'फू-लेक्सलेट' के खिलाफ तर्क अभी भी खड़े हैं। – user4815162342

उत्तर

6

lexical-let और के बाद से शाब्दिक बाध्यकारी के let नहीं करते काफी समान (खासतौर पर lexical-let हमेशा शाब्दिक बंधन का उपयोग करता है, जबकि let का उपयोग करता है या तो गतिशील बंधन या शाब्दिक बंधन पर कि क्या वर था defvar 'घ या नहीं निर्भर करता है) , मुझे लगता है कि आपका दृष्टिकोण जितना अच्छा हो उतना अच्छा है। आप आसानी से इसे में Edebug कदम कर सकते हैं, यद्यपि:

(defmacro foo-lexlet (&rest letforms) 
    (declare (indent 1) (debug let)) 
    (if (bound-and-true-p lexical-binding) 
     `(let ,@letforms) 
    `(lexical-let ,@letforms))) 

आप declare पर निर्भर नहीं करना चाहते हैं, तो आप (put 'foo-lexlet 'edebug-form-spec 'let) उपयोग कर सकते हैं।

+0

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

2

एक संभावित समाधान defadvice का उपयोग lexical-let विस्तार को हुक करने के लिए करना है। मैंने निम्नलिखित सलाह लिखी, और ऐसा लगता है कि यह ठीक काम करता है। यह भी byte-compile जागरूक है।

(defadvice lexical-let (around use-let-if-possible (bindings &rest body) activate) 
    (if (and (>= emacs-major-version 24) 
      (boundp 'lexical-binding) 
      lexical-binding) 
     (setq ad-return-value `(let ,bindings . ,body)) 
    ad-do-it)) 
+0

क्या आप इस सलाह का उपयोग अपने '.emacs' में उपयोगकर्ता के रूप में करते हैं, या अपने पैकेज में किसी तृतीय-पक्ष पैकेज लेखक के रूप में करते हैं? यह मेरे लिए स्पष्ट नहीं है कि इस सलाह को सक्रिय करने से उपयोगकर्ता के पीछे पीछे हर जगह 'लेक्सिकल-लेट' का व्यवहार नहीं बदलेगा। – user4815162342

-1

शाब्दिक-देना, देना रूप में एक ही arglist प्रारूप के लिए लग रहा है तो क्या कुछ इस तरह के बारे में:

(if (older-emacs-p) 
    (setf (macro-function 'let) (macro-function 'lexical-let)) 
    (setf (macro-function 'lexical-let) (macro-function 'let))) 

यह शिम नए Emacs पुराने कोड का शाब्दिक-जाने अंश पढ़ने के लिए अनुमति चाहिए, साथ ही दूसरी तरफ (पुराने Emacs को पढ़ने के लिए नए कोड के भाग दें)।

हालांकि यह सामान्य लिस्प है। किसी को भी Emacs में अनुवाद करने की परवाह है?

और यदि आप एक विशेष रूप (मैक्रो नहीं) के रूप में लागू किया गया है तो आप परेशानी में भाग सकते हैं।

इसके अलावा, अगर यह पुराने Emacs में परिभाषित किया गया है तो यह पूरी तरह से अनुकूल संगत केस तोड़ सकता है। क्या यह? (मुझे Emacs के बारे में बहुत कम पता है, यह मेरा चुने हुए संपादक नहीं है)। लेकिन पिछड़ा-संगत मामला परवाह किए बिना अधिक महत्वपूर्ण हो सकता है।

+0

दूसरा 'सेटफ़' अनावश्यक प्रतीत होता है - क्या आपका मतलब' लेट 'और' लेक्सिकल-लेट 'के मैक्रो फ़ंक्शंस का आदान-प्रदान करने के लिए एक' psetf' का उपयोग करना था? ऐसा लगता है कि यह एक पैकेज को संकलित करने के लिए शेष Emacs सत्र में 'let' का अर्थ बदल देगा। एक मॉड्यूल जिसने चेतावनी के बिना उपयोगकर्ता को गंभीर रूप से तोड़ दिया होगा। – user4815162342

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^