2009-12-03 33 views
5

假設我有這樣的函數foo在返回CLISP lambda函數,然後評估它

[92]> (defun foo() (lambda() 42)) 
FOO 
[93]> (foo) 
#<FUNCTION :LAMBDA NIL 42> 
[94]> 

現在,假設我想實際使用和返回42

我怎樣做那?我一直在研究谷歌,我似乎無法提出正確的語法。

回答

11

你想要的FUNCALL功能:

* (defun foo() (lambda() 42)) 
FOO 
* (funcall (foo)) 
42 
2

你的函數foo返回function。即使參數集爲空,也可以使用funcall函數將參數應用於參數。

在這裏你可以看到foo返回function類型的值:

CL-USER> (let ((f (foo))) 
      (type-of f)) 
FUNCTION 
CL-USER> (let ((f (foo))) 
      (funcall f)) 
42 
CL-USER> (type-of (foo)) 
FUNCTION 
CL-USER> (funcall (foo)) 
42 
2

除了FUNCALL另一種方法是適用於:

(apply (foo) nil)

FUNCALL是這裏的慣用方式,但你」當你有一個參數列表時,你需要申請。

6

這裏的相關術語是「Lisp-1」和「Lisp-2」。

您的調用嘗試可以在Lisp-1中工作,如計劃或Clojure。 Common Lisp是一個Lisp-2,但它大致意味着變量名和函數名是分開的。

因此,爲了調用綁定到一個變量,你要麼需要使用特殊的形式funcallapply正如其他人所指出的,或將符號foo而不是變量值的函數值的函數。

前者基本上採用符號的變量值,假設/檢查該值是一個函數,然後調用函數(參數無論你傳遞給funcall/apply

你真的不想要做後者,因爲這是在所有的,但非常專業的情況相當愚蠢,但是對於completness的緣故,這是大概你會怎麼做:

CL-USER> (setf (symbol-function 'foo) (lambda() 42)) 
#<FUNCTION (LAMBDA()) {C43DCFD}> 
CL-USER> (foo) 
42 

你也應該要考慮的labelsflet特殊形式(這是常用的) - 你真的在那裏使用後面的方法(這些形式創建符號的臨時函數綁定)。

所以,你的問題會不會有這樣的:

(flet ((foo() 
     42)) 
    (foo)) 

即在這裏,你的符號foo功能值暫時綁定到該函數返回42.在這臨時的上下文,那麼你可以調用(foo)像定期的全球職能。

+0

這是一個很好的答案! – 2009-12-07 15:54:39