Racket 中的 SICP Ch5 eceval 编译器:set-cdr!进入引用列表(不是重复的)
SICP Ch5 eceval compiler in Racket: set-cdr! into quoted list (not a dup)
这不是
set-car!, set-cdr! unbound in racket? 或
的
或属于
How to install sicp package module in racket?,
而是一个后续问题,因为其中提出的解决方案没有
为我工作。一、需要:Section 5.5.5 of SICP, compiler plus
显式控制评估器 (code here in "ch5-eceval-compiler.scm"),是
完全依赖于 set-car!
和 set-cdr!
进入显式引用列表。我
想要复制和修改此代码而不进行完整的、自下而上的重写
不变的形式。我也接受对可以的方案实现的引用
运行 开箱即用的代码或经过一些最小的、直接的改编,
即,具有 set-car!
和 set-cdr!
或一些的方案
解决方法。诡计和诡计都没有让我轻松 运行 编写此代码。
编辑:mit 方案将加载 eceval 编译器。我把这个问题留给那些可能想让它进入球拍的人(例如,我宁愿)。
这里有更深入的解释,包括我探索和尝试的东西,以及
我如何将引用列表诊断为最深层次的问题。当我手动转换
引用列表变成 mlists
的 mquoted
嵌套,代码崩溃得更糟
方式和兔子洞变得更深。几次后我不得不恢复
数小时精细的脑部手术失败了。
这里是5.5.5节所依赖的那种结构的MVE。这个很小,但是结构跟真的一样:
(define foo '(a b))
(set-cdr! foo '(c))
真正的事情是这样开始的:
(define eceval
(make-machine
'(exp env val proc argl continue unev
compapp ;*for compiled to call interpreted
)
eceval-operations ;; ----------------------------------------------
'( ;; <<<<<<<<======== BIG QUOTED LIST CAUSING TROUBLE / NOT MCONSES!
;;SECTION 5.4.4, as modified in 5.5.7 ;; -------------------------------
;;*for compiled to call interpreted (from exercise 5.47)
(assign compapp (label compound-apply))
;;*next instruction supports entry from compiler (from section 5.5.7)
(branch (label external-entry))
read-eval-print-loop
(perform (op initialize-stack))
(perform
(op prompt-for-input) (const ";;; EC-Eval input:"))
...
并持续了很长一段时间。评估者是引用中的 "machine-code"
列表,各种生成的代码将 set-car!
和 set-cdr!
放入寄存器
和环境框架和其他东西。代码加载失败。
似乎没有简单的方法可以将计算器转换为不可变形式
没有完全重写,我正在努力避免这种情况。当然,set-car!
和
set-cdr!
在 #lang racket
中不可用,我认为它们不在
诡计,要么(至少诡计拒绝加载 "ch5-eceval-compiler.scm,"
抛出一个可变性错误,对此我没有深入研究)。
中提出的一个解决方案
set-car!, set-cdr! unbound in racket? 是
根据 (require
compatibility/mlist) (require rnrs/mutable-pairs-6)
使用 mcons
、mcar
、mlist
等重写代码。那些兼容性
包无法替代 quote
,因此我尝试编写自己的 mquote
。我
在这样的重构上花了几个小时,但练习不是
收敛,在兔子洞里越来越深,最后得到
甚至更深层次的问题。似乎要进行重构我必须
了解更多关于 "ch5-eceval-compiler.scm," 的语义,如果我必须,我
不妨以不可变的形式重写它。
中提出了更简单的解决方案
set-car!, set-cdr! unbound in racket?
是使用 #lang sicp
或 #lang r5rs
。下面进行三个实验
参考了堆栈溢出的其他答案:
#lang r5rs
(define foo '(a b))
(set-cdr! foo '(c))
foo
Error: struct:exn:fail:contract:variable
set-cdr!: undefined;
cannot reference an identifier before its definition
in module: "/usr/share/racket/pkgs/r5rs-lib/r5rs/main.rkt"
-----------------------------------------------
指向set-cdr!
明确定义的地方:
...
(module main scheme/base
(require scheme/mpair
racket/undefined
(for-syntax scheme/base syntax/kerncase
"private/r5rs-trans.rkt")
(only-in mzscheme transcript-on transcript-off))
(provide (for-syntax syntax-rules ...
(rename-out [syntax-rules-only #%top]
[syntax-rules-only #%app]
[syntax-rules-only #%datum]))
(rename-out
[mcons cons]
[mcar car]
[mcdr cdr]
[set-mcar! set-car!] ;; --------------------------
[set-mcdr! set-cdr!] ;; <<<<<<<<======== LOOK HERE
[mpair? pair?] ;; --------------------------
[mmap map]
[mfor-each for-each])
= < > <= >= max min + - * /
abs gcd lcm exp log sin cos tan not eq?
call-with-current-continuation make-string
symbol->string string->symbol make-rectangular
exact->inexact inexact->exact number->string string->number
...
这里有一个与 #lang sicp
类似的失败
#lang sicp
(define foo '(a b))
(set-cdr! foo '(c))
foo
Error: struct:exn:fail:contract:variable
set-cdr!: undefined;
cannot reference an identifier before its definition
in module: "/home/rebcabin/.racket/7.2/pkgs/sicp/sicp/main.rkt"
----------------------------------------------------
指向仅间接定义 set-cdr!
的代码,但在
合适的包裹:
....
#lang racket
(require racket/provide ;; --------------------------------------------
(prefix-in r5rs: r5rs) ;; <<<<<<<<======== PULL IN SET-CDR! ETC. HERE?
(rename-in racket [random racket:random])) ;; ------------------------
(provide (filtered-out (λ (name) (regexp-replace #px"^r5rs:" name ""))
(except-out (all-from-out r5rs) r5rs:#%module-begin))
(rename-out [module-begin #%module-begin]))
(define-syntax (define+provide stx)
(syntax-case stx ()
[(_ (id . args) . body) #'(begin
(provide id)
(define (id . args) . body))]
[(_ id expr) #'(begin
(provide id)
(define id expr))]))
...
我深入挖掘
并找到
(require (only-in (combine-in rnrs/base-6
rnrs/mutable-pairs-6)
set-car!
set-cdr!))
(define foo '(a b))
(set-cdr! foo '(c))
foo
屈服
Error: struct:exn:fail:contract
set-mcdr!: contract violation
expected: mpair?
given: '(a b)
argument position: 1st
other arguments...:
'(c)
此错误表明问题确实出在引用列表上。我没有
将 eceval 中的大引用列表变成 mlist
或链的简单方法
mcons
。我试过了,它非常冗长且容易出错,而且我认为代码
加载 eceval 扫描和列出的补丁,因此它使用其他列表操作。
一路南下,不得不折返
也许我错过了一些自动化转换的方法,一个宏,但那是
更深的兔子洞(我的方案宏富太老了)
所以我卡住了。没有什么容易或推荐的作品。我想 (1) 知道一个方案实现,它将 运行 这段代码 (2) 我可以通过某种方式在球拍中实现 set-car!
和 set-cdr!
(3) 一些其他类型的解决 (4) 或者我只是犯了一个愚蠢的错误,你们中的好心人会很容易地改正。
Mit-scheme 将从问题中提到的代码删除中加载 eceval 编译器。在 Ubuntu 上,mit-scheme 加载 sudo apt-install mit-scheme
。 geiser package of emacs 通过 run-mit
找到 mit。问题解决了。
我试过了(直接 运行 racket
或通过 DrRacket 运行)
#lang sicp
(define foo '(a b))
(set-cdr! foo '(c))
foo
并输出 (a c)
.
这也有效:
#lang r5rs
(define foo '(a b))
(set-cdr! foo '(c))
(display foo)
要回答有关 SICP(我目前正在维护)实施的问题,您是正确的,(prefix-in r5rs: r5rs)
将导入 set-cdr!
。
更新:我刚刚安装了 Geiser,现在遇到了与我 C-c C-b
时相同的问题。但是,C-c C-a
按预期工作。
就个人而言,我会使用 racket-mode
而不是 Geiser。
这不是
set-car!, set-cdr! unbound in racket? 或
的
set-car!
和 set-cdr!
进入显式引用列表。我
想要复制和修改此代码而不进行完整的、自下而上的重写
不变的形式。我也接受对可以的方案实现的引用
运行 开箱即用的代码或经过一些最小的、直接的改编,
即,具有 set-car!
和 set-cdr!
或一些的方案
解决方法。诡计和诡计都没有让我轻松 运行 编写此代码。
编辑:mit 方案将加载 eceval 编译器。我把这个问题留给那些可能想让它进入球拍的人(例如,我宁愿)。
这里有更深入的解释,包括我探索和尝试的东西,以及
我如何将引用列表诊断为最深层次的问题。当我手动转换
引用列表变成 mlists
的 mquoted
嵌套,代码崩溃得更糟
方式和兔子洞变得更深。几次后我不得不恢复
数小时精细的脑部手术失败了。
这里是5.5.5节所依赖的那种结构的MVE。这个很小,但是结构跟真的一样:
(define foo '(a b))
(set-cdr! foo '(c))
真正的事情是这样开始的:
(define eceval
(make-machine
'(exp env val proc argl continue unev
compapp ;*for compiled to call interpreted
)
eceval-operations ;; ----------------------------------------------
'( ;; <<<<<<<<======== BIG QUOTED LIST CAUSING TROUBLE / NOT MCONSES!
;;SECTION 5.4.4, as modified in 5.5.7 ;; -------------------------------
;;*for compiled to call interpreted (from exercise 5.47)
(assign compapp (label compound-apply))
;;*next instruction supports entry from compiler (from section 5.5.7)
(branch (label external-entry))
read-eval-print-loop
(perform (op initialize-stack))
(perform
(op prompt-for-input) (const ";;; EC-Eval input:"))
...
并持续了很长一段时间。评估者是引用中的 "machine-code"
列表,各种生成的代码将 set-car!
和 set-cdr!
放入寄存器
和环境框架和其他东西。代码加载失败。
似乎没有简单的方法可以将计算器转换为不可变形式
没有完全重写,我正在努力避免这种情况。当然,set-car!
和
set-cdr!
在 #lang racket
中不可用,我认为它们不在
诡计,要么(至少诡计拒绝加载 "ch5-eceval-compiler.scm,"
抛出一个可变性错误,对此我没有深入研究)。
中提出的一个解决方案
set-car!, set-cdr! unbound in racket? 是
根据 (require
compatibility/mlist) (require rnrs/mutable-pairs-6)
使用 mcons
、mcar
、mlist
等重写代码。那些兼容性
包无法替代 quote
,因此我尝试编写自己的 mquote
。我
在这样的重构上花了几个小时,但练习不是
收敛,在兔子洞里越来越深,最后得到
甚至更深层次的问题。似乎要进行重构我必须
了解更多关于 "ch5-eceval-compiler.scm," 的语义,如果我必须,我
不妨以不可变的形式重写它。
中提出了更简单的解决方案
set-car!, set-cdr! unbound in racket?
是使用 #lang sicp
或 #lang r5rs
。下面进行三个实验
参考了堆栈溢出的其他答案:
#lang r5rs
(define foo '(a b))
(set-cdr! foo '(c))
foo
Error: struct:exn:fail:contract:variable set-cdr!: undefined; cannot reference an identifier before its definition in module: "/usr/share/racket/pkgs/r5rs-lib/r5rs/main.rkt" -----------------------------------------------
指向set-cdr!
明确定义的地方:
...
(module main scheme/base
(require scheme/mpair
racket/undefined
(for-syntax scheme/base syntax/kerncase
"private/r5rs-trans.rkt")
(only-in mzscheme transcript-on transcript-off))
(provide (for-syntax syntax-rules ...
(rename-out [syntax-rules-only #%top]
[syntax-rules-only #%app]
[syntax-rules-only #%datum]))
(rename-out
[mcons cons]
[mcar car]
[mcdr cdr]
[set-mcar! set-car!] ;; --------------------------
[set-mcdr! set-cdr!] ;; <<<<<<<<======== LOOK HERE
[mpair? pair?] ;; --------------------------
[mmap map]
[mfor-each for-each])
= < > <= >= max min + - * /
abs gcd lcm exp log sin cos tan not eq?
call-with-current-continuation make-string
symbol->string string->symbol make-rectangular
exact->inexact inexact->exact number->string string->number
...
这里有一个与 #lang sicp
#lang sicp
(define foo '(a b))
(set-cdr! foo '(c))
foo
Error: struct:exn:fail:contract:variable set-cdr!: undefined; cannot reference an identifier before its definition in module: "/home/rebcabin/.racket/7.2/pkgs/sicp/sicp/main.rkt" ----------------------------------------------------
指向仅间接定义 set-cdr!
的代码,但在
合适的包裹:
....
#lang racket
(require racket/provide ;; --------------------------------------------
(prefix-in r5rs: r5rs) ;; <<<<<<<<======== PULL IN SET-CDR! ETC. HERE?
(rename-in racket [random racket:random])) ;; ------------------------
(provide (filtered-out (λ (name) (regexp-replace #px"^r5rs:" name ""))
(except-out (all-from-out r5rs) r5rs:#%module-begin))
(rename-out [module-begin #%module-begin]))
(define-syntax (define+provide stx)
(syntax-case stx ()
[(_ (id . args) . body) #'(begin
(provide id)
(define (id . args) . body))]
[(_ id expr) #'(begin
(provide id)
(define id expr))]))
...
我深入挖掘
(require (only-in (combine-in rnrs/base-6
rnrs/mutable-pairs-6)
set-car!
set-cdr!))
(define foo '(a b))
(set-cdr! foo '(c))
foo
屈服
Error: struct:exn:fail:contract set-mcdr!: contract violation expected: mpair? given: '(a b) argument position: 1st other arguments...: '(c)
此错误表明问题确实出在引用列表上。我没有
将 eceval 中的大引用列表变成 mlist
或链的简单方法
mcons
。我试过了,它非常冗长且容易出错,而且我认为代码
加载 eceval 扫描和列出的补丁,因此它使用其他列表操作。
一路南下,不得不折返
也许我错过了一些自动化转换的方法,一个宏,但那是 更深的兔子洞(我的方案宏富太老了)
所以我卡住了。没有什么容易或推荐的作品。我想 (1) 知道一个方案实现,它将 运行 这段代码 (2) 我可以通过某种方式在球拍中实现 set-car!
和 set-cdr!
(3) 一些其他类型的解决 (4) 或者我只是犯了一个愚蠢的错误,你们中的好心人会很容易地改正。
Mit-scheme 将从问题中提到的代码删除中加载 eceval 编译器。在 Ubuntu 上,mit-scheme 加载 sudo apt-install mit-scheme
。 geiser package of emacs 通过 run-mit
找到 mit。问题解决了。
我试过了(直接 运行 racket
或通过 DrRacket 运行)
#lang sicp
(define foo '(a b))
(set-cdr! foo '(c))
foo
并输出 (a c)
.
这也有效:
#lang r5rs
(define foo '(a b))
(set-cdr! foo '(c))
(display foo)
要回答有关 SICP(我目前正在维护)实施的问题,您是正确的,(prefix-in r5rs: r5rs)
将导入 set-cdr!
。
更新:我刚刚安装了 Geiser,现在遇到了与我 C-c C-b
时相同的问题。但是,C-c C-a
按预期工作。
就个人而言,我会使用 racket-mode
而不是 Geiser。