我正在使用 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)