Hello again Peter,
On 11/1/26 21:01, Peter McGoron wrote:
> Hello,
>
> SRFI 128 was voted into the Scheme Red ballot. However, the behavior of
> default comparators is very tricky. They are the subject of two PFNs and
> will behave in unpredictable ways if two comparators with overlapping
> test predicates are added to it.
>
> I think a successor SRFI that does away with the default comparator
> interface would be better.
As the maintainer of SRFI 128 for CHICKEN, I also agree with this, but I
don't know how often in practice it matters as I always find myself
skipping past the "default comparator" if I can avoid it with something
more specific.
>
> Such a successor can also incorporate SRFI 162 (sublibrary) and SRFI 228
> (composing comparators).
>
I think aside from any organizational problems with R7RS-large this
would be overall good. As someone who spends too much of his free time
packaging software, it can be frustrating to have to maintain these as
all separate standards, when you often want them all in one place (at
least, 128 and 228).
> There could also be some additions to the comparators library. I would
> want them to be backwards compatible with old comparators. Some
> interesting additions:
>
> 1. Hash function utilities[1].
> 2. Creating comparators from a three-way-comparison procedure.
>
> Thoughts?
Hash function helpers could certainly be interesting, as I think they're
probably the hardest "from scratch" procedure to generate today.
Besides the proposed ideas, I have in the past toyed with the idea of
splitting comparators up somewhat. My main criticism is that in practice
I find that they try to bundle up too many unrelated operations, which
results in a lot of headache to understand which operations are valid,
which are not, which are only partially defined, and whether the
comparator is something that can be re-used in a local context.
The corresponding properties of comparators roughly break into:
1. Partial equality (e.g., defined for all floats except NAN == NAN)
2. Total equality (i.e., all representable values can compare equality)
3. Hash-able (Requires `(equal? k1 k2) -> (equal? (hash k1) (hash k2))`)
4. Partial Ordering (e.g., all floats with exceptions for
positive/negative NAN)
5. Total Ordering (see something like total_cmp below)
<https://doc.rust-lang.org/std/primitive.f64.html#method.total_cmp>
Apologies for pointing to a completely different language for this, but
Rust has what I would argue a better representation of these properties
in the form of PartialEq/Eq/PartialOrd/Ord/Hash, at least for a very
statically typed language. But is serves as a good frame of reference
for why I broke it down this way, because those properties matter in
different ways in different contexts.
Where I find I have problems with SRFI 128 in practice today is that a
single comparator is the intersection of all of these properties into
one type-class (versus having 3-5 type-classes). This is mostly fine,
but I have complained in the past (on IRC and elsewhere) that unless you
are very generous with your comparators or types you end up struggling
to always know whether a comparator is re-usable or if it is
inappropriate for the context.
Ultimately, what I end up doing in practice is over-specifying my
comparators beyond what is needed in the local context because they are
often embedded into my containers/datatypes (such as SRFI 146
mappings/hashmaps). If I don't have a comparator that has definitions
for equality and ordering and hashing, my fear is that it can get
re-used somewhere else if one extracts it from the container. The
micro-effects of such are often an (error ...) and an annoying debugging
session, but more broadly it does make me wonder if I'm just "holding it
wrong" in a way that they aren't designed for.
Composing comparators from N of 5 separate properties could be one way
around this, but in some ways is also a form of busywork. I can't say I
have a total answer for this yet. I'd look forward to any proposal that
can make SRFI 128 more useful though, and the default comparator
behaviour is really bad in regards to how I described the above
problem(s), so doing away with it would be fine.
Regards,
--
Jeremy Steward