Scheme 有人能向我解释一下在阴谋/骗局上的平等吗?

Scheme 有人能向我解释一下在阴谋/骗局上的平等吗?,scheme,racket,equality,quote,Scheme,Racket,Equality,Quote,所以我今天偶然发现了这一点,这让我感到困惑 (define (x) '(1)) (eq? (x) (x)) ;=> #t (eq? '(1) '(1)) ;=> #f (define (y) (list 1)) (eq? (y) (y)) ;=> #f (eq? (list 1) (list 1)) ;=> #f 有人能解释这里发生了什么吗?检查对象是否相同(想想“指针是否指向内存中的相同地址”

所以我今天偶然发现了这一点,这让我感到困惑

(define (x) '(1))
(eq? (x) (x))             ;=> #t
(eq? '(1) '(1))           ;=> #f


(define (y) (list 1))
(eq? (y) (y))             ;=> #f
(eq? (list 1) (list 1))   ;=> #f
有人能解释这里发生了什么吗?

检查对象是否相同(想想“指针是否指向内存中的相同地址”)

在第一种情况下,您使用的是编译时创建的文本。比较(和修改)文本通常是未定义的行为。在这里,过程
x
每次返回相同的文本,但在第二个表达式中,两个文本看起来不一样。正如我所说,未定义的行为


在第二种情况下,您不使用文本,而是在执行时创建一个新列表。因此,每次调用
y
list
都会创建一个新的列表。

编译此程序时

(define (x) '(1))
(eq? (x) (x))             
(eq? '(1) '(1)) 
被编译成(类似于):

因此
(x)
将始终返回存储在
datum1
中的对象。 另一方面,表达式
(eq?'(1)
将 找出
datum2
datum3
不存储相同的对象

注意:编译器编写器有一个选择。许多方案实施将编译上述程序,以:

(define datum1 '(1))
(define (x) datum1)
(eq? (x) (x))             
(eq? datum1 datum1) 
然后结果在这两种情况下都是正确的


注意:
quote
的文档没有明确说明程序中多次出现的
'(1)
是否会产生相同的值。因此,这种行为将来可能会改变。[尽管我认为目前的行为是一个深思熟虑的选择]

uselpa的答案是正确的。†不过,我想进一步阐述引用的数据是什么

正如您所知,所有Scheme程序都作为语法树在内部读入。特别是在Racket中,您可以使用
readsyntax
过程执行以下操作:

> (define stx (with-input-from-string "(foo bar)" read-syntax))
> stx
#<syntax::1 (foo bar)>
quote
是一种特殊形式,它所做的是返回语法树中引用的部分作为基准。这就是为什么对于许多Scheme实现,您的
x
过程每次都返回相同的对象:它将语法树的相同部分作为数据返回。(这是一个实现细节,方案实现不需要有这种行为,但它有助于解释为什么会看到所看到的。)

正如uselpa的回答所说,
list
每次都会创建一个新的列表,如果列表不是空的。这就是为什么与
eq?
相比,
list
的两个独立非空调用的结果总是不同的原因

(在Scheme中,空列表需要表示为单例对象。因此
(eq?'())
保证为真,正如
(eq?(list)())
(eq?(cdr(list'foo))(list))
等)


< P> >我不使用短语“未定义的行为”来比较文字,因为这很容易混淆UB的C和C++含义,尽管比较文字的结果可能不是你所期望的,但是它不会导致程序崩溃。当然,修改文字是鼻魔。正如我在回答中所解释的,澄清文字的比较与修改:比较文字可能会给你意想不到的结果,但实际上不会导致鼻恶魔,而修改文字则完全是鼻恶魔的领地。感谢你的详细解释,但这只会给我带来更多的问题。我想我真的不明白引用的意思:(我是其他几种语言(javascript、ruby、php)的老手。这些语言中有类似的机制吗?未定义的行为是一个通用术语,不限于修改文字。例如@naomik JS、ruby和php不是同形符号(“代码就是数据”)语言,所以它们没有引用功能。我最喜欢的解释是进入“数据模式”,即引用的内容被视为数据而不是代码。请随意问更多的问题来帮助理解-我真的很想帮助。:-@naomik我特别喜欢小阴谋家书籍所采取的方法,其中代码和数据以不同的字体呈现。它使它立即在视觉上清晰可见。无论如何,任何时候你想在代码中嵌入数据,你都可以使用
quote
@ChrisJester-Young-interest。我由衷地感谢你的热心帮助。自从上次见面以来,我已将您的博客添加到我的订阅中。我目前正在通过SICP工作,但还没有遇到报价。小阴谋家也在我的阅读清单上,但还没到那个地步。我想我会继续阅读我的材料,看看在进一步学习之后还有什么问题。
> (define stx (with-input-from-string "(foo bar)" read-syntax))
> stx
#<syntax::1 (foo bar)>
> (syntax->datum stx)
'(foo bar)