首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SICP Ch5电子级编译器在球拍: set-cdr!被引用的名单(不是dup)

SICP Ch5电子级编译器在球拍: set-cdr!被引用的名单(不是dup)
EN

Stack Overflow用户
提问于 2019-03-24 18:26:17
回答 2查看 224关注 0票数 2

这不是设置-汽车!,设置-cdr!不绑在球拍里?利用球拍实现SICP评价器如何在球拍中安装sicp封装模块?的重复,而是一个后续问题,因为其中提出的解决方案对我不起作用。首先,需要:SICP的5.5.5节,编译器加上显式控制评估器(这里的代码在“CH5-eceval编译器.ch5”中),完全依赖于set-car!set-cdr!的显式引号列表。我想复制和修改这段代码,而不需要完全、自下而上的不可变形式重写。我还会接受对一个方案实现的引用,该方案可以开箱即用,也可以进行一些简单、简单的调整,即具有set-car!set-cdr!或一些变通性的方案。无论是欺骗还是欺骗都不能让我轻松地运行这段代码。

编辑:麻省理工学院方案将加载电子版本编译器。我把这个问题留给那些想让它在球拍里运行的人(例如,我宁愿)。

这里有一个更深层次的解释,包括我所探索和尝试过的东西,以及我如何将引用的列表诊断为最深的问题。当我手动将引用的列表转换为mquotedmlists嵌套时,代码以更糟糕的方式崩溃,兔子洞变得更深了。我不得不在几个小时的脑外科手术失败后恢复原状。

这是第5.5.5节所依赖的那种结构的MVE。这是小的,但在结构上像真实的东西:

代码语言:javascript
复制
(define foo '(a b))
(set-cdr! foo '(c))

真正的开始是这样的:

代码语言:javascript
复制
(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:"))
...

持续了很长一段时间。评估器是引用列表中的“机器代码”,各种生成的代码将set-car!set-cdr!转换为寄存器、环境帧和其他东西。代码在加载时失败。

在没有完全重写的情况下,要将评估器转换成不可变的形式,似乎没有一种简单的方法,我试图避免这种情况。当然,set-car!set-cdr!#lang racket中是不可用的,而且我也不认为它们是在guile中(至少guile拒绝加载“CH5-eceval编译器. did”,这会引发一个易变错误,我没有对此进行深入的研究)。

设置-汽车!,设置-cdr!不绑在球拍里?中提出的一种解决方案是使用mconsmcarmlist等根据(require compatibility/mlist) (require rnrs/mutable-pairs-6)重写代码。这些兼容性包无法替代quote,所以我尝试编写自己的mquote。我花了几个小时进行这样的重构,但是这个练习并没有收敛,只是越来越深的深入到兔子洞里,最终导致了更深的问题。似乎为了进行重构,我必须了解更多关于“CH5-eceva-编译器. seems”的语义,如果必须的话,我还不如以不可变的形式重写它。

设置-汽车!,设置-cdr!不绑在球拍里?中提出的更简单的解决方案是使用#lang sicp#lang r5rs。下面三个实验引用了堆栈溢出的其他答案:

代码语言:javascript
复制
#lang r5rs
(define foo '(a b))
(set-cdr! foo '(c))
foo

错误:struct:exn:fail: cannot :variable set-cdr!:undefined;无法在模块:"/usr/share/racket/pkgs/r5rs-lib/r5rs/main.rkt“中引用其定义之前的标识符

它指向一个明确定义set-cdr!的地方:

代码语言:javascript
复制
...
(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类似的故障

代码语言:javascript
复制
#lang sicp
(define foo '(a b))
(set-cdr! foo '(c))
foo

错误:struct:exn:fail: cannot :variable set-cdr!:undefined;无法在模块:"/home/rebcabin/.racket/7.2/pkgs/sicp/sicp/main.rkt“中引用其定义之前的标识符

指向仅间接定义set-cdr!的代码,但显然是在适当的包中:

代码语言:javascript
复制
....
#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))]))
...

我深入研究了利用球拍实现SICP评价器并发现

代码语言:javascript
复制
(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

屈服

错误: struct:exn:fail:contract mcdr!:合同违约预期: mpair?给予:“(A)( b)论点立场:第1项其他论点.:”(C)

此错误意味着问题实际上是引用的列表。我没有一种简单的方法,可以将大的引用列表作为mlistmcons链。我试过了,它非常冗长且容易出错,而且我认为加载eceval扫描和列表修补程序的代码也是如此,所以它使用了其他列表操作。我不得不在南下一段糟糕的路后恢复过来。

也许我错过了一些自动转换的方法,宏,但那是一个更深的兔子洞(我的方案宏-fu太老了)。

所以我卡住了。不容易或推荐的作品。我想要么(1)知道一个将运行此代码的方案实现(2)我可以在racket (3)实现set-car!set-cdr! (3)其他类型的工作(4),或者我只是犯了一个愚蠢的错误,你们中的一个善良的人会很容易修复。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-24 21:08:46

我尝试过(通过直接运行racket或通过DrRacket运行它)

代码语言:javascript
复制
#lang sicp

(define foo '(a b))
(set-cdr! foo '(c))
foo

并输出(a c)

这也适用于:

代码语言:javascript
复制
#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。

票数 2
EN

Stack Overflow用户

发布于 2019-03-24 19:17:36

Mit-方案将从问题中提到的代码删除中加载eceval编译器。在Ubuntu,麻省理工学院-方案负载与sudo apt-install mit-scheme.geiser电子邮件包通过run-mit找到麻省理工学院。问题解决了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55327063

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档