When reading the code of IntervalSets.jl I saw a constructor defined like this:
checked_conversion{T}(::Type{T}, a, b) = _checked_conversion(T, convert(T, a), convert(T, b))
_checked_conversion{T}(::Type{T}, a::T, b::T) = a, b
_checked_conversion{T}(::Type{T}, a, b) = throw(ArgumentError("$a and $b are not both of type $T"))
immutable ClosedInterval{T} <: AbstractInterval{T}
left::T
right::T
ClosedInterval(l::T, r::T) = new(l, r)
end
ClosedInterval{T}(left::T, right::T) = ClosedInterval{T}(left, right)
(::Type{ClosedInterval{T}}){T}(left, right) =
ClosedInterval{T}(checked_conversion(T, left, right)...)
function ClosedInterval(left, right)
# Defining this as ClosedInterval(promote(left, right)...) has one problem:
# if left and right do not promote to a common type, it triggers a StackOverflow.
T = promote_type(typeof(left), typeof(right))
ClosedInterval{T}(checked_conversion(T, left, right)...)
end
My question: is this the current best practice? Reading the manual on parametric constructors I was not aware of the issue.