为什么" eq?"在以下上下文中评估为false,否则为真?

时间:2018-04-28 22:39:48

标签: scheme racket evaluation quote

我目前正在练习球拍语言,我遇到了一个有趣的问题。我想比较两个列表的元素。通常,如果我比较两个符号,我会得到以下内容:

let letters = ["a", "b", "c"]

let quux = letters.map { Array(repeating: $0, count: 3) }
// [["a", "a", "a"], ["b", "b", "b"], ["c", "c", "c"]]

let quuz = letters.flatMap { Array(repeating: $0, count: 3) }
// ["a", "a", "a", "b", "b", "b", "c", "c", "c"]

出于某种原因,在比较两个列表的第一个元素时,即使它们相等,我也会得到错误。

> (eq? 'leet 'leet)
#t
> (eq? 'let 'notleet)
#f

当我基本上比较相同的两件事时,为什么评价为假?

3 个答案:

答案 0 :(得分:3)

Sylwester的答案是正确和详细的,但我想带出TL / DR;这里:

请勿使用eq?。相反,请使用equal?

这是整个故事吗?不,当然不。但是,如果你正在寻找一个可以粘在你脑中的单线眼镜,它就应该是这个; equal?几乎总是做你想要的,而eq?通常不会。

答案 1 :(得分:2)

  

当我基本上比较相同的两件事时

你不是。 (first '('leet 'a 'f))'(quote leet),而不是‘leet。所以你要比较列表,而不是符号。

'(...)已经引用了列表的内容。如果您在列表中添加了其他',则会自行引用这些内容。由于'foo(quote foo)的快捷方式,引用它会为您提供包含这些符号的列表。

如果您只是在没有内部引号的情况下编写'(leet a f),它将按预期工作。

答案 2 :(得分:2)

表达式'expression(quote expression)的缩写。在计算表达式时,它将expression计算为数据结构或原子值。重要的是要知道expression中的任何内容都不会被进一步评估。因此,''x (quote (quote x))成为列表(quote x)

eq?用于比较同一个对象。这意味着:

(eq? (list 'leet) (list 'leet)) ; ==> #f

现在两个参数看起来都像(leet),但这两个列表位于计算机的不同内存位置,因此不一样。

"string"'(some list)之类的常量可能会被创建一次,然后被多次引用,但在不同的实现中,可能会为代码中的每个位置新创建常量。因此:

(eq? "test" "test")   ; ==> #t or #f
(eq? '(leet) '(leet)) ; ==> #t or #f

在您的代码中,您有多余的',因此(first '('leet 'a 'f))实际上是数据(quote leet),这是一个包含两个符号的列表。因此,您应用与上面的最后一个表达式完全相同的结果,您可以从某些实现中获得#f,从其他一些实现中获得#t。比较列表与比较符号不同。

因此,您可以通过删除额外的'来解决此问题。然后我假设您没有尝试制作列表(quote leet)

(eq? (first '(leet a f)) (first '(leet coder a f f)))
; ==> #t

如果您想比较列表,请使用equal?

(equal? (first '('leet 'a 'f)) (first '('leet 'coder 'a 'f 'f)))
; ==> #t

并且知道(first '('leet 'a 'f)) REPL中的#lang racket打印''leet两个'。第一个'是球拍有趣的方式打印值,评估它应该打印的值,也许这是混乱的来源,第二个是指示你有一个列表(quote leet)但是许多方案将其缩写为'leet