在两个文件中重载一个函数(在 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.fB.f 成为相同的函数(在上面的示例中,它们只是具有相同名称的不同函数)。然后你可以在每个模块中重载一个方法,多个分派将完成它的工作。

实现此目的的方法是让其中一个模块从另一个模块导入函数 f(例如 import A.f in B),然后再使用新方法对其进行扩展,或者添加第三个模块 CAB 都导入的 f 函数(你可以使用像 f(::Union()) = nothing 这样永远不会应用于创建一个函数而不添加任何实际方法)。我们直接从其他模块扩展函数,如

function A.f(x::Atype)
    println("f called with A")
end

这会让 Julia 明白这两个 f 指的是同一个概念,它们实际上是两个模块中的同一个对象。添加方法会修改通用函数对象,因此在使用 f 的任何地方都可以看到此更改。