Very often, especially when prototyping, I compute different quantities, and I want all of them to be easily accessible. The easiest way is to return a named tuple:
function foo()
x = 1
y = "hello"
z = [x,2,3]
# ... and more
(x=x,y=y,z=z)
end
Is there some way or an existing macro that I can use to avoid repetitions in the return argument “x=x” , “y=y” , etc ? Usually the variable names are much longer, and this is prone to errors.
In relation to that, I also have this issue when saving variables on a file, for example:
using JLD2
x=123
y = 456
jldopen("somefile.jld2","w") do f
f["x"]=x
write(f,"y",y)
end
I have to write “x” and “y” twice. With the @save macro I would not have this issue, but it’s often the case that I do not want to save the whole working environment.
macro returnnt(x...)
ex = [:($(esc(z)) = $(esc(z))) for z in x]
return :(return ($(ex...),))
end
function foo()
x = 1
y = "hello"
z = [x,2,3]
# ... and more
@returnnt x y z
end
I’m sure there yet be dragons lurking in the corners of this implementation, but as a proof of concept, hope it’s enough for you for a start.
Thaks a lot , it seems to do the job. I tried to define a macro, but I got lost in the elements that I needed to escape. I am probably asking too much now, but it would be cool to have something like this, as well…
my_values = @wishfulthinkingmacro begin
x = 1
y = "hello"
z = [x,2,3]
end
using Testing
@test my_values.x == 1 # etc
zero repetitions and even less prone to typos ! I would try to build it myself, but of course I am very open to any advice.
Well that was a fun diversion. Way more caveats on this one (!!), but it works for the simple case you provided:
julia> using MacroTools
julia> using MacroTools: combinedef, postwalk
julia> macro autoreturn(f)
fparts = splitdef(f)
fbody = block(fparts[:body])
vars = Symbol[]
postwalk(fbody) do ex
if @capture(ex, return x_)
@warn "Explicit return seen!"
end
if @capture(ex, x_Symbol = y_)
push!(vars, x)
end
ex
end
retpairs = [:($z = $z) for z in vars]
push!(fbody.args, :(return ($(retpairs...),)))
fparts[:body] = esc(fbody)
return combinedef(fparts)
end
julia> @autoreturn function foo()
x = 1
y = "hello"
z = [x,2,3]
end
julia> foo()
(x = 1, y = "hello", z = [1, 2, 3])
Thanks a lot for your help and very quick response ! It seems to work well for testing and prototyping… and hopefully I will gain some useful insights about metaprogramming.