# Struct, push!, unexpected result

**URL:** <https://discourse.julialang.org/t/struct-push-unexpected-result/73901>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [January 1, 2022, 6:01pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901 "2022-01-01T18:01:13Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![das](https://avatars.discourse-cdn.com/v4/letter/d/46a35a/32.png) [@das](https://discourse.julialang.org/u/das)\
**Post date:** [January 1, 2022, 6:01pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/1 "2022-01-01T18:01:13Z")

</div>

I am trying to append a (musical) note of type Note to a sequence, which is a Vector of type Note. When i is 1, the result is:

sequence: Note[Note(0x00000002, 0x5d, 0x38, 0x0000000d, 0x40)]

which is correct. When i = 2, makeRndNote produces a new note but the result:

sequence: Note[Note(0x00000005, 0x2b, 0x54, 0x0000000b, 0x40), Note(0x00000005, 0x2b, 0x54, 0x0000000b, 0x40)]

is 2 instances of only the second set of values, i.e.: [second note, second note], not [first note, second note]

I’d sure appreciate a solution!

Don

===============================================================================

include(“/home/das/Development/julia/include/MIDIcodes.jl”)  
include(“/home/das/Development/julia/include/stddef.jl”)

mutable struct Note  
delta::UInt32 # time until event occurs  
pitch::UInt8 # middle C = 60  
velocity::UInt8 # mf = 60  
duration::UInt32  
panposition::UInt8  
end

function makeRndNote(note::Note, delta)  
note.delta = delta  
note.pitch = rand(1:(MAXNOTE - MINNOTE)) + MINNOTE  
note.velocity = rand(1:(MAXVELOCITY - MINVELOCITY)) + MINVELOCITY  
note.duration = rand(1:(MAXDELTA - MINDELTA)) + MINDELTA  
note.panposition = CENTERPAN  
end

function main()

```
note = Note(MINDELTA, MIDDLEC, MINVELOCITY, QUARTERNOTE, CENTERPAN)
sequence = Note[]

for i in 1:2
	delta = rand(1:(MAXDELTA - MINDELTA))
	makeRndNote(note, delta)
	push!(sequence, note)
	println("\nsequence: ", sequence)
end

```

end

main()

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [January 1, 2022, 6:26pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/2 "2022-01-01T18:26:13Z")

</div>

Functions in Julia (including `push!`) do not copy their arguments, so you are passing around and mutating the same `Note` over and over. If you want a new object for each iteration, then you need to make a new `Note` each time.

---

<div class="post-metadata">

**Author:** ![das](https://avatars.discourse-cdn.com/v4/letter/d/46a35a/32.png) [@das](https://discourse.julialang.org/u/das)\
**Post date:** [January 1, 2022, 6:49pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/3 "2022-01-01T18:49:10Z")

</div>

Thanks. That’d be very cumbersome. Can you suggest an approach that would allow me to append a new note (of type Note) to a list of notes? Thanks.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [January 1, 2022, 7:07pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/4 "2022-01-01T19:07:30Z")

</div>

I could not test because I do not know the values of MAXNOTE etc, but here is something that might work:

```julia
function makeRndNote(delta)
    pitch = rand(1:(MAXNOTE - MINNOTE)) + MINNOTE
    velocity = rand(1:(MAXVELOCITY - MINVELOCITY)) + MINVELOCITY
    duration = rand(1:(MAXDELTA - MINDELTA)) + MINDELTA
    panposition = CENTERPAN
    return Note(delta, pitch, velocity, duration, panposition)
end

```

---

<div class="post-metadata">

**Author:** ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)\
**Post date:** [January 1, 2022, 7:24pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/5 "2022-01-01T19:24:53Z")

</div>

One option is that you could call `copy` or `deepcopy` and mutate the copy.

The other option is that you could make Note immutable and then either make new `Note`s manually or use something like Setfield.jl to do that for you.

> **[GitHub - jw3126/Setfield.jl: Update deeply nested immutable structs.](https://github.com/jw3126/Setfield.jl)**
>
> Update deeply nested immutable structs. Contribute to jw3126/Setfield.jl development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![das](https://avatars.discourse-cdn.com/v4/letter/d/46a35a/32.png) [@das](https://discourse.julialang.org/u/das)\
**Post date:** [January 1, 2022, 7:26pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/6 "2022-01-01T19:26:00Z")

</div>

Thanks Christopher. The problem isn’t actually making the note (that works fine in the original) – it’s how to extending a list of notes (which is what the unidimensional “sequence” vector is) by adding a new note as they are generated. push! doesn’t produce the correct result.

---

<div class="post-metadata">

**Author:** ![das](https://avatars.discourse-cdn.com/v4/letter/d/46a35a/32.png) [@das](https://discourse.julialang.org/u/das)\
**Post date:** [January 1, 2022, 7:55pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/7 "2022-01-01T19:55:30Z")

</div>

> [@Christopher\_Fisher](#):
>
> ```julia
> function makeRndNote(delta)
> pitch = rand(1:(MAXNOTE - MINNOTE)) + MINNOTE
> velocity = rand(1:(MAXVELOCITY - MINVELOCITY)) + MINVELOCITY
> duration = rand(1:(MAXDELTA - MINDELTA)) + MINDELTA
> panposition = CENTERPAN
> return Note(delta, pitch, velocity, duration, panposition)
> end
> 
> ```

Christopher! that works!!! Thanks so much. Now push!(sequence, makeRndNote(delta)) is correct.

(I wish I really understood what it is about how things are done that makes the difference as the basic logic is the same.)

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [January 1, 2022, 8:54pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/8 "2022-01-01T20:54:24Z")

</div>

No problem. As redets noted, your initial code was making multiple references of your first note object, rather than distinct note objects. As a result, you were making multiple references to the same underlying note. The new code creates a new, distinct note with the constructor function `Note()`. As a simple example, consider

```julia
julia> a = [1 2; 3 4]
2×2 Matrix{Int64}:
 1 2
 3 4

julia> b = a
2×2 Matrix{Int64}:
 1 2
 3 4

julia> b[1] = -100
-100

julia> a
2×2 Matrix{Int64}:
 -100 2
    3 4

julia> b
2×2 Matrix{Int64}:
 -100 2
    3 4

```

Matrices `a` and `b` are references to the same data. This is essentially what your code was doing. Now consider

```julia
julia> a = [1 2; 3 4]
2×2 Matrix{Int64}:
 1 2
 3 4

julia> b = [1 2; 3 4]
2×2 Matrix{Int64}:
 1 2
 3 4

julia> b[1] = - 100
-100

julia> b
2×2 Matrix{Int64}:
 -100 2
    3 4

julia> a
2×2 Matrix{Int64}:
 1 2
 3 4

```

In the second set of code, `[]` is a constructor for a matrix, which creates a new, distinct matrix rather than a reference.

As a side note, you might want to be careful with global variables such `MAXNOTE`. It is better to pass variables as arguments through a function in order to avoid side effects and performance problems. The [performance tips](https://docs.julialang.org/en/v1/manual/performance-tips/) in the documentation is a good resource.

---

<div class="post-metadata">

**Author:** ![das](https://avatars.discourse-cdn.com/v4/letter/d/46a35a/32.png) [@das](https://discourse.julialang.org/u/das)\
**Post date:** [January 1, 2022, 9:15pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/9 "2022-01-01T21:15:04Z")

</div>

Thanks so much! I’m going to study this carefully in the morning with my coffee. LOL

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [January 2, 2022, 2:38pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/10 "2022-01-02T14:38:35Z")

</div>

Do the delta and duration need to be UInt32? Would UInt16 suffice?  
You could cut the size in half of each note by using UInt16 (from 16 bytes to 8)  
Also, making them immutable would also make things a lot more efficient.

---

<div class="post-metadata">

**Author:** ![das](https://avatars.discourse-cdn.com/v4/letter/d/46a35a/32.png) [@das](https://discourse.julialang.org/u/das)\
**Post date:** [January 2, 2022, 9:49pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/11 "2022-01-02T21:49:52Z")

</div>

Got it! It’s a bit different it seems than some other languages I’m familiar with. Thanks again Christopher.

---

<div class="post-metadata">

**Author:** ![das](https://avatars.discourse-cdn.com/v4/letter/d/46a35a/32.png) [@das](https://discourse.julialang.org/u/das)\
**Post date:** [January 2, 2022, 10:00pm UTC](https://discourse.julialang.org/t/struct-push-unexpected-result/73901/12 "2022-01-02T22:00:22Z")

</div>

Thanks Scott. UInt16 works fine! Re mutability, I need to check what happens here and there.
