Lisp 我能把车放好!设置cdr!可以作为宏实现吗?

Lisp 我能把车放好!设置cdr!可以作为宏实现吗?,lisp,scheme,metaprogramming,abstract-syntax-tree,Lisp,Scheme,Metaprogramming,Abstract Syntax Tree,是否可以执行set car和设置cdr

是否可以执行
set car
设置cdrset在方案中?或者这是否需要对底层存储系统进行特殊访问

我这样问是因为我正在实现我自己的Scheme解释器,我希望在Scheme代码中有尽可能多的内容

我第一次尝试设置cdr是:

(define-syntax set-cdr!
  (syntax-rules ()
    ((set-cdr! location value)
     (set! location (cons (car location) value)))))
这主要起作用,但不适用于循环列表:

#; mickey> (define x (list 1 2))
#; mickey> x
(1 2)
#; mickey> (set-cdr! x x)
#; mickey> x
(1 1 2)
将宏体包装在
let
中对我也没有帮助,因为当我执行
(设置!(cons(汽车位置)值)
时,
值已被评估为
”(12)

(set! location (cons (car location) value))
表达式
(cons(汽车位置)值)
分配一个新的对

set cdr!
的目的是变异现有的一对


因此,实现
set cdr!
确实需要对底层存储进行“特殊”访问。

下面是一个使用闭包实现Cons、Car、cdr、set Car!和set cdr!的示例

(define (Cons x y)
  (lambda (message . val)
    (cond
      [(eq? message 'car) x]
      [(eq? message 'cdr) y]
      [(eq? message 'set-car!) 
       (set! x (car val))]
      [(eq? message 'set-cdr!) 
       (set! y (car val))]
      [else 'unknown-message])))

(define (Car pair)
  (pair 'car))

(define (Cdr pair)
  (pair 'cdr))

(define (Set-cdr! pair val)
  (pair 'set-cdr! val))

(define (Set-car! pair val)
  (pair 'set-car! val))

(define p (Cons 1 2))
(Car p)
(Cdr p)
(Set-car! p 3)
(Car p)
(Set-cdr! p 4)
(Cdr p)

基本上,您可以在不使用set!的情况下实现set!但我不认为您可以在不使用变异对或模拟对的情况下实现set car!/set cdr!(如soegaard的示例)

由于您似乎在Scheme中实现方案,我会使用set car!/set cdr!在解释器中实现它,或者根本不实现它们。我会从define、if、quote、pair?、eq?、cons、car和cdr开始(类似于,但更具模式性)首先要有一个基本的最小实现,然后进一步增强它

无论如何..您的实现,如果您实现了,它应该能够做到:

(define odds (list 1 3 5 7 9 11))
(set-car! (cddr odds) #f)
odds
===> (1 3 #f 7 9 11)

但我认为scheme只需要一个非常严格的核心,通常包含if/cond、lambda、quote、set!和一些其他原语(加上基本数据类型和常量)。我不确定问题是否出在
cons
上。相反,我们无法得到
value
的地址(它是经过计算的)。如果你真的想,你可以用闭包来模拟成对,但这是非常无效的。请看下面的答案。当然,但这不是我想要的。:)我已经设置了
set,我要
设置汽车
设置cdr。无论如何,实现
set是有效的。我看到
集了
设置车辆不同。假设一个位置
x
包含(有指向)一对的指针,那么设置(使用set!)只是在该位置放置一个不同的指针。另一方面
设置汽车更改值“内部”的内容。--但要回答您的问题,您必须指定解释器的工作级别。您是在模拟自己的内存(比如说使用一个巨大的字节向量),还是仅仅使用来自底层Scheme系统的值?如果要从基础系统继承对,则需要继承
set car也是。假设现在我们想要实现
设置汽车
一起设置。如何表示成对?唯一的思考
可以做的是将新值存储到变量绑定到的位置。因此,我们不得不选择一种表示法,其中成对的两部分是两个位置,每个位置都绑定到一个变量。分配此类值的唯一(合理的?)方法是构造一个闭包。因此,
设置的所有解决方案单独用于执行
设置车辆
将或多或少地作为答案,其中对表示为闭包。为什么不在Dr Racket中使用mpair库?您可以使用(require scheme/mpair),然后说(define list mlist)…(define cons mcons)…(define set car!set mcar!)。。但是,所有的列表默认都是可变的。@ RjjES:因为我在C++中从头开始编写了一个几乎完整的完整的方案:我只想把我可以作为库文件的函数移出库中,而不是用C++实现很多函数。但是谢谢你的建议!手术功能必须是原始的。就是这样。下面的工作在Joice方案中,但在赤壁,Guile,MZTrase/MIT方案:<代码>(定义一个(CONS 1 2))< /C> >代码>(SET!(CDR A)A)< /Cord> >,它创建了一个循环列表。我在C++中实现它。这是非常容易实现的设置!,设置汽车!设置cdr!从C++里面,因为我可以访问我使用的指针,而且它工作得很好。但是,如果只有一套就更好了!然后执行设定车!etc在方案源代码库中。唉……当我坐在车上的时候!设置cdr!实际更改数据指针,设置!其实很不一样。设置既可用于参数,也可用于全局变量,在一个过程中,您要更改的是该过程的环境。如果要实现解释器,则需要实现帧。若你们正在实现一个编译器,那个么你们可以删除集合!通过将闭包包装在另一个lambda中,您可以在其中装箱发生变化的变量,例如,生成器可能会转换为(lambda(x)(let((x(cons x)))(lambda(n)(let((old(car x))(set car!x(+old n))old()()()))))41