【问题标题】:How does eq? in Racket work with symbols and number?eq 怎么样?在球拍中使用符号和数字?
【发布时间】:2020-05-19 09:45:45
【问题描述】:

Racket 文档告诉我“eq? return #t if v1v2 指的是同一个对象”,但是根据eq?,两个fixnums= 也是一样的, = “如果所有参数在数值上相等,则返回 #t”。我找不到任何关于“数字”和“符号”的消息,但在我找到的示例中:

> (eq? 'yes 'yes)
#t

这和上面是矛盾的,因为上面从来没有提到symbol是特殊的,所以'yes'yes是不一样的。

这个让我更加困惑:

> (eq? (expt 2 100) (expt 2 100))
#f
> (eq? (* 6 7) 42)
#t

如果对数字进行数字测试,那么(eq? (expt 2 100) (expt 2 100))应该返回#t,否则通过引用测试数字,那么(eq? (* 6 7) 42)应该返回#f,所以我猜以上两种情况都不对。 .

为什么?!

【问题讨论】:

    标签: racket


    【解决方案1】:
    (expt 2 100)
    

    太大而不能成为fixnum。让我们尝试评估一下:

    (expt 2 100)  ; => 1267650600228229401496703205376
    (fixnum? (expt 2 100)) ; => #f
    (expt 2 10) ; => 1024
    (fixnum? (expt 2 100)) ; => #t
    

    这是因为大量数字被分配在几个内存单元中(将它们视为一组数字的列表)。

    另一方面,每个符号在阅读时都是“内化的”。这意味着第一次读取它时,会为其创建一个新的符号值。随后,当再次读取时,系统会检查是否已存在具有该名称的符号,在这种情况下,会返回旧的符号值,而不会在内存中创建任何新对象。所以:

    (eq 'yes 'yes) ; => #t
    

    因为显然两个同名的不同符号实际上是内存中的同一个对象。

    【讨论】:

    • 谢谢,我大概明白了,但是如何检查数据类型是否“内部化”?是否仅仅取决于它是否分配在几个内存单元中?
    【解决方案2】:

    这是为了提供除了@Renzo 的答案之外的其他信息

    如何检查数据类型是否“内部化”

    答案是复杂的。

    一个因素是reader

    阅读器在read-syntax模式下产生的符号、关键字、字符串、字节串、正则表达式、字符和数字是interned,这意味着read-syntax的结果中的这些值是当它们是equal? 时,总是eq?(无论是来自同一呼叫还是不同呼叫read-syntax)。符号和关键字在readread-syntax 模式下都被保留。通过位置通道发送一个内部值不一定会在接收位置产生一个内部值。另见datum-intern-literaldatum->syntax

    所以(eq? (expt 2 100) (expt 2 100)) 返回#f,因为(expt 2 100) 需要在运行时计算。另一方面,(eq? 1267650600228229401496703205376 1267650600228229401496703205376) 返回 #t,因为值在读取时很明显,从而允许 Racket 对数字进行实习。

    另一个因素是数据类型。例如,根据https://docs.racket-lang.org/reference/numbers.html

    ,即使在读取时该值不明显,也始终保留一个 fixnum

    根据eq?= 的两个固定编号也相同。否则,eq? 应用于两个数字的结果是未定义的

    这意味着(eq? (+ 1 2) 3) 保证为#t

    符号通常是被实习的,但可以通过 string->uninterned-symbolgensym 将其变为 uninterned

    一个符号就像一个不可变的字符串,但是符号通常是intern的,所以两个具有相同字符内容的符号通常是eq?。

    两个过程 string->uninterned-symbol 和 gensym 生成 uninterned 符号,即不 eq?、eqv? 或不相等的符号?到任何其他符号,尽管它们可能与其他符号打印相同。

    所以:

    > (eq? (string->symbol "ab") (string->symbol (string-append "a" "b")))
    #t
    > (eq? (string->uninterned-symbol "ab") (string->uninterned-symbol "ab"))
    #f
    

    【讨论】:

      猜你喜欢
      • 2013-07-08
      • 1970-01-01
      • 2019-05-02
      • 2016-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-19
      相关资源
      最近更新 更多