我目前正在练习球拍语言,我遇到了一个有趣的问题。我想比较两个列表的元素。通常,如果我比较两个符号,我会得到以下内容:
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
当我基本上比较相同的两件事时,为什么评价为假?
答案 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
。