在 Julia 中定义抽象类型的默认方法
Define default method on abstract type in Julia
如何在单独的模块中提供 Julia 方法的默认实现?如果抽象类型存在于同一个模块中,我没有问题,例如,这正如我所期望的那样工作:
abstract type Foo end
howdy(x::Foo)::Union{String, Nothing} = nothing
struct Bar <: Foo end
function howdy(x::Bar)::Union{String, Nothing}
"I'm a Bar!"
end
struct Baz <: Foo end
if abspath(PROGRAM_FILE) == @__FILE__
bar = Bar()
s = howdy(bar)
if isa(s, String)
println(s)
end
baz = Baz()
t = howdy(baz)
if isa(t, String)
println(t)
end
end
但是,一旦我将抽象类型放入它自己的模块中,它就不再起作用了:
在src/qux.jl
中,我输入:
module qux
abstract type Foo end
howdy(x::Foo)::Union{String, Nothing} = nothing
export Foo, howdy
end # module
然后在 reproduce.jl
我输入:
using qux
struct Bar <: Foo end
function howdy(x::Bar)::Union{String, Nothing}
"I'm a Bar!"
end
struct Baz <: Foo end
if abspath(PROGRAM_FILE) == @__FILE__
bar = Bar()
s = howdy(bar)
if isa(s, String)
println(s)
end
baz = Baz()
t = howdy(baz)
if isa(t, String)
println(t)
end
end
然后我得到:
julia --project=. reproduce.jl
I'm a Bar!
ERROR: LoadError: MethodError: no method matching howdy(::Baz)
Closest candidates are:
howdy(::Bar) at ~/qux/reproduce.jl:5
Stacktrace:
[1] top-level scope
@ ~/qux/reproduce.jl:18
in expression starting at ~/qux/reproduce.jl:11
Julia 手册中here 解释了您的问题。
问题在于您的代码,如您在此处所见:
julia> module qux
abstract type Foo end
howdy(x::Foo)::Union{String, Nothing} = nothing
export Foo, howdy
end # module
Main.qux
julia> using .qux
julia> struct Bar <: Foo end
julia> function howdy(x::Bar)::Union{String, Nothing}
"I'm a Bar!"
end
howdy (generic function with 1 method)
julia> methods(howdy)
# 1 method for generic function "howdy":
[1] howdy(x::Bar) in Main at REPL[4]:1
julia> methods(qux.howdy)
# 1 method for generic function "howdy":
[1] howdy(x::Foo) in Main.qux at REPL[1]:5
您有两个不同的 howdy
函数,每个函数都有一个方法。一个在 qux
模块中定义,另一个在 Main
模块中定义。
您要做的是向 qux
模块中定义的 howdy
函数添加一个方法。我通常会通过使用模块名称限定导出的函数名称来做到这一点,因为这是一种明确的方式来表明你想做什么:
julia> module qux
abstract type Foo end
howdy(x::Foo)::Union{String, Nothing} = nothing
export Foo, howdy
end # module
Main.qux
julia> using .qux
julia> struct Bar <: Foo end
julia> function qux.howdy(x::Bar)::Union{String, Nothing}
"I'm a Bar!"
end
julia> methods(qux)
# 0 methods:
julia> methods(howdy)
# 2 methods for generic function "howdy":
[1] howdy(x::Bar) in Main at REPL[4]:1
[2] howdy(x::Foo) in Main.qux at REPL[1]:5
如您所见,您现在有一个 howdy
函数,它有两个方法,所有方法都可以按您的意愿工作。
如何在单独的模块中提供 Julia 方法的默认实现?如果抽象类型存在于同一个模块中,我没有问题,例如,这正如我所期望的那样工作:
abstract type Foo end
howdy(x::Foo)::Union{String, Nothing} = nothing
struct Bar <: Foo end
function howdy(x::Bar)::Union{String, Nothing}
"I'm a Bar!"
end
struct Baz <: Foo end
if abspath(PROGRAM_FILE) == @__FILE__
bar = Bar()
s = howdy(bar)
if isa(s, String)
println(s)
end
baz = Baz()
t = howdy(baz)
if isa(t, String)
println(t)
end
end
但是,一旦我将抽象类型放入它自己的模块中,它就不再起作用了:
在src/qux.jl
中,我输入:
module qux
abstract type Foo end
howdy(x::Foo)::Union{String, Nothing} = nothing
export Foo, howdy
end # module
然后在 reproduce.jl
我输入:
using qux
struct Bar <: Foo end
function howdy(x::Bar)::Union{String, Nothing}
"I'm a Bar!"
end
struct Baz <: Foo end
if abspath(PROGRAM_FILE) == @__FILE__
bar = Bar()
s = howdy(bar)
if isa(s, String)
println(s)
end
baz = Baz()
t = howdy(baz)
if isa(t, String)
println(t)
end
end
然后我得到:
julia --project=. reproduce.jl
I'm a Bar!
ERROR: LoadError: MethodError: no method matching howdy(::Baz)
Closest candidates are:
howdy(::Bar) at ~/qux/reproduce.jl:5
Stacktrace:
[1] top-level scope
@ ~/qux/reproduce.jl:18
in expression starting at ~/qux/reproduce.jl:11
Julia 手册中here 解释了您的问题。
问题在于您的代码,如您在此处所见:
julia> module qux
abstract type Foo end
howdy(x::Foo)::Union{String, Nothing} = nothing
export Foo, howdy
end # module
Main.qux
julia> using .qux
julia> struct Bar <: Foo end
julia> function howdy(x::Bar)::Union{String, Nothing}
"I'm a Bar!"
end
howdy (generic function with 1 method)
julia> methods(howdy)
# 1 method for generic function "howdy":
[1] howdy(x::Bar) in Main at REPL[4]:1
julia> methods(qux.howdy)
# 1 method for generic function "howdy":
[1] howdy(x::Foo) in Main.qux at REPL[1]:5
您有两个不同的 howdy
函数,每个函数都有一个方法。一个在 qux
模块中定义,另一个在 Main
模块中定义。
您要做的是向 qux
模块中定义的 howdy
函数添加一个方法。我通常会通过使用模块名称限定导出的函数名称来做到这一点,因为这是一种明确的方式来表明你想做什么:
julia> module qux
abstract type Foo end
howdy(x::Foo)::Union{String, Nothing} = nothing
export Foo, howdy
end # module
Main.qux
julia> using .qux
julia> struct Bar <: Foo end
julia> function qux.howdy(x::Bar)::Union{String, Nothing}
"I'm a Bar!"
end
julia> methods(qux)
# 0 methods:
julia> methods(howdy)
# 2 methods for generic function "howdy":
[1] howdy(x::Bar) in Main at REPL[4]:1
[2] howdy(x::Foo) in Main.qux at REPL[1]:5
如您所见,您现在有一个 howdy
函数,它有两个方法,所有方法都可以按您的意愿工作。