了解如何扩展 Julia 模块

Understanding how Julia modules can be extended

我很难理解如何在 Julia 中扩展模块。具体来说,我想创建自己的 LinearAlgebra 矩阵,其父 class 是 AbstractMatrix{T} 并实现其类似于 DiagonalUpperTriangular 矩阵的功能在实际的 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}),这对于您的库的用户来说更具可读性。