JuliaDynamics / ResumableFunctions.jl

C# style generators a.k.a. semi-coroutines for Julia.
Other
158 stars 19 forks source link

Caveat: when code is first executed #40

Closed baggepinnen closed 3 years ago

baggepinnen commented 4 years ago

I have the following definition of a resumable function. I notice that if I call batchview with a d where isready(d) returns false, I do not get the desired error until I try to get the first element

@resumable function batchview(d::AbstractDiskDataProvider, size=d.batchsize)
    isready(d) || error("You can only create a buffered iterator after you have started reading elements into the buffer.")
    for inds in Iterators.partition(1:length(d), size)
        @yield buffered_batch(d, inds)
    end
end

example run

julia> isready(dataset)
false

julia> bw = batchview(dataset)
DiskDataProviders.var"##409"(0x00, #undef, QueueDiskDataProvider{Array{Float64,1},Int64,Array{Float32,2}}, length: 100
, #undef, #undef, 2, #undef, #undef)

julia> first(bw)
ERROR: You can only create a buffered iterator after you have started reading elements into the buffer.
Stacktrace:
 [1] (::DiskDataProviders.var"##409")(::Nothing) at /home/fredrikb/.julia/packages/ResumableFunctions/bdcq7/src/macro.jl:121
 [2] iterate at /home/fredrikb/.julia/packages/ResumableFunctions/bdcq7/src/macro.jl:86 [inlined]
 [3] iterate at /home/fredrikb/.julia/packages/ResumableFunctions/bdcq7/src/types.jl:24 [inlined]
 [4] first(::DiskDataProviders.var"##409") at ./abstractarray.jl:342
 [5] top-level scope at none:0

I now understand this behavior, but it caught me by surprise. Is there a way to have some code run at the creation of the iterator rather than at the first call to iterate on it?

BenLauwens commented 4 years ago

Hi

I can see your issue. Often I start a resumable function with some initialisation code that is run during the first call and the normal behaviour starts from the second call on.

Kind regards

Ben