Proposal for SharedFunctions.jl package for optional dependency management

The whole Base or a hacked, opt-in global namespace package for method merging smells wrong.

There seem to be two cases: (1) packages are sharing types and methods that act on those types. That should be in a Base package for sure and requires coordination; and (2) packages just want to share a function name, which may or may not be punned.

The solutions for (1) are already there, and it is convenient enough for package developers to work around. They should be jointly designing types and likely using import instead of using in their packages.

The problem tends to be (2), which is what this SharedFunctions.jl is intended to solve.

I vehemently disagree with this approach, not because I don’t think this is all an issue, but because it is such a big issue that it means we should step back before hacking. Using packages just to share function namespaces puts the impetus on method merging on the wrong people at the wrong place in the code. That is, it is at the point of using that the decision to merge should be made.

So what is the alternative? This has been brought up many times before, but I have come around to thinking it is the only solution: have a way to do a “using” which merges methods. Then it is up to the point of usage whether they want to merge or not. Users who want a convenient using for multiple packages with non-conflicting solve! methods can do so, where they are taught to avoid merging if possible, that clashes for possible for general types, but it is usually safe for types built into the package itself.

A merge using MyPackage vs. a using MyPackage are different in that the first one merges methods. It is up to users whether they want to do that or not. As a package developer, you write for the namespaces and generic interfaces that make sense and don’t worry about it anymore.

Also, merge function myfunc() end would also merge a defined function for a user into the current myfunc if it exists. This gets around the ordering of using fragility.

This is the sort of thing that can kind of be done in macros - GitHub - chakravala/ForceImport.jl: Macro that force imports conflicting methods in modules , but this is a hack with all sorts of eval-trickery. The only way it would be a successful solution to the issue is if it was integrated into the language, the documentation, testing, packagecompiler, etc. Assuming that it is possible, the whole thing is very teachable and is not a breaking change.

Later, there are ways that a warning could be made to detect conflicting generic concepts for the methods when merging (effectively it involves looking for overlap in the tree of dispatching for the methods) but that can wait.

True, but this is a large administrative burden for anyone creating packages, tagging them, setting versions, dealing with user complaints with using clashes for new packages, etc. What will happen when not every package creator is on a first-name basis in slack? When shared types are involved, it is necessary, but just for method merging it is a sledgehammer solution that becomes a pain for everyone involved.

Plus: it doesn’t solve the usability issue of users who may want to just have two concurrent (and non-clashing) method names concurrently.

And trying not to rehash all of the discussions in Function name conflict: ADL / function merging? and "Meaning", type-piracy, and method merging but…

Change that to


struct Player end

function push!(p::Player)

end

and that is typically innocuous and there is no overlap in the dispatching. push! is a bad function to pun, but frequently it is perfectly possible to have overlapping generic interfaces. Just like in single-dispatch languages where XXX.push!(p) allows punning for any sort of XXX type without any issues.

Until Julia has actual definitions of generic interfaces (i.e. not just agreement on names) and ways to help them coexist, making things purposely inconvenient just makes people look for for crazy workarounds… Leave it up to the users whether they want to merge methods and make multiple generic concepts convenient.

6 Likes