# Problem with parentheses around quoted expression in generated function

**URL:** <https://discourse.julialang.org/t/problem-with-parentheses-around-quoted-expression-in-generated-function/73347>\
**Category:** General Usage\
**Tags:** question, metaprogramming\
**Created:** [December 19, 2021, 8:47pm UTC](https://discourse.julialang.org/t/problem-with-parentheses-around-quoted-expression-in-generated-function/73347 "2021-12-19T20:47:59Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![evf](https://avatars.discourse-cdn.com/v4/letter/e/b5ac83/32.png) [@evf](https://discourse.julialang.org/u/evf)\
**Post date:** [December 19, 2021, 8:47pm UTC](https://discourse.julialang.org/t/problem-with-parentheses-around-quoted-expression-in-generated-function/73347/1 "2021-12-19T20:47:59Z")

</div>

Hello everyone.

I’m trying to use generated functions to write functions that would return the sum of the values of the nearest neighbors of given site in a multidimensional integer periodic lattice.

For example: In a periodic 2D lattice, the sum of the values of the nearest neighbors of the site s would be

```julia
lattice[mod1(s[1] - 1, size(lattice, 1)), s[2]] + lattice[mod1(s[1] + 1, size(lattice, 1)), s[2]] + lattice[s[1], mod1(s[2] - 1, size(lattice, 2))] + lattice[s[1], mod1(s[2] + 1, size(lattice, 2))]

```

**My attempt**

Reading through the examples provided in the Manual, I came up with the following:

```julia
# Sum of nearest neighbors of site $s$ in a periodic integer lattice
function square_lattice_nn_sum_impl(lattice::Type{Array{Int,dims}}, s::Type{NTuple{dims,Int}}) where dims
    # Accumulate final expression
    ex = :()
    # Loop on the dimensions
    for d in 1:dims
        # Indices for both nearest neighbors in the current dimension
        idx_prev_nn = :(mod1(s[$d] - 1, size(lattice, $d)))
        idx_next_nn = :(mod1(s[$d] + 1, size(lattice, $d)))
        # Fill indices before the current dimension
        idx_before = :()
        for k in d-1:-1:1
            idx_before = :(s[$k], $idx_before)
        end
        # Fill indices after the current dimension
        idx_after = :()
        for k in d+1:dims
            idx_after = :($idx_after, s[$k])
        end
        # Accumulate sum
        ex = :($ex + lattice[$idx_before $idx_prev_nn $idx_after] + lattice[$idx_before $idx_next_nn $idx_after])
    end
    return :($ex)
end

# Extract generated function to the body of a regular function
@generated function square_lattice_nn_sum(lattice::Array{Int,dims}, s::NTuple{dims,Int}) where dims
    square_lattice_nn_sum_impl(lattice, s)
end

```

For the 2D case, my program returns the following expression:

```julia
julia> square_lattice_nn_sum_impl(Array{Int,2}, NTuple{2,Int})

:((() + lattice[() mod1(s[1] - 1, size(lattice, 1)) ((), s[2])] + lattice[() mod1(s[1] + 1, size(lattice, 1)) ((), s[2])]) + lattice[(s[1], ()) mod1(s[2] - 1, size(lattice, 2)) ()] + lattice[(s[1], ()) mod1(s[2] + 1, size(lattice, 2)) ()])

```

Which would be the desired result if it wasn’t for the several misplaced parentheses.

**My questions**

Is it possible to accumulate quoted expression without parentheses around them?

Is there a better way of achieving this?

Are generated functions even the right tool for this job?

Thanks.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [December 19, 2021, 9:30pm UTC](https://discourse.julialang.org/t/problem-with-parentheses-around-quoted-expression-in-generated-function/73347/2 "2021-12-19T21:30:27Z")

</div>

There are other ways but I’d make arrays of expressions, and splat them. Rather than try to recursively build what aren’t really recursive expressions.

```julia
julia> function new_short(lattice::Type{Array{Int,dims}}, s::Type{NTuple{dims,Int}}) where dims
           terms = map(1:dims) do d
               idx_prev_nn = :(mod1(s[$d] - 1, size(lattice, $d)))
               idx_next_nn = :(mod1(s[$d] + 1, size(lattice, $d)))

               idx_before = [:(s[$k]) for k in d-1:-1:1]
               
               term = :(lattice[$(idx_before...), $idx_prev_nn] + lattice[$(idx_before...), $idx_next_nn])
           end
           return :(+($(terms...)))
       end;

julia> new_short(Array{Int,2}, NTuple{2,Int})
:((lattice[mod1(s[1] - 1, size(lattice, 1))] + lattice[mod1(s[1] + 1, size(lattice, 1))]) + (lattice[s[1], mod1(s[2] - 1, size(lattice, 2))] + lattice[s[1], mod1(s[2] + 1, size(lattice, 2))]))

julia> new_short(Array{Int,3}, NTuple{3,Int})
:((lattice[mod1(s[1] - 1, size(lattice, 1))] + lattice[mod1(s[1] + 1, size(lattice, 1))]) + (lattice[s[1], mod1(s[2] - 1, size(lattice, 2))] + lattice[s[1], mod1(s[2] + 1, size(lattice, 2))]) + (lattice[s[2], s[1], mod1(s[3] - 1, size(lattice, 3))] + lattice[s[2], s[1], mod1(s[3] + 1, size(lattice, 3))]))

julia> function orig_short(lattice::Type{Array{Int,dims}}, s::Type{NTuple{dims,Int}}) where dims
           ex = :() # Trimming the original function to the same degree
           for d in 1:dims
               idx_prev_nn = :(mod1(s[$d] - 1, size(lattice, $d)))
               idx_next_nn = :(mod1(s[$d] + 1, size(lattice, $d)))
               idx_before = :()
               for k in d-1:-1:1
                   idx_before = :(s[$k], $idx_before)
               end
               ex = :($ex + lattice[$idx_before $idx_prev_nn] + lattice[$idx_before $idx_next_nn])
           end
           return :($ex)
       end
orig_short (generic function with 1 method)

julia> orig_short(Array{Int,2}, NTuple{2,Int})
:((() + lattice[() mod1(s[1] - 1, size(lattice, 1))] + lattice[() mod1(s[1] + 1, size(lattice, 1))]) + lattice[(s[1], ()) mod1(s[2] - 1, size(lattice, 2))] + lattice[(s[1], ()) mod1(s[2] + 1, size(lattice, 2))])

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 19, 2021, 9:36pm UTC](https://discourse.julialang.org/t/problem-with-parentheses-around-quoted-expression-in-generated-function/73347/3 "2021-12-19T21:36:43Z")

</div>

> [@evf](#):
>
> I’m trying to use generated functions to write functions that would return the sum of the values of the nearest neighbors of given site in a multidimensional integer periodic lattice.

You don’t need a generated function for this. See: [Seemingly unnecessary allocation within for loop - #8 by stevengj](https://discourse.julialang.org/t/seemingly-unnecessary-allocation-within-for-loop/72556/8)
