重定义Scheme标准过程是否会影响其他依赖它的标准过程行为
关于Scheme重定义标准过程
car的行为规范问题 两种常见的重定义写法
我们通常可以通过以下两种写法尝试重定义Scheme内置的标准过程car:
第一种写法:
(define (car) (display "vroom vroom!"))
第二种写法:
(set! car (lambda () (display "vroom vroom!")))
核心疑问
在符合Scheme官方标准规范的实现中,上述重定义car的操作,是否会对其他内部依赖car实现的标准过程的运行行为产生影响?
比如:Scheme实现是否被允许在内部将cadr定义为(define (cadr x) (car (cdr x))),使得用户在REPL环境中重定义car后,会直接改变REPL中cadr的运行行为?
标准规范给出的结论
- 首先从R5RS、R7RS等主流Scheme标准的规定来看,用户重定义顶层环境中的标准过程绑定(比如
car、cdr这类内置基础过程)的后果属于未定义行为。标准不会对这类重定义的影响范围做任何强制约束,不同实现可以完全自主选择处理策略,不存在唯一的“正确行为”。 - 你提到的「
cadr直接依赖顶层car绑定、重定义car后cadr行为同步改变」的实现方式是完全合规的。标准并没有要求内置的派生过程必须持有对原始基础过程的私有独立引用,实现完全可以把cadr这类派生过程直接定义在顶层环境中,和用户代码走同一套顶层绑定查找逻辑。 - 反过来,「重定义顶层
car完全不影响其他标准过程运行」的实现也同样符合标准要求。不少Scheme实现为了运行性能、避免用户误修改标准绑定导致整个环境崩溃,会给标准库内部使用的基础过程保留独立的私有引用——比如内部实现cadr、map等过程时,调用的是实现内部留存的原始car逻辑,根本不会读取用户修改后的顶层car绑定,这种设计没有任何违反标准的地方。 - 补充一个细节:你给出的两种重定义写法本身和原始
car的函数签名不匹配——原始car需要接收1个序对类型的参数,你重定义的是0参数版本,就算实现采用了绑定联动的设计,其他标准过程调用这个新car的时候也会先触发参数数量不匹配的错误,根本执行不到输出vroom vroom!的逻辑。
内容的提问来源于stack exchange,提问作者Flux
相关产品推荐
相关产品推荐

