【问题标题】:Understanding how Julia modules can be extended了解如何扩展 Julia 模块
【发布时间】:2020-08-07 22:16:12
【问题描述】:

我很难理解如何在 Julia 中扩展模块。具体来说,我想创建自己的LinearAlgebra 矩阵,其父类为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

但是,当我尝试运行它时,我得到了

方法定义错误:必须显式导入函数 LinearAlgebra.isdiag 才能扩展

好的,没问题,我可以将定义更改为function LinearAlgebra.isdiag(),它可以工作。但是,如果我还将另一个函数的定义更改为 function LinearAlgebra.issymmetric() 并运行一个简单的测试,我现在会得到错误

错误:MethodError:没有方法匹配 issymmetric(::MyLinearAlgebra.LocalMatrix{Float64})

所以我很难过。显然我有一个解决方法可以让我现在继续工作,但我一定只是误解了 Julia 模块的工作原理,因为我似乎无法区分这两个函数。为什么需要显式扩展?为什么其他不能?在这种情况下,他们之间甚至有什么区别?这里扩展包模块的正确方法是什么?感谢您的帮助。

【问题讨论】:

    标签: module julia linear-algebra


    【解决方案1】:

    您需要明确声明您正在向现有函数添加新方法,因此它应该是:

    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-d 数组,你会得到一个类型转换错误,而当你使用我建议的语法时,会得到no method matching LocalMatrix(::Array{Int64,3}),这对于你的库的用户来说更具可读性。

    【讨论】:

    • 所以在测试这个库的任何代码中,我都必须显式导入LinearAlgebraMyLinearAlgebra 才能使用我编写的函数之一?进口不是从进口我的“结转”而来的吗?
    • 并且要清楚你的建议也完全等同于在我的模块定义中写import LinearAlgebra: isdiag,同时保持函数定义相同?
    • 你需要在测试代码中导入什么取决于你测试什么。但是,一个高质量的包应该包含对其所有方法的测试,因此我希望您的测试文件包含using LinearAlgrbra 行。关于import - Julia 中的标准通常是使用using 而不是导入(从包中导入单个函数是 Pytonish 编写代码的方式,而不是 Julian)。导入单个方法以重载将起作用,但不是 Julian 风格。
    猜你喜欢
    • 2021-06-19
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多