Macro that force imports conflicting methods in Julia modules
Forces imports of exported methods from
Module, even if there are conflicts.
@force using Module
If you are using this package, then the
@force is strong in you and the Module!
Allows using packages that export conflicting definitions of methods and imports them into the module.
module Foo export + +() = 7 end module Bar using ForceImport @force using Foo end julia> Bar.:+() 7
Note that if the conflicting definition of the method is used before the import, then
@force will not be effective.
julia> 1+1 2 julia> @force using Foo WARNING: ignoring conflicting import of Foo.+ into Main
Hence the macro has to be called before the relevant methods have been called.
Local method extension technique
The principle which all
@force users must keep in mind is this: the goal is to extend
Base methods locally without affecting the global method table by type piracy, and to be able to import them into another package to have the same local effect. In order to avoid the type piracy, one must define a new local complementary
n-ary method that will fall back on the base method with
Any arguments. Then there will be a tiered alternative dispatch layer within the local package scope that redirects to the default
Base dispatch generically. This has many advantages, including a
2x-improvement in precompile time (since the precompilation is now tiered), which actually makes a big difference if this technique is applied to a large number of operations (on the order of 50-100 in
module ExtendedPackage +(x...) = Base.:+(x...) +(x::Symbol,y::Number...) = Expr(:call,:+,x,y...) end
Then you can use it locally with the
@force macro, which automatically forces imports of all exported methods one by one;
module NewScope using ForceImport @force using ExtendedPackage end
You will now have the property
julia> Base.:+ == NewScope.:+ false
+ in the
NewScope is now the extended plus that falls back on
Base, which is also different from the
Main. All it takes is the application of this principle, which has been pioneered with the development of the Reduce.Algebra module (defined in src/args.jl and src/unary.jl).
The main difficulty lies in properly designing the redirection from the tiered method dispatch so that the infix operations work naturally with a variety of syntax.