unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: Zelphir Kaltstahl <zelphirkaltstahl@posteo.de>
To: Stefan Schmiedl <s@xss.de>
Cc: guile-user@gnu.org
Subject: Re: Surprising behavior of eq?
Date: Sun, 20 Sep 2020 17:42:26 +0200	[thread overview]
Message-ID: <0fd978e7-1538-fc52-a52f-d66cf57610d8@posteo.de> (raw)
In-Reply-To: <687423933.20200920155743@xss.de>

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	other threads:[~2020-09-20 15:42 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-20 12:16 Surprising behavior of eq? Zelphir Kaltstahl
2020-09-20 12:19 ` Zelphir Kaltstahl
2020-09-20 12:58   ` Christopher Lemmer Webber
2020-09-20 13:09   ` Zelphir Kaltstahl
2020-09-20 13:52     ` John Cowan
2020-09-20 15:37       ` Zelphir Kaltstahl
2020-09-20 16:18         ` tomas
2020-09-20 17:05         ` John Cowan
2020-09-20 20:51           ` Linus Björnstam
2020-09-20 21:42             ` John Cowan
2020-09-20 13:57     ` Stefan Schmiedl
2020-09-20 15:42       ` Zelphir Kaltstahl [this message]
2020-09-20 17:26 ` Taylan Kammer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0fd978e7-1538-fc52-a52f-d66cf57610d8@posteo.de \
    --to=zelphirkaltstahl@posteo.de \
    --cc=guile-user@gnu.org \
    --cc=s@xss.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).