लेक्सिकल बाइंडिंग के साथ डिफ्यूज के अंदर बाइट-संकलित चेतावनी देता है "फ़ंक्शन को परिभाषित नहीं किया जाता है"


13

मैं क्लोजर बनाने के लिए शाब्दिक बंधन defunके letसाथ अंदर का उपयोग करके एक स्थिर चर का प्रभाव प्राप्त करना चाहता हूं । हालाँकि, जब बाइट फ़ाइल संकलित करता है, तो मुझे एक चेतावनी मिलती है। क्या मैं कुछ गलत कर रहा हूं, या नहीं तो क्या इस चेतावनी को दबाने का कोई तरीका है?

मैंने एक MCVE बनाया है:

;; -*- lexical-binding: t -*-

(let ((count 0))
  (defun increase-count ()
    (interactive)
    (setq count (1+ count))
    (message "Count is: %d" count))

  ;; The warning happens here.
  (increase-count))

कोड अपेक्षित रूप से काम करता है: फ़ंक्शन increase-countप्रिंट करता है "काउंट इज: एन" जहां एन हर बार इसे बढ़ाना कहा जाता है। हालाँकि, जब बाइट इस फ़ाइल को संकलित करता है, तो मुझे निम्नलिखित चेतावनी मिलती है:

In end of data:
mcve.el:11:1:Warning: the function ‘increase-count’ is not known to be
    defined.

ऐसा लगता है कि increase-countलेट-ब्लॉक के अंत में कॉल करने से पहले इसे हमेशा परिभाषित किया जाना चाहिए। क्या यह मामला नही है?


defunवह नहीं करता जो आप सोचते हैं कि वह करता है, यह हमेशा एक शीर्ष-स्तरीय परिभाषा बनाता है। इस योजना के बाद भी
एलिस्स

2
मुझे पता है कि यह एक शीर्ष-स्तरीय परिभाषा बनाता है; मैं यही चाहता था। मैं बस यही चाहता हूं कि शीर्ष स्तर की परिभाषा बंद हो। यह इस बाइट-संकलन चेतावनी को छोड़कर, मेरे इच्छित तरीके से काम कर रहा है।
कुंकेल Will

जवाबों:


7

बाइट-कंपाइलर का तरीका यह तय करने का तरीका है कि किसी फ़ंक्शन को परिभाषित किया जाएगा या नहीं, बहुत "भोला" है और आपके "स्पष्ट" मामले में भी मूर्ख हो जाता है। लेकिन आप इसे इस तरह से लिख सकते हैं जिससे कंपाइलर समझ सके कि क्या होता है:

(defalias 'increase-count
  (let ((count 0))
    (lambda ()
      (interactive)
      (setq count (1+ count))
      (message "Count is: %d" count))))

बेशक, बाइट-कंपाइलर के तर्क को बेहतर बनाने के लिए बेहतर होगा: पैच उसके लिए स्वागत है।


5

बाइट-कंपाइलर चेतावनी को दबाने के लिए, अपने कोड से पहले इसे जोड़ने का प्रयास करें, कॉलम 0 (सबसे बाईं ओर) शुरू करें:

(declare-function increase-count "your-file-name.el")

C-h f declare-function तुमको बताता हू:

declare-functionमें एक लिस्प मैक्रो है subr.el

(declare-function FN FILE &optional ARGLIST FILEONLY)

बाइट-कंपाइलर को बताएं कि फ़ंक्शन FNपरिभाषित है, में है FILEFILEतर्क बाइट-संकलक द्वारा नहीं किया जाता है, लेकिन द्वारा check-declareपैकेज है, जो जांच करता है कि फ़ाइल के लिए कोई परिभाषा में शामिल है FN

FILEया तो एक लिस्प फ़ाइल हो सकती है (जिस स्थिति में ".el" विस्तार वैकल्पिक है), या सी फ़ाइल। सी फाइलें Emacs "src/"निर्देशिका के सापेक्ष विस्तारित हैं । लिस्प फ़ाइलों का उपयोग करने के लिए खोज की जाती है locate-library, और यदि वह विफल हो जाती है, तो उन्हें घोषणा वाले फ़ाइल के स्थान के सापेक्ष विस्तारित किया जाता है। एक उपसर्ग के FILEसाथ एक "ext:"बाहरी फ़ाइल है। check-declareयदि वे पाए जाते हैं, तो ऐसी फ़ाइलों की जांच करेंगे और यदि वे नहीं हैं तो उन्हें बिना किसी त्रुटि के छोड़ दें।

वैकल्पिक ARGLISTनिर्दिष्ट करता FNहै, या तर्क tनिर्दिष्ट करने के लिए नहीं FNहै। एक ARGLISTचूक चूक t, नहीं nil: एक nil ARGLISTखाली तर्क सूची को निर्दिष्ट करता है, और एक स्पष्ट t ARGLISTएक प्लेसहोल्डर है जो बाद के arg की आपूर्ति करने की अनुमति देता है।

वैकल्पिक FILEONLYगैर- का nilमतलब है कि check-declareकेवल वही FILEमौजूद होगा जो यह जाँचता है कि यह परिभाषित नहीं है FN। यह फ़ंक्शन परिभाषाओं के लिए अभिप्रेत है जो check-declareपहचान नहीं करता है, उदा defstruct

ध्यान दें कि इस उद्देश्य के लिए check-declare, यह कथन एक लाइन पर पहला गैर-व्हाट्सएप होना चाहिए।

अधिक जानकारी के लिए, जानकारी नोड देखें (elisp)Declaring Functions


क्या FILEONLYहाथ में मामले के लिए गैर-शून्य तर्क आवश्यक है? BTW, मैं एक ही जवाब दिया होता; ;-)
तोबियस

@ टोबियास: FILEONLYयहाँ, मेरे लिए जरूरी नहीं लगता था। जो इंगित करता है कि check-declareमान fऔर gमान को पहचानता है।
ड्रू

@ मुझे लगता है कि अंतिम टिप्पणी के बारे में fऔर gकेवल emacs.stackexchange.com/q/39439 के संदर्भ में समझ में आता है ?
फिल्स

@ एफिल्स: हां, मेरा कहने का मतलब यह FILEONLYथा : मेरे लिए यहां जरूरत नहीं लगती। जो यह दर्शाता है कि मानहानि check-declareको increase-countपहचानता है। ;-)
आकर्षित किया

3

मेरा मानना ​​है कि परिभाषा में प्रश्न को परिभाषित eval-and-compileकरना भी सतही रूप से उसी परिणाम को प्राप्त करेगा जैसे कि स्टीफन के सही उत्तर में :

(eval-and-compile
  (let ((count 0))
    (defun increase-count ()
      (interactive)
      (setq count (1+ count))
      (message "Count is: %d" count))))

मैं, हालांकि, उपयोग करने की सूक्ष्मताओं से बमुश्किल परिचित हूं eval-and-compileऔर, इस दृष्टिकोण से किसी भी तरह से बेहतर होने की उम्मीद नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.