guile-user
[Top][All Lists]
Advanced

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

Re: Surprising behavior of eq?


From: Linus Björnstam
Subject: Re: Surprising behavior of eq?
Date: Sun, 20 Sep 2020 22:51:35 +0200
User-agent: Cyrus-JMAP/3.3.0-325-g8593b62-fm-20200916.004-g0f995879-bis

Just a quick note on guile: if you are testing equality against literals guile 
will optimize to the fastest kind. (equal? b 27) becomes (eq? b 27). This was 
added by Andy sometime since 3.0, after Aleix discovered that match was slower 
than cond-with-eqv? for chars, and that the difference was huge. I wrote an 
awful patch, which made Andy barf so he fixed it properly (no. He was very 
polite. If he barfed, he didn't mention it).

A simple optimization that shaved something like 15% of time spent in json->scm 
in guile-json on one of the files we used for benchmarking. It was converted to 
cond for the benefit of 2.2, though, but it is still a nice thing to be able to 
rely on when writing macros.

-- 
  Linus Björnstam

On Sun, 20 Sep 2020, at 19:05, John Cowan wrote:
> On Sun, Sep 20, 2020 at 11:37 AM Zelphir Kaltstahl <
> zelphirkaltstahl@posteo.de> wrote:
> 
> > "This is where the eqv? predicate comes into picture. The eqv? is exactly
> > the same as the eq? predicate, except that it will always return #t for
> > same primitive values."
> >
> > Of course SO is not a standard. Either it is simply wrong, or I
> > misunderstood "primitive values" in that phrase. I thought: "Ah strings are
> > a primitive value, so eqv? should work in all cases when comparing
> > strings." However, this has been debunked.
> >
> Strings tend to be treated as primitive values, but technically they are
> compound values, just as much as vectors are.  And like vectors, you can
> change the characters of a string without changing its identity.
> 
> > The only thing I do not quite understand yet is: What is the difference
> > between (eqv? ...) and (eq? ...) then?
> >
> Efficiency only.
> 
> > If (eqv? ...) is only #t if things get consolidated in the same store
> > place, would that not be the same as pointer equivalence?
> >
> Eq? is allowed to return #f on identical-looking characters and numbers
> because they may or may not involve allocation.  Characters and fixnums
> (integers up to about 2^60) are generally not allocated and eq? will return
> #t on them, but larger integers and other types almost certainly will not:
> 
> (let ((i (* 48923498234892340 78902372789023)) (j (* 48923498234892340
> 78902372789023))) (eq? i j)) => #f
> 
> That's because the values of both i and j have to be allocated, and
> therefore aren't represented by the same pointers.  But unlike strings, you
> can't mutate the digits of an integer, so providing eqv? gives us an
> abstract notion of identity.  The Scheme standards simplify the situation
> by saying that eq? may return #f even when eqv? returns #t in the cases of
> numbers and characters.
> 
> Because of these strange effects, I recommend (and this is just me) not
> using eq? unless you can prove that you need the additional effi.
> 
> Note that (eq? 5 5.0) and (eqv? 5 5.0) are both #f, so if you want to
> compare for numeric equality you should use (= 5 5.0) => #t.  The reason
> they are not identical is that they behave differently:  (/ 5.0 2) => 2.5,
> whereas (/ 5 2) => 5/2.
> 
> Here's an example that shows us that Guile does not consolidate number
> literals, although it could:
> 
> (eqv? 3860180095872584138419938783820 3860180095872584138419938783820) =>#f
> 
> (In R7RS, procedures that are eqv? aren't necessarily eq? either, and in
> R6RS even procedures that seem totally identical may be neither eq? nor
> eqv?.  That's another story.)
>



reply via email to

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