You can define a macro to effortlessly unpack a large number of values at once from a single object.
Sample code:
struct Foo{A, B, C} a::A; b::B; c::C end
"""
`@unpackall_Foo(obj)` unpacks all fields of the object `obj` of type `Foo`.
"""
macro unpackall_Foo(obj)
names = fieldnames(Foo)
Expr(:(=),
Expr(:tuple, names...),
Expr(:tuple, (:($obj.$name) for name in names)...)
) |> esc
end
@doc @unpackall_Foo
@unpackall_Foo(obj)
unpacks all fields of the objectobj
of typeFoo
.
Input:
@macroexpand @unpackall_Foo foo
Output:
:((a, b, c) = (foo.a, foo.b, foo.c))
Input:
@unpackall_Foo Foo(1, 2.0, "three")
a, b, c
Output:
(1, 2.0, "three")
With this macro, there is no need to share a large number of global constants between multiple functions.
Just pass the object foo
, which contains the values shared between multiple functions, to a function as an argument each time, and unpack it in the function.
Input:
foo = Foo(1, 2.0, "three")
function f(foo::Foo)
@unpackall_Foo foo
@show a b c
return
end
f(foo)
Output:
a = 1
b = 2.0
c = "three"
In the above, we unpack only a
, b
, and c
from foo
, but you can increase the number of them as much as you want.
To increase the number of fields in the style of struct Foo{A, B, C} a::A; b::B; c::C end
as much as you want, you can use ConcreteStructs.jl (my example).
Jupyter notebook: https://github.com/genkuroki/public/blob/main/0018/How%20to%20define%20unpacking%20macros.ipynb