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
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.
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?
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).
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.
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.
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.
Correspondingly, you can overload Accessors.insert(::YourType, ::typeof(last), x).