I like the macro version. Why? Because you can also check (in the macro) which type of indexing is used. That is, one could call the macro with a single index, range indexing, an array of indices, …
Then I was thinking; why specify the symbol and the indexing as two arguments? There’s the @view macro, which you can also use as @view x[1:3]. I didn’t look up how it is implemented but wanted to come up with my own solution (as an exercise), and it works!
macro ntplaccess(expr)
sym = expr.args[1] # the symbol
idx = expr.args[2] # the index, or the indexing expression
if typeof(idx) <: Int
# single index
return :($(esc(sym))[$idx])
else
# range, array, tuple
elements = []
if idx.head == :call && idx.args[1] == :(:)
# range
for i in (idx.args[2]:idx.args[3])
push!(elements, :($(esc(sym))[$i]))
end
elseif idx.head == :tuple || idx.head == :vect
# tuple or array
for i in idx.args
push!(elements, :($(esc(sym))[$i]))
end
end
return :( ($(elements...),) )
end
end
# can do...
f(y) = @ntplaccess y[1]
f(y) = @ntplaccess y[[3,5]]
f(y) = @ntplaccess y[(1,4,7)]
f(y) = @ntplaccess y[1:4]