# Macro: replace array indexing by function call in expression

**URL:** <https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234>\
**Category:** General Usage\
**Created:** [August 29, 2018, 10:35am UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234 "2018-08-29T10:35:37Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [August 29, 2018, 10:35am UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/1 "2018-08-29T10:35:37Z")

</div>

I’m a complete macro noob. Given an expression which contains (multiple) array indexing operations `g[i1, i2]`, how do I replace all such occurrences by a function call `G(i1,i2)`? So what I want is all `g[i1,i2]` become `G(i1,i2)`.

For example,

`:(A[j, y, x] += real(g[i1, i4]*g[i2, i3] - g[i1, i3]*g[i2, i4])`

should become

`:(A[j, y, x] += real(G(i1, i4)*G(i2, i3) - G(i1, i3)*G(i2, i4))`

Note, that `A[j, y, x]` doesn’t change. What’s the easiest way to achieve that?

PS: I don’t want to redefine `getindex`.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [August 29, 2018, 10:42am UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/2 "2018-08-29T10:42:10Z")

</div>

I managed to replace `g` by `G` using MacroTools.jl’s `postwalk`. But how to transform reference `[]` into call `()` ?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [August 29, 2018, 10:58am UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/3 "2018-08-29T10:58:13Z")

</div>

Couldn’t you use your own type for `A` and `G` and define a `getindex` method to your liking?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 29, 2018, 11:55am UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/4 "2018-08-29T11:55:22Z")

</div>

What do you want to achieve? Why is redefining `getindex` for a custom type not an option?

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [August 29, 2018, 12:16pm UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/5 "2018-08-29T12:16:03Z")

</div>

I’d like to avoid redefining `getindex` for two reasons:

1. The method call to `G` will also involve further arguments in my real use case. I.e. the example should actually become `:(A[j, y, x] += real(G(i1, i4, a, b, c, d)*G(i2, i3, a, b, c, d) - G(i1, i3, a, b, c, d)*G(i2, i4, a, b, c, d))`. `getindex` only has two integer arguments.
2. This is a large codebase where `g` shows up a lot and I need this functionality only in a very local part of the code. Changing the type of `g` for this purpose has a global effect.

Hope that makes sense.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 29, 2018, 12:33pm UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/6 "2018-08-29T12:33:00Z")

</div>

I’m still not quite clear on why you want to solve this using a macro - as far as I’m aware you’d have to tell the macro somehow about those additional arguments. Is defining a new function taking `g`, the indices and the additional arguments and changing the code in the relevant places not an option?

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [August 29, 2018, 12:36pm UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/7 "2018-08-29T12:36:47Z")

</div>

It is an option and also how I do it currently. However, basically for readability reasons, I’d like to use a macro to hide all the “ugly function calls”. What I want is to write

```julia
@mymacro a b c d begin
    # my code here, for example:
    A[j, y, x] += real(g[i1, i4]*g[i2, i3] - g[i1, i3]*g[i2, i4])
end

```

and have it become

```julia
A[j, y, x] += real(G(i1, i4, a, b, c, d)*G(i2, i3, a, b, c, d) - G(i1, i3, a, b, c, d)*G(i2, i4, a, b, c, d)

```

for example.

(I have much more code than just one line.)

---

<div class="post-metadata">

**Author:** ![traktofon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/traktofon/32/591_2.png) [@traktofon](https://discourse.julialang.org/u/traktofon)\
**Post date:** [August 29, 2018, 12:39pm UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/8 "2018-08-29T12:39:57Z")

</div>

You can still keep the structure with a short `g` without changing the global `G` by introducing a helper class that has `getindex`:

```julia
struct GHelper{A}; args::A; end
GHelper(args...)=GHelper(args)
Base.getindex(gh::GHelper, idx...) = G(idx..., gh.args...)

g=GHelper(0,-1,1.0,0.0) # construct with the extra arguments for G
G(args...)=args # for testing
g[4,6]
# calls G with arguments (4, 6, 0, -1, 1.0, 0.0)

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 29, 2018, 12:43pm UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/9 "2018-08-29T12:43:57Z")

</div>

Although a nice idea, since there are calls that should not be affected, I don’t think it’s going to work for @crstnbr… maybe it’s possible by enclosing the part where it should be done with a `let` block and those definitions?

---

<div class="post-metadata">

**Author:** ![traktofon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/traktofon/32/591_2.png) [@traktofon](https://discourse.julialang.org/u/traktofon)\
**Post date:** [August 29, 2018, 12:46pm UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/10 "2018-08-29T12:46:16Z")

</div>

Yes, precisely. Instead of `@mymacro a b c d begin` you’d have

```julia
let g=GHelper(a,b,c,d)
    A[j, y, x] += real(g[i1, i4]*g[i2, i3] - g[i1, i3]*g[i2, i4])
end

```

and all the `g[]` accesses result in function calls of `G`.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 29, 2018, 12:49pm UTC](https://discourse.julialang.org/t/macro-replace-array-indexing-by-function-call-in-expression/14234/11 "2018-08-29T12:49:54Z")

</div>

While a neat solution for this particular case, I feel this is very much against sane code conventions and a proper refactoring of the code to separate those use cases where this transform is needed is a better solution overall. Even if it’s just for the sake of maintainability…
