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.