在两个文件中重载一个函数(在 Julia 中)
Overloading a function in two files (in Julia)
我将用一个最小的例子来解释我的问题。假设我有三个文件:
A.jl
module A
export Atype, f
type Atype
end
f = function(x::Atype)
println("f called with A")
end
end #module
B.jl
module B
export Btype, f
type Btype
end
f = function(x::Btype)
println("f called with B")
end
end #module
Main.jl
using A
using B
main = function()
x = Atype()
f(x)
end
main()
这里我有两个版本的f
函数。如果我正确理解多重分派的想法,应该在运行时扣除应该使用哪个版本。因此,我预计 运行 Main.jl 会打印 f called with A
。不幸的是,我得到
$ julia Main.jl
ERROR: type: anonymous: in typeassert, expected Btype, got Atype
in include at /usr/bin/../lib64/julia/sys.so
in process_options at /usr/bin/../lib64/julia/sys.so
in _start at /usr/bin/../lib64/julia/sys.so
while loading /home/grzes/julia_sucks/Main.jl, in expression starting on line 9
如果我注释掉using B
,它工作正常。显然,B.jl 中的 f
覆盖了 A.jl 中的 f
。
那么,问题来了:问题出在哪里?在我的方法中还是在我使用的 Julia 版本 (0.3.7) 中?我怎样才能避免这种情况?
请注意,将 using A
替换为 import A
并使用完全限定名称(例如 A.f
)并不是一个好的解决方案。它与多重调度的症结相矛盾——在编译时我不知道我应该使用 A.f
还是 B.f
.
您必须使 A.f
和 B.f
成为相同的函数(在上面的示例中,它们只是具有相同名称的不同函数)。然后你可以在每个模块中重载一个方法,多个分派将完成它的工作。
实现此目的的方法是让其中一个模块从另一个模块导入函数 f
(例如 import A.f
in B
),然后再使用新方法对其进行扩展,或者添加第三个模块 C
和 A
和 B
都导入的 f
函数(你可以使用像 f(::Union()) = nothing
这样永远不会应用于创建一个函数而不添加任何实际方法)。我们直接从其他模块扩展函数,如
function A.f(x::Atype)
println("f called with A")
end
这会让 Julia 明白这两个 f
指的是同一个概念,它们实际上是两个模块中的同一个对象。添加方法会修改通用函数对象,因此在使用 f
的任何地方都可以看到此更改。
我将用一个最小的例子来解释我的问题。假设我有三个文件:
A.jl
module A
export Atype, f
type Atype
end
f = function(x::Atype)
println("f called with A")
end
end #module
B.jl
module B
export Btype, f
type Btype
end
f = function(x::Btype)
println("f called with B")
end
end #module
Main.jl
using A
using B
main = function()
x = Atype()
f(x)
end
main()
这里我有两个版本的f
函数。如果我正确理解多重分派的想法,应该在运行时扣除应该使用哪个版本。因此,我预计 运行 Main.jl 会打印 f called with A
。不幸的是,我得到
$ julia Main.jl
ERROR: type: anonymous: in typeassert, expected Btype, got Atype
in include at /usr/bin/../lib64/julia/sys.so
in process_options at /usr/bin/../lib64/julia/sys.so
in _start at /usr/bin/../lib64/julia/sys.so
while loading /home/grzes/julia_sucks/Main.jl, in expression starting on line 9
如果我注释掉using B
,它工作正常。显然,B.jl 中的 f
覆盖了 A.jl 中的 f
。
那么,问题来了:问题出在哪里?在我的方法中还是在我使用的 Julia 版本 (0.3.7) 中?我怎样才能避免这种情况?
请注意,将 using A
替换为 import A
并使用完全限定名称(例如 A.f
)并不是一个好的解决方案。它与多重调度的症结相矛盾——在编译时我不知道我应该使用 A.f
还是 B.f
.
您必须使 A.f
和 B.f
成为相同的函数(在上面的示例中,它们只是具有相同名称的不同函数)。然后你可以在每个模块中重载一个方法,多个分派将完成它的工作。
实现此目的的方法是让其中一个模块从另一个模块导入函数 f
(例如 import A.f
in B
),然后再使用新方法对其进行扩展,或者添加第三个模块 C
和 A
和 B
都导入的 f
函数(你可以使用像 f(::Union()) = nothing
这样永远不会应用于创建一个函数而不添加任何实际方法)。我们直接从其他模块扩展函数,如
function A.f(x::Atype)
println("f called with A")
end
这会让 Julia 明白这两个 f
指的是同一个概念,它们实际上是两个模块中的同一个对象。添加方法会修改通用函数对象,因此在使用 f
的任何地方都可以看到此更改。