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()

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, 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 => [0]

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

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[2] = @view(D[:]). However, a change in D will not be updated in vectors[2]/

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

vectors[2] = @view(D[:]);
D[1] = 77;
julia> vectors
3-element Vector{Vector{Int64}}:
 [0]
 [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[2] = @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, 0]

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

julia> vectors
3-element Vector{AbstractVector{Int64}}:
 [0]
 [55, 69]
 [0, 0, 0]

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

julia> D[1] = 77
77

julia> vectors
3-element Vector{AbstractVector{Int64}}:
 [0]
 [77, 69]
 [0, 0, 0]

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

IMHO this should just error.

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

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.

Yes, they form a concrete vector. Accessing vectors[2] 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.

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.

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.