关于Scheme中结合continuation的函数参数求值合规性的问询
Scheme参数求值与continuation的标准合规性解答
核心结论
- 旧版本Gauche(0.9.4及更早)内联lambda场景下的复用修改值行为不符合R6RS/R7RS标准
- 符合标准的行为为:continuation调用时,所有在捕获点之前完成求值的参数,必须使用原始求值结果,不受之前函数调用对形参修改的影响
标准依据
Scheme R6RS、R7RS标准中有两个明确的约束:
- 函数调用的执行顺序为:先完成所有参数的求值(求值顺序由实现自定义),再将求值得到的结果绑定到函数形参,最后执行函数本体。形参是函数作用域内的本地绑定,对形参的
set!操作仅修改该次函数调用的本地绑定,不会影响参数本身的原始求值结果。 - continuation捕获的是捕获时刻的执行上下文,仅会重演捕获点之后的执行逻辑。在你描述的场景中,
arg1在call/cc执行前就已完成求值,该结果是固定值,调用continuation时仅会重新执行捕获点后的逻辑(求值arg3、绑定参数、执行函数),不会重新求值arg1,也不会复用之前函数调用修改后的形参值。
旧版本Gauche异常行为原因
该异常是内联优化bug导致:旧版本Gauche对内联lambda做优化时,错误地将参数求值的结果存储到了可被后续函数调用修改的内存位置,混淆了参数原始求值结果和函数本地形参绑定,导致后续continuation调用时错误读取了前一次修改后的值。0.9.5及之后的版本修复了该优化漏洞,行为回归标准要求。
内容的提问来源于stack exchange,提问作者Tom Karzes
相关产品推荐
相关产品推荐

