Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add iterate (from next) #603

Closed
lobingera opened this issue Aug 6, 2018 · 7 comments
Closed

Add iterate (from next) #603

lobingera opened this issue Aug 6, 2018 · 7 comments

Comments

@lobingera
Copy link

UndefVarError: iterate not defined 

in 0.6 + Compat

after following

┌ Warning: `next(s::AbstractString, i::Integer)` is deprecated, use `iterate(s, i)` instead.

in 0.7

@mlhetland
Copy link

I guess the following should do it?

iterate(iter) = next(iter, start(iter))
iterate(iter, state) = done(iter, state) ? nothing : next(iter, state)

@mlhetland
Copy link

Hm. Actually. Maybe that's too simple. At least when I use that version on a Channel, with a setup that works in 1.0, I get issues with undefined references in 0.6:

julia> chnl = Channel(c->foreach(i->put!(c,i), 1:4))
Channel{Any}(sz_max:0,sz_curr:1)

julia> start(chnl)
Base.ChannelIterState{Any}(false, #undef)

Trying to call next using that fails, it seems. It actually assumes that you call done before using next:

julia> chnl = Channel(c->foreach(i->put!(c,i), 1:4))
Channel{Any}(sz_max:0,sz_curr:1)

julia> state = start(chnl)
Base.ChannelIterState{Any}(false, #undef)

julia> done(chnl, state)
false

julia> state
Base.ChannelIterState{Any}(true, 1)

So, in case there's other code out thare relying on this for loop behavior, I guess one could throw that in:

# Calling done, because e.g. Channel relies on it:
iterate(iter) = (state = start(iter); done(iter, state); next(iter, state))
iterate(iter, state) = done(iter, state) ? nothing : next(iter, state)

@mlhetland
Copy link

I guess that could be simplified to the more intuitive

iterate(iter, state=start(iter)) = done(iter, state) ? nothing : next(iter, state)

@oyd11
Copy link

oyd11 commented Dec 9, 2018

Is anyone adding this Compat then? moving some (private for now) package 0.6 -> 1.0 , I've implemented some icky logic around this for now ...

@oyd11
Copy link

oyd11 commented Dec 9, 2018

Note: the missing functionality - is future compatibility for maintaining 0.6 code working after re-writing the code with the newer 'iterate()' interface.
I have if VERSION < VersionNumber(0,7) code now with done()/next() implemented hiding a state variable in the iterator to hack this out.
And the semantics of 'start' not doing the first step, while iterate(oneArg) - doing the first step - would make writing this macro difficult in the general case.

@oyd11
Copy link

oyd11 commented Dec 9, 2018

I've ended up with a semi-generic code:

mutable struct It
# what-ever-was there before, plus:
 tmp_state # remove when 0.6 compat isn't needed anymore
end 

iterate_(it, state)  = # 1.0 style impl
iterate_(it) = # 1.0 style impl 

if VERSION >= VersionNumber(0,7)
    Base.iterate(it::It) = iterate_(it)
    Base.iterate(it::It, state) = iterate_(it, state)
else # VERSION 0.6
    function Base.start(it::It)
        it.tmp_state  = iterate_(it)
        _, state = it.tmp_state
        return state
    end

   Base.done(it::It, state) = nothing ==  it.tmp_state

   function Base.next(it::It, state)
        prev = it.tmp_state
        it.tmp_state = iterate_(it, state)
        return prev
   end
end # VERSION 0.6

@martinholters
Copy link
Member

Closing as outdated since we've dropped support for Julia prior to 1.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants