2014-03-06 34 views
1

這裏的設置:Elisp:使符號函數返回源代碼?

(defun square (x) 
    (* x x)) 
;; square 
(symbol-function 'square) 
;; (lambda (x) (* x x)) 
(byte-compile 'square) 
;; #[(x) "\211_\207" [x] 2] 
(symbol-function 'square) 
;; #[(x) "\211_\207" [x] 2] 

有沒有辦法獲取源square(lambda (x) (* x x))已經字節編譯?

我能想到的兩種用法是內聯當前函數調用 並執行調試步驟。

我試着find-definition-noselect搞亂獲取源, 但我不知道是否有更好的方法,因爲它有時會引發

(error "Don't know where ... is defined") 

回答

0

沒有辦法獲得一個函數對象的來源。字節編譯不是內射函數,所以你不能恢復它。即使不考慮宏擴展,也不存在從操作碼到Lisp表達式的直接映射。

反正我看不到用例。

調試

要步入功能進行調試,導航到其定義(即find-definition)和儀器的定義用於調試(例如用edebug)。這是合理調試Emacs Lisp函數的唯一方法。您不能使用函數單元的內容進行調試,因爲它受到宏擴展的限制。

因此,功能單元可能看起來與實際定義完全不同。如果你在函數單元中發現一個錯誤,你很難在實際的函數定義中找到相同的錯誤。

內聯

對於內聯,使用宏或defsubst中的Emacs Lisp定義內聯函數。但是,要小心不要在庫的公共接口上意外地公開這些函數,因爲編譯時內聯函數會將編譯時間依賴性強加到您的庫上,所以需要爲每個庫的版本重新編譯相關庫。由於package.el目前還不支持,宏和替換很容易造成嚴重破壞。

+0

你誤解了內聯部分。我的意思是內聯擴展,即將'(square 5)' 替換爲內部的'(* 5 5)'。 同樣適用於調試:在上面的情況中,我想跳轉到'square'的定義,而 在頂層將'arg'設置爲'5'。沒有錯。 我不喜歡'edebug',因爲它使源只讀。我更願意在調試時編寫代碼。 –

2

Emacs的跟蹤哪些功能定義在文件(此信息被保存在load-history)。爲了找到定義,Emacs查找load-history,如果該函數在那裏列出,它會查找相應的源文件,然後在該文件中查找看起來像函數可能定義的東西(使用正則表達式)。這就是find-definition-noselect所做的。

至於源代碼,通常沒有Emacs不保留源定義。如果使用cl-defsubst定義函數,則源保持周圍,否則不是。對於Edebugging而言,獲取源代碼無論如何不會起作用(因爲Edebug不僅需要源代碼鱈魚,還需要每個子表達式的精確位置);對於簡單的調試,源代碼也不是真正需要的(您可以隨時點擊函數的名稱跳轉到源代碼);因爲內聯源也不是必需的(實際上,字節編譯器可以內聯在源代碼級別,但也可以在字節碼級別內聯)。