I’m writing a query API that allows a user to pass in a closure to be run on every entry satisfying the query, however this usually results in undesirable boxing. For example, here’s the kind of API I want to offer, with the query replaced by a simple foreach loop.
function foreach(f, x) for i = 1:length(x) f(x[i]) end end function bench() x = rand(1000) count = 0 @time foreach(x) do val count += 1 end count end x = rand(1000) bench(x) # 0.000005 seconds (489 allocations: 7.641 KiB)
Now I know why this is allocating, because
Ints aren’t mutable and the compiler boxes
count on each iteration so that it can be incremented in the closure, but this is sort of a nonintuitive bug for my users. I want to provide this kind of API rather than some pre canned
count, etc. function because this is flexible and the compiler should be able to optimise for it. How can I provide an API like this that doesn’t suck performance wise?