I am calculating a sum of values returned by a function, which is supposed to be type stable. The function may be costly, and returns values that are either finite or -Inf
. In case of -Inf
, I would like to return early.
MWE (which is of course not costly, the first version does not return early):
observation_logdensity(μ, x) = x > μ ? -abs2(x - μ) : oftype(promote(x, μ), -Inf)
sample_logdensity1(μ, xs) = sum(observation_logdensity(μ, x) for x in xs)
Now I am wondering how to program what I want, so that the accumulator does not change type. The function can return a <: Real
type (in a type-stable way), especially ForwardDiff.Dual
. I would like to have a way to figure out the accumulator type. This version does not, so the type changes inevitably:
function sample_logdensity2(μ, xs)
total = 0 # in general, I don't know the return type of observation_logdensity
for x in xs
total += observation_logdensity(μ, x)
total == -Inf && return total # terminate early
end
total
end
This version should figure it out (if observation_logdensity
is type stable), but it is cumbersome:
function sample_logdensity3(μ, xs)
isempty(xs) && return -Inf
total = observation_logdensity(μ, first(xs))
for x in Iterators.drop(xs, 1)
total += observation_logdensity(μ, x)
total == -Inf && return total # terminate early
end
total
end
I wonder if there is a way to write it in a more compact way idiomatically. xs
can be any iterable.