我正在尝试在Julia中为具有三个元素的向量定义类型(结构?)。我认为我找到的最接近Optimally passing dimensions of fixed size array in julia和Declare the size of an array attribute in a type definition的东西,但是它们是0.6之前的版本,因为不可变不再是一回事。而且,这似乎是错误的。
用例是我知道函数要使用的向量的大小
function myFunc(v::threeVec,u::threeVec)
Do stuff to u and v
end
进一步的搜索使我想到了构造函数。 https://docs.julialang.org/en/stable/manual/constructors/ 我特别看到了例子
struct OrderedPair
x::Real
y::Real
OrderedPair(x,y) = x > y ? error("out of order") : new(x,y)
end
但是,这是一个单独的对象,即使这样,我也不确定如何将类似的东西传递给函数。我考虑改用三元组,因为它们的类型为Tuple(Int,Int,Int),但是我要对u和v进行矢量/矩阵算术运算,所以我不必转换它们。
我可以在函数内部检查向量的长度,但是我读到一些提示,由于调度程序的原因,它首选使用类型。对于此特定功能,在这种情况下,这是一种合理的实现方式,但是在其他用例中,这可能不是一个好主意,因此我现在想以“正确的方式”来实现。
答案 0 :(得分:2)
有很多方法可以处理这种情况;我将根据您提供的想法在下面概述其中一些。
StaticArrays.jl软件包提供对定长数组的支持。
using StaticArrays
const ThreeVec{T} = SVector{3,T}
function myFunc(u::ThreeVec, v::ThreeVec)
u .+ v # example functionality
end
仅当两个参数的长度均为3的myFunc
时,此实现才允许调用SVector
。
julia> myFunc(SVector(1, 2, 3), SVector(4, 5, 6))
3-element SArray{Tuple{3},Int64,1,3}:
5
7
9
julia> myFunc(SVector(1, 2, 3), SVector(4, 5))
ERROR: MethodError: no method matching myFunc(::SArray{Tuple{3},Int64,1,3}, ::SArray{Tuple{2},Int64,1,2})
Closest candidates are:
myFunc(::SArray{Tuple{3},T,1,3} where T, ::SArray{Tuple{3},T,1,3} where T) at REPL[13]:2
还可以使用内部构造函数定义自定义类型,以断言长度正确。但是,除了潜在的低效率之外,这还要求您重载各种方法来支持StaticArrays已处理的自定义类型。
取决于您计划执行的向量/矩阵算术运算,元组可能已经可以通过广播原生支持该功能。例如,尽管不能添加元组,但是可以在其元素上广播添加。
julia> u = (1, 2, 3);
v = (4, 5, 6);
julia> u + v # not allowed
ERROR: MethodError: no method matching +(::Tuple{Int64,Int64,Int64}, ::Tuple{Int64,Int64,Int64})
Closest candidates are:
+(::Any, ::Any, ::Any, ::Any...) at operators.jl:502
Stacktrace:
[1] top-level scope at none:0
julia> u .+ v # element-wise broadcasting
(5, 7, 9)
如果您想对内置Vector
类型进行操作,则只要输入无效就可以抛出错误,将错误处理从编译转移到运行时。
function myFunc(u::Vector, v::Vector)
length(u) == 3 || throw(ArgumentError("Invalid length of (u = $u), should be 3"))
length(v) == 3 || throw(ArgumentError("Invalid length of (v = $v), should be 3"))
u .+ v # example functionality
end