Lisp 我能把车放好!设置cdr!可以作为宏实现吗?
是否可以执行Lisp 我能把车放好!设置cdr!可以作为宏实现吗?,lisp,scheme,metaprogramming,abstract-syntax-tree,Lisp,Scheme,Metaprogramming,Abstract Syntax Tree,是否可以执行set car和设置cdr
set car代码>和设置cdr使用set代码>在方案中?或者这是否需要对底层存储系统进行特殊访问
我这样问是因为我正在实现我自己的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