There’s nothing wrong with the code you posted above (although I agree it’s a bit verbose). Your implementation is efficient and the code is easy to understand, so you might want to consider just writing a function to encapsulate that behavior and call it a day (after all, the best thing about Julia is that your hand-written function will be just as fast as any built-in solution).
But if you want a different approach, you could consider:
Store the result tuples and then just grab the relevant element from each:
out = [f(x[i], y[i]) for i in 1:N] # or f.(x, y)
out_x = first.(out) # or getindex.(out, 1)
out_y = last.(out) # or getindex.(out, 2)
Consider whether it makes more sense to treat the pair (x, y) as a scalar in your downstream code. If you’re computing those results together, perhaps they should actually stay together? For example, rather than storing x coordinates and y coordinates, consider storing a vector of xy points. If you do that, then your original problem just goes away. This is not applicable in all cases, but it’s something I’ve found myself doing more as I’ve gotten more comfortable with Julia.
I realize this thread is older, but I would like to add a question anyway. Is there a way to do basically this if you have array slices on the left side, e.g. something along the line
function f(x)
a=...
b=...
return a,b
end
myarray[:,1:2]=f.(x)
where x is a vector or iterator and a and b are vectors due to broadcasting ? This does not appear to work with Destruct.jl. If that would work one could also do fancy things like, assuming f.(x) returns four vectors,
a,myarray[:,1:2],c=f.(x)
you get the idea.
Of course this behaviour can be achieved with using an explicit loop which is only a small modification of the loop in the original question or (after googling this) fancy constructs like
function ttest(t)
x=3.0*sin(t)
y=2.0*cos(t)
return x,y
end
t=range(0.0,step=0.1,length=2)
delta=zeros(2,3)
map(x->delta[:,x].=collect(ttest.(t))[x], 1:size(collect(ttest.(t)),1))
map(x->delta[:,x].=[ttest.(t)...][x], 1:size(collect(ttest.(t)),1))
but it might be that in these cases the function is called twice as many times as needed compared to storing the result in a temporary vector, which in turn would be unneeded if the return values could be assigned to array slices directly.