# How to write a Macro to define the multi-index symbols

**URL:** <https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514>\
**Category:** General Usage\
**Created:** [April 13, 2020, 3:40pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514 "2020-04-13T15:40:23Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 13, 2020, 3:40pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/1 "2020-04-13T15:40:23Z")

</div>

I write a Macro to define the symbols with one index as following

```julia
macro varjs(x, j::Int64)
    vars=Expr(:block)
    for i = 1:j
        push!(vars.args, Expr(:(=), esc(Symbol("$x$i")), Expr(:quote,Symbol("$x$i"))))
    end
    push!(vars.args, Expr(:tuple,map(esc, "$x".*map(string,1:j).|>Symbol)...))
    vars
end

```

The macro is called as following

> @varjs α 16  
> The output is

> (:α1, :α2, :α3, :α4, :α5, :α6, :α7, :α8, :α9, :α10, :α11, :α12, :α13, :α14, :α15, :α16)

Each αi is defined as a symbol variable.

Then I plan to define the macro for multi-index variables. I have no ideal about this except for writing the “for loop” one by one. Is there any better way to realize the feature?  
For example, 3-index varibales with three value for each index, the macro should looks like @varjs α 3 3 3 and automatically define the symbol varialbes α111, α112, α113,α121,α122,α123,α131,α132,α133,α211, α212, α213,α221,α222,α223,α231,α232,α233,α311, α312, α313,α321,α322,α323,α331,α332,α333.

---

<div class="post-metadata">

**Author:** ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)\
**Post date:** [April 13, 2020, 4:10pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/2 "2020-04-13T16:10:11Z")

</div>

A variable-dimensional loop can be implemented using `Iterators.product`, e.g.

```julia
varjs(s,j...) = [:($(Symbol(s,i...)) = $(Expr(:quote,Symbol(s,i...)))) for i in Iterators.product((1:k for k in j)...)]

```

But also, the thing you are trying to achieve seems suspicious. Why would you want to create variables named `α11, α12, α21` etc., rather than have the values inside a single array called `α`?

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 13, 2020, 4:16pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/3 "2020-04-13T16:16:48Z")

</div>

Thanks. I use the Multi-index symbol to denote the component of tensors.

---

<div class="post-metadata">

**Author:** ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)\
**Post date:** [April 13, 2020, 4:25pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/4 "2020-04-13T16:25:09Z")

</div>

You can have the components in an array `α`, and refer to them in code as `α[1,1]` and so on. If `α` is a `StaticArray` it will probably be roughly as efficient as a variable for each component (and if the size of `α` only becomes known at runtime, the macro approach is probably hopeless anyway).

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [April 13, 2020, 4:30pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/5 "2020-04-13T16:30:23Z")

</div>

Have you tried any of the existing tensor packages (e.g. [Tensors.jl](https://github.com/KristofferC/Tensors.jl), [TensorOperations.jl](https://github.com/Jutho/TensorOperations.jl))? They don’t have the symbolic indexing you’re describing, but they have a solid base of functionality that you’d otherwise have to build yourself.

If symbolic field names are critical, consider using [FieldArrays](https://juliaarrays.github.io/StaticArrays.jl/latest/pages/api/#StaticArrays.FieldArray) from StaticArrays.jl.

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [April 13, 2020, 4:47pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/6 "2020-04-13T16:47:17Z")

</div>

You can also snag the `@unpack` macro from Parameters.jl in conjunction with FieldArrays:

```julia
julia> using StaticArrays, Parameters

julia> @with_kw struct Stress <: FieldMatrix{2,2,Float64}
           xx::Float64
           yx::Float64
           xy::Float64
           yy::Float64
       end

julia> function f(σ::Stress)
           @unpack_Stress σ
           return xx + yy - sqrt(xy * yx)
       end

julia> σ = Stress(3, 1, 1, 2)
2×2 Stress with indices SOneTo(2)×SOneTo(2):
 3.0 1.0
 1.0 2.0

julia> f(σ)
4.0

```

You also get free functionality via StaticArrays.jl:

```julia
julia> using LinearAlgebra

julia> det(σ) + tr(σ)
10.0

```

---

<div class="post-metadata">

**Author:** ![non-Jedi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/non-jedi/32/3645_2.png) [@non-Jedi](https://discourse.julialang.org/u/non-Jedi)\
**Post date:** [April 13, 2020, 5:08pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/7 "2020-04-13T17:08:33Z")

</div>

You should look at the [`Base.Cartesian` module](https://docs.julialang.org/en/v1/devdocs/cartesian/). I think it already has all the functionality you could want along these dimensions.

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 13, 2020, 6:03pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/8 "2020-04-13T18:03:27Z")

</div>

Your method works perfectly.

```julia
macro varjst(x, j...)
    vars=Expr(:block)
    for i in Iterators.product((1:k for k in j)...)
        push!(vars.args, Expr(:(=), esc(Symbol("$x$(i...)")), Expr(:quote,Symbol("$x$(i...)"))))
    end
    push!(vars.args, Expr(:tuple,map(esc, "$x".*map(string,["$(i...)" for i in Iterators.product((1:k for k in j)...)]).|>Symbol)...))
    vars
end

> vars=@varjst α 3 3 3
(:α111, :α211, :α311, :α121, :α221, :α321, :α131, :α231, :α331, :α112, :α212, :α312, :α122, :α222, :α322, :α132, :α232, :α332, :α113, :α213, :α313, :α123, :α223, :α323, :α133, :α233, :α333)
> length(vars)

> α231
:α231

```

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 13, 2020, 6:04pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/9 "2020-04-13T18:04:21Z")

</div>

Thanks for the help from all of you. The problem is solved.

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 13, 2020, 6:06pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/10 "2020-04-13T18:06:49Z")

</div>

Interesting module. It seems also useful. Thanks

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 13, 2020, 8:53pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/11 "2020-04-13T20:53:35Z")

</div>

Thanks for the suggestion. TensroOperations.jl does related to my following project. Nice to know it in advance.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [April 13, 2020, 11:40pm UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/12 "2020-04-13T23:40:34Z")

</div>

What happens with `@varjst α 11 11 11`…?  
Is `α1111` (1,11,1), (11,1,1), or (1,1,11)?

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 14, 2020, 5:12am UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/13 "2020-04-14T05:12:46Z")

</div>

it is α1111 … So do not use this if the dimension\>=10. In genral space dimesion is 3 (2 for surface). Even encluding time, 4 is enough.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [April 14, 2020, 6:21am UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/14 "2020-04-14T06:21:29Z")

</div>

I was just pointing out the ambiguity. The first case you showed went up to length 16.  
Although it is many more characters, it shouldn’t be hard to modify the macro to produce `α_1_11_1` to avoid this.

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 14, 2020, 7:02am UTC](https://discourse.julialang.org/t/how-to-write-a-macro-to-define-the-multi-index-symbols/37514/15 "2020-04-14T07:02:24Z")

</div>

agree
