Iterating through the fieldnames of tuples

Hello,
I have a problem where I use several named tuples with common structure and field names, e.g.:

a = (x=ones(N), y=ones(N), z=ones(N))
b = (x=ones(N), y=ones(N), z=ones(N))

I would like to loop through the fields of the tuples and apply some arithmetic operation, for now I do:

a.x .+= c*b.x + d
a.y .+= c*b.y + d
a.z .+= c*b.z + d

where c and d are either scalars or vectors of size N.

Is there a way to use a loop and the fact that tuple structure are similar to do this operation instead of doing it manually?
If not, is there another type of data structure that would be more suitable?
Thanks!

you can use fieldtypes(typeof(a) and fieldnames(typeof(a)) if you are ok with scalar indexing to get the types of the tuple entries

Try

map(a, b) do a, b
    a .+= c * b + d
end
2 Likes

Slight broadcasting edit. But works:

let
    N = 10
    c = 3
    d = fill(5, N)
    a = (x=ones(N), y=ones(N), z=ones(N))
    b = (x=ones(N), y=ones(N), z=ones(N))
    map(a, b) do a, b
        a .+= c .* b .+ d
    end
end

1 Like

yes, it does the job great on this example.
How could that work when using tuples of tuples, e.g. in in the case a and b are already fields of a tuple?

You can use a recursive function definition. Something like

function apply!(a, b)
	a .+= c .* b .+ d
end
function apply!(a::Tuple, b::Tuple)
	map(apply!, a, b)
end

I did not test this so there’s some chance there’s a subtle mistake. But the gist is usable.

For this, just call apply!(a,b) and it will keep drilling down through Tuple layers until it reaches a non-Tuple input pair, at which point it applies your calculation.

You’ll have to decide whether you want it to continue recursing until you stop seeing a particular type (like here, where it goes until it gets non-tuples) or stop recursing when you reach a specific type (where you would instead specialize the base case, for example when a and b are AbstractArray or AbstractArray{<:Number}).

thanks for your answer. Not sure I follow you, would you mind expanding a bit?