Lisp 条件语句:if、cond、case
在 Lisp 编程中,控制程序走向的核心手段是条件语句。Common Lisp 提供了三种主要的条件结构:if、cond 和 case。它们各有适用场景,掌握其用法能让你写出更清晰、高效的代码。
使用 if 处理二选一逻辑
if 是最简单的条件结构,适用于只有“成立”或“不成立”两种结果的情况。
基本语法:
(if 条件表达式
真值分支
假值分支)
- 编写一个条件表达式,例如
(> x 0)。 - 提供当条件为真时执行的表达式(真值分支)。
- 可选地提供当条件为假时执行的表达式(假值分支)。如果省略假值分支,且条件为假,则返回
NIL。
例如:
(if (> 5 3)
"大"
"小")
这段代码会返回 "大",因为 5 > 3 成立。
注意:if 只能处理单一条件和两个分支。如果需要嵌套多个判断,代码会迅速变得难以阅读,此时应改用 cond。
使用 cond 处理多分支逻辑
当你有多个互斥条件需要依次判断时,使用 cond 更清晰。
基本语法:
(cond
(条件1 结果1)
(条件2 结果2)
...
(t 默认结果))
- 列出多个子句,每个子句是一个括号包裹的列表,第一个元素是条件,后续是该条件为真时要执行的一个或多个表达式。
- 从上到下依次求值每个条件,一旦某个条件为真(非
NIL),就执行对应的结果表达式,并返回最后一个表达式的值。 - 使用
t作为最后一个条件,表示“否则”(因为t永远为真),相当于其他语言中的else。
例如:
(cond
((< x 0) "负数")
((= x 0) "零")
(t "正数"))
如果 x 是 -2,返回 "负数";如果是 0,返回 "零";其他情况返回 "正数"。
你也可以在一个子句中写多个表达式:
(cond
((> score 90)
(print "优秀")
"A")
(t "不及格"))
当分数大于 90 时,先打印消息,再返回 "A"。
使用 case 根据具体值选择分支
当你需要根据某个表达式的确切值来决定执行哪段代码时,case 是最佳选择。它类似于其他语言中的 switch,但更安全、更简洁。
基本语法:
(case 测试表达式
(值1 结果1)
(值2 结果2)
...
(otherwise 默认结果))
- 计算测试表达式(如变量
x或函数调用)。 - 将结果与各子句的第一个元素比较(使用
eql进行相等性判断)。 - 匹配成功后执行对应的结果表达式。
- 使用
otherwise表示默认分支(也可用t,但otherwise更具可读性)。
例如:
(case grade
(A "优秀")
(B "良好")
(C "及格")
(otherwise "无效成绩"))
如果 grade 的值是 B,则返回 "良好"。
注意以下关键点:
case使用eql比较,因此只适用于数字、字符、符号等简单类型,不能用于字符串或列表(因为eql对字符串返回NIL即使内容相同)。- 子句中的“值”可以是单个值,也可以是值的列表。例如:
(case day ((mon tue wed thu fri) "工作日") ((sat sun) "周末") (otherwise "无效"))当
day是mon、tue等之一时,返回"工作日"。
如何选择正确的条件结构
选择哪种条件语句取决于你的判断逻辑类型。以下是决策参考:
| 判断场景 | 推荐结构 | 原因 |
|---|---|---|
| 只有两种可能结果(是/否) | if |
语法最简,意图明确 |
| 多个条件需顺序判断(如范围、复杂谓词) | cond |
支持任意布尔表达式,灵活 |
| 根据某个表达式的精确值分支(且值为符号、数字等) | case |
代码简洁,避免重复写 (= x ...) |
不要强行用 if 嵌套实现多分支,也不要试图用 case 处理范围判断(如 x > 10),那样会导致代码错误或难以维护。
常见错误与避坑指南
-
在
if中遗漏假值分支导致意外返回NIL
如果你期望函数总有返回值,务必提供假值分支:;; 错误:当 x <= 0 时返回 NIL (if (> x 0) "正") ;; 正确 (if (> x 0) "正" "非正") -
在
cond中忘记t导致无匹配时返回NIL
如果所有条件都可能不满足,加上(t ...)确保有兜底逻辑。 -
误用
case比较字符串;; 错误:永远不会匹配 (case input ("yes" t) ("no" nil))应改用
cond:(cond ((string= input "yes") t) ((string= input "no") nil) (t nil)) -
混淆
case中的单值与列表
如果想匹配多个值,必须用括号包裹成列表:;; 匹配 mon, tue, wed 中任意一个 ((mon tue wed) ...) ;; 错误写法:这只会匹配一个叫 (mon tue wed) 的符号(不存在) (mon tue wed ...)
正确使用 if、cond 和 case,能让你的 Lisp 程序逻辑清晰、结构紧凑。记住:简单二选一用 if,复杂条件链用 cond,精确值匹配用 case。

暂无评论,快来抢沙发吧!