这是我的Common Lisp代码:
(defun caller (f)
(format t "caller: f: ~a~%" f)
(funcall f 10))
(defun callee (x)
(format t "callee: x: ~a~%" x))
(caller #'callee)
(caller 'callee)
以下是我使用clisp
获得的输出:
$ clisp foo.lisp
caller: f: #<FUNCTION CALLEE (X) (DECLARE (IN-DEFUN CALLEE)) (BLOCK CALLEE (FORMAT T callee: x: ~a~% X))>
callee: x: 10
caller: f: CALLEE
callee: x: 10
我想知道语法#'callee
和语法'callee
之间的区别。
虽然使用这两种语法,但我能够将callee
传递给caller
,但caller: f:
输出似乎表明两种语法都有一些细微差别:{{ 1}}似乎引用了一个函数对象,但#'callee
似乎只引用了函数名。
以下是我的问题:
'callee
语法与#'callee
语法之间的区别是什么?'callee
如何在两种情况下成功调用funcall
?答案 0 :(得分:1)
差异主要在于如何查找功能。如果将符号传递给funcall
,则会在全局(而不是词汇)环境中查找。相关文档为http://clhs.lisp.se/Body/f_funcal.htm。我稍微修改了文档中的示例:
(defun cons* (&rest rest)
(apply 'cons rest))
(flet ((cons* (x y) `(kons ,x ,y)))
(let ((cons* (symbol-function '+)))
(funcall #'cons*
(funcall 'cons* 1 2)
(funcall cons* 1 2))))
;; => (KONS (1 . 2) 3)
答案 1 :(得分:1)
#'callee
扩展为(function callee)
,而'callee
扩展为(quote callee)
。
#'
在函数名称空间中查找。 (Common Lisp是一个2-Lisp,意味着它有2个独立的命名空间,允许函数可以具有相同的名称,如变量/数据 - Scheme / Racket是1-Lisp,其中函数和变量共享相同的命名空间 - 意思是......具有特定名称的是某个其他对象的函数或名称。)
'
不会在任何地方查找,但会将以下符号名称评估为自己的名称。
funcall
在函数名称空间中查找其参数名称,并返回分配给它的函数。如果执行普通函数调用(callee 10)
,则Lisp解释器会从函数名称空间中隐式查找callee
,因为列表中的第一个位置是为函数名保留的。当函数名作为参数给出时,在除第一个之外的其他位置,您必须首先对它们应用funcall
或#'
,以便解释器知道它必须在函数名称空间中查找该名称而不是在正常的变量名称空间。
试试这个:
(defun d (x) x) ;; declares a function d in the function name space
(setf d 1) ;; declares variable d in the variable name space
(list d #'d d #'d)
;; returns:
(1 #<FUNCTION D (X) (DECLARE (SYSTEM::IN-DEFUN D)) (BLOCK D X)> 1
#<FUNCTION D (X) (DECLARE (SYSTEM::IN-DEFUN D)) (BLOCK D X)>)
;; when `#'` is given, the d is looked up from the function name space,
;; without, d is looked up from the normal variable name space
(d d)
;; the first position d gets looked up from the function name space but
;; the argument d from the variable name space
;; since the function d is the identity function and variable d has the value 1,
;; this evaluates the identity function on 1, thus to
1
(d #'d) ;; now the argument `d` is looked up from the function name space
;; thereby returning a function:
#<FUNCTION D (X) (DECLARE (SYSTEM::IN-DEFUN D)) (BLOCK D X)>