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 < > zelphirkaltst...@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.) >