DrRacket中的"not a proper list"报错
在看SICP,在3.3.3的位置写了一个table。(使用DrRacket)
code_0.scm
#lang scheme
(require rnrs/base-6)
(require rnrs/mutable-pairs-6)
(define nil '())
(define (make-table)
(list '*table*))
(define (assoc key records)
(cond ((null? records)
false)
((equal? key (caar records))
(car records))
(else
(assoc key (cdr records)))))
(define (insert! key value table)
(let ((record (assoc key (cdr table))))
(if record
(set-cdr! record value)
(set-cdr! table
(cons (cons key value)
(cdr table)))))
'OK)
(define (lookup key table)
(let ((record (assoc key (cdr table))))
(if record
(cdr record)
false)))
(define table (make-table))
(insert! 0 0 table)
(insert! 1 1 table)
(insert! 2 2 table)
正常运行。
我想将此代码用成一个库文件供引用,将code_0.scm中的"#lang scheme"删掉,然后写了下面的code_1.scm:
#lang scheme/load
(load "code_0.scm")
(define table-0 (make-table))
(insert! 0 0 table-0)
(insert! 1 0 table-0)
(insert! 2 0 table-0)
报错:
assoc: not a proper list: {{0 . 0}}
问题出在哪,LIST,DrRacket的load,还是语言版本?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
原因就是那个
#lang scheme/load
scheme/load这个和其他模块相比有点特殊,它的identifier绑定机制导致你在递归时候有些意外发生,我举个例子
在这个例子中,递归了
+
这个procedure,如果按照常理来说,这应该是个死循环,但是在#lang scheme/load
的模式下,奇迹般的运行正常,输出了结果20如果你把上面的
#lang scheme/load
换成#lang scheme
或者#lang racket
,都会无限递归下去,那么为何#lang scheme/load
就能正常工作了呢?这就是内部绑定的问题了,在我上面定义的内部,那个
+
并不是外面我定义的,而是scheme原本的那个+
,这就是#lang scheme/load的绑定的特殊表现了。所以楼主的问题就很清晰了,你这个和list或者load都无关,纯粹是因为#lang scheme/load,你的那个assoc是scheme本身就存在的procedure,你重新定义一个assoc以后,内部递归的时候assoc还是用的scheme本身的,而它要求参数是个list,而你递归到那一步以后已经是个pairs了。
所以最简单的修改方法就是给你定义的assoc改名,随便改个scheme不存在的名就好了,比如说叫assoc_x.
还有一种方法就是不要用load了(实际上load这个东西太古老了),换用require/provide
你在code_0.scm文件里导出要用的,记住前面得加个
#lang scheme
在code_1.scm文件里把load换成require,这就就能完美执行了。
如果你偏要用load,那你可以在code_0.scm把
#lang scheme
那一行改掉,比如说这样处理然后在code_1.scm里可以照着原样写了
还有一种方式就是弃用DrRacket,该用其他scheme实现来做习题。