Thanks for bringing the distinction piracy/punning to the front, this helps clarify the discussion.
I think a the core, the difference of views comes from:
I’m afraid by overviewing this aspect, you miss the point I tried to convey (in a clumsy way, possibly).
When you look at it, there’s only one place where a function gets defined, which is within its parent module.
On the contrary, methods - whether “original” or by punning - can be defined in the parent module or in some other custom modules respectively.
Thus, the intent of the function is quite univocal, and is only up to the writer of the parent (original) module. All other punning methods are strongly compelled to (or should I say requested to) comply to the original purpose, in a similar fashion to interfaces. In that view, this is: “deviate at your own risk”.
… at least, this is the consequence of the interpretation framework I tried to convey.
The practical use is then quite straightforward: look at the function to understand what you can/can’t do when punning without messing things around. Use it as a tool for good practice (we often neglect all the good that can bring mundane good practices)
In that light, because Base.:+
is used consistently throughout Base.:+
, you get this nice side effect that other functions relying on it such as sum
or +=
works. (and this is a good thing)
Now to some caveats & comments:
- There’s other valid way to interpreted the possibilities offered by multiple dispatch, feel free to use your own (obviously! )
- One could be concerned that documentation is not always well and good, so the function’s purpose may be unclear. But:
- Punning is discouraged for non-public functions (or even just using non-public functions)
- Public functions are more often than not well documented (especially for mature packages not expected to break things)
Regarding the issue of coordination:
- There’s no need for strong coordination: just adapt to what the function is … which is not expected to change much for a package which is >= 1.0.0
- … If it is < 1.0.0, then it is at your own risk.
Lastly, regarding the example of process
, I’d say that because it is very abstract, you should refrain to specialize it on custom types (there’s no need to). See Base.map
or Base.reduce
for example, which only specializes on iterator type (collection
or AbstractArray
).
On the contrary, Base.size
’s purpose is quite clear. As per help: “Return a tuple containing the dimensions of A”. Deviating from that is a good way to mess with other people’s mind.
But you’re free to define Clothing.size
and return what you want with that.
Btw, this is for this very reason that you can’t import say Clothing.size
into Main
as size
, even though the methods you’ve written don’t overlap with Base.size
: otherwise, which size
do you intent to use? (in e.g. Main
)