了解如何扩展 Julia 模块
Understanding how Julia modules can be extended
我很难理解如何在 Julia 中扩展模块。具体来说,我想创建自己的 LinearAlgebra
矩阵,其父 class 是 AbstractMatrix{T}
并实现其类似于 Diagonal
或 UpperTriangular
矩阵的功能在实际的 LA 包中实现。如果我真的可以将我的矩阵添加到原始包中,那么我会的,但现在我满足于创建我自己的 MyLinearAlgebra
包,它只导入原始包并对其进行扩展。这是我目前在 MyLinearAlgebra.jl
中得到的:
module MyLinearAlgebra
import LinearAlgebra
import Base: getindex, setindex!, size
export
# Types
LocalMatrix,
SolutionVector,
# Functions
issymmetric,
isdiag
# Operators
# Constants
include("SolutionVector.jl")
include("LocalMatrix.jl")
end
现在只关注 LocalMatrix.jl
,我有:
"""
struct LocalMatrix{T} <: AbstractMatrix{T}
Block diagonal structure for local matrix. `A[:,:,s,iK]` is a block matrix for
state s and element iK
"""
struct LocalMatrix{T} <: AbstractMatrix{T}
data::Array{T,4}
function LocalMatrix{T}(data) where {T}
new{T}(data)
end
end
[... implement size, getindex, setindex! ... all working perfectly]
"""
issymmetric(A::LocalMatrix)
Tests whether a LocalMatrix is symmetric
"""
function issymmetric(A::LocalMatrix)
println("my issymmetric")
all(LinearAlgebra.issymmetric, [@view A.data[:,:,i,j] for i=1:size(A.data,3), j=1:size(A.data,4)])
end
"""
isdiag(A::LocalMatrix)
Tests whether a LocalMatrix is diagonal
"""
function isdiag(A::LocalMatrix)
println("my isdiag")
all(LinearAlgebra.isdiag, [@view A.data[:,:,i,j] for i=1:size(A.data,3), j=1:size(A.data,4)])
end
当我尝试 运行 然而,我得到
error in method definition: function LinearAlgebra.isdiag must be explicitly imported to be extended
好的,没问题,我可以将定义改为 function LinearAlgebra.isdiag()
,它可以工作。但是如果我也将另一个函数的定义更改为 function LinearAlgebra.issymmetric()
和 运行 一个简单的测试我现在得到错误
ERROR: MethodError: no method matching issymmetric(::MyLinearAlgebra.LocalMatrix{Float64})
所以我很难过。显然我有一个让我现在继续工作的解决方法,但我一定只是误解了 Julia 模块的工作方式,因为我似乎无法区分这两个函数。为什么需要显式扩展?为什么另一个不能?在这种情况下,它们之间的区别是什么?扩展包模块的正确方法是什么?感谢您的帮助。
您需要明确声明您正在向现有函数添加新方法,因此它应该是:
function LinearAlgebra.issymmetric(A::LocalMatrix)
...
end
function LinearAlgebra.isdiag(A::LocalMatrix)
...
end
您收到错误的最可能原因是您忘记在测试包的代码中导入 LinearAlgebra
。
请注意,您的构造函数也应更正:
struct LocalMatrix{T} <: AbstractMatrix{T}
data::Array{T,4}
function LocalMatrix(data::Array{T,4}) where {T}
new{T}(data)
end
end
使用当前的构造函数,您需要编写 LocalMatrix{Float64}(some_arr)
而不是简单的 LocalMatrix(some_arr)
。更糟糕的是,如果您为构造函数提供一个 3 维数组,则会出现类型转换错误,而当您使用我建议的语法时,会得到 no method matching LocalMatrix(::Array{Int64,3})
,这对于您的库的用户来说更具可读性。
我很难理解如何在 Julia 中扩展模块。具体来说,我想创建自己的 LinearAlgebra
矩阵,其父 class 是 AbstractMatrix{T}
并实现其类似于 Diagonal
或 UpperTriangular
矩阵的功能在实际的 LA 包中实现。如果我真的可以将我的矩阵添加到原始包中,那么我会的,但现在我满足于创建我自己的 MyLinearAlgebra
包,它只导入原始包并对其进行扩展。这是我目前在 MyLinearAlgebra.jl
中得到的:
module MyLinearAlgebra
import LinearAlgebra
import Base: getindex, setindex!, size
export
# Types
LocalMatrix,
SolutionVector,
# Functions
issymmetric,
isdiag
# Operators
# Constants
include("SolutionVector.jl")
include("LocalMatrix.jl")
end
现在只关注 LocalMatrix.jl
,我有:
"""
struct LocalMatrix{T} <: AbstractMatrix{T}
Block diagonal structure for local matrix. `A[:,:,s,iK]` is a block matrix for
state s and element iK
"""
struct LocalMatrix{T} <: AbstractMatrix{T}
data::Array{T,4}
function LocalMatrix{T}(data) where {T}
new{T}(data)
end
end
[... implement size, getindex, setindex! ... all working perfectly]
"""
issymmetric(A::LocalMatrix)
Tests whether a LocalMatrix is symmetric
"""
function issymmetric(A::LocalMatrix)
println("my issymmetric")
all(LinearAlgebra.issymmetric, [@view A.data[:,:,i,j] for i=1:size(A.data,3), j=1:size(A.data,4)])
end
"""
isdiag(A::LocalMatrix)
Tests whether a LocalMatrix is diagonal
"""
function isdiag(A::LocalMatrix)
println("my isdiag")
all(LinearAlgebra.isdiag, [@view A.data[:,:,i,j] for i=1:size(A.data,3), j=1:size(A.data,4)])
end
当我尝试 运行 然而,我得到
error in method definition: function LinearAlgebra.isdiag must be explicitly imported to be extended
好的,没问题,我可以将定义改为 function LinearAlgebra.isdiag()
,它可以工作。但是如果我也将另一个函数的定义更改为 function LinearAlgebra.issymmetric()
和 运行 一个简单的测试我现在得到错误
ERROR: MethodError: no method matching issymmetric(::MyLinearAlgebra.LocalMatrix{Float64})
所以我很难过。显然我有一个让我现在继续工作的解决方法,但我一定只是误解了 Julia 模块的工作方式,因为我似乎无法区分这两个函数。为什么需要显式扩展?为什么另一个不能?在这种情况下,它们之间的区别是什么?扩展包模块的正确方法是什么?感谢您的帮助。
您需要明确声明您正在向现有函数添加新方法,因此它应该是:
function LinearAlgebra.issymmetric(A::LocalMatrix)
...
end
function LinearAlgebra.isdiag(A::LocalMatrix)
...
end
您收到错误的最可能原因是您忘记在测试包的代码中导入 LinearAlgebra
。
请注意,您的构造函数也应更正:
struct LocalMatrix{T} <: AbstractMatrix{T}
data::Array{T,4}
function LocalMatrix(data::Array{T,4}) where {T}
new{T}(data)
end
end
使用当前的构造函数,您需要编写 LocalMatrix{Float64}(some_arr)
而不是简单的 LocalMatrix(some_arr)
。更糟糕的是,如果您为构造函数提供一个 3 维数组,则会出现类型转换错误,而当您使用我建议的语法时,会得到 no method matching LocalMatrix(::Array{Int64,3})
,这对于您的库的用户来说更具可读性。