Common Lisp中的高阶函数语法

时间:2013-04-10 21:32:59

标签: lisp common-lisp

我正在使用Norvig的人工智能编程范例来教授自己的Common Lisp,并且遇到了一些我不理解的事情,他没有解释。

(defun mappend (fn the-list)
  (apply #'append (mapcar fn the-list)))

如下调用高阶函数,higherOrderFunc #'funcName funcArg和在没有mapcar调用#'时他做了什么有什么区别?调用高阶函数时需要#'吗?

3 个答案:

答案 0 :(得分:8)

Common Lisp具有不同的函数和变量名称空间。

(defun mappend (fn the-list)
   (apply #'append (mapcar fn the-list)))

上面MAPPEND定义了两个局部变量fnthe-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))

答案 1 :(得分:6)

#'function的语法糖:#'foo被视为(function foo)

Function是一个特殊的运算符,它返回绑定到给定名称的函数值。如果将函数作为参数传递,则该参数(在您的情况下为fn)将其值绑定到函数。要将其传递给另一个函数,您只需将变量名称放入调用表单即可。但是,要获取名称的函数值,您需要使用function

访问它

答案 2 :(得分:2)

严格要求使用#'。相反,如果您只是传递'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#'foo或'foo是等价的:

  

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)