在这之上,我们可以创建一个通用的结合函数:

    1. (apply (combiner (car args))
    2. args))

    它接受任何类型的参数,并以适合它们类型的方式结合。(为了简化这个例子,我们假定所有的实参,都有着一样的类型。)

    1. > (combine 2 3)
    2. 5
    3. > (combine '(a b) '(c d))
    4. (A B C D)

    2.10 小节提过词法变量(lexical variables)只在被定义的上下文内有效。伴随这个限制而来的是,只要那个上下文还有在使用,它们就保证会是有效的。

    如果函数在词法变量的作用域里被定义时,函数仍可引用到那个变量,即便函数被作为一个值返回了,返回至词法变量被创建的上下文之外。下面我们创建了一个把实参加上 3 的函数:

    闭包结合了函数与环境(environment);无论何时,当一个函数引用到周围词法环境的某个东西时,闭包就被隐式地创建出来了。这悄悄地发生在像是下面这个函数,是一样的概念:

    1. (mapcar #'(lambda (x)
    2. lst))

    这函数接受一个数字及列表,并返回一个列表,列表元素是元素与传入数字的和。在 lambda 表达式里的变量 num 是自由的,所以像是这样的情况,我们传递了一个闭包给 mapcar

    一个更显着的例子会是函数在被调用时,每次都返回不同的闭包。下面这个函数返回一个加法器(adder):

    1. (defun make-adder (n)
    2. #'(lambda (x)
    3. (+ x n)))

    它接受一个数字,并返回一个将该数字与其参数相加的闭包(函数)。

    1. (let ((counter 0))
    2. (setf counter 0))
    3. (setf counter (+ counter 1))))

    这样的一对函数或许可以用来创建时间戳章(time-stamps)。每次我们调用 stamp 时,我们获得一个比之前高的数字,而调用 reset 我们可以将计数器归零:

    1. > (list (stamp) (stamp) (reset) (stamp))
    2. (1 2 0 1)

    你可以使用全局计数器来做到同样的事情,但这样子使用计数器,可以保护计数器被非预期的引用。

    Common Lisp 有一个内置的函数 complement 函数,接受一个谓词,并返回谓词的补数(complement)。比如:

    有了闭包以后,很容易就可以写出这样的函数:

    1. (defun our-complement (f)
    2. #'(lambda (&rest args)