I am trying to write a function that
- picks keys from a
NamedTuple
, - uses each key to obtain values from two objects (not necessarily
NamedTuple
s, they supportgetproperty
, may have other properties not used by this function) - applies a function to each triplet,
- sums the result.
Example that is not type stable:
function ntpicker_naive(nt, a, b)
mapreduce(k -> getproperty(a, k) * getproperty(b, k) * getproperty(nt, k), +,
keys(nt))
end
I came up with a recursive implementation that is type stable for short named tuples, but not long ones:
@inline _ntpicker(acc, a, b, ::NamedTuple{(),Tuple{}}) = acc
@inline function _ntpicker(acc, a, b, nt::NamedTuple{K}) where K
K1 = first(K)
v = values(nt)
p1 = getproperty(a, K1) * getproperty(b, K1) * first(v)
_ntpicker(acc + p1, a, b, NamedTuple{Base.tail(K)}(Base.tail(v)))
end
ntpicker(nt::NT, a, b) where {NT <: NamedTuple} = _ntpicker(0, a, b, nt)
nt2 = (c = 1, d = 2)
nt4 = (c = 1, d = 2, e = 3, f = 4)
@code_warntype ntpicker(nt2, nt2, nt2) # OK
@code_warntype ntpicker(nt4, nt4, nt4) # Any
Is there a way I could make this work for arbitrarily long NamedTuple
s, or should I just use generated functions?