2009-02-27 15 views
23

मैं फ्लाई पर एक फ़ंक्शन बनाने की कोशिश कर रहा हूं जो एक निरंतर मूल्य लौटाएगा।मैं Emacs Lisp में बंद कैसे करूं?

जावास्क्रिप्ट और अन्य आधुनिक जरूरी भाषाओं में मैं बंद का प्रयोग करेंगे:

function id(a) { 
    return function() {return a;}; 
} 

लेकिन Emacs तुतलाना उन का समर्थन नहीं करता।

मैं पहचान फ़ंक्शन और आंशिक फ़ंक्शन एप्लिकेशन का मिश्रण बना सकता हूं लेकिन यह या तो समर्थित नहीं है।

तो मैं यह कैसे कर सकता हूं?

+0

जहां तक ​​मैंने सुना है, जावास्क्रिप्ट वास्तव में कार्यात्मक है। – Svante

+0

यह किसी के दृष्टिकोण पर निर्भर करता है। मेरे लिए यदि भाषा में अधिकांश कोड अनिवार्य है तो यह जरूरी है। यहां मामला कौन सा है। – vava

+0

संस्करण 24 के अनुसार, Emacs में अब लेक्सिकल स्कॉइंग है। –

उत्तर

8

बेवकूफ विचार: कैसे के बारे में:

(defun foo (x) 
    `(lambda() ,x)) 

(funcall (foo 10)) ;; => 10 
+1

जब आप कुछ लिखना चाहते हैं तो यह टूट जाता है: (lexical-let ((0)) (विपक्ष (लैम्ब्डा() ए) (लैम्ब्डा (नया-ए) (सेट एक नया-ए))) – jrockway

28

मिले के साथ एक और समाधान शाब्दिक-जाने

(defun foo (n) 
    (lexical-let ((n n)) #'(lambda() n))) 

(funcall (foo 10)) ;; => 10 
6

मैं Emacs लिस्प में फर्म नहीं हूँ, लेकिन जहाँ तक मुझे पता है, से एक बड़ा अंतर सामान्य लिस्प यह है कि यह पूरे गतिशील स्कोपिंग का उपयोग करता है। Emacs Lisp Manual बताता है कि Emacs Lisp बंद नहीं है।

मैं गतिशील स्कॉइंग के अपने सैद्धांतिक ज्ञान को लागू करने का प्रयास करूंगा।

आप एक समारोह id जो सिर्फ my-id का मान देता है: के कॉल करने के लिए रास्ते पर

 
(defun some-other-place() 
    (id)) 

और कहीं:

 
(defun id() 
    my-id) 

और आप कुछ अन्य समारोह में इसका इस्तेमाल करते हैं id उदाहरण के माध्यम से आप my-id बांधें एक करते हैं:

 
(defun even-elsewhere() 
    (let ((my-id 5)) 
    (some-other-place))) 

इस वापस देना चाहिए 5.

मुझे पता है कि गतिशील scoping एक अजीब जानवर है जब आप शाब्दिक scoping के लिए उपयोग किया जाता है, लेकिन शायद आप अपने वांछित व्यवहार को लागू करने में इसका उपयोग कर सकते हैं।

+0

वाह , यह अच्छा है :) – vava

7

Emacs lisp में केवल गतिशील स्कॉइंग है। एक lexical-let मैक्रो है जो एक भयानक हैक के माध्यम से लेक्सिकल स्कोपिंग का अनुमान लगाता है।

+9

बेशक, अन्य भाषा कार्यान्वयन के कवर के तहत 'बल्कि भयानक हैक' चल रहा है। – jrockway

4

Emacs 24 शाब्दिक बाध्यकारी है।

http://www.emacswiki.org/emacs/LexicalBinding

+0

[वैरिएबल स्कोपिंग] पर https://NU Emacs मैन्युअल में सेक्शन में भी देखें (https://www.gnu.org/software/emacs/manual/html_node/elisp/Variable-Scoping.html#Variable-Scoping) – dat

12

रियल (नकली नहीं) Emacs में क्लोजर 24.

हालांकि Emacs 24 शाब्दिक स्कूपिंग है जब चर शाब्दिक बाध्यकारी है मूल्य टी, defun विशेष फॉर्म स्पष्ट रूप से बाध्य संदर्भों में ठीक से काम नहीं करता है (कम से कम Emacs 24.2.1 में नहीं।) यह मुश्किल बनाता है, लेकिन असंभव है, वास्तविक परिभाषित करने के लिए (नकली नहीं) बंद।उदाहरण के लिए:

(let ((counter 0)) 
    (defun counting() 
    (setq counter (1+ counter)))) 

अपेक्षा के अनुरूप है क्योंकि defun में प्रतीक काउंटर उस नाम के वैश्विक चर के लिए बाध्य होंगे काम नहीं करेगा, अगर वहाँ एक है, और नहीं शाब्दिक चर रहा है में परिभाषित दें। जब की गणना की जाती है, तो वैश्विक चर नहीं है, तो यह स्पष्ट रूप से विफल हो जाएगा। होवर यदि ऐसा ग्लोबल वैरिएबल है तो इसे अपडेट किया जा सकता है, जो शायद नहीं था और यह बग का पता लगाने में मुश्किल हो सकती है क्योंकि फ़ंक्शन ठीक से काम कर रहा है।

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

(defmacro defun** (name args &rest body) 
    "Define NAME as a function in a lexically bound context. 

Like normal `defun', except that it works correctly in lexically 
bound contexts. 

\(fn NAME ARGLIST [DOCSTRING] BODY...)" 
    (let ((bound-as-var (boundp `,name))) 
    (when (fboundp `,name) 
     (message "Redefining function/macro: %s" `,name)) 
    (append 
    `(progn 
     (defvar ,name nil) 
     (fset (quote ,name) (lambda (,@args) ,@body))) 
    (if bound-as-var 
     'nil 
     `((makunbound `,name)))))) 

आप गिनती इस प्रकार परिभाषित हैं:

(let ((counter 0)) 
    (defun** counting() 
    (setq counter (1+ counter)))) 

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

चेतावनी: मैक्रो ठीक से काम नहीं करेगा अगर आप defun करने की कोशिश ** lexically बाध्य चर के रूप में एक ही नाम के साथ एक समारोह। यदि आप कुछ ऐसा करते हैं:

(let ((dont-do-this 10)) 
    (defun** dont-do-this() 
    ......... 
    .........)) 

मैं कल्पना नहीं कर सकता कि वास्तव में ऐसा करने वाला कोई भी व्यक्ति है लेकिन यह उल्लेखनीय था।

नोट: मैं मैक्रो defun नाम दिया **इतना है कि यह मैक्रो defun *सीएल पैकेज में के साथ संघर्ष नहीं है, लेकिन यह उस पर किसी भी तरह से निर्भर नहीं करता है पैकेज।

+0

क्या आप एक पूरा उदाहरण दें? ऐसा लगता है कि कोड (चलो ((काउंटर 0)) (डीफन ** गिनती() (सेटक काउंटर (1+ काउंटर)))) अपेक्षित काम नहीं करते हैं। – toolchainX

+1

'डिफुन' के साथ बंद करने को परिभाषित करने के लिए सीमा wrt Emacs-24.3 में हटा दिया गया था (जहां 'defun' अब एक विशेष रूप के बजाय मैक्रो के रूप में परिभाषित किया गया है)। इसलिए 24.3 'डिफ्यून' आपके 'डिफ्यून **' मैक्रो (जैसे टूटे हुए '(डिफवर, नाम शून्य) के समान काम करता है और' डिफलीस 'की बजाय' fset' 'के उपयोग जैसे विभिन्न नाबालिग डाउनसाइड्स को ठीक करना और संभालना इसलिए "गतिशील डॉकस्ट्रिंग" कहा जाता है जिसके लिए बाइटकंपेलर में परिवर्तन की आवश्यकता होती है)। – Stefan

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