Recommended way to destructuring a type

I would like to provide destructuring assignment as a syntactic sugar for a custom type.

I understand that the way to do it is iteration, but I am wondering if there is something more elegant than the MWE below, also compiler-friendly (constant folding of iterator state).

struct Foo{T}
    a::T
    b::T
    c::T
end

function Base.iterate(foo::Foo, index = 1)
    if index == 1
        foo.a, 2
    elseif index == 2
        # NOTE: deliberately reverse c, b
        foo.c, 3
    elseif index == 3
        foo.b, 4
    else
        nothing
    end
end

which works as

julia> x, y, z = Foo(1, 2, 3);

julia> (x, y, z)
(1, 3, 2)

That is to say, is there a convenient shortcut which would just tell destructuring to collect the fields (:a, :c, :b)?

Just to clarify, the user would still manually specify the result, just not define the rather inelegant Base.iterate above.

Named tuple:

(; a, b, c) = Foo(1,2,3)

Works also with single fields

(; b) = Foo(5,6,7)

That was not my question; I specifically want destructuring via iterables (as linked in the docs), not property-based destructuring.

you could also do something along the lines of iterate(f::Foo, i=1) = (i <= nfields(f)) ? (getfield(f, i), i+1) : nothing

Note how b and c are exchanged, that is deliberate in the MWE.

perhaps instead of getfield(f, i) you can define some const permutation and make that getfield(f, PERM[i]) ?

or: iterate(f::Foo, state...) = iterate((f.a, f.c, f.b), state...)

This is a bit wacky, as it hides the result in the state:

# this can be reused, eg from a package
function proxy_iterate((proxy, inner_state...),)
    result = iterate(proxy, inner_state...)
    if result ≡ nothing
        nothing
    else
        elt, inner_state′ = result
        elt, (proxy, inner_state′)
    end
end

# the user would define this
Base.iterate(foo::Foo, state = ((foo.a, foo.c, foo.b), )) = proxy_iterate(state)

You could convert your type to Tuple and use Tuple iteration:

Base.Tuple(foo::Foo) = (foo.a, foo.c, foo.b)
Base.iterate(foo::Foo, state...) = iterate(Tuple(foo), state...)