我自学的是使用Norvig的AI编程范式的Common Lisp,遇到了一些我不明白的东西,他也没有解释。Common Lisp中的高阶函数语法
(defun mappend (fn the-list)
(apply #'append (mapcar fn the-list)))
是什么叫高阶函数如下,higherOrderFunC#'funcName funcArg
并呼吁mapcar
没有#'
时,他做什么区别呢?调用高阶函数时需要#'
吗?
我自学的是使用Norvig的AI编程范式的Common Lisp,遇到了一些我不明白的东西,他也没有解释。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))
在计划,它没有单独的名称空间一个会写这样的事:
(define (list-me lst)
(list lst))
#'
是句法糖function
:#'foo
被读作(function foo)
。
Function
是一个特殊的运算符,它返回给定名称的函数值bound。如果您将函数作为参数传递,那么该参数(在您的情况下为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)
Practially# '富或' 富是等效的:
X3J13投[...],以允许 '功能' 的唯一类型 '符号' 的 或'功能'; [...]必须在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)
但是,不要这样做, '#'foo'和''foo'不等于'(function foo)'和'(quote foo)'。也就是说,即使它们可以在某些相同的情况下使用,也不是很好。无论哪种方式,使用带引号的符号都会遮掩代码的含义。 – jwmc 2013-04-11 07:36:18
不适用于本地功能。 '(flet((foo()'bar))(funcall'foo))'不起作用。另外,在'(funcall(function bar))'和(funcall'bar)之间使用优化编译器时可能会有细微的差别。后者可能会始终通过符号查找函数,而第一个可能会查看优化后的查找,并使用当前(编译期间)函数绑定期间的查找。文件编译器可能想要这样做。所以:使用'FUNCTION'或'#''是一致的。如果您想要全局函数的后期绑定,请使用该符号。 – 2013-04-11 08:29:02
更新为'flet'使用。注意:我同意使用'#''但我的选择不是在OQ中提出的。 – GoZoner 2013-04-11 18:02:30
你能解释一下使用“FLET”和它有什么不同“让”?似乎以'let'定义某个临时变量的范围的方式来定义一些临时函数的范围。 – vrume21 2013-04-11 00:53:05
Rainer的答案是为了澄清其中隐含的一点:当你调用'mappend'时,你需要传递函数参数为'#'some-func'。获得符号“some-func”的函数值,然后将其作为'fn'的值传递给'mappend'。 – Mars 2013-04-11 03:58:17