# Unexpected additional behavior when using zip to construct NamedTuple

**URL:** <https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623>\
**Category:** General Usage\
**Created:** [June 13, 2024, 9:09pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623 "2024-06-13T21:09:34Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![duzaichuan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/duzaichuan/32/206666_2.png) [@duzaichuan](https://discourse.julialang.org/u/duzaichuan)\
**Post date:** [June 13, 2024, 9:09pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623/1 "2024-06-13T21:09:34Z")

</div>

Hi, I use Julia1.10.4 in Archlinux.  
I try to use zip to dynamically create a named tuple, like this

```julia
test = (; zip((:a, :b), fill(zeros(3), 2))...)

=> (a=[0.0, 0.0, 0.0], b=[0.0, 0.0, 0.0])

```

However, very strange, when I make a change to the `a` filed, the `b` is also altered unexpectedly!

```julia
test.a[1] = 1.0

=> (a=[1.0, 0.0, 0.0], b=[1.0, 0.0, 0.0])

```

Is this a feature of zip or simply a bug? Found this really confusing.

If I do the named tuple construction manually instead of using zip, I get `(a=[1.0, 0.0, 0.0], b=[0.0, 0.0, 0.0])`, which is what I am expecting.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [June 13, 2024, 9:27pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623/2 "2024-06-13T21:27:36Z")

</div>

The issue is coming from `fill` which doesn’t instantiate copies, but fills the container with references to the same input object.

```julia
julia> x = fill(zeros(3),2)
2-element Vector{Vector{Float64}}:
 [0.0, 0.0, 0.0]
 [0.0, 0.0, 0.0]

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

julia> x[1][1] = 1.0
1.0

julia> x
2-element Vector{Vector{Float64}}:
 [1.0, 0.0, 0.0]
 [1.0, 0.0, 0.0]

```

You can get the expected behavior with `map`

```julia
julia> test = (; zip((:a, :b), map(_ -> zeros(3), 1:2))...)
(a = [0.0, 0.0, 0.0], b = [0.0, 0.0, 0.0])

julia> test.a[1] = 1.0
1.0

julia> test
(a = [1.0, 0.0, 0.0], b = [0.0, 0.0, 0.0])

```

---

<div class="post-metadata">

**Author:** ![duzaichuan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/duzaichuan/32/206666_2.png) [@duzaichuan](https://discourse.julialang.org/u/duzaichuan)\
**Post date:** [June 13, 2024, 9:37pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623/3 "2024-06-13T21:37:07Z")

</div>

Hi @mrufsvold, thanks for such quick and detailed response!

I see the point very clearly. Coming from matlab, I find this copy type of programming error really hard to debug. Took me a whole night locating this in my code.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [June 13, 2024, 10:02pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623/4 "2024-06-13T22:02:08Z")

</div>

Very smart folks thought through these APIs, and I don’t mean to backseat drive them, but I resonate with friction in places like this!

I have a difficult time thinking of a use case where I actually want a vector of copies of the same thing, seems like `fill` should default to using `copy` unless told otherwise.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [June 13, 2024, 10:13pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623/5 "2024-06-13T22:13:08Z")

</div>

Fill works well with immutable elements, i.e., value types, such as numbers: `fill(1.23, 4)`. For mutable stuff, comprehensions are an easy and readable alternative: `[zeros(3) for _ in 1:4]` (albeit slightly longer).

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [June 13, 2024, 10:31pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623/6 "2024-06-13T22:31:43Z")

</div>

Totally correct and exactly what the docstring recommends, but I still don’t agree that this is the right design. The fact that the docs need to have a caveat because this problem comes up so much is evidence to me that handling mutable objects differently would be better.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [June 14, 2024, 4:56pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623/7 "2024-06-14T16:56:09Z")

</div>

Fair enough, maybe `fill` could be extended with methods taking factory functions, e.g., `fill(() -> zeros(3), 2)`, or a wrapper type marking copies, e.g., `fill(Copied(zeros(3)), 2)`?

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [June 14, 2024, 6:52pm UTC](https://discourse.julialang.org/t/unexpected-additional-behavior-when-using-zip-to-construct-namedtuple/115623/8 "2024-06-14T18:52:56Z")

</div>

I love the idea of a `Copied` type! But certainly an anonymous function would be lower friction.

Although, I guess it is technically breaking since you could right now call `fill(f, 3)` to get an array of functions.
