Scheme “为什么?”;等式?“;在以下上下文中计算为false,否则为true?
我目前正在练习球拍语言,我遇到了一个有趣的问题。我试图比较两个列表的元素。通常,如果我比较两个符号,我会得到以下结果:Scheme “为什么?”;等式?“;在以下上下文中计算为false,否则为true?,scheme,racket,evaluation,quote,Scheme,Racket,Evaluation,Quote,我目前正在练习球拍语言,我遇到了一个有趣的问题。我试图比较两个列表的元素。通常,如果我比较两个符号,我会得到以下结果: > (eq? 'leet 'leet) #t > (eq? 'let 'notleet) #f 出于某种原因,当比较两个列表的第一个元素时,即使它们相等,我也会得到false > (eq? (first '('leet 'a 'f)) (first '('leet 'coder 'a 'f 'f))) #f 当我基本上在比较相同的两件事时,为什么这个值是假
> (eq? 'leet 'leet)
#t
> (eq? 'let 'notleet)
#f
出于某种原因,当比较两个列表的第一个元素时,即使它们相等,我也会得到false
> (eq? (first '('leet 'a 'f)) (first '('leet 'coder 'a 'f 'f)))
#f
当我基本上在比较相同的两件事时,为什么这个值是假的
当我基本上比较相同的两件事
你不是<代码>(第一个“('leet'a'f))是”(引用leet)
,而不是'leet
。所以你是在比较列表,而不是符号
(…)已经引用了列表的内容。如果您在列表中添加了额外的,
s,这些将被引用。由于'foo
是(quote foo)
的快捷方式,因此引用它会给出包含这些符号的列表
如果你只写
”(leetaf)
,而不带内引号,它会像你期望的那样工作。表达式'expression
是(引号表达式)
的缩写。当对表达式求值时,它将作为数据结构或原子值求值为expression
。重要的是要知道,表达式
中的任何内容都不会得到进一步的计算。因此,“x
,即(quote(quote x))
成为列表(quote x)
eq?
用于比较同一对象。这意味着:
(eq? (list 'leet) (list 'leet)) ; ==> #f
现在这两个参数看起来都像(leet)
,但这两个列表位于计算机中不同的内存位置,因此并不相同
像“string”
和”(一些列表)
这样的常量可以创建一次,然后引用多次,但是在不同的实现中,可以为代码中的每个位置新创建常量。因此:
(eq? "test" "test") ; ==> #t or #f
(eq? '(leet) '(leet)) ; ==> #t or #f
在代码中有多余的”
,因此(first'('leet'a'f))
实际上是数据(quote leet)
,一个带有两个符号的列表。因此,您正在应用与上面最后一个表达式完全相同的表达式,您可以从一些实现中获得#f
,从其他一些实现中获得#t
。比较列表与比较符号不同
因此,您可以通过删除额外的“
来修复此问题。那么我假设您没有尝试创建列表(引用leet)
如果要比较列表,应使用equal?
:
(equal? (first '('leet 'a 'f)) (first '('leet 'coder 'a 'f 'f)))
; ==> #t
并且知道
(第一个“('leet'a'f))
在#lang racket
REPL打印“leet
和两个”
。第一个,
是rackets一种有趣的打印值的方式,它的计算结果是它应该打印的值,这可能是这种混淆的根源,第二个是你有一个列表(引用leet)
,但许多方案将其缩写为“leet,Sylvester的答案是正确和详细的,但我想提出TL/DR;在这里:
不要使用eq?
。相反,请使用equal?
。
这就是全部吗?不,当然不是。但是如果你想在你的大脑中找到一条直线,那么应该是这条equal?
几乎总是做你想做的事,而eq?
通常不做。你不是在比较两个符号'leet
和'leet
,而是在比较两个列表,(列表'quote'leet)
和(列表'quote'leet)
。我建议您避免使用报价
进行列表和阅读。如果您使用list
,则程序可以运行,如(第一个(list'leet'a'f))
和(第一个(list'leet'coder'a'f')
。
(equal? (first '('leet 'a 'f)) (first '('leet 'coder 'a 'f 'f)))
; ==> #t