# Best Practice for Initializing an Array Prior to for Loop

**URL:** https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502
**Category:** New to Julia
**Tags:** question, loops
**Created:** [October 16, 2020, 5:01pm UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502 "2020-10-16T17:01:33Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![highflyer737](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@highflyer737](https://discourse.julialang.org/u/highflyer737)
#### Post date: [October 16, 2020, 5:01pm UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502/1 "2020-10-16T17:01:33Z")

</div>

Hello,

Is there a best practice for initializing arrays prior to for loops / does it matter? (I’ve seen a few similar posts but I don’t think there’s any that _explain_ the differences, or when you might want to use one method or the other.)

E.g. is there a difference between, say:

a = fill(0.0, 10)

and

a = Vector{Float64}(undef, 10)

prior to, something like:

for i in eachindex(a)  
a[i] = _some calculation_  
end

Thanks,

Dave

---

<div class="post-metadata">

### Author: ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)
#### Post date: [October 16, 2020, 5:12pm UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502/2 "2020-10-16T17:12:02Z")

</div>

I typically use `zeros(dims...)`, which takes a bit longer than `undef`, but allows simpler control flow when doing, e.g., `a[i] += <some calculation>`. For simple calculations, I’ll use array comprehensions:

```julia
a = [<some calculation> for i in 1:10]

```

For more-complicated calculations, you can use `map` with a `do`-block:

```julia
a = map(1:10) do aᵢ
    <some calculation>
end

```

Comprehension/`map`-ing has an additional advantage: it determines the output’s eltype and shape for you, which is great for some of Julia’s messier parametric types - who wants to type `Array{MArray{Tuple{3}, Float64, 1, 3}}(undef, 10)`?

---

<div class="post-metadata">

### Author: ![jonathanBieler](https://avatars.discourse-cdn.com/v4/letter/j/82dd89/32.png) [@jonathanBieler](https://discourse.julialang.org/u/jonathanBieler)
#### Post date: [October 16, 2020, 6:18pm UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502/3 "2020-10-16T18:18:31Z")

</div>

When using `fill` you’ll go over the whole array in memory fill that with your value, which takes more time. It doesn’t matter for small arrays but for large ones it can be significant :

```julia
julia> @time Vector{Float64}(undef, 100_000_000);
  0.000017 seconds (2 allocations: 762.940 MiB)

julia> @time fill(0.0, 100_000_000);
  0.229996 seconds (2 allocations: 762.940 MiB)

```

(not sure why the allocation numbers are the same?)

The downside of `Vector` is that your array will be filled with random numbers (whatever is in memory), so if you use these values by mistakes it can lead to hard to find bugs.

Personally I use `Vector` mainly when I have a vector of object more complicated that numbers that I don’t wand to initialize yet (e.g. `Array{Matrix,1}(undef, 20)`)

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [October 16, 2020, 8:08pm UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502/4 "2020-10-16T20:08:18Z")

</div>

One disadvantage of using `fill` is that the array is filled _with the same object_, compared to an comprehension which fills it with _distinct objects_:

```julia
julia> mutable struct example f::Int end

julia> a = fill(example(1), 3)
3-element Array{example,1}:
 example(1)
 example(1)
 example(1)

julia> b = [example(1) for _ in 1:3]
3-element Array{example,1}:
 example(1)
 example(1)
 example(1)

julia> a[1] === a[2]
true

julia> b[1] === b[2]
false

julia> a[1].f = 3
3

julia> a
3-element Array{example,1}:
 example(3)
 example(3)
 example(3)

julia> b[1].f = 3
3

julia> b
3-element Array{example,1}:
 example(3)
 example(1)
 example(1)

```

This is because the expression in the comprehension is evaluated for each loop iteration, whereas the argument to `fill` is only evaluated once (before the call).

* * *

As for best practice - each version has its (dis)advantages, so whichever version suits the representation of your problem best. I usually go with comprehensions if the initialization is a long piece of code (which I then put into its own function). When all the function does is initializer an array, I usually either go with the `undef` version if the initialitization is a little bit more complicated and with `zeros` if I was going to start with zeroing the memory anyway.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [October 16, 2020, 8:12pm UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502/5 "2020-10-16T20:12:51Z")

</div>

> [@jonathanBieler](#):
>
> (not sure why the allocation numbers are the same?)

The allocation numbers are the same because in both cases, only the backing memory is allocated. Each Float64 is 8 byte and 800\_000\_000 byte === 762.940 MiB.

---

<div class="post-metadata">

### Author: ![aachener](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aachener/32/18112_2.png) [@aachener](https://discourse.julialang.org/u/aachener)
#### Post date: [October 18, 2020, 1:00am UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502/6 "2020-10-18T01:00:30Z")

</div>

Thanks for the explanation.

I tried your code on my machine using julia 1.5.2, the following result is interesting.

Why initiating the array using undef is much slower than using Float64?

```julia
julia> @time Vector(undef,10^8);
  0.366178 seconds (2 allocations: 762.940 MiB, 11.75% gc time)

julia> @time Vector{Float64}(undef,10^8);
  0.072459 seconds (2 allocations: 762.940 MiB, 97.68% gc time)

julia> @time fill(0.0,10^8);
  0.481662 seconds (2 allocations: 762.940 MiB, 14.65% gc time)

```

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [October 18, 2020, 1:03am UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502/7 "2020-10-18T01:03:20Z")

</div>

> [@aachener](#):
>
> `Vector(undef,10^8)`

this is an `Array{Any,1}`, with elements undefined.

---

<div class="post-metadata">

### Author: ![BrunoVasco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brunovasco/32/16742_2.png) [@BrunoVasco](https://discourse.julialang.org/u/BrunoVasco)
#### Post date: [April 16, 2021, 4:32pm UTC](https://discourse.julialang.org/t/best-practice-for-initializing-an-array-prior-to-for-loop/48502/8 "2021-04-16T16:32:57Z")

</div>

Array comprehensions are generally the most elegant solutions in julia. Its easy to not think about them when we are thinking in for loops and sequential steps and things that we would have done to make it work in Fortran or C… but julia was made to work better with things like that.  
Sometimes I forget, but thanks @stillyslalom for helping me remeber it!

`a = [<some calculation> for i in 1:10]`

Thats a hell of an one-liner!
