# 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))
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://emacs-lisp.ivory.cafe/qiu-zhi/biao-da-shi/10.2.4-han-shu-fu-hao-zhuan-yi-done.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
