On 10.12.2010 23:00, Jonathan M Davis wrote:
[snip]
Overall, I don't really see the benefit of your proposal. The main advantage of
fwdRange and bwdRange in the interval types instead of just a single function is
that they allow you to verify that you're iterating in the correct direction.
In my proposal it still checks this, what I meant is - there is no need
to define them inside range,
in fact it's quite easy to define generic fwdRange, that works on any
interval, which is what I did
(it still lacks PopFirst.yes customabilty and such, but that can be
easily fixed).
Otherwise, you risk an infinite loop. If we were willing to forgoe that, then
you
could make it so that you only had one function, but I think that that would be
a definite loss.
It _is_ annoying to have to give Direction.fwd or Direction.bwd to the functions
in IRange when you're feeding it to fwdRange or bwdRange since it does seem
redundant, but those functions need to know what direction you want them to
iterate in, and both fwdRange and bwdRange are designed for general delegates -
not necessarily just those generated by IRange - so they assume the direction.
But since the functions in IRange default to Direction.fwd and that's almost
always what you'd want, I don't think that it's ultimately that big an issue.
Agreed, It's not a big issue. But I thought delegate can go back and
forth as it's internal logic suggests, it's when it hits the end of
interval that's important (and I assumed that would be the end of
iteration).
Conceptually, I think that it makes perfect sense that the interval would have
the range functions on them - that's certainly what happens with containers. I
don't see the benefit in splitting them out.
It's where we are disagreeing it seems. For me, the less monolithic the
interval struct, the better.
After the interval provided begin and end (ether one), it's trivial to
implement generic fwdRange and bwdRange outside, and they also provide
'contains' function.
Your solution makes it so that a range is infinite separately from whether the
interval is infinite. I don't think that that makes sense. A range is only
infinite because it's iterating over something infinite. By making the range
infinite separately, it's then possible to try and iterate infinitely over a
non-
infinite interval, which would be a problem.
For me the problem would be to iterate over infinite range assuming it's
finite.
For the most part, it looks like all you've done is try to make it so that the
ranges are unrelated to the intervals that they iterate over. That seems like a
bad idea to me, and I fail to see the benefit. What does your solution do that
mine can't?
Delegate can generate range of seemingly unrelated time points, or for
which you may not know the interval or it's pointless or hard to
calculate. Consider you need date of next 5 blue dragon years (that's
that Chinese calendar thingy) ?
That's solvable,with a dummy infinite interval. My point is that when
you need custom delegate, it's only for specific tasks, for which
interval may not be interesting at all.
My solution is completely generalized. You can use take() and all of those
std.range and std.algorithm functions on the ranges in std.datetime. You can
give it a delegate defined as you like as long is it takes a time point and
returns a time point of the same type. If you got your range via fwdRange(),
then the time point returned must be after the one given, and if you got your
range via bwdRange(0, then the time point must be after the one given. It's
fairly straightforward and not error-prone.
I can't take if I don't know the interval beforehand, or need to create
a dummy infinite one. Or even worse delegate could produce time points
in non-directed way, like consider +1 day, -2day, +3day (no, it's not
common but... you are the one to talk about generalizations).
I agree that the IRange functions are a bit ugly, but they're an attempt to make
it easier to create common delegates to pass to fwdRange() and bwdRange() rather
than you having to create your own. You don't have to use them. They're for
convenience. And they include a function which generates a delegate which causes
the range it iterate by a given duration every iteration: IRange.everyDuration!
().
Yes, there I suggest to introduce a shortcut, like
auto byDay = fwdRange(interval, dur!"days"(1));
auto byYear = fwdRange(interval, 1); //months = 0, duration = dur!"days"(0)
I fear It's just a matter of taste.
I'm certainly open to suggestions, but I don't understand what's broken about my
solution that yours fixes. My seems fairly straightword.
1. You have an interval - be it infinite or finite.
There I thought is a problem in generalization , you may not know the
interval.
2. You want a range, you pass a delegate (which determines how to iterate over
the interval) to fwdRange() if you want to iterate forwards and bwdRange() if
you want to iterate backwards. fwdRange() and bwdRange() verify that the
delegates that you give the return time points which are valid for iterating
over the interval (so, not duplicating the previous time point or iterating in
the wrong direction).
Yes, that's check could be a good thing. In my proposal you'd get an
empty range or infinite, still can be added, of course.
3. If you don't want to create your own delegate, then you use one of the
functions in IRange to generate one for you.
4. Once you have your range, you can do whatever you normally do with input and
forward ranges.
In fact, that's where the user need to get, and the easier the better.
- Jonathan M Davis
--
Dmitry Olshansky