使用Racket实现SICP评估程序

时间:2015-09-16 15:56:39

标签: scheme racket sicp

我正在研究4.1.4 Running the Evaluator as a Program的metacircular评估员,用Racket构建它:

#lang racket

(require (combine-in rnrs/base-6
                     rnrs/mutable-pairs-6))

(define (evaluate exp)
  (cond 
    ; ...
    ((definition? exp) (display exp)
                       (display " is a definition\n"))
    ; ...
    (else (display exp) 
          (display " is something else\n"))))

(define (definition? exp)
  (tagged-list? exp 'define))

(define (tagged-list? exp tag)
  (if (pair? exp)
      (eq? (car exp) tag)
      false))

(define (driver-loop)
  (let ((input (read)))
    (let ((output (evaluate input)))
      output))
  (driver-loop))

(driver-loop)

获得一个成功读取DrRacket输入的框后,我输入(define a 0),结果显示:

(define a 0) is something else

如果我删除

,我们可以认出来
(require (combine-in rnrs/base-6
                     rnrs/mutable-pairs-6))

但如果没有,我将无法拨打set-car!set-cdr!。是否有set-函数的替代方法?

或者我可以从rnrs/base-6rnrs/mutable-pairs-6选择要导入的内容吗?

2 个答案:

答案 0 :(得分:0)

应该运行正常。我用你给的代码做了快速测试。

(define (evaluate exp)
  (cond 
    ; ...
    ((definition? exp) (display exp)
                       (display " is a definition\n"))
    ; ...
    (else (display exp) 
          (display " is something else\n"))))

(define (definition? exp)
  (tagged-list? exp 'define))

(define (tagged-list? exp tag)
  (if (pair? exp)
      (eq? (car exp) tag)
      false))

(define (driver-loop)
  (let ((input (read)))
    (let ((output (evaluate input)))
      output))
  (driver-loop))

(driver-loop)

用球拍语言运行会给我:

--> is user input
-->(define a 0)
   (define a 0) is a definition
-->(list 1 2 3)
   (list 1 2 3) is something else

正如您所见,输入了条件的右分支。

您确定错误来自else分支吗?由于您的错误消息包含:,因此在其他分支中不包含display

编辑:您在输入提示中输入了什么? 混淆可能是对Racket的eval函数的调用需要一个列表作为参数(eval '(define a 0))。但是,如果您在输入提示中输入此内容,它将无法正常工作。您必须像正常定义一样编写(define a 0)

答案 1 :(得分:0)

这是错误:

(require (combine-in rnrs/base-6
                     rnrs/mutable-pairs-6))

rnrs/base-6rnrs/mutable-pairs-6带来了一些不可预测的变化,cons(以及carcdr)领导(define a 0)未被改变被definition?

抓住了

解决方案:

(require (only-in (combine-in rnrs/base-6
                              rnrs/mutable-pairs-6)
                  set-car!
                  set-cdr!))

始终将only-in放入require以避免任何不受欢迎的绑定。