# \`push!\` semantics

**URL:** <https://discourse.julialang.org/t/push-semantics/103234>\
**Category:** General Usage\
**Created:** [August 26, 2023, 9:36pm UTC](https://discourse.julialang.org/t/push-semantics/103234 "2023-08-26T21:36:08Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ross\_Boylan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ross_boylan/32/9210_2.png) [@Ross\_Boylan](https://discourse.julialang.org/u/Ross_Boylan)\
**Post date:** [August 26, 2023, 9:36pm UTC](https://discourse.julialang.org/t/push-semantics/103234/1 "2023-08-26T21:36:08Z")

</div>

It doesn’t seem to me the behavior of `push!`, as seen in the program below, is clear from the documentation. Should I file an issue about it, or is this just my confusion?

Specifically, I wasn’t sure whether the `Vector` got a copy of the object pushed, or the object itself. The semantics have tripped up [others](https://discourse.julialang.org/t/unexpected-push-behavior/23967), and that question by @gideonsimpson has an answer by @kristoffer.carlsson. The answer is that the `Vector` will contain the original object. Of course, one can push an explicit `copy()` if that’s the goal.

I came to this wondering about the behavior of objects that are sent through a `Channel`; I suspect the story is the same there since, at least when buffered, `Channel` uses a `Vector` internally (julia 1.9.2).

No doubt part of the confusion stems from interference from knowledge about `C++`, which is all over handling this kind of stuff explicitly. Since `julia` has no pointers, references (well, not sure what `Ref()` does), copy constructors, in-place update … it’s a much different world.

I’m also a bit disturbed because I thought `Vector` was roughly giving me a continguous block of bits which would allow more efficient processing. At least for structs that seems not to be the case.

```julia
mutable struct TBag
    a::Int16
    b::Int16
end

function main()
    v = Vector{TBag}()
    b = TBag(1, 44)
    push!(v, b) # does v get a copy of b, or b itself?
    b.a = 99
    println(v[1].a) # 1 or 99?
end
main()

```

99 is the result.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [August 26, 2023, 9:52pm UTC](https://discourse.julialang.org/t/push-semantics/103234/2 "2023-08-26T21:52:09Z")

</div>

the answer here is that Julia uses “pass by sharing” which means that mutable objects are always passed by reference (immutables let the compiler choose since you can’t observe a difference)

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [August 27, 2023, 12:03am UTC](https://discourse.julialang.org/t/push-semantics/103234/3 "2023-08-27T00:03:50Z")

</div>

> [@Ross\_Boylan](#):
>
> No doubt part of the confusion stems from interference from knowledge about `C++`, which is all over handling this kind of stuff explicitly. Since `julia` has no pointers, references (well, not sure what `Ref()` does), copy constructors, in-place update … it’s a much different world.

Julia does have pointers, references, copy constructors, and in-place update.

```julia
julia> v = collect(1:5)
5-element Vector{Int64}:
 1
 2
 3
 4
 5

julia> pointer(v)
Ptr{Int64} @0x00007f7a2b56aa40

julia> unsafe_load(ans, 5)
5

julia> Ref(v, 3)
Base.RefArray{Int64, Vector{Int64}, Nothing}([1, 2, 3, 4, 5], 3, nothing)

julia> unsafe_store!(pointer(v), 9, 3)
Ptr{Int64} @0x00007f7a2b56aa40

julia> Ref(v, 3)[]
9

```

---

<div class="post-metadata">

**Author:** ![Ross\_Boylan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ross_boylan/32/9210_2.png) [@Ross\_Boylan](https://discourse.julialang.org/u/Ross_Boylan)\
**Post date:** [August 27, 2023, 12:46am UTC](https://discourse.julialang.org/t/push-semantics/103234/4 "2023-08-27T00:46:22Z")

</div>

@Oscar_Smith if calls were pass by value then it would be impossible for a called function, `push!()` in this case, to refer to the original object. Since it is pass by sharing, it can refer to the original value. But I don’t think knowing that alone is enough to know what it does with the value. If my mental model of a `Vector` as a continuous chunk of `TBag` structures had been correct (it isn’t), it would have to be a different object that it stored, albeit one with the same property values. Or, the function could have always made a copy on its own.

Putting it more directly, it seems to me `push!` could behave in either way–using the original or keeping its own copy–and be consistent with the documentation, i.e., the documentation is ambiguous.

@mkitti Thanks for the correction. Would one ever use any of those constructs except for programming on the language?

I don’t know who changed the title of this topic to “does push! copy?” or marked it solved, but I wish you hadn’t. I changed it back. Since my initial question stated that `push!` did not copy, I didn’t make the post to find the answer to that question. Nor, for the reasons given above, do I think the first response answers the question about whether it copies. Again, my question was " Should I file an issue about it, or is this just my confusion?". One possible response would be pointing to something in the documentation that does resolve the issue.

---

<div class="post-metadata">

**Author:** ![Keno](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/keno/32/285_2.png) [@Keno](https://discourse.julialang.org/u/Keno)\
**Post date:** [August 27, 2023, 1:16am UTC](https://discourse.julialang.org/t/push-semantics/103234/5 "2023-08-27T01:16:26Z")

</div>

I think the basic answer is that in Julia, essentially no API ever does an implicit copy and we do not currently have any mechanism that allows precise enough control of memory placement that some of the fancier mechanism from other languages would be required in Julia (that doesn’t mean that Julia is necessarily slower of course - the defaults are quite well optimized). As a result, it’s not really clear where this piece of documentation should go. `push!` isn’t really the right place, because from a julia user’s perspective, there’s no reason to expect it to do anything other than store the reference it has in the vector, because that is always julia semantics. Perhaps the best place to put this would be in the noteworthy differences section: [Noteworthy Differences from other Languages · The Julia Language](https://docs.julialang.org/en/v1/manual/noteworthy-differences/#Noteworthy-differences-from-C/C)

---

<div class="post-metadata">

**Author:** ![liuyxpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/liuyxpp/32/9870_2.png) [@liuyxpp](https://discourse.julialang.org/u/liuyxpp)\
**Post date:** [August 27, 2023, 2:53am UTC](https://discourse.julialang.org/t/push-semantics/103234/6 "2023-08-27T02:53:35Z")

</div>

In my experience, it should do no harm to duplicate information in such case because as a newcomer he/she will either go to `push!` or [Noteworthy Differences from other Languages · The Julia Language](https://docs.julialang.org/en/v1/manual/noteworthy-differences/#Noteworthy-differences-from-C/C).
