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.