在我的大学里,我们不得不使用 Racket,因为我有点喜欢它,所以我从 No Starch 买了最近出版的书“Realm Of Racket”。
到目前为止它很棒,但是,当他们试图解释 eq? 的工作原理时,我无法弄清楚他们在第 4 章中的含义:
- 首先,他们解释了如何相等?比较两个值是否由相同的部分组成。好的,没问题,我明白了:equal? 与 Java 的 equals(someObject) 方法几乎一样。如果两个对象/结构/任何内容相同,则返回 #t。
- 然后,我想,eq? 一定等同于 Java 的 == 运算符,后者不按内容进行比较,而是基于引用。
这个想法似乎被书中的以下句子所证实:“eq?比较改变一个结构是否会改变另一个结构……”太棒了!让我们将其与以下 Java 代码进行比较:
Point p1 = new Point(5, 5); Point p2 = p1; System.out.println(p1 == p2); // true, since the reference has been copied. System.out.println(p1.x); // 5 System.out.println(p2.x); // 5 p1.x = 42; System.out.println(p1.x); // 42 System.out.println(p2.x); // Accordingly, 42
让我们在 Racket 中试试这个:
(define cons1 (cons 1 empty)) (define cons2 cons1) (eq? cons1 cons2) ;; #t, since the refernce has been copied. (set! cons1 (cons 2 empty)) cons1 ;; Returns '(2) - as expected. cons2 ;; Still returns '(1).
为什么? cons2 指向 cons1,cons1 本身指向 '(2)。另外,他们不是说只要一改变就等于吗?
显然,现在我不明白为什么它没有按预期运行,因此,我不明白 eq? 在做什么。也许我错了,它与引用文献没有任何关系......
如果有人知道这一点,请分享您的智慧;)
最佳答案
有关 eq?
工作原理的技术解释,请查看当前的 specification ,您找不到更详细的引用资料。或者简单地检查 Racket 的 documentation关于这个主题,特别是程序 eq?
、eqv?
和 equal?
。关于您的问题 - 结果符合预期并且在 Scheme 代码中是正确的,让我们看看为什么。请注意,在 Java 的这一行中:
p1.x = 42;
您正在修改p1
和p2
所指向的相同 对象。而在这一行中:
(set! cons1 (cons 2 empty))
您正在创建一个新,不同的对象并设置 cons1
指向它,但是 cons2
仍然指向旧对象.您可以确认这一点,在上一行之后,比较 (eq? cons1 cons2)
将返回 #f
。
重点是:示例不等价。 Java 示例处理由两个不同引用指向的单个对象,而 Scheme 示例处理两个对象和两个引用。
为了进行比较,这里有一个类似于 Java 代码的 Scheme 示例,并且按您预期的方式工作,因为在这里我们正在修改一个由两个引用指向的可变对象:
#lang racket
(require scheme/mpair) ;; `m` stands for "mutable"
(define p1 (mlist 5 5))
(define p2 p1)
(eq? p1 p2) ;; #t
(mcar p1) ;; 5
(mcar p2) ;; 5
(set-mcar! p1 42)
(eq? p1 p2) ;; #t
(mcar p1) ;; 42
(mcar p2) ;; 42
关于lisp - 情商如何?在 Racket 工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17572181/