Although the suggestion above is of course valid, I think it is not a common pattern (please Elrod correct me if I’m wrong), because:
-
That function specializes for every len
. Thus, if the lengths of your arrays are changing frequently in your code, that will cause dynamic dispatch to kick in (every time you call the function with a different len it will call a different method of the function). In these cases using static arrays may not be worthwhile anyway.
-
Most commonly the length of the array you want to create can be deduced from some of the input parameters of your function. For example, this is more common:
julia> f(x::T) where T = x + rand(T)
f (generic function with 1 method)
julia> x = SVector{3,Float64}(1,1,1)
3-element SVector{3, Float64} with indices SOneTo(3):
1.0
1.0
1.0
julia> @btime f($x)
10.620 ns (0 allocations: 0 bytes)
3-element SVector{3, Float64} with indices SOneTo(3):
1.9554100262060785
1.1736294084146963
1.5112265205467528
You don’t need to specify explicitly the size of the random vector that is being created inside, because you know that it has to be of the same size as x
. And if x
is a static array, the random vector will have the same type.
As you see, in the example above there is no “uninitialized” array, the rand(T)
creates the random vector, which is added to x
. There are may ways (which do not solve all problems, but many of them), to build these arrays, for example, using ntuples:
julia> g(x::SVector{N,T}) where {N,T} = x + SVector{N,T}(ntuple(i -> 2*i, N))
g (generic function with 1 method)
julia> x = SVector{3,Int}(1,1,1)
3-element SVector{3, Int64} with indices SOneTo(3):
1
1
1
julia> @btime g($x)
0.022 ns (0 allocations: 0 bytes)
3-element SVector{3, Int64} with indices SOneTo(3):
3
5
7
Here x
is being added to a static vector of the same type, but which is constructed from a n-tuple. Since N
is the length of the ntuple and is a parameter of the type of x
, it is known at compile time as well, and the function specializes to it.
With the do
syntax you can build pretty complicated arrays with that:
julia> function h(x::SVector{N,T}) where {N,T}
y = ntuple(N) do i
if i == 1
zero(T)
else
10*i*rand(T)
end
end
return x + SVector{N,T}(y)
end
h (generic function with 1 method)
julia> x = zeros(SVector{5,Float64});
julia> @btime h($x)
21.608 ns (0 allocations: 0 bytes)
5-element SVector{5, Float64} with indices SOneTo(5):
0.0
2.4393119543628927
8.108974913748623
37.62484099830813
13.538314396037276