文章目录

Lisp 条件语句:if、cond、case

发布于 2026-04-04 04:16:05 · 浏览 2 次 · 评论 0 条

Lisp 条件语句:if、cond、case

在 Lisp 编程中,控制程序走向的核心手段是条件语句。Common Lisp 提供了三种主要的条件结构:ifcondcase。它们各有适用场景,掌握其用法能让你写出更清晰、高效的代码。


使用 if 处理二选一逻辑

if 是最简单的条件结构,适用于只有“成立”或“不成立”两种结果的情况。

基本语法

(if 条件表达式
    真值分支
    假值分支)
  1. 编写一个条件表达式,例如 (> x 0)
  2. 提供当条件为真时执行的表达式(真值分支)。
  3. 可选地提供当条件为假时执行的表达式(假值分支)。如果省略假值分支,且条件为假,则返回 NIL

例如:

(if (> 5 3)
    "大"
    "小")

这段代码会返回 "大",因为 5 > 3 成立。

注意:if 只能处理单一条件和两个分支。如果需要嵌套多个判断,代码会迅速变得难以阅读,此时应改用 cond


使用 cond 处理多分支逻辑

当你有多个互斥条件需要依次判断时,使用 cond 更清晰。

基本语法

(cond
  (条件1 结果1)
  (条件2 结果2)
  ...
  (t 默认结果))
  1. 列出多个子句,每个子句是一个括号包裹的列表,第一个元素是条件,后续是该条件为真时要执行的一个或多个表达式。
  2. 从上到下依次求值每个条件,一旦某个条件为真(非 NIL),就执行对应的结果表达式,并返回最后一个表达式的值。
  3. 使用 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 默认结果))
  1. 计算测试表达式(如变量 x 或函数调用)。
  2. 将结果与各子句的第一个元素比较(使用 eql 进行相等性判断)。
  3. 匹配成功后执行对应的结果表达式
  4. 使用 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 "无效"))

    daymontue 等之一时,返回 "工作日"


如何选择正确的条件结构

选择哪种条件语句取决于你的判断逻辑类型。以下是决策参考:

判断场景 推荐结构 原因
只有两种可能结果(是/否) if 语法最简,意图明确
多个条件需顺序判断(如范围、复杂谓词) cond 支持任意布尔表达式,灵活
根据某个表达式的精确值分支(且值为符号、数字等) case 代码简洁,避免重复写 (= x ...)

不要强行用 if 嵌套实现多分支,也不要试图用 case 处理范围判断(如 x > 10),那样会导致代码错误或难以维护。


常见错误与避坑指南

  1. if 中遗漏假值分支导致意外返回 NIL
    如果你期望函数总有返回值,务必提供假值分支:

    ;; 错误:当 x <= 0 时返回 NIL
    (if (> x 0) "正")
    
    ;; 正确
    (if (> x 0) "正" "非正")
  2. cond 中忘记 t 导致无匹配时返回 NIL
    如果所有条件都可能不满足,加上 (t ...) 确保有兜底逻辑。

  3. 误用 case 比较字符串

    ;; 错误:永远不会匹配
    (case input
      ("yes" t)
      ("no" nil))

    应改用 cond

    (cond
      ((string= input "yes") t)
      ((string= input "no") nil)
      (t nil))
  4. 混淆 case 中的单值与列表
    如果想匹配多个值,必须用括号包裹成列表:

    ;; 匹配 mon, tue, wed 中任意一个
    ((mon tue wed) ...)
    
    ;; 错误写法:这只会匹配一个叫 (mon tue wed) 的符号(不存在)
    (mon tue wed ...)

正确使用 ifcondcase,能让你的 Lisp 程序逻辑清晰、结构紧凑。记住:简单二选一用 if,复杂条件链用 cond,精确值匹配用 case

评论 (0)

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

扫一扫,手机查看

扫描上方二维码,在手机上查看本文