2012-06-20 17 views
3

emacs 23.1和24.1之間的某個地方更改了url-retrieve的接口。在Emacs 23.1,它看起來像這樣:如何管理elisp中的底層接口更改

(url-retrieve URL CALLBACK &optional CBARGS) 

在24.1版本,它看起來像這樣:

(url-retrieve URL CALLBACK &optional CBARGS SILENT INHIBIT-COOKIES) 

我有一個使用此功能的emacs的包。我想利用emacs 24.1上的新參數SILENT參數,同時保持與不支持它的舊版emacs的向後兼容性。

管理這個最好的方法是什麼?我可以在運行時獲取最大數量的參數嗎?

回答

2
(defun try-call-with-more-args (function a b c d) 
    (condition-case var 
     (progn 
     (funcall function a b c d) 
     (message "there was no error")) 
    (wrong-number-of-arguments (funcall function a b c)))) 

(try-call-with-more-args #'message "b = %d, c = %d" 1 2 3) 

即使一個發佈的三分球傑克遜更聰明,這是更簡單,實際上有很好的工作機會,即使你的目標是本機C功能:)

+0

寫這個遞歸版本會很有趣,不斷從arglist中刪除一個,直到(希望)成功。 –

+1

你有一個缺少'(progn ...)'包裝'funcall'和'消息'。 此外,您不應該捕獲'錯誤',而只是'錯誤的參數數量',以減少由於一些不相關的錯誤而導致回退舊調用約定的風險。 – Stefan

5

您可以使用此函數來獲取參數列表:

(defun my-get-arglist (obj) 
    ;; code taken from disassemble-internal 
    (let ((macro 'nil) 
     (name 'nil) 
     (doc 'nil) 
     args) 
    (while (symbolp obj) 
     (setq name obj 
      obj (symbol-function obj))) 
    (if (subrp obj) 
     (error "Can't disassemble #<subr %s>" name)) 
    (if (and (listp obj) (eq (car obj) 'autoload)) 
     (progn 
      (load (nth 1 obj)) 
      (setq obj (symbol-function name)))) 
    (if (eq (car-safe obj) 'macro) ;handle macros 
     (setq macro t 
       obj (cdr obj))) 
    (if (and (listp obj) (eq (car obj) 'byte-code)) 
     (setq obj (list 'lambda nil obj))) 
    (if (and (listp obj) (not (eq (car obj) 'lambda))) 
     (error "not a function")) 
    (if (consp obj) 
     (if (assq 'byte-code obj) 
      nil 
      (setq obj (byte-compile obj)))) 
    (cond ((consp obj) 
      (setq obj (cdr obj))  ;throw lambda away 
      (setq args (car obj)) ;save arg list 
      (setq obj (cdr obj))) 
      ((byte-code-function-p obj) 
      (setq args (aref obj 0))) 
      (t (error "Compilation failed"))) 
    args)) 
+0

我必須與「檢查版本號」作爲解決方案,但這是一個很好的工具。 – phils

3

你可以檢查emacs-major-version並確保它> = 24

+0

我仍然認爲這通常是解決問題的最簡單方法(也是最簡單的方法)。對於其他用例,「emacs-minor-version」或者「emacs-version」變量也可能適用。各種'version *'函數可以用於測試。 – phils

1

如果它是舊的emacs版本,寫aw說唱歌手圍繞舊功能:

(let ((orig-fun #'symbol-name-of-orig-fun)) 
    (defun symbol-name-of-orig-fun (arglist of new function interface) 
    (declare (ignore new function interface)) 
    (funcall orig-fun arglist of))) 

這會生成一個詞法閉包,它將舊函數的引用存儲在新函數中。我不知道emacs方言,但我敢打賭,這種模式可以在emacs中使用。我每隔一段時間在普通的口音中使用它。

+0

Emacs版本<24中的詞法綁定並不那麼簡單(並且在24中需要在文件中明確聲明可以使用詞法綁定)。 – phils

+0

然後用動態全局進行:將let改爲defvar,在var名稱周圍放上耳罩,並將它放在頂層 –

相關問題