# Is there a generic function for appending an element to an immutable collection?

**URL:** <https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883>\
**Category:** General Usage\
**Tags:** question\
**Created:** [February 7, 2024, 4:14pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883 "2024-02-07T16:14:27Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 7, 2024, 4:14pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/1 "2024-02-07T16:14:27Z")

</div>

Suppose `v::T` supports `getindex` and `length`, but it is not necessarily an `<:AbstractVector` and may not be mutable.

Is there a generic function (possibly defined in a package, not `Base`) for appending one element, creating a new value?

Eg calling it `add_element`, it could be defined like

```julia
add_element(t::Tuple, e) = (t..., e)

function add_element(v::AbstractVector, e)
    if ismutable(v) # I am ignoring promotion to keep it simple
        push!(copy(v), e)
    else # note: none of these alternatives are great
        vcat(v, [e])
    end
end

```

etc.

There is `StaticArrays.push`, but I could not find a generic API defined for this.

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [February 7, 2024, 4:19pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/2 "2024-02-07T16:19:28Z")

</div>

> **[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.

> **[GitHub - JuliaFolds/BangBang.jl: Immutables as mutables, mutables as immutables.](https://github.com/JuliaFolds/BangBang.jl)**
>
> Immutables as mutables, mutables as immutables. Contribute to JuliaFolds/BangBang.jl development by creating an account on GitHub.

Either of those work?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 7, 2024, 4:27pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/3 "2024-02-07T16:27:44Z")

</div>

Can you be more specific about your recommendation? Eg `BangBang.push!!` only returns a new value when the argument is immutable. I want a new value always.

Similarly, what is the syntax for appending in Setfield.jl?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 7, 2024, 4:46pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/4 "2024-02-07T16:46:52Z")

</div>

I would use Accessors.jl for this.

```julia-repl
julia> using Accessors

julia> let c = [1,2,3]
           @btime @insert $c[4] = 4
       end
  30.571 ns (2 allocations: 160 bytes)
4-element Vector{Int64}:
 1
 2
 3
 4

julia> let t = (1,2,3,4,5)
           @btime @insert $t[6] = "hi"
       end
  2.374 ns (0 allocations: 0 bytes)
(1, 2, 3, 4, 5, "hi")

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 7, 2024, 5:12pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/5 "2024-02-07T17:12:36Z")

</div>

Just a sidenote, it seems that Accessors was missing a method required to make `c[end+1] = 4` work (only because `end` specifically is a bit funky), but it’s a pretty easy addition: [Support `insert` with dynamic `DynamicIndexLens` by MasonProtter · Pull Request #132 · JuliaObjects/Accessors.jl · GitHub](https://github.com/JuliaObjects/Accessors.jl/pull/132)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 7, 2024, 5:29pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/6 "2024-02-07T17:29:23Z")

</div>

Sorry, the question was not clear. I am mainly interested in the following:

Suppose a type has a way of _implementing_ this particular operation cleanly.

Is there a generic function used at least by some packages it could use for _exposing_ this, it should it define its own?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 7, 2024, 5:37pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/7 "2024-02-07T17:37:31Z")

</div>

Ah I see. For that, I’d say the only generic function that is already in active use by multiple people that would make sense to overload here would be `Accessors.insert`, i.e. you should implement the method `Accessors.insert(::YourType, ::IndexLens, x)`.

The only other function I can think of would be `++` from [GitHub - tlienart/PlusPlus.jl: ++ as array vcat and string concat](https://github.com/tlienart/PlusPlus.jl), but that is not in use by anyone, and has many of the same bad-properties that `vcat` has.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [February 7, 2024, 5:44pm UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/8 "2024-02-07T17:44:56Z")

</div>

Nevermind, there actually is a function you can use and recommend here: `BangBang.NoBang.push`. This is the version of `push!!` that is guarenteed to not mutate, and BangBang.jl is indeed a package with a good number of active users.

```julia
julia> using BangBang.NoBang: push

julia> push((1,2,3), 4)
(1, 2, 3, 4)

julia> push([1,2,3], 4)
4-element Vector{Int64}:
 1
 2
 3
 4

```

This sub-module should be advertised more in the BangBang.jl docs.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 8, 2024, 9:41am UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/9 "2024-02-08T09:41:11Z")

</div>

I am thinking about raising an issue in StaticArrays.jl to suggest that `pop`, `push`, `popfirst`, and `pushfirst` be factored out into a package that could be called `ImmutableDequeuInterface.jl` or similar, keeping the semantics in the former. But I will sleep over it, not entirely sure if that is the best solution.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [February 27, 2024, 11:34am UTC](https://discourse.julialang.org/t/is-there-a-generic-function-for-appending-an-element-to-an-immutable-collection/109883/10 "2024-02-27T11:34:06Z")

</div>

> [@Mason](#):
>
> `@insert c[4] = 4`

To append the a element, the cleanest is `@insert last(c) = 4`. It has a symmetric way `@insert first(c) = 4` to prepend as well.  
Also gives more opportunities for a performant specialized implementation, if insertion is only efficient at the first/last position.

> [@Mason](#):
>
> For that, I’d say the only generic function that is already in active use by multiple people that would make sense to overload here would be `Accessors.insert`, i.e. you should implement the method `Accessors.insert(::YourType, ::IndexLens, x)`.

Correspondingly, you can overload `Accessors.insert(::YourType, ::typeof(last), x)`.
