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