我在 Julia 模块中编写了以下算法
module two_algo
export two
function two(type)
a = construct(type)
b = construct(type)
result = construct(type)
unity(a)
unity(b)
add(a,b,result)
return result
end
end
有一次我在模块外定义了这个算法,它可以编译并可以分派到任何定义了构造、统一和添加方法的类型。但是在一个模块中它不会编译。它不知道如何找到构造、统一和添加。我不想从某个特定模块导入它们,因为我可能有许多模块,例如每个模块都定义了构造、统一和添加。我需要做什么才能编译它?在我过去的 C/C++ 时代,我记得做过一些像声明“extern 构造”这样简单的事情。模块内。我真的希望我可以让 two() 函数采用单一类型,而不是传入实现构造、统一和添加的函数。理想情况下,我也想避免泛型。感谢您的指点。
答案 0 :(得分:1)
首先,让我说您可能不需要这里的模块:将您的项目组织在单独的文件中(以便您轻松地在源代码中导航)可能是一个好主意,但是拥有单独的模块会带来一些复杂性,这可能会此处不需要(例如,不存在需要使用单独模块/命名空间来避免的名称冲突风险)。
话虽如此,这里组织事物的一种方法是使辅助函数(如 unity
或 add
)与使用它们的通用算法属于同一个模块。这是一个最小的例子:
module Algo
export algo
# These functions are only declared; they have no method
function unity end
function add end
function algo(T)
a = unity(T)
add(a, a)
end
end
定义新类型的代码的其他部分然后必须扩展模块中的函数以添加特定方法:
using .Algo
struct MyType
val :: Int
end
# Explicitly extend the `unity` and `add` function from module `Algo`
# (instead of merely defining new functions with the same name
Algo.unity(::Type{MyType}) = MyType(1)
Algo.add(a::MyType, b::MyType) = MyType(a.val + b.val)
这应该按预期工作:
julia> Algo.algo(MyType)
MyType(2)
编辑:一个更复杂的组织允许通过在“基本”模块中声明泛型函数来将所有算法(也可能是所有类型)相互隔离,所有其他模块都知道关于:
module AlgoBase
export unity, add
function unity end
function add end
end
module Algo1
using ..AlgoBase # allows using unity and add
export algo1
function algo1(T)
a = unity(T)
add(a, a)
end
end
module Types1
using ..AlgoBase
export Type1
struct Type1
val :: Int
end
# Explicitly extend the `unity` and `add` function from module `AlgoBase`
# (instead of merely defining new functions with the same name
AlgoBase.unity(::Type{Type1}) = Type1(1)
AlgoBase.add(a::Type1, b::Type1) = Type1(a.val + b.val)
end
using .Algo1
using .Types1
algo1(Type1)
这或多或少是 Julia 生态系统的整个部分的设计方式,多个包协作提供与给定领域相关的算法,而不必相互依赖:它们只需要了解一个“基础”包(例如 StatsBase
,它声明了许多有用的构建块,类型可以实现,算法可以使用)。然而,这样的架构通常用于使整个(和不相关的)包协作,即不是真正以单个包内的子模块的规模。赞一个
答案 1 :(得分:0)
这是对弗朗索瓦回答的轻微修改,解决了我的问题。我仍然接受他的回答,因为他做了大部分的发现和工作。
module UnityBase
export unity
function unity end
end
module AddBase
export add
function add end
end
module TwoAlgo
using ..UnityBase, ..AddBase
export two
function two(T)
a = unity(T)
add(a, a)
end
end
module MyTypeMod
using ..AddBase, ..UnityBase
export MyType
struct MyType
val :: Int
end
UnityBase.unity(::Type{MyType}) = MyType(1)
AddBase.add(a::MyType, b::MyType) = MyType(a.val + b.val)
end
using .TwoAlgo
using .MyTypeMod
println(two(MyType))