简体   繁体   English

Common Lisp中的#'callee和'callee之间的区别

[英]Difference between #'callee and 'callee in Common Lisp

Here is my Common Lisp code: 这是我的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)

Here is the output I get with clisp : 这是我通过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

I want to know what is the difference between the syntax #'callee and the syntax 'callee . 我想知道语法#'callee和语法'callee之间有什么区别。

Although with both syntaxes, I am able to pass the callee to the caller , the caller: f: output seems to indicate that there is some subtle difference in both the syntaxes: #'callee seems to refer to a function object but 'callee seems to refer to just the function name. 尽管使用这两种语法,我都可以将callee caller传递给callee caller ,即caller: f:输出似乎表明两种语法都存在一些细微的区别: #'callee似乎引用了一个函数对象,但是'callee似乎仅指功能名称。

Here are my questions: 这是我的问题:

  1. What's the difference between the #'callee syntax and the 'callee syntax? #'callee语法和'callee语法有什么区别?
  2. How is it that funcall is able to invoke the callee in both cases successfully? 在两种情况下, funcall如何能够成功调用callee调用callee
  3. Is there any best practice or pros and cons associated with both syntaxes due to which one is preferred over another? 是否存在与这两种语法相关的最佳实践或优缺点,因此哪种语法优先于另一种语法?

The difference is largely one of how the function is looked up. 区别很大程度上是该功能的查找方式之一。 If one passes a symbol to funcall , it is looked up in the global (rather than lexical) environment. 如果将符号传递给funcall ,则会在全局(而不是词法)环境中查找该符号。 The relevant documentation is http://clhs.lisp.se/Body/f_funcal.htm . 相关文档是http://clhs.lisp.se/Body/f_funcal.htm I've slightly modified the example from the docs: 我已经从文档中稍微修改了示例:

(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)

#'callee expands to (function callee) while 'callee expands to (quote callee) . #'callee扩展为(function callee)'callee扩展为(quote callee)

#' looks up in the function name space. #'在函数名称空间中查找。 (Common Lisp is a 2-Lisp, meaning it has 2 separate namespaces which allows that a function can have the same name like a variable/data - Scheme/Racket is a 1-Lisp where function and variables share the same namespace - meaning sth with a specific name is either a function or a name for some other object). (Common Lisp是2个Lisp,这意味着它具有2个独立的名称空间,这使函数可以具有与变量/数据相同的名称-Scheme / Racket是1个Lisp,其中函数和变量共享相同的名称空间-意味着……具有特定名称的名称可以是函数,也可以是其他对象的名称)。

' doesn't look up anywhere but evaluates the following symbol name to itself a name. '不会在任何地方查找,而是将以下符号名称评估为一个名称。

funcall looks up its arguments name in the function name space and returns the function assigned to it. funcall在函数名称空间中查找其参数名称,并返回分配给它的函数。 If you do a normal function call (callee 10) , the Lisp interpreter implicitely looks up callee from the function namespace, because the first position in a list which gets executed is reserved for the function name. 如果执行正常的函数调用(callee 10) ,则Lisp解释器会隐式地从函数名称空间中查找callee ,因为要执行的列表中的第一个位置是为函数名保留的。 When functionnames are given as arguments, in other positions than the first, you have to apply funcall or #' on them first, so that the interpreter knows that this name it has to lookup in the function name space and not in the normal variable name space. 当将函数名作为参数给定时,必须在函数名的第一个位置以外的其他位置首先使用funcall#' ,以便解释器知道该名称必须在函数名称空间而不是常规变量名称中查找。空间。

Try this: 尝试这个:

(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)>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM