Add copy
This PR adds a copy method. The easiest way to do this was to call deepcopy, @ararslan @timholy is there any hidden issue in doing this?
FWIW, I remember Jeff being opposed to having a copy for immutable objects, and I think that Base has removed a number of copy methods already. Eg.
julia> copy((1,2))
ERROR: MethodError: no method matching copy(::Tuple{Int64,Int64})
I think this is a better example:
julia> copy(1:2)
1:2
is there any hidden issue in doing this?
With using deepcopy, you mean? Not as far as I'm aware. It ensures that BigFloats are properly copied because (IIRC) copy(::BigFloat) is a no-op as it is with the immutable number types, and deepcopy itself is a no-op for bits types.
Ah I didn't realise BigFloat behaved like that:
julia> copy(x) === x
true
julia> BigFloat(1) === BigFloat(1)
false
Perhaps I should just do a standard copy explicitly for Interval.
If you want to make sure that mutating a BigFloat in one interval doesn't affect another interval, deepcopy is probably your best bet.
BigFloats are mutable? In that case isn't its copy behaviour a bug?
¯\_(ツ)_/¯
BigFloat is supposed to be semantically immutable but their implementation doesn't let us do that now. copy(1:2) has to work because it's part of the AbstractArray interface. Given that copy(3) works then I think it's good to define it for intervals too.
deepcopy can be a huge performance trap, so I'm a bit opposed to implementing copy via deepcopy. What problem did using deepcopy solve?
I don’t think it actually solves a problem. I’m inclined to change it to
copy(d::Domain) = d
Isn't defining copy for concrete subtypes like Interval much safer option? If it's too cumbersome, how about
copy(d::Domain) = isbits(d) ? d : deepcopy(d)
You are certainly right, at least in theory. In practice, I can’t think of a case where it matters.
But for the sake of not intentionally writing “bad“ code I’ll make that change and only override for TypedEndpointsInterval.