guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Surprising behavior of eq?


From: Zelphir Kaltstahl
Subject: Re: Surprising behavior of eq?
Date: Sun, 20 Sep 2020 17:42:26 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0

Hello Stefan!

Thank you for your explanation as well!

On 9/20/20 3:57 PM, Stefan Schmiedl wrote:
> 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 

I even learned a little bit about store locations and that a "store"
exist as a concept in the implementation of Scheme and GNU Guile ; )

> * that eqv? is not the right predicate for content based string comparison
I see! Thanks!
> 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  

Best regards,

Zelphir



reply via email to

[Prev in Thread] Current Thread [Next in Thread]