On 14.11.2010 7:47, Jonathan M Davis wrote:
On Thursday 11 November 2010 13:42:37 Dmitry Olshansky wrote:
I'm afraid that I don't really get what you're trying to do here. A range
needs to be created from an interval. It really wouldn't make sense to
do it otherwise. And when you create a range, it needs a delegate which
generates the time points for that range. So, you create an interval and
call either fwdRange() or bwdRange() on it to give it the
range-generating delegate. I happen to have provided some helper
functions for generating delegates, but there's nothing to stop you from
creating your own.
If you have provided them, then it's OK.
What I meant is we have retro(someRange) to go backwards where applicable.
   And I do believe you could return range of DateTime's  that's
bidirectional ?
Then there is no need to duplicate the std.algorithm/range
functionality, that's all.
None of the ranges in std.datetime are bi-directional, so you can't use retro on
them (or any other algorithm which requires bi-directional ranges). It's a side
effect of them being generated as you iterate. I considered having 
bi-directional
ranges, but it was just too messy. You'd have to provide two separate generative
functions (one for each direction), and in many cases, when iterating over
dates, you wouldn't get the same results because many date calculations aren't
reversible (the main problem being that months and years don't have the same
number of days).
So bi-directionality is one of places where generator-on-previous-date approach is failing. I see that with current API the user need to be aware which delegate use when: auto func = IRange.everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.friday);//note the Direction.bwd bit
auto range = interval.bwdRange(func);//also note the bwd thingy
I get it would just throw exception if bwdRange got replaced by fwdRange? It's acceptable, but still not clean.
Are you trying to say that the range should automatically provide _all_
possible time points in an interval and then you specifically filter
them? That's nowhere near as flexible, and in the case of SysTime in
particular, think about how many time points that is. It has
hecto-nanosecond (100 ns) precision.  That's 10 million time points a
second. It could get really inefficient to try and filter all of those.
Also, I'm not sure that filter would work with an infinite range (I'd
have to check), which would be a huge setback. I really don't get the
benefit of your suggestion, though I can undkerstand it if it's not
entirely clear how ranges in std.datetime are supposed to work.
Not at all, you provide the precision that the user asks for. E.g. if
users want tot iterate by days - no problem iterate by days.
If by hnseconds, well he(or she) knows better ... Right?
The point is we don't need some predefined delegates, just the natural
ones e.g. by secs, hours and so on as with the roll/add methods.
That's doable, but it seems far less flexible.
OK, got it.
Skimming again through docs I'd say we just see the API at different sides, i.e.
I was mostly referring to IRange block, it's slightly cumbersome.

For now, I as user see it more as interval functions:
Interval.byDur(Duration) + Interval.by!"days"(x).... Interval.by!"months"(x) + Interval.by"years"(x)

where only byDur, by"months" and by"years" are necessary the other are just a convenience. They could be implemented as one-liners in terms of yours IRange (I still don't get why such a name?).
Then it would be just an implementation detail with IRange being private.

But then it would cost in some extra lines, plus as you told there should be fwd/back param somewhere. Then it goes like Interval.by!("days",Direction.Back) with default being Fwd of course...
For instance, how would you
calculate each successive Easter? Or a holiday which always occurred on the Xth
day of the week of a particular month? A number of calculations could easily be
based on the dates that came before rather than examining each date on its own
and determining whether it was one of the ones that you were looking to iterate
over.
Yeah, with that simplified approach using filtering by e.g. days could suck in term of speed, need checking. It's however possible, see my later point. If speed is of concern IMO I would just create a special
range by hand, it's a standard library right?
About speed: because of flexibility yours bwdRange and fwdRange are checking on both bounds(if any)
 at each iteration, for trivial tasks that's also costs.
Maybe we need some realistic date-time benchmarks (if there is such a thing)?
I mean, even iterating over each successive month with that wouldn't work
very well. If the first date were 2010-07-31, would 2010-09-30 be one of the
dates to iterate over? In order to know one way or the other, you'd need to have
state (like what the last date to be iterated over was), and using a filter does
not give you state.
Filter based on delegate  could have state, so no problem at all.
    int n = 1;//state
    auto fn = (int i){
        if(i == n){
             ++n;
            return true;
        }
        return false;
    };
    int f[] = array(filter!(fn)([1,2,3,4,5,7,8]));
    assert(f == [1,2,3,4,5]);//passes
Or better you could use function-like object or what not, that's what std.algorithm is good at.
It seems to me that using a filter could work well in simple cases but that it
falls apart in more complex ones.
As you said it's not a simple case, and how would you handle it with current API anyway? Custom generator-delegate for grunted. So custom in any way (range or delegate), and not everything we generate needs previous timepoint.
Well, I'm not saying it's bad/or some such. I, first of all, told you
it's damn good.
Things could be simplified though if you relay some of burden on
std.algorithm/range and such.
That's the main point I couldn't get for the moment.
I think that the real concern is whether the ranges in std.datetime can be used
with all of the algorithms in std.range and std.algorithm that they're likely to
be want to used with. As they stand, they aren't bi-directional, which could be
a problem, but I don't see a good way to make them bi-directional, since date
calculations aren't always reversible.
Yeah, that's a pity.
You also can't swap them at all, but they
have a fixed order by their very nature, so I don't see that as being a problem.
There could be problems that I'm not seeing though.
Regardless, I don't see std.algorithm or std.range as being much help in
generating ranges in std.datetime. It might be nice to use retro to produce
ranges which iterate into the past, but the lack of reversibility of date
calculations makes it so that doesn't work. And in most cases, a delegate which
calculates the next date in the range given the previous one is quite
straightforward - if it isn't, it's because the calculation itself is
complicated, and attempts at using filter and the like won't make the 
calculation
any simpler.

Indeed, so please, at least just consider changing status of IRange from public API to implementation artifact.
- Jonathan M Davis


--
Dmitry Olshansky

Reply via email to