Terminate in collect



I have a generator which yields state, weight pairs. The type of state is not known in advance. I would like to collect enough states so that the sum of weights is at least S. I prefer to utilize the nice “narrowest type” machinery of collect to do this, so that the resulting vector has the narrowest type.

Two-pass implementation MWE (note that here of course the type of states is known, but let’s pretend it isn’t):

function collect_upto(f, S)
    result = Any[]
    s = zero(S)
    while s ≤ S
        x, w = f()
        s += w
        push!(result, x)

collect_upto(()->(rand(),rand(1:10)), 100)

Is it possible to do this in a single pass without writing a custom iterator (which seems overkill)?


For implementation, https://github.com/JuliaLang/julia/blob/ceb06740e307a8b2d43f3480efaa33311a90f021/base/array.jl#L426
You can also create a filter iterator/comprehension but it can be non-trivial given your function has side effect and the termination condition does not only depend on current element.