Let’s say I want to change how Base.write works with a Base type, NTuple{N,UInt8} from a package.
Currently, writing NTuple via Base.write errors.
julia> iob = IOBuffer()
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
julia> data = (0x01,0x02,0x03)
(0x01, 0x02, 0x03)
julia> Base.write(iob, data)
ERROR: MethodError: no method matching write(::IOBuffer, ::Tuple{UInt8, UInt8, UInt8})
julia> typeof(data)
Tuple{UInt8, UInt8, UInt8}
julia> typeof(data) == NTuple{3,UInt8}
true
Under type piracy rules, I should not do the following because
- I did not originate the types.
- I did not orginate the method.
function Base.write(io::IO, data::NTuple{N,T}) where {N,T} 
    sum(map(1:N) do i
        Base.write(io, data[i])
    end)
end
julia> write(iob, data)
3
To evade commiting piracy, I will originate a new method called Foo.write.
module Foo
    # Edit: comment out the export here. People should do this more explicitly.
    # export write
    # Fallback to Base implementation
    write(args...; kwargs...) =
        Base.write(args...; kwargs...)
    function write(io::IO, data::NTuple{N,T}) where {N,T} 
        sum(map(1:N) do i
            Base.write(io, data[i])
        end)
    end
end
This is not piracy because I did not violate both criteria I outlined above. I can use this as follows in a fresh REPL session.
# Explicitly indicate the use Foo.write instead of Base.write
julia> using .Foo: write
julia> @which write
Main.Foo
julia> iob = IOBuffer()
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
julia> data = (0x01,0x02,0x03)
(0x01, 0x02, 0x03)
                                                                  
julia> write(iob, data)
3
julia> write(iob, 4)
8
julia> write(iob, 0x5)
1
julia> take!(iob)
12-element Vector{UInt8}:
 0x01
 0x02
 0x03
 0x04
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00
 0x05
One could also use a baremodule to not have Base imported.
Another important effect is that I do not invalidate any uses of Base.write and thus do not force recompilation for any other packages.
Using the language of object oriented programming, Foo.write is a submethod that inherits from Base.write. Foo.write does everything Base.write does but it also writes NTuple. Is there a preexisting name for this?
Can you think of a better name?
Edit: Commented out the export write from the example.
