# 11.2 条件判断（DONE）

条件控制结构会在众多的选项中做选择。Emacs Lisp中包含5种条件表达式：if（和绝大多数其他语言中的类似）；when和unless（这些为if的变体）；cond（更通用的条件表达式）；以及pcase（更通用的cond）。

\[Special Form] if condition then-form else-forms...

if 会基于condition的求值结果，选择对then-form求值还是对else-forms求值。若condition的求值结果为non-nil，那么会对then-form求值，并将其求值结果返回。否则，将会依次对else-forms中的表达式进行求值，并返回其最后一个表达式的求值结果。（if的else部分被隐式实现了progn）

若condition求值为nil，并且未提供else-forms，那么返回nil。

if 是一个特殊表达式，其中没有被选择的分支将不会被求值。因此在下面这个例子里，true将不会被打印，因为print根本就不会被调用：

```lisp
(if nil
    (print 'true)
    'very-false)
=>   very-falses
```

\[Macro] when condition then-forms...

这是if的一个变体，该变体中不包含else-forms，但可以包含若干then-forms。

特别的，

```lisp
(when condition a b c)
```

和下面完全等价

```lisp
(if condition (progn a b c) nil)
```

\[Macro] unless condition forms...

这是if的一个变体，该变体中不包含then-from：

```lisp
(unless condition a b c)
```

和下面完全等价

```lisp
(if condition nil
    a b c)
```

\[Specila Form] cond clause...

cond会在任意数量的分支中做出选择。cond中每个clause都必须是一个列表。该列表的car部分为condition而余下的部分均为表达式体body-forms。也就是说，一个clause看起来像这样：

```lisp
(condition body-forms...)
```

cond会依次尝试测试每个clause中的condition，直到某个condition求值为non-nil；然后cond会对对应clause的body-forms进行求值，并将其中最后一个表达式的求值结果作为整体的求值结果。任何余下的clause都会被忽略。

clause同样可以类似这样：

```lisp
(condition)
```

此时若condition求值为non-nil，那么cond表达式会将该值作为结果返回。

若每个condition求值均为nil，也就是所有的clause测试都未通过，那么cond会返回nil。

下面这个例子中有4个clause，其中每个clause分别测试x是否是数字、字符串、缓冲区以及符号：

```lisp
(cond ((numberp x) x)
      ((stringp x) x)
      ((bufferp x)
       (setq temporary-hack x)
       (buffer-name x))
      ((symbolp x) (symbol-value x)))
```

通常我们想在最后设置一个默认clause，当前面所有的clause都未通过测试时求值。此时我们可以将t作为该clause的condition，就像这样(t body-forms)。表达式t求值后得到t，永远通过测试，因此该clause永远不会失败。举个例子：

```lisp
(setq a 5)
(cond ((eq a 'hack) 'foo)
      (t "default"))
=>  "default"
```

若a求值结果为hack，则返回foo，否则返回字符串"default"。

任何条件结构都可以使用cond或if组合出来。因此，使用哪一个仅仅是风格问题。比如下面两个就是等价的：

```lisp
(if a b c)

(cond (a b) (t c))
```


---

# 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/kong-zhi-jie-gou/tiao-jian-pan-duan.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.
