灯下 登录
计算机科学 / SICP / 5.4.4 Running the Evaluator

Exercise 5.30 · 习题

Exercise 5.30: Our evaluator currently catches
and signals only two kinds of errors—unknown expression types and unknown
procedure types. Other errors will take us out of the evaluator
read-eval-print loop. When we run the evaluator using the register-machine
simulator, these errors are caught by the underlying Scheme system. This is
analogous to the computer crashing when a user program makes an
error. It is a
large project to make a real error system work, but it is well worth the effort
to understand what is involved here.

Errors that occur in the evaluation process, such as an attempt to access an
unbound variable, could be caught by changing the lookup operation to make it
return a distinguished condition code, which cannot be a possible value of any
user variable. The evaluator can test for this condition code and then do what
is necessary to go to signal-error. Find all of the places in the
evaluator where such a change is necessary and fix them. This is lots of work.

Much worse is the problem of handling errors that are signaled by applying

primitive procedures, such as an attempt to divide by zero or an attempt to

extract the car of a symbol. In a professionally written high-quality

system, each primitive application is checked for safety as part of the

primitive. For example, every call to car could first check that the

argument is a pair. If the argument is not a pair, the application would

return a distinguished condition code to the evaluator, which would then report

the failure. We could arrange for this in our register-machine simulator by

making each primitive procedure check for applicability and returning an

appropriate distinguished condition code on failure. Then the

primitive-apply code in the evaluator can check for the condition code

and go to signal-error if necessary. Build this structure and make it

work. This is a major project.

练习 5.30:我们的求值器目前只捕获并报告两类错误——未知表达式类型和未知过程类型。其他错误会将我们带出求值器的读入-求值-打印循环。在使用寄存器机器模拟器运行求值器时,这些错误由底层 Scheme 系统捕获。这类似于用户程序出错时计算机崩溃。构建一个真正可用的错误系统是一项大型工程,但理解其中的要点是很值得的。

求值过程中发生的错误——例如试图访问未绑定变量——可以通过修改查找操作来捕获:使其在找不到变量时返回一个特殊条件码,该条件码不可能是任何用户变量的值。求值器随后检测该条件码,执行必要操作并跳转至 signal-error。找出求值器中所有需要作此修改的地方并加以修正。工作量相当大。

更棘手的是处理由应用基本过程所引发的错误,例如试图除以零或对符号求 car。在专业级高质量系统中,每个基本过程的应用都会在内部进行安全检查。例如,每次调用 car 时都先检查参数是否为序对。若参数不是序对,该应用向求值器返回一个特殊条件码,求值器随后报告失败。我们可以在寄存器机器模拟器中实现这一点:让每个基本过程检查可应用性,在失败时返回适当的特殊条件码。然后,求值器中的 primitive-apply 代码检测该条件码,并在必要时跳转至 signal-error。请构建这一结构并使其正常工作。这是一个重大项目。