一个函数可以作为一个表达式的值返回,就像其它对象一样。这里有一个接受一个参数的函数,返回对应参数类型的合并函数:
(defun combiner (x) (typecase x (number #'+) (list #'append) (t #'list)))
(defun combine (&rest args) (apply (combiner (car args)) args))
[3]> (combine 2 3) 5 [4]> (combine '(a b) '(c d)) (A B C D)
如果一个函数被定义在一个词法变量的域内,那么它就能继续引用那个变量,即使这个函数作为值返回到了创建这个变量的上下文之外。这里我们创建了一个函数,这个函数将对它的参数做加3操作:
[5]> (setf fn (let ((i 3)) #'(lambda (x) (+ x i)))) #<FUNCTION :LAMBDA (X) (+ X I)> [6]> (funcall fn 2) 5
一个闭包是一个函数和一个环境的组合。当一个函数从周围的词法环境中引用某些东西的时候,就隐式地创建了一个闭包。这种事情是在无声中发生的,就像下面的这个,但是想法是一样的:
(defun add-to-list (num lst) (mapcar #'(lambda (x) (+ x num)) lst))
一个更加明显的例子是每次调用都返回不同闭包的函数。下面的函数返回一个加法器:
(defun make-adder (n) #'(lambda (x) (+ x n)))
[8]> (setf add3 (make-adder 3)) #<FUNCTION :LAMBDA (X) (+ X N)> [9]> (funcall add3 2) 5 [10]> (setf add27 (make-adder 27)) #<FUNCTION :LAMBDA (X) (+ X N)> [11]> (funcall add27 2) 29
(let ((counter 0)) (defun reset () (setf counter 0)) (defun stamp () (setf counter (+ counter 1))))
[13]> (list (stamp) (stamp) (reset) (stamp) ) (1 2 0 1)
Common Lisp有一个内置的函数complement,它会接收一个断言,然后返回断言的反面:
[17]> (mapcar (complement #'oddp ) '(1 2 3 4 5 6)) (NIL T NIL T NIL T)
(defun our-complement (f) #'(lambda (&rest args) (not (apply f args))))
[19]> (mapcar (our-complement #'oddp ) '(1 2 3 4 5 6)) (NIL T NIL T NIL T)