2013-11-15 21 views
0

我想知道在使用eval之類的函數時,數據vs代碼替換是如何工作的,該函數允許我傳遞任何打印命令,如printprinc等等以及一些文本和它使用該命令在其輸出:eval如何以這種方式處理函數

(defun print-test (fn text) 
    (eval '(fn 'text))) 

我已經試過各種方法,但我不能讓這個運行。我也試過:

(defun print-test (fn text) 
    (eval ('fn 'text))) 

..和其他變化。所以我顯然錯過了一些東西。我希望能夠做到這一點:

(print-test 'princ 'some-text)

我通常得到一個錯誤fn is undefined。但是因爲我正在實時評估代碼,所以我認爲從我的輸入中可以得到fn

我知道還有其他的方法可以做到這一點,比如傳入一個像#'princ這樣的實際函數對象,但我很好奇eval機制如何在運行中生成代碼。

回答

3

fn is undefined這樣的錯誤沒有告訴你princ是未定義的,但符號fn沒有函數綁定。您不想調用符號fn,您想調用變量fn

它看起來像你想評估一個列表,其第一個元素是fn的值,其第二個元素是值text。您可以在(list fn text)中使用函數list創建這樣的列表。然後,你可撥打eval它:

(defun print-test (fn text) 
    (eval (list fn text))) 

你也可以使用反引號標記,並做

(defun print-test (fn text) 
    (eval `(,fn ,text))) 

在這種情況下,如果你想有作爲(princ 'hi)同樣的效果,你需要fn將符號princtext設爲列表'hi(是的,該列表,因爲'hi(quote hi)的簡寫)。你會這樣調用,則:

(print-test 'princ ''hi) 

如果第二個參數應該總是要在生成的文本引用,你可以也可以下列任何一項:

(eval `(,fn ',text)) 
(eval `(,fn (quote ,text))) 
(eval (list fn (list 'quote text))) 

所有這一切說,雖然,這似乎是一個非常奇怪的方式使用eval。除非有特別好的理由,爲什麼不使用funcall?畢竟,如果fn作爲評估表單的車是合法的,而text是一個參數,那麼這難道不是簡單的以下嗎?

(defun print-test (fn text) 
    (funcall fn text)) 

當然,這會被稱爲有點不同。在這裏,如果你想同樣的效果(princ 'hi),你只需通過符號princhi

(print-test 'princ 'hi) 
+0

我意識到這是一個簡單的例子,但我想了解EVAL作品。但是,當我嘗試使用你的版本時,我仍然會遇到錯誤:'(print-test'princ'hi)''變量HI沒有綁定。' – johnbakers

+0

@OpenLearner如果你嘗試評估' princ hi)'?當我在REPL中輸入'(princ hi)'時,我得到'hi is undefined'。我期望'eval'給我同樣的東西。 –

+0

我試圖評估'(princ'hi)'所以'hi'需要通過但仍然引用 – johnbakers

相關問題