In a package, I have a method foos which currently returns a collection of 
Bars. This is a little unfortunate, so I would like to instead return a 
value of type FooCollection on which I can call the bar function to get the 
array of Bars. I can get backwards compatibility by making FooCollection 
iterable, by implementing start, next and done. Now, I have the following:

immutable Bar end
immutable FooCollection
    bars::Vector{Bar}
end

foos() = FooCollection(Bar[])
bars(fc::FooCollection) = fc.bars

start(fc::FooCollection) = start(fc.bars)
next(fc::FooCollection, state) = next(fc.bars, state)
done(fc::FooCollection, state) = done(fc.bars, state)

This works - both the new and the old api:s are supported, and they do the 
right thing.

Next, I’d like to deprecate iteration on FooCollection, to make it obvious 
to users that although their code isn’t broken, they’re relying on an API 
that might not work forever. Instead of for bar in foos() I want them to 
write for bar in bars(foos()). Thus, I make the following changes to the 
iteration protocol:

@deprecate start(fc::FooCollection) start(bars(fc))
@deprecate next(fc::FooCollection, state) next(bars(fc), state)
@deprecate done(fc::FooCollection, state) done(bars(fc), state)

This works and gives deprecation messages when I write for bar in foos() 
println(bar) end, but the messages aren’t very helpful; for one thing, I 
get three of them (one for each method), and for another they refer to 
functions which aren’t present in the user’s code (and which the user won’t 
realize why they’re called unless they know how to implement iterators in 
Julia…).

Is there a better/more helpful way to do this, without having to 
re-implement the @deprecate machinery entirely?

// T
​

Reply via email to