How bad is it if x < y doesn't return a Bool?

gdalle
Thu, 23 May 2024 07:52:41 +0000
General Usage

Suppose I define a number type T for which order comparison is not meaningful: <(x::T, y::T) doesn’t make any mathematical sense, because T actually contains a set. There are good reasons why I’m doing this, see SparseConnectivityTracer.jl, but that’s not the topic of today.

My problem is that I still want to allow control flow with ifelse. In my scenario, ifelse(x < y, a, b) should ignore the comparison result and just return some function f(a, b) (essentially taking both branches at once).
How bad is it if I define something like the following?

struct T <: Real
    s::Set{Int}
end

f(a::T, b::T) = T(union(a.s, b.s))
Base.:<(x::T, y::T) = missing
Base.ifelse(::Missing, a::T, b::T) = f(a, b)

It works:

julia> a, b = T(Set([1, 2, 3])), T(Set([3, 4, 5]));

julia> ifelse(a < b, a, b)
T(Set([5, 4, 2, 3, 1]))

But I’m afraid it might lead to invalidations or other bad behavior. How criminal is it to break the convention that < must return a Bool?

23 posts - 7 participants