# How to generate independent vectors via for-loop?

At a point in my real code, I want to generate a number of independent vectors based on parameter `N`(which is calculated at a certain point in the code). For example, if `N=3`, then I need to generate the following vectors:

``````vector_1 = [0,0];
vector_2 = [0,0,0];
vector_3 = [0,0,0,0];
``````

So, I tried to write something like below. However, there are two problems:
1- Syntax of `vector_"\$i"` gives error . How to write the correct syntax?
2- Assuming the syntax is correct, an error is given at `S = vector_"\$i"` since the vectors are not seen out of the `for-loop` scope. How to make the generated vectors seen out of `for-loop` scope?

``````function dd()
N =3;
for i = 1:N
vector_"\$i" = zeros(i+1); # gives `ERROR: UndefVarError: @vector__str not defined`
end
S = vector_1; # gives `ERROR: UndefVarError: vector_1 not defined`
end
dd()

``````

Store these vectors in a dictionary. Don’t try to make them variables.

``````function dd()
N = 3
out Dict()
for i = 1:N
out[i] = zeros(i + 1)
end
return out
end

vector_dict = dd()
``````
3 Likes

or a vector of vectors

``````julia> vectors = Vector{Int}[]
for i in 1:3
push!(vectors, zeros(i))
end

julia> vectors
3-element Vector{Vector{Int64}}:

[0, 0]
[0, 0, 0]
``````

(also I would recommend typing the `Dict`, if the case `Dict{Int,Vector{Int}}(()`:

``````julia> d = Dict{Int,Vector{Int}}()
Dict{Int64, Vector{Int64}}()

julia> for i in 1:3
d[i] = zeros(i)
end

julia> d
Dict{Int64, Vector{Int64}} with 3 entries:
2 => [0, 0]
3 => [0, 0, 0]
1 => 
``````
2 Likes

Or even as a tuple

``````julia> ntuple(i->zeros(i+1), 3)
([0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0])
``````

You can dynamically generate variables using `eval`, but they will necessarily live in global scope. Don’t do it. Seriously. It leads to hard to read and reason about code, and a cluttered global namespace. Nevertheless:

``````julia> for i = 1:N
var = Symbol("vector_\$i")
eval( :( \$var = zeros(\$i+1) ));
end

julia> vector_1
2-element Vector{Float64}:
0.0
0.0

julia> vector_2
3-element Vector{Float64}:
0.0
0.0
0.0
``````
1 Like

Thanks for your comment. The issue here is that I need to connect the generated vectors to other ones (which are changing in time-domain loop. For example, `vectors = @view(D[:])`. However, a change in `D` will not be updated in `vectors`/

``````D = [55,69];
vectors = Vector{Int}[]
for i in 1:3
push!(vectors, zeros(i))
end

vectors = @view(D[:]);
D = 77;
julia> vectors
3-element Vector{Vector{Int64}}:

[55, 69]
[0, 0, 0]
``````

Thank you very much for your note. Can I restrict the generated vectors to be ONLY in scope of dd() function?

``````function dd()
N=3
for i = 1:N
var = Symbol("vector_\$i")
eval( :( \$var = zeros(\$i+1) ));
end
end

dd()
``````

That’s because `vectors` is of type `Vector{Vector{Int}}` whereas `@view(D[:])` is a subarray. Upon assignment `vector = @view(D[:])` a conversion to the former type, i.e. an implicit copy is made.
You could widen the container type

``````julia> vectors = AbstractVector{Int}[]

julia> for i in 1:3
push!(vectors, zeros(i))
end

julia> vectors
3-element Vector{AbstractVector{Int64}}:

[0, 0]
[0, 0, 0]

julia> vectors = @view(D[:]);

julia> vectors
3-element Vector{AbstractVector{Int64}}:

[55, 69]
[0, 0, 0]

julia> vectors
2-element view(::Vector{Int64}, :) with eltype Int64:
55
69

julia> D = 77
77

julia> vectors
3-element Vector{AbstractVector{Int64}}:

[77, 69]
[0, 0, 0]
``````
3 Likes

No, that’s what I stated. `eval` evaluates an expression in the global scope of the module.

1 Like

IMHO this should just error.

1 Like

Thank you very much!
From a performance point of view, Do the values of vectors are allocated in order in memory (column-major)? In other words, do working on the vector `vector_2` is the same as on `vectors`?

``````vector_1 = [0,0];
vector_2 = [0,0,0];
vector_3 = [0,0,0,0];

``````

Performance-wise this will be quite bad in general, because you are handling a container with an abstract type.

If you need performance there you probably want something else, and this becomes a xy problem.

2 Likes

Yes, they form a concrete vector. Accessing `vectors` is bad performance-wise because of the abstract container type. If you can live with that depends on the kind of work and how much indexing is done. Using a function barrier might be sufficient to make the overhead from the type instability due to indexing into `vectors` negligible.

2 Likes

Another option if you know how many you want at compile time:

``````sizes = (2,3,4)
Base.Cartesian.@nexprs 3 j->vector_j = zeros(sizes[j])
``````

Now the variables `vector_1`, `vector_2`, and `vector_3` exist with the sizes you have asked for.

3 Likes

I am sorry if I could not deliver my point clearly from the beginning.
Thanks for pointing this out. I will be more precise and accurate next times to make the discussion more productive.
From a performance point of view, can you recommend someting?

That depends a lot on the performance of what. It is not possible to answer that without further information.

1 Like