英文:
Julia Module calling User Defined Function
问题
抱歉,我注意到你要求只翻译代码部分,这是你提供的代码的翻译:
我有一个模块,用于为我想要执行的仿真建立一些抽象级别。假设最低的抽象级别是 `node`(如果我们将其截断为两个抽象级别,我们将其构建为 `system`),它是我在模块中定义的抽象类型的子类型。`node` 使用用户定义的 `update!` 函数进行更新。
我希望用户能够定义一个新的 `node` 和 `update!` 函数,但 `update!` 函数应该可以从模块的 `system_update!` 函数中调用。下面提供了一个示例:
```# 定义模块
module test_pack
abstract type Node end
struct System{N<:Node}
nodes::Array{N,1}
end
function system_update!(s::System)
update!.(s.nodes)
end
export Node, System, system_update!
end
# 导入模块
using Main.test_pack
# 用户定义的类型和函数
mutable struct My_Node<:Node
state
end
function update!(n::My_Node)
n.state *= 2
end
# 定义用户定义节点的系统
sys = System([My_Node(1), My_Node(2)])
# 运行系统
system_update!(sys)
运行此代码会出现以下错误:
ERROR: LoadError: UndefVarError: update! not defined
但是,如果我将 My_Node 和 update! 的定义移至模块内,并导出 My_Node,则代码会执行并返回适当的输出 2,4。
是否有一种方法可以启用我期望的行为,即用户定义类型和 update! 函数,但模块定义的 System 可以调用这些函数?
英文:
I have a module which builds up some levels of abstraction for a simulation I'd like to perform. Let's say the lowest level of abstraction is a node (which we build into systems, if we truncate this at two levels of abstraction), which is a subtype of an abstract type I define in the module. The nodes are updated with a user-defined update! function.
I want the user to be able to define a new node and update! function, but the update! function should be callable from the module's system_update! function. An example is provided below:
module test_pack
abstract type Node end
struct System{N<:Node}
nodes::Array{N,1}
end
function system_update!(s::System)
update!.(s.nodes)
end
export Node, System, system_update!
end
# import module
using Main.test_pack
# User-defined types and functions
mutable struct My_Node<:Node
state
end
function update!(n::My_Node)
n.state *= 2
end
# Define system of user defined nodes
sys = System([My_Node(1), My_Node(2)])
# Run the system
system_update!(sys)
Running this code gives
ERROR: LoadError: UndefVarError: update! not defined
However, if I move the definition of My_Node and update! to within the module and then export My_Node, the code executes and return the appropriate 2,4 output.
Is there a way I can enable the type of behavior I expect, where the user defines the type and update! function, but the module-defined System can call those functions?
答案1
得分: 4
以下是翻译好的部分:
一种实现你想要的方式是,通过这样的方式设置,即由模块定义update! 函数,定义My_Node类型的代码(派生自Node)也定义了一个特定的方法,扩展了update!函数。
在这里,由于没有针对抽象类型Node的参数的update!的默认实现,可以定义一个空的通用函数,仅将函数标记为属于模块,而不提供任何实现。实现TestPack.update!(::My_Node)方法明确扩展了这个函数,通过完全限定的名称引用它。
module TestPack
abstract type Node end
struct System{N<:Node}
nodes::Array{N,1}
end
function update! end
function system_update!(s::System)
update!.(s.nodes)
end
export Node, System, system_update!
end
# 导入模块
using .TestPack
# 用户定义的类型和函数
mutable struct My_Node<:Node
state
end
function TestPack.update!(n::My_Node)
n.state *= 2
end
sys = System([My_Node(1), My_Node(2)])
# 运行系统
system_update!(sys)
上面的代码可以正常运行并产生以下结果:
julia> sys
System{My_Node}(My_Node[My_Node(2), My_Node(4)])
另外,值得一提的是,在Julia中,习惯使用CamelCase表示模块的名称;在上面的示例中,我将你的模块重命名为TestPack,以遵循这个风格约定。
模块也可以被称为using .TestPack而不是using Main.TestPack,这被称为相对模块路径。
英文:
One way of doing what you want would be to set things up in such a way that the update! function is defined by the module, and the code which defines the My_Node type (deriving from Node) also defines a specific method extending the update! function.
Here, since there is no default implementation for update! working on an argument of abstract type Node, an empty generic function can be defined to only mark the function as "belonging" to the module, without providing any implementation.<br/>
The implementation of the TestPack.update!(::My_Node) method explicitly extends this function, referring to it via a fully qualified name.
module TestPack
abstract type Node end
struct System{N<:Node}
nodes::Array{N,1}
end
function update! end
function system_update!(s::System)
update!.(s.nodes)
end
export Node, System, system_update!
end
# import module
using .TestPack
# User-defined types and functions
mutable struct My_Node<:Node
state
end
function TestPack.update!(n::My_Node)
n.state *= 2
end
sys = System([My_Node(1), My_Node(2)])
# Run the system
system_update!(sys)
The code above runs without problem and yields:
julia> sys
System{My_Node}(My_Node[My_Node(2), My_Node(4)])
As an aside, note that it is customary in Julia to use CamelCase notations for the name of modules; in the example above, I renamed your module to TestPack to follow this stylistic convention.
The module can also be referred to as using .TestPack instead of using Main.TestPack; this is called a relative module path.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论