struct MyStruct
a
b
c
end
function calculation(C::MyStruct)
fieldnames(MyStruct)... = C
2a+3b+c
end
i was trying this workaround
struct My
a
b
c
end
function __unpack_genexpr(S)
a=quote
end
for x in fieldnames(typeof(S))
a=quote
$(a)
$x=$S.$x
end
end
a
end
macro unpack(S)
:(eval($__unpack_genexpr($S)))
end
function bla()
@unpack My(6,7,8)
a,b,c
end
bla() # (6,7,8)
it is ugly as hell and it leaks in the main module, what can i do?
struct MyStruct
a
b
c
end
@generated function calculation(ms::MyStruct)
assignments = Expr(:block, [
:($field = ms.$field)
for field in fieldnames(ms)
]...)
quote
$assignments
2a+3b+c
end
end
julia> calculation(MyStruct(1,2,3))
11
The above implementation has (at least) the caveat that the name used for the function argument (ms in this case) must not conflict with any of the field names.
But I know that writing generated functions is often frowned upon; please let me know if there is something I overlooked.
One option is to go in a different way and interpolate the struct fields into the body. This can maybe serve as inspiration:
macro with(declaration, expr)
return esc(with_func(declaration, expr))
end
function with_func(declaration, expr)
@assert declaration.head == :(::)
v, typ = declaration.args
fields = fieldnames(getfield(@__MODULE__, typ))
expr = recursive_interpolation(expr, fields, v)
return expr
end
function recursive_interpolation(expr::Expr, fields, v)
return Expr(expr.head, recursive_interpolation.(expr.args, Ref(fields), v)...)
end
function recursive_interpolation(s::Symbol, fields, v)
if s in fields
return :($(v).$(s))
end
return s
end
recursive_interpolation(expr, fields, v) = expr
struct My
a
b
end
a = My(2, 3)
function f(x)
@with x::My begin
return a + 2b
end
end
f(a)
Disclaimer: I’m not entirely sure that @__MODULE__ does the right thing in all circumstances.