-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Can isless be defined for everything? #34815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Why is it desirable? |
I suppose this is required for storing arbitrary key/element in a comparison-based dictionary/set? This is required for sort-based group-by, too. (Though I guess I can live without this. I may be getting too greedy here.) I guess a practical "baby-step" request here is to define isless(a::T, b::T) where {T} =
if isstructtype(T)
isless(_fieldvalues(a), _fieldvalues(b))
else
throw(MethodError(isless, (a, b)))
end
_fieldvalues(x) = ntuple(i -> getfield(x, i), nfields(x)) Maybe even better definition is to be flexible for parametric types Given that |
Oh, no, wait. This does not work when there are type parameters that are not determined by the field types. |
Not a fan. There are times when absence of an operation helps you think clearly: for example if your calculation results in the answer |
I agree that a lack of definitions helps to find bugs. But I think that's in direct tension to using |
I guess the better approach would be to write a new dict type which accepts a type or function for ordering its elements. Well, I guess there's such thing already. Defining isless for all pairs explicitely is a bad idea IMO. If you are fine with an arbitrary ordering anyway just convert your objects to an arbitrary totally ordered space (e.g. hashing them, or taking objectid, though the latter changes between runs) and compare them there. That's the cleanest approach since it doesn't do weird default behaviour for incomparable objects. |
I think I'm convinced this is the only reasonable approach at least within 1.x. Traits for querying the existence of |
Regarding that I was recently (on slack) thinking about a more generic approach of isless(::HashComparator, a, b) = isless(CanonicalComparator(UInt), hash(a), hash(b))
isless(::CanonicalComparator{UInt}, x::UInt, x::UInt) = #some native call
isless(a,b) = isless(CanonicalComparator(typeof(a), typeof(b)), a, b)
isless(::PropagateMissing, a::Missing, b) = missing
isless(::PropagateMissing, a, b::Missing) = missing
isless(x::PropagateMissing, a, b) = isless(CanonicalComparator(typeof(a), typeof(b)), a, b)
<(a,b) = isless(PropagateMissing(), a, b) We can extend that behaviour to Then we'd also add a trait |
The semantics of ordering objects mathematically and ordering them for reproducibility are distinct. Trying to use I agree that it's sometimes useful to impose a total order on a collection of (or all) objects. For example, an order on dictionary keys, or the order in which terms are printed in a symbolic algebra program. I have to totally order terms in expressions printed (and stored) by Symata. In this case, trying to extend |
I thought my comment #34744 (comment) may be distracting the original issue so I open it as a separate issue. My questions are:
isless
for everything?isless
?I think the answer to point 1 is yes, since I can do
isless(a, b) = isless(objectid(a), objectid(b))
. This is stupid, but I think it's OK as a proof of possibility. In particular, this means that, if we define equivalence by mapping to an integer, we get a total ordering "for free."For point 2, I think there are cases where optimization is trivial and covers a wide range of practical use. For example, we can lower
isless(a::T, b::T)
with struct typeT
toisless
on the tuples of field values.If the philosophy behind the compatibility between hasing and sorting is to support consistent behavior of hash-based and comparison-based containers, I think the answer to point 3 is yes too. But I don't think I have thought enough about it so maybe I'm missing something. In particular, it may be impossible to avoid ordering that changes
julia
process to process (like howhash
behaves).The text was updated successfully, but these errors were encountered: