news 2026/4/14 22:41:29

Chez Scheme 7 天入门计划( 第 2 天)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Chez Scheme 7 天入门计划( 第 2 天)

📅 第 2 天:让程序学会“做选择”(条件判断与逻辑)

🎯 今日目标

  1. 彻底搞懂 Scheme 中的“真假”概念(只有#f是假)。
  2. 掌握多重条件判断cond(相当于其他语言的 if-else if-else)。
  3. 学会逻辑组合and,or,not
  4. 理解逻辑运算符的“短路”特性。

💡 核心心法

昨天我们只用了if做二选一,今天我们要处理复杂的世界。
记住:在 Scheme 眼里,除了#f(false),连 0、空字符串""、空列表()全都是真的!这点和 Python/C/Java 完全不同,千万别惯性思维。


📚 理论讲解 + 10 个实战例子

1. 真假值的真相

在大多数语言里,0 是假。在 Scheme 里,0 是真!只有#f是假。

例子 1:0 也是真

; 如果 0 是假,应该返回 "False",但实际返回 "True" (if 0 "True" "False") ; 结果:"True" ; 空字符串也是真 (if "" "True" "False") ; 结果:"True" ; 只有 #f 是假 (if #f "True" "False") ; 结果:"False"
2. 逻辑组合:and, or, not

它们可以接受任意多个参数,不仅仅是两个。

例子 2:and (与)
; 所有条件都为真,结果才为真。返回最后一个真值,或者第一个假值。
(and #t #t “全是真的”)
; 结果:“全是真的”

(and #t #f “这就没了”)
; 结果:#f (遇到假就停止)

(and (> 5 3) (< 5 10))
; 结果:#t

例子 3:or (或)
; 只要有一个为真,结果就为真。返回第一个真值,或者最后一个假值。
(or #f #f “终于有个真的了”)
; 结果:“终于有个真的了”

(or #f 0 “0 也是真哦”)
; 结果:0 (注意:返回的是第一个真值本身,这里是 0)

例子 4:not (非)
(not #t)
; 结果:#f

(not 0)
; 结果:#f (因为 0 是真,取反就是假)

3. 多重选择:cond

if不够用时(比如要分 5 种情况),用cond。它是if-elif-else的超级版。
语法:

(cond (条件 1 结果 1) (条件 2 结果 2) ... (else 默认结果))

例子 5:成绩分级

(define (get-grade score) (cond ((>= score 90) "A") ((>= score 80) "B") ((>= score 60) "C") (else "F"))) ; else 相当于默认情况 (get-grade 85) ; 结果:"B"

注意:每个条件都要包在括号里((>= score 90) "A"),别漏了内层括号!

例子 6:cond 的求值顺序
; cond 从上往下测,一旦命中就停止,后面的不再看。
(cond
((> 10 5) “第一个命中”)
((> 10 2) “这个虽然也对,但不会执行”))
; 结果:“第一个命中”

4. 结合昨天知识的综合应用

define, 数学运算,if/cond, 逻辑符串起来。

例子 7:判断闰年 (经典逻辑题)
规则:能被 4 整除但不能被 100 整除,或者能被 400 整除。

(define (is-leap-year? year) (or (and (= (remainder year 4) 0) (not (= (remainder year 100) 0))) (= (remainder year 400) 0))) (is-leap-year? 2000) ; #t (is-leap-year? 1900) ; #f (能被 4 整除,也能被 100 整除,但不能被 400 整除) (is-leap-year? 2024) ; #t

注:remainder是取余数函数,相当于%

例子 8:符号比较 (eq?)
; 昨天学了符号 'apple,今天用来做状态机
(define (check-traffic-light color)
(cond
((eq? color 'red) “Stop”)
((eq? color 'yellow) “Wait”)
((eq? color 'green) “Go”)
(else “Unknown color”)))

(check-traffic-light 'yellow)
; 结果:“Wait”

*注意:比较符号常用 `eq?`,比较数字用 `=`,比较通用内容用 `equal?`。*

例子 9:嵌套逻辑
; 判断一个数是否是“正偶数”
(define (is-positive-even? n)
(and
(> n 0)
(= (remainder n 2) 0)))

(is-positive-even? 4) ; #t
(is-positive-even? 3) ; #f
(is-positive-even? -2) ; #f

例子 10:利用短路特性避免错误
; 假设我们有一个函数只在数字大于 0 时才安全调用
; 如果直接写 (and (> n 0) (danger-func n))
; 当 n <= 0 时,danger-func 根本不会执行,程序不会崩。
(define (safe-divide a b)
(if (and (number? b) (not (= b 0)))
(/ a b)
“Error: Div by zero or not a number”))

(safe-divide 10 2) ; 5.0
(safe-divide 10 0) ; “Error…”


📝 练习题 (仅限前两天知识)

请尝试在不使用列表(List)、递归或循环(明天学)的情况下完成。

1. 三角形类型判断器
编写函数triangle-type,接收三个边长a,b,c

  • 如果任意两边之和不大于第三边,返回"Impossible"(构不成三角形)。
  • 如果三边相等,返回"Equilateral"(等边)。
  • 如果只有两边相等,返回"Isosceles"(等腰)。
  • 否则返回"Scalene"(不等边)。
    提示:先用cond检查合法性,再检查相等性。

2. 简易计算器
编写函数simple-calc,接收三个参数:num1,op(符号),num2

  • 如果op'+',返回和。
  • 如果op'-',返回差。
  • 如果op'*',返回积。
  • 如果op'/',且num2不为 0,返回商;否则返回字符串"DivByZero"
  • 其他操作符返回"Unknown Op"
    测试:(simple-calc 10 '+ 5)-> 15,(simple-calc 10 '/' 0)-> “DivByZero”

3. 年龄组分类
编写函数age-group,接收年龄age

  • 0-12 岁:"Child"
  • 13-19 岁:"Teen"
  • 20-59 岁:"Adult"
  • 60 岁以上:"Senior"
  • 如果年龄小于 0 或大于 120,返回"Invalid Age"

4. 逻辑挑战:全真检测
编写函数all-true?,接收三个参数x,y,z
只有当这三个参数全部为真(即都不等于#f)时,返回#t,否则返回#f
注意:不要直接用and,尝试用ifcond实现逻辑,或者思考and本身的返回值特性(提示:题目要求返回严格的布尔值#t#f,而and可能返回具体的值如 0 或字符串,你需要处理一下)。


⚠️ 常见坑

  1. cond的括号地狱

    • 错误:(cond (条件 1 结果 1) (条件 2 结果 2))-> 这是错的!条件本身也要括号。
    • 正确:(cond ((条件 1) 结果 1) ((条件 2) 结果 2))
    • 记忆法cond的每一项都是(测试 动作),而测试本身通常是个表达式如(> x 0),所以看起来是((> x 0) ...)
  2. else的位置

    • else必须放在cond的最后一项,且前面不能加条件判断,直接写(else 结果)。如果在else前加了条件(else (> x 0))是语法错误。
  3. 相等性判断的混淆

    • 数字比较用=
    • 符号(如'red)比较最好用eq?
    • 字符串或复杂结构比较用equal?
    • (= 'a 'a)会报错,因为=只能用于数字!
  4. if缺少分支

    • Scheme 的if必须有两个分支(真和假),除非你确定永远为真。
    • 错误:(if (> x 0) "Positive")-> 如果 x 是负数,返回未定义值,可能导致后续计算出错。
    • 补救:(if (> x 0) "Positive" #f)或者直接用cond
  5. 逻辑运算的返回值

    • andor返回的不是单纯的#t#f,而是导致结果的那个值
    • (and 1 2 3)返回3
    • (or #f 0 "hi")返回0(因为 0 是真,且是第一个真值)。
    • 如果你需要严格的布尔值,记得最后包一层判断,比如(if (or a b) #t #f)

🚀 下一步预告

明天我们将进入 Scheme 最核心、最性感的部分:递归与列表 (Recursion & Lists)
我们将抛弃变量赋值的思维,学习如何用“头 (car)"和“尾 (cdr)"像剥洋葱一样处理数据,并用递归代替for循环。准备好让你的大脑升级了吗?

现在,去挑战上面的练习题吧!如果有报错,记得看括号是不是又没数对~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 22:41:16

AI 写作不是抄袭!订阅号合规发文实用技巧

「这篇文章是你自己写地吗&#xff1f;」 越来越多的订阅号作者&#xff0c;被读者、平台甚至合作方这样追问&#xff0c;特别当行文流畅、节奏统一&#xff0c;却又不像作者平时的风格时。这背后&#xff0c;是 AI 写作工具的大规模进入内容生产现场。但「用 AI」不等于「抄袭…

作者头像 李华
网站建设 2026/4/14 22:41:14

3步实现微信群消息自动转发:告别手动复制的智能解决方案

3步实现微信群消息自动转发&#xff1a;告别手动复制的智能解决方案 【免费下载链接】wechat-forwarding 在微信群之间转发消息 项目地址: https://gitcode.com/gh_mirrors/we/wechat-forwarding 你是否厌倦了在多个微信群之间来回切换&#xff0c;重复复制粘贴重要信息…

作者头像 李华
网站建设 2026/4/14 22:41:11

3分钟免费搞定:城通网盘直连解析终极指南

3分钟免费搞定&#xff1a;城通网盘直连解析终极指南 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 还在为城通网盘下载速度慢、广告多而烦恼吗&#xff1f;城通网盘解析器正是解决这些问题的利器&…

作者头像 李华
网站建设 2026/4/14 22:28:22

2025届最火的六大降重复率网站横评

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 运用人工化句式替代固定模板&#xff0c;抛弃千篇一律的模板化表达&#xff0c;用更为灵活多…

作者头像 李华
网站建设 2026/4/14 22:28:17

如何利用 Provide 实现全局主题切换?响应式状态注入的实战技巧

全局主题切换需用 ref 包裹主题状态并 provide&#xff0c;配合 useTheme 封装切换逻辑&#xff1b;子组件 inject 时传默认值并 watch 响应变化&#xff1b;CSS 变量动态设置实现样式解耦。用 Provide 实现全局主题切换&#xff0c;核心不是“把主题塞进去”&#xff0c;而是让…

作者头像 李华