在两个文件中重载一个函数(在 Julia 中)

Posted

技术标签:

【中文标题】在两个文件中重载一个函数(在 Julia 中)【英文标题】:Overloading a function in two files (in Julia) 【发布时间】:2015-07-25 12:50:46 【问题描述】:

我将用一个最小的例子来解释我的问题。假设我有三个文件:

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

【问题讨论】:

【参考方案1】:

您必须使A.fB.f 具有相同的功能(在上面的示例中,它们只是具有相同名称的不同功能)。然后,您可以在每个模块中重载一个方法,并且多个分派将完成其工作。

实现这一点的方法是让一个模块从另一个模块导入函数f(例如B 中的import A.f),然后用新方法扩展它,或者添加第三个模块@987654326 @ 带有 AB 导入的 f 函数(您可以使用像 f(::Union()) = nothing 这样的虚拟签名,它在不添加任何实际方法的情况下永远适用于创建函数)。我们直接从其他模块扩展功能,如

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

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

【讨论】:

这是否意味着“通用函数”有自己的范围?例如,A.f() 是一个仅在模块 A 范围内通用的函数? 为我工作,谢谢!但是我花了一段时间才注意到我应该使用 importall C 而不是 using C :) 绑定有范围,而不是值(对象)。泛型函数是一个(可变)值,本质上不属于任何范围。但是,如果您尝试将方法添加到当前作用域中不存在的函数 f,则 Julia 将隐式创建一个新的泛型函数对象,并在当前作用域中以名称 f 为其创建绑定.但是如果你将它导入另一个模块,它就和原来的模块一样。 请使用特定的导入(例如import A.f)而不是importall,它往往会避免一些意想不到的副作用。或者直接用A.f(x) = ...扩展例如A.f

以上是关于在两个文件中重载一个函数(在 Julia 中)的主要内容,如果未能解决你的问题,请参考以下文章

从两个角度理解为什么 JS 中没有函数重载

如何实现JS函数的重载

函数重载的使用

如何手动实现在python中添加整数的函数重载?

java函数重载

C++运算符重载函数作为友元函数