Irrational numbers are singleton types and are unique, so we have something like
julia> Irrational{:pi}() === Irrational{:pi}()
true
Not many irrational numbers are defined in Base, therefore packages are free to define their own numbers. However the macro Base.@irrational that may be used to define a new irrational number a simultaneously defines Base.Float64(a). This therefore means that a second package that also defines the same number a overwrites the original method definition of Float64(a) with the new – albeit identical – type. For example:
julia> module A
Base.@irrational a 1.0 float(big(1))
end
Main.A
julia> module B
Base.@irrational a 1.0 float(big(1))
end
Main.B
julia> @which Float64(A.a)
Float64(::Irrational{:a}) in Main.B at irrationals.jl:189
Now this isn’t really a problem for the most part (aside from the unexpected type piracy), since
julia> A.a === B.a
true
and the results would be identical. However when functions are overwritten like this, package precompilation gets broken. One solution appears to be to import A.a inside B, but this means that B needs to depend on A that might otherwise be unrelated. Another solution is to rename the number in B and call it something other than a. However this is undesirable, eg. you wouldn’t name ℯ as something else. So which package gets to define the number without precompilation hurdles?
For example, StatsFuns.jl defines quite a few irrationals. How to avoid conflicts with StatsFuns if eg. we want to define sqrt2?