# How to overload push!

**URL:** <https://discourse.julialang.org/t/how-to-overload-push/26810>\
**Category:** General Usage\
**Created:** [July 25, 2019, 9:36pm UTC](https://discourse.julialang.org/t/how-to-overload-push/26810 "2019-07-25T21:36:35Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)\
**Post date:** [July 25, 2019, 9:36pm UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/1 "2019-07-25T21:36:35Z")

</div>

Hi folks,

I’m trying to define an object that stores some data with associated time tags. The time tags are constrained to be in consecutive order. As a consequence I’ve defined a struct with the pertinent data fields, and would now like to define a version of push!() which operates on them, calculating a new time tag as an increment of the time associated with the last element in the collection and then call Base.push! on the result.

I’ve tried this:

```
import Base.push!
function Base.push!(collection::Array{Stuff,1}, new::Stuff)
    Base.push!(collection, f(new))
end

```

which results in a nasty infinite loop, because the inner push! call doesn’t call the actual Base.push! function, it instead calls the push! function I’m redefining. So I’m trying to force an evaluation of the Base.push! function. I’ve gotten this far:

```
import Base.push!
function Base.push!(collection::Array{Stuff,1}, new::Stuff)
    invoke(Base.push!, Tuple{Array{Any,1}, Any}, collection, f(new))
end

```

…and this results in an “invoke: argument type error”.

I can’t find any code where you define an overloaded Base method that does some stuff, then calls the original Base method. Can anyone help me out?

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [July 25, 2019, 10:54pm UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/2 "2019-07-25T22:54:15Z")

</div>

I think your best bet will be to do something like:

```julia
struct TimeCollection
    data::Array{Stuff, 1}
end

function Base.push!(c::TimeCollection, new::Stuff)
    push!(c.data, new)
end

```

This more defines a “new” collection type which sounds like what you are actually doing. What you more wrote was a new way to add Stuff to an array, which I think would merit a new function since couldn’t you add other things using time tags…in theory?

Edit: Which I guess should be more like this to be generic. 🙂

```julia
struct TimeCollection{T}
    data::Array{T, 1}
end

function Base.push!(c::TimeCollection, new)
    push!(c.data, new)
end

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 26, 2019, 12:38am UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/3 "2019-07-26T00:38:23Z")

</div>

You don’t need to do anything here because the Base definition of `push!` already does what you want. In fact, specialization stuff on `SomeType{T}` where you don’t own `SomeType` is generally not a good idea.

---

<div class="post-metadata">

**Author:** ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)\
**Post date:** [July 26, 2019, 12:52am UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/4 "2019-07-26T00:52:44Z")

</div>

Unfortunately, no it doesn’t. I left out some code that is in my own version of push! in order to make the example code snippets more readable. I’ve now edited the OP to hopefully make this more clear.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 26, 2019, 12:56am UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/5 "2019-07-26T00:56:43Z")

</div>

You should make a new array type then.

Something like

```julia
struct MappedArray{T, N, F}
    x::Array{T, N}
    f::F 
end

```

and then define `push!` on `MappedArray`. Perhaps [https://github.com/JuliaArrays/MappedArrays.jl](https://github.com/JuliaArrays/MappedArrays.jl) is of interest.

---

<div class="post-metadata">

**Author:** ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)\
**Post date:** [July 29, 2019, 6:59pm UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/6 "2019-07-29T18:59:47Z")

</div>

Perhaps I’m dense. How do you create a new, empty TimeCollection struct here? I can’t manage it.

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [July 29, 2019, 7:12pm UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/7 "2019-07-29T19:12:33Z")

</div>

```julia
struct TimeCollection
    data::Array{Stuff, 1}
end

function Base.push!(c::TimeCollection, new::Stuff)
    push!(c.data, new)
end

Base.setindex!(c::TimeCollection, value, key) = setindex(c.data, value, key)
Base.getindex(c::TimeCollection, key) = getindex(c.data, key)
Base.delete!(c::TimeCollection, key) = delete!(c.data, key)

```

That should give you the basics…There are also other functions you can implement like `haskey()`, `get()`, `keys()`, and `values()`, etc…but the `setindex!()` and `getindex()` will give you the square bracket ability.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [July 29, 2019, 10:21pm UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/8 "2019-07-29T22:21:17Z")

</div>

The others commented on why this is often a questionable idea, so let me answer the actual question: You got the type signature wrong. You should write

```julia
julia> function Base.push!(collection::Vector{Stuff}, x::Stuff)
       @show x
       invoke(Base.push!, Tuple{Vector, Any}, collection, x)
       end

```

You wrote `Vector{Any}`, which is the concrete type of arbitrarily heterogeneous vectors. Your input type is `Vector{Stuff}`, and in order to avoid the recursion, you want to invoke the more generic method for `Vector{T} where T`, i.e. the `push!` for arbitrary vectors.

---

<div class="post-metadata">

**Author:** ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)\
**Post date:** [July 31, 2019, 2:22pm UTC](https://discourse.julialang.org/t/how-to-overload-push/26810/9 "2019-07-31T14:22:14Z")

</div>

Thanks everyone. I learned a lot about Julia from this exchange. It’s working now.
