julia> module A
import Base: +
+(x::Symbol, y::Symbol) = :(+($x, $y))
end
A
I would like to use it in some module B, but since adding 2 symbols might be error prone, I don’t want it to be exported to other modules. Yet, since +(::Symbol, ::Symbol) extends Base.+, it becomes automatically available to all modules whenever A is loaded. E.g. in REPL / Main module:
julia> :x + :y
:(x + y)
Is there a way to define +(::Symbol, ::Symbol), but keep it private unless explicitly imported?
No. Base has one set of method tables for +, and all other modules that use Base’s + will see any changes you make to it. That’s why this practice is known as “type piracy” and is discouraged. Extending methods of another module’s generic function on a type signature which is all types from other modules can change the behavior of unrelated code when your module is loaded. Either use a different function/operator name, or one that’s not imported from another module, or make sure at least one of the types in the signatures you extend are types you’ve defined in your own module. You could make a simple wrapper type around Symbol to avoid changing the behavior of other code.
I wouldn’t recommend it. The problem is that this method will not get called in various cases, e.g. if you combine it with other dot operations, due to loop fusion. Even if you just do (:x .⊕ :y) .⊕ :z, it will fuse into broadcast((x,y,z) -> (x ⊕ y) ⊕ z, :x, :y, :z).
Basically, in 0.6 you shouldn’t be thinking of .⊕ or .+ as operators by themselves, but rather as syntactic sugar for a (fusing) broadcast call.
@kristoffer.carlsson correct. In any case where Base.:+ would have been statically resolved, it’s easy for the compiler to inline A.:+, effectively eliding it completely. Forwarding functions like this sometimes runs the risk of overloading the inlining heuristic, but that’s easy to avoid with an @inline annotation.
@nsmithBase.:fft is the same as Base.fft, i.e. it gets that named object from another module. With operators Base.+ doesn’t work (I assume because it’s ambiguous with broadcast operators like x.+y) so the colon version is required.