【问题标题】:Why does "eq?" evaluate to false in the following context but true otherwise?为什么是“eq”?在以下情况下评估为假,否则为真?
【发布时间】:2018-04-28 22:39:47
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 您不是在比较两个符号'leet'leet,而是在比较两个列表(list 'quote 'leet)(list 'quote 'leet)。我建议您避免将quote 用于列表并阅读What is the difference between quote and list?。如果您改用list,您的程序就可以工作,例如(first (list 'leet 'a 'f))(first (list 'leet 'coder 'a 'f 'f))

标签: scheme racket evaluation quote


【解决方案1】:

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

不要使用eq?。请改用equal?

这就是故事的全部吗?不,当然不。但是,如果您正在寻找一种可以插入大脑的单线,那么应该是这个; equal? 几乎总是做你想做的事,而eq? 经常做不到。

【讨论】:

    【解决方案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
    

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

    【讨论】:

      【解决方案3】:

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

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

      '(...) 已经引用了列表的内容。如果您在列表中添加了额外的's,它们本身就会被引用。由于'foo(quote foo) 的快捷方式,因此引用它会为您提供包含这些符号的列表。

      如果您只写'(leet a f) 而不带内引号,它将按您的预期工作。

      【讨论】:

        猜你喜欢
        • 2018-07-01
        • 1970-01-01
        • 2013-04-24
        • 2016-08-25
        • 1970-01-01
        • 2012-12-06
        • 2011-10-11
        • 1970-01-01
        • 2014-05-19
        相关资源
        最近更新 更多