Emacs जाने की सलाह देते हैं


14

मैं कोड के एक टुकड़े में एक फ़ंक्शन को अस्थायी रूप से ओवरराइड करना चाहता हूं।

उदाहरण के लिए, निम्नलिखित लें:

(defun nadvice/load-quiet (args)
  (cl-destructuring-bind
      (file &optional noerror nomessage nosuffix must-suffix)
      args
    (list file noerror t nosuffix must-suffix)))

(defun nadvice/idle-require-quiet (old-fun &rest args)
    (advice-add 'load :filter-args #'nadvice/load-quiet)
    (apply old-fun args)
    (advice-remove #'load #'nadvice/load-quiet))

(advice-add 'idle-require-load-next :around #'nadvice/idle-require-quiet)

क्या काम नहीं करता है:

  • इस। यह बहुत साफ होगा अगर मैं मैन्युअल रूप से सक्षम और अक्षम करने से बच सकता हूं और चीजों की देखभाल के लिए एमएसीएस के एकल-थ्रेडेड प्रकृति पर भरोसा कर सकता हूं।
  • cl-letfमुझे मूल फ़ंक्शन का संदर्भ नहीं देने देंगे, इसलिए मैं उन चीजों को लागू नहीं कर सकता जो :filter-argsसामान्य रूप से होती हैं।
  • cl-flet अन्य कार्यों में कार्यों को ओवरराइड नहीं कर सकते।
  • nofletएक बाहरी पैकेज है, जिससे मैं बचना चाहूंगा। (मेरी आवश्यकता से बहुत अधिक)

जवाबों:


16

(cl-)letfमूल फ़ंक्शन को स्वयं संदर्भित करते समय आप उपयोग नहीं कर सकते थे ?

कुछ इस तरह:

;; Original function
(defun my-fun (arg)
  (message "my-fun (%s)" arg))


;; Standard call
(my-fun "arg") ;; => my-fun (arg)


;; Temporary overriding (more or less like an around advice)
(let ((orig-fun (symbol-function 'my-fun)))
  (letf (((symbol-function 'my-fun)
          (lambda (arg)
            ;; filter arguments
            (funcall orig-fun (concat "modified-" arg)))))
    (my-fun "arg")))
;; => my-fun (modified-arg)


;; The overriding was only temporary
(my-fun "arg") ;; => my-fun (arg)



यदि आप इसे पुन: उपयोग करने की योजना बनाते हैं, तो आप इसे मैक्रो में भी लपेट सकते हैं:

(defmacro with-advice (args &rest body)
  (declare (indent 1))
  (let ((fun-name (car args))
        (advice   (cadr args))
        (orig-sym (make-symbol "orig")))
    `(cl-letf* ((,orig-sym  (symbol-function ',fun-name))
                ((symbol-function ',fun-name)
                 (lambda (&rest args)
                   (apply ,advice ,orig-sym args))))
       ,@body)))

ऊपर दिए गए उदाहरण को निम्नलिखित की तरह फिर से लिखा जा सकता है:

(defun my-fun (arg)
  (message "my-fun (%s)" arg))


(my-fun "my-arg")

(with-advice (my-fun
              (lambda (orig-fun arg)
                (funcall orig-fun (concat "modified-" arg))))
  (my-fun "my-arg"))

(my-fun "my-arg")

धन्यवाद, यह वही है जो मैं देख रहा था। केवल एक चीज जिसे मैं बदलूंगा, वह cl-letf*है दोनों के लिए उपयोग let।
— PythonNut

मैंने एक मैक्रो संस्करण जोड़ा, जो letf*दोनों बाइंडिंग के लिए केवल एक फॉर्म का उपयोग करता है ।
— फ्रांस्वा फ़ेवोटे 19

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