Julia:为特定大小的向量创建类型

Ner*_*ris 6 types vector julia

我正在尝试在 Julia 中为具有三个元素的向量定义类型(结构?)。我认为我发现的最接近的事情是在 julia 中优化传递固定大小数组的维度在类型定义中声明数组属性的大小,但是这些是 0.6 之前的,因为不可变不再是一回事。而且,这似乎是错误的。

用例是我知道我的函数将采用并想要的向量的大小

function myFunc(v::threeVec,u::threeVec)
    Do stuff to u and v
end
Run Code Online (Sandbox Code Playgroud)

进一步的搜索使我成为了构造函数。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
Run Code Online (Sandbox Code Playgroud)

然而,这是一个单独的对象,即使那样,我也不确定如何将类似的东西传递给函数。我考虑使用三元组,因为它们的类型为 Tuple(Int,Int,Int) 但是我将在 u 和 v 上进行向量/矩阵算术,所以我不必转换它们。

我可以在函数内部检查向量长度,但我在提示中读到,由于调度程序,它更喜欢您为此使用类型。对于这个特定的功能,在这种情况下这是一种合理的做法,但在其他用例中,这可能不是一个好主意,所以我现在想以“正确的方式”来做。

Har*_*din 7

有很多方法可以处理这种类型的场景;我将根据您提供的想法在下面概述其中的一些。

选项 1:静态数组

所述StaticArrays.jl包提供了固定长度的阵列的支持。

using StaticArrays
const ThreeVec{T} = SVector{3,T}

function myFunc(u::ThreeVec, v::ThreeVec)
    u .+ v  # example functionality
end
Run Code Online (Sandbox Code Playgroud)

myFunc仅当两个参数SVector的长度均为3时才允许调用此实现。

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
Run Code Online (Sandbox Code Playgroud)

也可以使用内部构造函数定义自定义类型来断言长度是正确的。但是,除了潜在的低效率之外,这还需要您重载各种方法来支持您的自定义类型,StaticArrays 已经处理了这些方法。

选项 2:元组

根据您计划执行的向量/矩阵算法,元组可能已经通过广播本地支持该功能。例如,虽然不能添加元组,但可以通过它们的元素广播添加。

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)
Run Code Online (Sandbox Code Playgroud)

选项 3:运行时错误

如果您想对内置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
Run Code Online (Sandbox Code Playgroud)