如何在DrRacket中借助Simply Scheme扩展实现句子处理
解决Scheme句子处理的类型转换、扩展获取与功能实现问题
咱们一步步拆解你遇到的问题,逐个解决:
1. 先理清类型错误与相等判断的核心问题
你输入的'(h)是一个符号列表(在DrRacket的SICP语言里显示为(mcons 'h '())),而你用的symbol->string、list->string这些函数都有明确的参数要求,直接用列表肯定会报错:
symbol->string需要单个符号(比如'h),不是列表,你得先取列表的第一个元素:(symbol->string (car '(h))),这样就能得到字符串"h"。list->string要求列表元素是字符(比如'(#\h)),不是符号,所以用'(h)会触发类型违规。- 关于相等判断:
eq?判断的是两个对象是否是同一个内存引用,所以'(h)和'(h)在SICP语言里是不同的cons单元,返回#f,你应该用equal?来判断内容相等:(equal? '(h) '(h))会返回#t。- 要判断符号
'h和字符串"h"是否相等,得先把符号转成字符串:(equal? (symbol->string 'h) "h"),结果是#t。
2. 获取《Simply Scheme》的扩展函数
DrRacket直接支持《Simply Scheme》的扩展,两种简单方式:
- 直接切换语言:打开DrRacket后,点击顶部"Language"菜单,选择"Choose Language...",搜索并选中"Simply Scheme",确认后就能直接用书中的
sentence、word、keep、last等函数。 - 通过包导入:如果找不到语言选项,打开"File"菜单的"Package Manager...",搜索
simply-scheme安装。安装完成后,在代码开头加(require simply-scheme),就能调用所有扩展函数了。
3. 实现ends-e句子处理功能
方式一:用《Simply Scheme》扩展(最简洁)
完全贴合你需求的写法,利用书中的封装函数:
(define (ends-e sent) ; keep函数筛选句子中符合条件的单词 (keep (lambda (wd) ; last取单词最后一个字符,判断是否为'e' (equal? (last wd) 'e)) sent))
测试效果:
> (ends-e '(only the good die young)) '(the die)
方式二:标准Scheme自行实现
如果想在SICP等标准Scheme环境里写,核心是把符号转成字符串处理字符,再筛选:
(define (ends-e sent) ; filter函数筛选列表元素 (filter (lambda (wd) (let ((word-str (symbol->string wd))) ; 取字符串最后一个字符,判断是否为字符类型的#\e (equal? (string-ref word-str (- (string-length word-str) 1)) #\e))) sent))
测试同样能得到预期结果:
> (ends-e '(only the good die young)) '(the die)
总结
- 标准Scheme里没有"sentence"类型,你说的句子本质是符号列表,每个符号对应一个单词,处理时要在符号、字符串、字符之间做转换。
- 《Simply Scheme》的扩展能大幅简化句子和单词的处理逻辑,DrRacket里获取这些扩展非常方便。
- 相等判断要选对函数:
eq?判断同一对象,equal?判断内容相等,跨类型比较时记得先做类型转换。
内容的提问来源于stack exchange,提问作者Asher
相关产品推荐
相关产品推荐

