Anonymous Functions(匿名函数)

Once you start writing, or even simply using, functions that accept other functions as arguments, you’re bound to discover that sometimes it’s annoying to have to define and name a whole separate function that’s used in only one place, especially when you never call it by name.

一旦开始编写或只是使用那些可以接受其他函数作为实参的函数,你就必然发现,有时不得不去定义和命名一个仅使用一次的函数是(尤其是你可能从不用名字来调用它时),这会让人相当恼火。

When it seems like overkill to define a new function with DEFUN, you can create an “anonymous” function using a LAMBDA expression. As discussed in Chapter 3, a LAMBDA expression looks like this:

觉得没必要用 DEFUN 来定义一个新函数时,可以使用一个 LAMBDA 表达式来创建匿名的函数。第 3 章里讨论过,一个 LAMBDA 表达式形式如下:

  1. (lambda (parameters) body)

One way to think of LAMBDA expressions is as a special kind of function name where the name itself directly describes what the function does. This explains why you can use a LAMBDA expression in the place of a function name with #'.

可以将 LAMBDA 表达式视为一种特殊类型的函数名,其名字本身直接描述函数的用途。这就解释了为什么可以使用一个带有 #'LAMBDA 表达式来代替一个函数名。

  1. (funcall #'(lambda (x y) (+ x y)) 2 3) ==> 5

You can even use a LAMBDA expression as the “name” of a function in a function call expression. If you wanted, you could write the previous FUNCALL expression more concisely.

甚至还可以在一个函数调用表达式中将 LAMBDA 表达式用作函数名。由此一来,我们也可以在需要时以更简洁方式来书写前面的 FUNCALL 表达式如下:

  1. ((lambda (x y) (+ x y)) 2 3) ==> 5

But this is almost never done; it’s merely worth noting that it’s legal in order to emphasize that LAMBDA expressions can be used anywhere a normal function name can be.

但几乎没人这样做。它唯一的用途是来强调将 LAMBDA 表达式用在任何一个正常函数名可以出现的场合都是合法的。

Anonymous functions can be useful when you need to pass a function as an argument to another function and the function you need to pass is simple enough to express inline. For instance, suppose you wanted to plot the function 2x. You could define the following function:

在需要传递一个作为参数的函数给另一个函数,并且需要传递的这个函数简单到可以内联表达时,匿名函数特别有用。例如,假设想要绘制函数 2x,你可以定义下面的函数:

  1. (defun double (x) (* 2 x))

which you could then pass to plot:

并随后将其传给 plot

  1. CL-USER> (plot #'double 0 10 1)
  2. **
  3. ****
  4. ******
  5. ********
  6. **********
  7. ************
  8. **************
  9. ****************
  10. ******************
  11. ********************
  12. NIL

But it’s easier, and arguably clearer, to write this:

但如果写成这样将会更简单和清晰:

  1. CL-USER> (plot #'(lambda (x) (* 2 x)) 0 10 1)
  2. **
  3. ****
  4. ******
  5. ********
  6. **********
  7. ************
  8. **************
  9. ****************
  10. ******************
  11. ********************
  12. NIL

The other important use of LAMBDA expressions is in making closures, functions that capture part of the environment where they’re created. You used closures a bit in Chapter 3, but the details of how closures work and what they’re used for is really more about how variables work than functions, so I’ll save that discussion for the next chapter.

LAMBDA 表达式的另一项重要用途是制作闭包(closure),即捕捉了其创建时环境信息的函数。你在第 3 章里使用了一点儿闭包,但要深入了解闭包的工作原理及其用途,更多的还是要从变量而非函数的角度去考察,因此我将在下一章里讨论它们。