我正在使用 Norvig 的人工智能编程范式自学 Common Lisp,遇到了一些我不理解的东西,他也没有解释。
(defun mappend (fn the-list)
(apply #'append (mapcar fn the-list)))
如下调用高阶函数和不higherOrderFunc #'funcName funcArg
调用时他做了什么有什么区别?调用高阶函数时有必要吗 ?mapcar
#'
#'
我正在使用 Norvig 的人工智能编程范式自学 Common Lisp,遇到了一些我不理解的东西,他也没有解释。
(defun mappend (fn the-list)
(apply #'append (mapcar fn the-list)))
如下调用高阶函数和不higherOrderFunc #'funcName funcArg
调用时他做了什么有什么区别?调用高阶函数时有必要吗 ?mapcar
#'
#'
Common Lisp 对函数和变量有不同的命名空间。
(defun mappend (fn the-list)
(apply #'append (mapcar fn the-list)))
上面MAPPEND
用两个局部变量定义fn
,the-list
APPLY
传递 的函数值APPEND
。
MAPCAR
传递 的变量值FN
。
类似的看到这个:
CL-USER 129 > (flet ((add-something (number)
(+ number 17)))
(let ((add-something (lambda (number)
(+ number 42))))
(list
(mapcar #'add-something '(1 2 3))
(mapcar add-something '(1 2 3)))))
->
((18 19 20) (43 44 45))
LET
创建局部变量,FLET
创建局部函数。
第一个mapcar
使用函数命名空间,第二个使用变量命名空间。
Common Lisp 使用一个特殊的函数命名空间,因为它被认为更高效(实现快速 Lisp 稍微容易一些)并且允许函数和变量具有相同的名称。
在 Common Lisp 中,我们可以这样写:
(defun list-me (list)
(list list))
在没有单独命名空间的 Scheme 中,可以这样写:
(define (list-me lst)
(list lst))
#'
是function
:的语法糖,#'foo
读作(function foo)
.
Function
是一个特殊的运算符,它返回绑定到给定名称的函数值。如果您将函数作为参数传递,则该参数(在您的情况下为fn
)将其值绑定到该函数。要将其传递给另一个函数,您只需将变量名放入调用表单即可。但是,要获取名称的函数值,您需要使用function
.
使用#'
不是严格要求。相反,如果您只是传递'foo
符号函数,则会被调用。考虑以下:
* (defvar foo #'(lambda (a) 'var))
* (setf (symbol-function 'foo) #'(lambda (a) 'fun))
* (mapcar 'foo '(a b))
(FUN FUN)
* (mapcar #'foo '(a b))
(FUN FUN)
* (mapcar foo '(a b))
(VAR VAR)
实际上 #'foo 或 'foo 是等价的:
X3J13 投票 [...] 允许 'function' 使用唯一的 'symbol' 或 'function' 类型;[...] 必须在 lambda 表达式 [...] 之前使用“函数”特殊形式 [...]。
函数的规范flet
有一些有趣的属性:
* (flet ((foo (a) 'FLET))
(mapcar foo '(a b))) ; Uses 'value' of foo
(VAR VAR)
* (flet ((foo (a) 'FLET))
(mapcar 'foo '(a b))) ; Uses 'function' of foo
(FUN FUN)
* (flet ((foo (a) 'FLET))
(mapcar #'foo '(a b))) ; Uses local binding 'flet' of foo
(FLET FLET)