[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Surprising behavior of eq?
From: |
Stefan Schmiedl |
Subject: |
Re: Surprising behavior of eq? |
Date: |
Sun, 20 Sep 2020 15:57:43 +0200 |
Let's have a little shop talk with guile:
$ guile-3.0
GNU Guile 3.0.4-dirty
scheme@(guile-user)> (eqv? "a" "a")
$1 = #t
Hypothesis:
guile's reader recognizes that the contents of both string literals
are the same and feeds the same string to the calling function.
Check:
If that were the case, the two strings should not only be eqv? but
also eq?
scheme@(guile-user)> (eq? "a" "a")
$2 = #t
To see a different behaviour we need to avoid these literals and replace
them by values not built while reading but while executing the code:
scheme@(guile-user)> (equal? (list->string (list #\a)) (list->string (list
#\a)))
$3 = #t
Now we compare two different string values which happen to end up with
identical content. And, behold: They are neither eqv? nor eq?.
scheme@(guile-user)> (eqv? (list->string (list #\a)) (list->string (list #\a)))
$4 = #f
scheme@(guile-user)> (eq? (list->string (list #\a)) (list->string (list #\a)))
$5 = #f
Now let's see if that is consistent with the standard:
According to r5rs, section 6.1 "Equivalence predicates":
The eqv? procedure returns #t if:
...
* obj1 and obj2 are pairs, vectors, or strings that denote
the same locations in the store (section 3.4).
So we have learned
* that guile's reader reuses "store locations" for
strings of identical content
* that eqv? is not the right predicate for content based string comparison
HTH
s.
"Zelphir Kaltstahl" <zelphirkaltstahl@posteo.de>, 20.09.2020, 15:09:
> And I've noticed something more about equality stuff in the context of
> tests:
> ~~~~
> (eqv? "a" "a")
> $3 = #t
> ;; but
(define char->>string
> (λ (c)
> (list->string
> (list c))))
> (import
> ;; unit tests
> (srfi srfi-64))
> (test-begin "string-utils-test")
> (test-group
> "char-to-string-test"
> (test-eqv "char->string converts a character to a string"
> "a"
> (char->string #\a)))
> (test-end "string-utils-test")
> %%%% Starting test string-utils-test (Writing full log to
> "string-utils-test.log")
> $2 = ("string-utils-test")
:19: FAIL char->>string converts a character to a string
> # of unexpected failures 1
> ~~~~
> So while (eqv? ...) gives the correct (?) result, the test procedure
> (test-eqv ...) which seems to indicate using (eqv? ...) via its name
> does not think of the two strings as equivalent.
> On 20.09.20 14:19, Zelphir Kaltstahl wrote:
>> Sorry, I misclicked "send" when I wanted to further edit my e-mail ...
>>
>> My Guile version is:
>>
>> ~~~~
>> (version)
>> $6 = "3.0.4"
>> ~~~~
>>
>> On 20.09.20 14:16, Zelphir Kaltstahl wrote:
>>> Hello Guile users,
>>>
>>> I just noticed something weird about eq?.
>>>
>>> My Guile version is:
>>>
>>>
>>> I get the different results, depending on whether I define some
>>> bindings in a let or using define:
>>>
>>> (In Emacs Geiser:)
>>>
>>> ~~~~
>>> (define x '(10 9))
>>> (define y '(10 9))
>>> (eq? x y)
>>> $2 = #f
>>>
>>> (let ([x '(10 9)]
>>> [y '(10 9)])
>>> (eq? x y))
>>> $3 = #t
>>> ~~~~
>>>
>>> Is this intentional or a bug?
>>>
>>> I first noticed something strange when writing the following code:
>>>
>>> ~~~~DEFINITION~~~~
>>> (define make-multiple-list-remover
>>> (λ (equal-proc)
>>> (λ (lst unwanted)
>>> (let loop ([remaining-list lst])
>>> (cond
>>> [(null? remaining-list)
>>> '()]
>>> [(equal-proc (car remaining-list) unwanted)
>>> (loop (cdr remaining-list))]
>>> [else
>>> (cons (car remaining-list)
>>> (loop (cdr remaining-list)))])))))
>>> ~~~~
>>>
>>> ~~~~TEST~~~~
>>> (let ([a '(9 10)]
>>> [b '(9 10)])
>>> (test-equal "make-multiple-list-remover-03"
>>> `(1 2 (3) (4) ,a)
>>> ((make-multiple-list-remover eq?)
>>> `(a b (c) (d) ,a) b)))
>>> ~~~~
>>>
>>> I was wondering, why the test fails. I think (eq? ...) should not be
>>> able to see the equivalence of both lists a and b, just like when
>>> defined using (define ...).
>>>
>>> I can also run it in the REPL and see the difference:
>>>
>>> ~~~~
>>> (define a '(9 10))
>>> (define b '(9 10))
>>> ((make-multiple-list-remover eq?)
>>> `(a b (c) (d) ,a) b)
>>> $4 = (a b (c) (d) (9 10))
>>>
>>> (let ([a '(9 10)]
>>> [b '(9 10)])
>>> ((make-multiple-list-remover eq?)
>>> `(a b (c) (d) ,a) b))
>>> $5 = (a b (c) (d))
>>> ~~~~
>>>
>>> Somehow the bindings of let seem to be different from the bindings
>>> created using define. What about using define inside let?
>>>
>>> ~~~~
>>>
>>> ~~~~
>>> --
>>> repositories: https://notabug.org/ZelphirKaltstahl
>> Somehow the bindings of let seem to be different from the bindings
>> created using define. What about using define inside let?
>>
>> ~~~~
>> (let ([unrelated 'bla])
>> (define a '(9 10))
>> (define b '(9 10))
>> ((make-multiple-list-remover eq?)
>> `(a b (c) (d) ,a) b))
>> $7 = (a b (c) (d))
>> ~~~~
>>
>> So there the define usage also differs from when I use define on the top
>> level. Perhaps that is the difference? On which level the bindings are
>> defined?
>>
>> Regards,
>> Zelphir
>>
--
Stefan Schmiedl
EDV-Beratung Schmiedl, Berghangstr. 5, 93413 Cham
Büro: +49 (0) 9971 9966 989, Mobil: +49 (0) 160 9981 6278
- Surprising behavior of eq?, Zelphir Kaltstahl, 2020/09/20
- Re: Surprising behavior of eq?, Zelphir Kaltstahl, 2020/09/20
- Re: Surprising behavior of eq?, Christopher Lemmer Webber, 2020/09/20
- Re: Surprising behavior of eq?, Zelphir Kaltstahl, 2020/09/20
- Re: Surprising behavior of eq?, John Cowan, 2020/09/20
- Re: Surprising behavior of eq?, Zelphir Kaltstahl, 2020/09/20
- Re: Surprising behavior of eq?, tomas, 2020/09/20
- Re: Surprising behavior of eq?, John Cowan, 2020/09/20
- Re: Surprising behavior of eq?, Linus Björnstam, 2020/09/20
- Re: Surprising behavior of eq?, John Cowan, 2020/09/20
- Re: Surprising behavior of eq?,
Stefan Schmiedl <=
- Re: Surprising behavior of eq?, Zelphir Kaltstahl, 2020/09/20
Re: Surprising behavior of eq?, Taylan Kammer, 2020/09/20