使用 Racket 实现 SICP 评估器

Implement SICP evaluator using Racket

我正在研究 4.1.4 Running the Evaluator as a Program 的元循环求值器,用 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 导入什么吗?

应该运行 没问题。我用你给的代码做了一个快速测试。

(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 分支吗?因为您的错误消息包含 :,else 分支中的 display 不要。

编辑:您在输入提示中究竟输入了什么? 混淆可能是对 Racket 的 eval 函数的调用需要一个列表作为参数,(eval '(define a 0))。但是,如果您在输入提示中输入它,它将不起作用。您必须像正常定义一样编写 (define a 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 中以避免任何不需要的绑定。