1

DrRacket 中的等式函数非常复杂。我无法理解它们之间的细微差别。

你能解释为什么这两个结果不同吗?为什么例如'a' == 'a',但“abc”!=“abc”?

(eqv? (integer->char 955) (integer->char 955))
; => true

(eqv? (number->string 955) (number->string 955))
; => false
4

3 回答 3

1

eqv?基本上做一个身份比较,除了在数字和字符的情况下,然后比较值。这就是为什么两个值为 955 的字符比较相同的原因。

我说的身份是什么意思?考虑一下:

(define a (number->string 955))
(define b (number->string 955))
(string-set! a 0 #\0)
(printf "a = ~s, b = ~s, (eqv? a b) = ~a~%" a b (eqv? a b))

您会注意到只有a' 字符串被更改,而不是b' 字符串。那是因为它们是不同的字符串对象。

相反的情况是涉及混叠时:

(define a (number->string 955))
(define b a)
(string-set! a 0 #\0)
(printf "a = ~s, b = ~s, (eqv? a b) = ~a~%" a b (eqv? a b))

在这里,ab指向同一个字符串对象, 的效果string-set!在两个地方都是可见的。

于 2013-11-01T01:45:57.493 回答
1

While the two "(number->string 955)" look the same, they return two separate objects in memory. With that in mind, let's compare:

(eq? (number->string 955) (number->string 955))
#f

This is false because eq? cares about identicality, that is: are the things being compared exactly the same object in memory. This check is fast, but is often not what you are wanting.

(eqv? (number->string 955) (number->string 955))
#f

This is again false, for the same reason as eq? -- these are not the same objects in memory. eqv? however makes an exception for numbers and characters: it will compare those by value, so two numbers are eqv? if they have the same value. This is still fast, and is usually what you want when you're doing number equality tests.

(equal? (number->string 955) (number->string 955))
#t

Now this is true. Why? The objects are still different, but equal? makes exceptions for strings (and other data types too, but I'll keep it simple). When equal? is given strings, it compares the strings lexically: so if they're the same length and the same sequence of characters, they're "equal". This is the check you want for strings.

于 2013-11-01T02:14:43.843 回答
1

There are a full two pages in the RNRS specification related to eq?, eqv?, equal? and =. Here is the Draft R7RS Specification. Check it out (pages 30 and 39)!

For eqv?, #t is returned if:

  • obj1 and obj2 are both characters and are the same character according to the char=? procedure (section 6.6).
  • obj1 and obj2 are pairs, vectors, bytevectors, records, or strings that denote the same location in the store (section 3.4).

In your case number->string returns a new 'location in the store' and thus #f is returned. (The Scheme standards do not require number->string to return a new location; returning the same string would be an optimization.) Whereas integer->char returns the same char.

于 2013-11-01T02:14:50.040 回答