I am implementing circular evaluator in Chapter 4 SICP with racket, it seems that the code running fine only it cannot add new frames to the environment due to set-car! issue.
I tried the followings:
- add the definitions into the code. The
set-car!is defined in the previous chapter in SICP as follows:
(define (cons x y)
(define (set-x! v) (set! x v))
(define (set-y! v) (set! y v))
(define (dispatch m)
(cond ((eq? m 'car) x)
((eq? m 'cdr) y)
((eq? m 'set-car!) set-x!)
((eq? m 'set-cdr!) set-y!)
(else
(error "Undefined operation: CONS" m))))
dispatch)
(define (car z) (z 'car))
(define (cdr z) (z 'cdr))
(define (set-car! z new-value)
((z 'set-car!) new-value) z)
(define (set-cdr! z new-value)
((z 'set-cdr!) new-value) z)
however, it reports error, because the definition primitive-procedures in the evaluator still use tradition definitions of list as shown below, which is incompatible with new definition of cons as dispatch precedure, thus cannot fetched by car, cdretc.
(define primitive-procedures
(list (cons 'car car)
(cons 'cdr cdr)
(cons 'cons cons)
(cons 'null? null?)
; <more primitives>
))
- I renamed the definitions of
consetc. tomcons,mcar,mcdr,etc.
(define (mcons x y)
(define (set-x! v) (set! x v))
(define (set-y! v) (set! y v))
(define (dispatch m)
(cond ((eq? m 'car) x)
((eq? m 'cdr) y)
((eq? m 'set-car!) set-x!)
((eq? m 'set-cdr!) set-y!)
(else
(error "Undefined operation: CONS" m))))
dispatch)
(define (mcar z) (z 'car))
(define (mcdr z) (z 'cdr))
(define (set-car! z new-value)
((z 'set-car!) new-value) z)
(define (set-cdr! z new-value)
((z 'set-cdr!) new-value) z)
but, it still reports error, for the same reason as 1. primitive-procedures still use build-in version of cons.
- according to Rahn's answer, I add the following code:
(require (only-in (combine-in rnrs/base-6
rnrs/mutable-pairs-6)
set-car!
set-cdr!))
but again, it reports error:
set-mcar!: contract violation
expected: mpair?
given: '((car cdr cons null?) (primitive #<procedure:car>) (primitive #<procedure:cdr>) (primitive #<procedure:cons>) (primitive #<procedure:null?>))
It seems SICP use set-car! frequently throughout the book, but it also use traditional definitions of cons such as cadr at the same time, which is quite confusing (when running with racket).
Any suggestions with the set-car! issue will be gratefully appreciated.
set-car!etc. The sicp lang (and others that are traditionally Schemey) use mutable mcons cells instead and import renamed copies ofset-mcar!etc.