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).
I’d like to avoid redefining getindex for two reasons:
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.
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.
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?
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
@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
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)
You can still keep the structure with a short g without changing the global G by introducing a helper class that has getindex:
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)
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?
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…