# Help to create a macro / overload to mimic setindex! behavior in SArrays

**URL:** <https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959>\
**Category:** General Usage\
**Created:** [August 23, 2018, 5:44pm UTC](https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959 "2018-08-23T17:44:48Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [August 23, 2018, 5:44pm UTC](https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959/1 "2018-08-23T17:44:48Z")

</div>

Hi guys!

I am trying to use `SArrays` in my project. I have tons of vectors and matrices that, in some cases, I need to modify only one index. What I am doing is to replace:

```julia
Trw[i] = T(0)

```

to

```julia
Trw = setindex(Trw, 0, i)

```

But it is somewhat strange. I am wondering if it is possible to overload `setindex!` or create a macro to make things easier.

I tried somethings without much success. Can anyone help me?

---

<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:** [August 23, 2018, 6:08pm UTC](https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959/2 "2018-08-23T18:08:00Z")

</div>

I wouldn’t recommend overloading `setindex!`, as it won’t have the expected behavior of _mutating_ the object, but will instead just be replacing it. Also, overloading a function you don’t own (`Base.setindex!`) on a type you don’t own (`SArray`) is type-piracy and is not recommended because it can silently change the behavior other people’s code.

On the other hand, a macro seems totally reasonable. You’re trying to turn this expression:

```julia
julia> dump(:(Trw[i] = 0))
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Expr
      head: Symbol ref
      args: Array{Any}((2,))
        1: Symbol Trw
        2: Symbol i
    2: Int64 0

```

into this one:

```julia
julia> dump(:(Trw = setindex(Trw, 0, i)))
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Symbol Trw
    2: Expr
      head: Symbol call
      args: Array{Any}((4,))
        1: Symbol setindex
        2: Symbol Trw
        3: Int64 0
        4: Symbol i

```

You can either do that by hand or use [GitHub - FluxML/MacroTools.jl: MacroTools provides a library of tools for working with Julia code and expressions.](https://github.com/MikeInnes/MacroTools.jl) to make it a bit easier.

---

<div class="post-metadata">

**Author:** ![Daniel\_Berge](https://avatars.discourse-cdn.com/v4/letter/d/eb9ed0/32.png) [@Daniel\_Berge](https://discourse.julialang.org/u/Daniel_Berge)\
**Post date:** [August 23, 2018, 6:18pm UTC](https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959/3 "2018-08-23T18:18:05Z")

</div>

You can also use [Setfield.jl](https://github.com/jw3126/Setfield.jl) to accomplish this with the `@set` macro.

```julia
using Setfield

a = @SVector [i for i=1:4]

julia> @set a[3]=10
4-element SArray{Tuple{4},Int64,1,4}:
  1
  2
 10
  4

```

---

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [August 23, 2018, 6:20pm UTC](https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959/4 "2018-08-23T18:20:21Z")

</div>

But, in this case, `a` will be updated?

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [August 23, 2018, 6:23pm UTC](https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959/5 "2018-08-23T18:23:21Z")

</div>

If you want to update `a` you need to do `a = @set a[3] = 10`.

---

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [August 23, 2018, 6:26pm UTC](https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959/6 "2018-08-23T18:26:21Z")

</div>

I see, that is what I would like to avoid. I am trying to create a macro that can do this automatically for me.

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [August 23, 2018, 6:35pm UTC](https://discourse.julialang.org/t/help-to-create-a-macro-overload-to-mimic-setindex-behavior-in-sarrays/13959/7 "2018-08-23T18:35:28Z")

</div>

There was an old version of Setfield, which had this functionality. You could implement it using Setfield as follows:

```julia
using Setfield
using Setfield: parse_obj_lens, IndexLens, compose

macro myset(ex)
    @assert ex.head isa Symbol
    @assert length(ex.args) == 2
    @assert ex.head == :(=)
    ref, val = ex.args
    obj, lens = parse_obj_lens(ref)
    val = esc(val)
    quote
        lens = $lens
        $obj = set(lens, $obj, $val)
    end
end

a = (1,2)
@myset a[1] = 10
a

```

(10, 2)
