On Wed, Jun 21, 2023, at 11:59 PM, Andrew Tropin wrote: > On 2023-06-21 18:54, Jean Abou Samra wrote: > >>> Le 21 juin 2023 à 18:46, Andrew Tropin <and...@trop.in> a écrit : >>> >>> Make sense, but it's hard for me to say something valuable on this >>> topic. Usually, I don't use eq? and don't have enough knowledge of its >>> internals. >> >> >> *Currently*, it just checks whether the two C-level SCM values are the >> same bitwise, so even implicit copies of fixnums will remain eq?. In >> theory, Guile could make copies of bignums. I am not aware of it doing >> so. >> >> However, all that is guaranteed is that (eq? a a) when a is a >> non-immediate (pair, string, vector, hashtable, etc) or one of a few >> constants like booleans, the empty list and *unspecified*. Notably, it >> isn't guaranteed for numbers or characters. >> > [...] I'm > almost sure that we need eq? here as we need to make sure that the value > previously stored and returned atomic-box-compare-and-swap! is the same > object in memory, however this example from manual is indeed confusing: > > --8<---------------cut here---------------start------------->8--- > (let ((n (+ 2 3))) > (eq? n n)) ==> _unspecified_ > --8<---------------cut here---------------end--------------->8--- > > So maybe you are right and it's better to use eqv? here. >
The problem with eqv? is that it doesn't correspond well to machine-level atomic compare-and-set instructions, so using it would defeat the purpose of lightweight atomic boxes. R6RS specifies that "the behavior of eq? on number objects and characters is implementation-dependent, but it always returns either #t or #f, and returns #t only when eqv? would also return #t." [1] I think the right thing to do here is for Guile to provide more guarantees about its implementation of eq?. Guaranteeing that fixnums are eq? when they are = would be particularly reasonable and extremely unlikely to cause constrain any future port of Guile: the whole point of fixnums is to support efficient machine operations like this. I also think most Schemers would be quite surprised if (lambda (x) (eq? x x)) ever returned #f. More broadly, *The Scheme Programming Language* says at the beginning of its documentation for eq? that, "In most Scheme systems, two objects are considered identical if they are represented internally by the same pointer value and distinct (not identical) if they are represented internally by different pointer values, although other criteria, such as time-stamping, are possible." In any case, the current documentation for atomic-box-compare-and-swap! is clear that the comparison is eq?: it just means that, when the behavior of eq? is unreliable, so is the behavior of atomic-box-compare-and-swap!. Tangentially, does atomic-box-compare-and-swap! handle spurious failures on architectures like ARM, or does it expose machine semantics to the programmer? Maybe that's covered by details of the C11 memory model, but I don't think "sequential consistency" alone is enough to answer the question. -Philip [1]: https://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_sec_11.5 [2]: https://scheme.com/tspl4/objects.html#./objects:s10