# 10.2.4 函数符号转义（DONE）

对于第一个元素为符号的非空列表，Lisp 解释器会先检查该符号的函数cell，然后用该cell的内容去求值。若该cell内容是另一个符号，那么 Lisp 会递归的检查此符号的函数cell，直到查找到一个非符号定义。这个过程称为函数符号转义(symbol function indirection)。查阅 函数名称 章节，以获取更多 函数符号转义 相关的信息。

很显然存在一种可能，即其转义序列是一个无穷的循环，这种情况下，符号的函数cell指回自身。除此之外，我们最终都会得到一个非符号定义，而这个非符号定义应当是函数，或其他合理的对象。

更具体的说，我们最终应当获取一个 Lisp 函数(lambda 表达式) ，或字节码函数，或基础函数，或 Lisp 宏，或 特殊表达式，或自动加载对象。以上列举的美中情况都会在后续章节介绍。如果获得的对象不是上面中列举的对象，Emacs 则会抛出 invalid-function 错误。

下面的例子展示了符号转义的过程。我们首先用 fset 设置符号的 函数cell，再用 symbol-function 来获取该函数 cell 的内容(具体查阅 Function Cells)。再具体一些，我们将符号 car 储存进 first 的函数cell，然后将符号 first 储存进 erste 的函数cell。

```
;; Build this function cell linkage:
;;   -------------       -----        -------        -------
;;  | #<subr car> | <-- | car |  <-- | first |  <-- | erste |
;;   -------------       -----        -------        -------
(symbol-function 'car)
     ⇒ #<subr car>
(fset 'first 'car)
     ⇒ car
(fset 'erste 'first)
     ⇒ first
(erste '(1 2 3))   ; Call the function referenced by erste.
     ⇒ 1
```

下面的例子不使用符号转义即可完成函数调用，因为其第一个元素是一个 Lisp 匿名函数，而非一个符号。

```
((lambda (arg) (erste arg))
 '(1 2 3))
     ⇒ 1
```

执行一个函数意味着对函数的body部分求值；这个例子里，其body部分使用了ersta的函数符号转义。

这种形式的写法已经很少用了，现在已经被废弃。替代的，你应该这么写：

```
(funcall (lambda (arg) (erste arg))
         '(1 2 3))
```

或者直接这么写

```
(let ((arg '(1 2 3))) (erste arg))
```

内置函数 indirect-function 提供了一个简单的方式，去显示地指向函数符号转义。

Function: indirect-function function \&optional noerror

该函数返回 function 的定义。如果 function 是 一个 符号，那么会继续查找函数的定义，直到找到一个值。如果 function 并不是一个符号，那么返回 function 本身。

如果递归的最终符号没有绑定，那么该符号会返回 nil。如果其符号转义链是循环的，则会抛出 cyclic-function-indirection 错误。

可选参数 noerror 已经废弃，这里是为了保持向后兼容。

这里是一个简略的 indirect-function 定义：

```
(defun indirect-function (function)
  (if (symbolp function)
      (indirect-function (symbol-function function))
    function))
```
