I also tried the generator approach, but it can be much slower than expanding the body directly into a for loop. See this:
module MyModule
export @Σ
# fancy macro to write sums
macro Σ(limits, expr)
@assert limits.head === :(=)
@assert length(limits.args) == 2
index = limits.args[1]
start, stop = limits.args[2].args
quote
local _start = $(esc(start))
local _stop = $(esc(stop))
$(esc(index)) = _start
local out = $(esc(expr))
for $(esc(index)) = (_start+1):_stop
out += $(esc(expr))
end
out
end
end
end
using MyModule
using BenchmarkTools
N = 400
x = randn(N, N)
fun1(x, j, N) = @Σ i=1:N x[i, j]
fun2(x, j, N) = sum(x[i, j] for i=1:N)
println(@benchmark fun1($x, 2, N))
println(@benchmark fun2($x, 2, N))
On my machine I get
Trial(320.763 ns)
Trial(5.931 μs)
that is twenty times faster.