From: Stefan Schmiedl <s@xss.de>
To: Zelphir Kaltstahl <zelphirkaltstahl@posteo.de>, guile-user@gnu.org
Subject: Re: Surprising behavior of eq?
Date: Sun, 20 Sep 2020 15:57:43 +0200 [thread overview]
Message-ID: <687423933.20200920155743@xss.de> (raw)
In-Reply-To: <bae0d6aa-b0fb-e835-5a01-03fb34c46650@posteo.de>
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
next prev parent reply other threads:[~2020-09-20 13:57 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 [this message]
2020-09-20 15:42 ` Zelphir Kaltstahl
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=687423933.20200920155743@xss.de \
--to=s@xss.de \
--cc=guile-user@gnu.org \
--cc=zelphirkaltstahl@posteo.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).