In Julia many packages add methods to well known existing functions. My simple question: How to decide whether to reuse an existing name as to come up with a new one?
An example: In
DataStructures.jl there is a
MutableLinkedList which offers
append!(m1,m2), but contrary to my experience with
Base.append! it adds
m1 and mutates
m2 to be empty. I understand that this behavior (saving memory) might be desired for a linked list, but it breaks what I have learned so far for this function. (In this particular case it doesn’t help that the implementation is buggy and has no proper documentation). So what should be done:
- document the difference to the typical behavior and keep using
- change the name to something that is maybe more fitting e.g.
merge! (althoughI don’t think
merge! mutate any arguments beside the first one)
- change the name of the function to something new
How much flexibility is okay? Wouldn’t stricter rules (“don’t do anything that base doesn’t do”) reduce surprises and therefore bugs?
- Keep using
append!(m1,m2) but remove the implicit
empty!(m2) behavior (and make the user do that explicitly).
I’d say this is a bug; it’s not following the
I would definitely agree to this as a rule of thumb. Even if there is no type piracy involved, it is possible to create very subtle bugs through extending base functions. Personally, I would choose new names if the function I’m writing doesn’t do the “exact same thing” just for a new type (e.g. you are implementing a new array type, of course you have to write the interface methods for your new type).
Perhaps the unwritten commandment to not commit type piracy should be complemented by “Don’t commit interface piracy either” ?
If I understand the whole recent development in code caching, compile time, and TTFX reduction correctly, then extending functions from other modules might also lead to a lot of unnecessary invalidations which increase inference/compile time. But I might be mixing up a few things here.
(I was thinking about this and this for example)
Definitely should lean towards keeping the same signature and behavior as Base.
append! function in DataStructures.jl was almost certainly added before the version in Base existed.
There is a (extremely slow moving) push to get DataStructures.jl to 1.0 as seen here. One of the requisite goals to accomplishing that is to align function behavior and signatures with those of Base. So even DataStructures.jl intends to amend this discrepancy.