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?