我想创建一个行为类似于primitive type
,但命名为Int64
的{{1}}。这可能吗?
我了解到here我可以做这样的事情
Foo
但是我不明白为什么,即使# Declare the new type.
primitive type MyInt8 <: Signed 8 end
# A constructor to create values of the type MyInt8.
MyInt8(x :: Int8) = reinterpret(MyInt8, x)
# A constructor to convert back.
Int8(x :: MyInt8) = reinterpret(Int8, x)
# This allows the REPL to show values of type MyInt8.
Base.show(io :: IO, x :: MyInt8) = print(io, Int8(x))
是MyInt8
(Signed
)的子类型,也没有用于该类型的方法:
MyInt8 <: Signed
我认为原始类型作为子类型也会自动“获得”超类型的所有方法。
我在哪里错了?
答案 0 :(得分:3)
作为Signed
的子类型,MyInt8
确实自动“获取”为数字定义的所有方法。实际上有很多:
julia> methodswith(MyInt8, supertypes=true) |> length
1218
julia> methodswith(MyInt8, supertypes=true)[1:10]
[1] poll_fd(s::RawFD, timeout_s::Real; readable, writable) in FileWatching at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/FileWatching/src/FileWatching.jl:649
[2] poll_file(s::AbstractString, interval_seconds::Real) in FileWatching at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/FileWatching/src/FileWatching.jl:784
[3] poll_file(s::AbstractString, interval_seconds::Real, timeout_s::Real) in FileWatching at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/FileWatching/src/FileWatching.jl:784
[4] watch_file(s::AbstractString, timeout_s::Real) in FileWatching at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/FileWatching/src/FileWatching.jl:687
[5] watch_folder(s::String, timeout_s::Real) in FileWatching at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/FileWatching/src/FileWatching.jl:716
[6] watch_folder(s::AbstractString, timeout_s::Real) in FileWatching at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/FileWatching/src/FileWatching.jl:715
[7] randcycle(r::Random.AbstractRNG, n::T) where T<:Integer in Random at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/Random/src/misc.jl:348
[8] randcycle(n::Integer) in Random at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/Random/src/misc.jl:349
[9] randexp(rng::Random.AbstractRNG, ::Type{T}, dim1::Integer, dims::Integer...) where T in Random at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/Random/src/normal.jl:204
[10] randperm(r::Random.AbstractRNG, n::T) where T<:Integer in Random at /home/francois/.local/julia-1.5.2/share/julia/stdlib/v1.5/Random/src/misc.jl:282
其中一些不需要MyInt8
符合任何特定的接口,并且可以“开箱即用”地工作:
julia> a = MyInt8(Int8(3))
3
julia> conj(a)
3
但是有些人会提供依赖MyInt8
且符合接口的实现:
# Here `imag` does not know how to build a zero of the MyInt8 type
julia> imag(a)
ERROR: MethodError: no method matching MyInt8(::Int64)
Closest candidates are:
MyInt8(::T) where T<:Number at boot.jl:716
MyInt8(::Int8) at REPL[7]:2
MyInt8(::Float16) where T<:Integer at float.jl:71
...
Stacktrace:
[1] convert(::Type{MyInt8}, ::Int64) at ./number.jl:7
[2] oftype(::MyInt8, ::Int64) at ./essentials.jl:367
[3] zero(::MyInt8) at ./number.jl:241
[4] imag(::MyInt8) at ./complex.jl:78
[5] top-level scope at REPL[37]:1
添加项属于最后一个类别:
# There is indeed a generic implementation that MyInt8 inherits
julia> which(+, (MyInt8, MyInt8))
+(a::Integer, b::Integer) in Base at int.jl:918
# But it relies on promotion features, which are not implemented for MyInt8
julia> a + a
ERROR: promotion of types MyInt8 and MyInt8 failed to change any arguments
Stacktrace:
[1] error(::String, ::String, ::String) at ./error.jl:42
[2] sametype_error(::Tuple{MyInt8,MyInt8}) at ./promotion.jl:306
[3] not_sametype(::Tuple{MyInt8,MyInt8}, ::Tuple{MyInt8,MyInt8}) at ./promotion.jl:300
[4] +(::MyInt8, ::MyInt8) at ./int.jl:921
[5] top-level scope at REPL[41]:1
在那种特殊情况下,+
的继承实现仅用于处理两个不同类型的操作数的加法;我猜您将不得不为+
自己实现MyInt8
,与Int8
实现自己的附加功能大致相同:
julia> which(+, (Int8, Int8))
+(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:86
我可能会去执行类似以下的实现:
julia> Base.:+(a::MyInt8, b::MyInt8) = MyInt8(Int8(a)+Int8(b))
julia> a + a
6
编辑:
这应该达到与本机Int8
类型相同的性能:
# two Int8 vectors
julia> a1 = rand(Int8, 1000); b1 = rand(Int8, 1000);
# same vectors, as MyInt8 values
julia> a2 = MyInt8.(a1); b2 = MyInt8.(b1);
# check that both ways of doing the calculation produce the same results
julia> @assert a1 .+ b1 == Int8.(a2 .+ b2)
# Benchmark
julia> using BenchmarkTools
julia> @benchmark $a1 .+ $b1
BenchmarkTools.Trial:
memory estimate: 1.06 KiB
allocs estimate: 1
--------------
minimum time: 145.274 ns (0.00% GC)
median time: 176.402 ns (0.00% GC)
mean time: 200.996 ns (4.20% GC)
maximum time: 1.349 μs (79.34% GC)
--------------
samples: 10000
evals/sample: 759
julia> @benchmark $a2 .+ $b2
BenchmarkTools.Trial:
memory estimate: 1.06 KiB
allocs estimate: 1
--------------
minimum time: 140.316 ns (0.00% GC)
median time: 172.119 ns (0.00% GC)
mean time: 195.947 ns (4.54% GC)
maximum time: 1.148 μs (73.34% GC)
--------------
samples: 10000
evals/sample: 750