2012-06-26 42 views
18

我感到困惑如何defun定義宏的工作方式,因爲爲什麼defun不一樣(setq <name><lambda>)?

(defun x() "hello") 

將創建函數x,但符號X仍然將是自由的。

如果我會結合一些拉姆達爲x,則x將有一個價值,但它不會被解釋的形式這樣視爲功能:

(x) 

我認爲這是關係到事實上,defun應該在全球環境中定義功能,但我不確定它到底意味着什麼。爲什麼我不能在當前的環境中使用它?

有沒有什麼辦法強制解釋器對待符號作爲函數,如果一些lambda綁定到它?例如:

(setq y (lambda() "I want to be a named function")) 
(y) 

P.S .:我正在使用SBCL。

回答

20

Common Lisp的有功能和價值不同的命名空間。

您可以在函數名稱空間中使用DEFUN,FLET,LABELS和其他一些函數定義函數。

如果你想獲得一個函數對象作爲一個值,你使用FUNCTION

(defun foo (x) (1+ x)) 

(function foo) -> #<the function foo> 

或更短:

#'foo -> #<the function foo> 

如果你想調用的函數,那麼你就寫(foo 100)

如果你想調用的函數的值,那麼你需要使用FUNCALLAPPLY

(funcall #'foo 1) 

您可以通過周圍的功能,並呼籲他們:

(defun bar (f arg) 
    (funcall f arg arg)) 

(bar #'+ 2) -> 4 

在的情況下, DEFUN:

它不是(setf (symbol-value 'FOO) (lambda ...))

它更像是(setf (symbol-function 'foo) (lambda ...))

注意這兩個命名空間讓你寫:

(defun foo (list) 
    (list list)) 

(foo '(1 2 3)) -> ((1 2 3)) 

有內置的功能LIST和可變LIST之間沒有衝突。由於我們有兩個不同的名稱空間,我們可以使用相同的名稱來實現兩個不同的目的。

還請注意,在本地功能的情況下,沒有符號參與。命名空間不一定與符號綁定。因此對於局部變量,通過符號名稱進行函數查找是不可能的。

5

Common Lisp對每個符號都有多個插槽,包括一個數值插槽和一個功能插槽。當您使用語法(x)時,common lisp會查找x的功能槽綁定。如果您想調用價值綁定,請使用funcallapply

http://cl-cookbook.sourceforge.net/functions.html

相關問題