datetime review part 2 [Update 4]

Tomek Sowiński just at ask.me
Thu Nov 11 16:31:56 PST 2010


Jonathan M Davis napisał:

> On Wednesday, November 10, 2010 15:03:11 Tomek Sowiński wrote:
>> Jonathan M Davis napisał:
>> > Latest: http://is.gd/gSwDv
>> 
>> My 2 cents:
>> 
>> Units of time are represented more naturally by an integer enum (could be
>> anonymous) than a string.
>> 
>> A problem recurring in many methods:
>> 
>>     /+ref+/ Date opOpAssign(string op, D)(in D duration) nothrow
>>         if((op == "+" || op == "-") &&
>>            (is(Unqual!D == Duration) ||
>>             is(Unqual!D == TickDuration)))
>>     {
>>         static if(op == "+")
>>         {
>>             static if(is(Unqual!D == Duration))
>>                 return addDays(convert!("hnsecs",
>> "days")(duration.total!"hnsecs")); else static if(is(Unqual!D ==
>> TickDuration))
>>                 return addDays(convert!("hnsecs",
>> "days")(duration.hnsecs)); }
>>         else
>>         {
>>             static if(is(Unqual!D == Duration))
>>                 return addDays(convert!("hnsecs",
>> "days")(-duration.total!"hnsecs")); else static if(is(Unqual!D ==
>> TickDuration))
>>                 return addDays(convert!("hnsecs",
>> "days")(-duration.hnsecs)); }
>>     }
>> 
>> If you're static if'ing each statement, it's a good sign the method
>> should be broken up into two overloads. BTW, what was the problem with
>> returning by ref?
> 
> I don't see any real benefit in splitting a function into two overloads
> rather than using static ifs in this manner. The resulting source code is
> likely nearly identical. You only end up with one function to document
> this way, and in this case the user doesn't necessarily care about what
> type of duration they're dealing with. If, they want to add or subtract a
> duration, here's the function to do it. If anything, I think that I tend
> to favor using static ifs over duplicate functions with different template
> constraints if there's no real difference in the from the users
> perspective.

Fair enough, although it's no excuse for copy-paste programming. It can be easily wrung out of 
duplication with no loss in readability:

    /+ref+/ Date opOpAssign(string op)(in Duration duration) nothrow
        if((op == "+" || op == "-") &&
            (is(Unqual!D == Duration) ||
             is(Unqual!D == TickDuration)))
    {
        static if (is(Unqual!D == Duration))
             auto hnecs = duration.total!"hnsecs";
        else
             auto hnecs = duration.hnsecs;

        return addDays(convert!("hnsecs", "days")(unaryFun!(op~"a")(hnsecs)));
    }

The user may not care, but the maintainer does. Not even convinced about the former, when writing I 
often seek introspection in Phobos source. Besides, this is the Standard Library, it should hold code 
of exemplary quality.

BTW, I still think units of time should be an enum, not a string.

> As for the ref, there are several bugs relating to that. One I remember
> right off the top of my head is that you can't have a template function
> return by ref for some reason. I think that there's at least one related
> to invariants too, though the one about invariants not being able to be
> pure has been fixed which has reduced some of the invariant-related
> problems. A number of bugs relating to const-correctness, purity, and
> invariants have caused me a lot of headaches when working on datetime.

Oh yeah, I know how that hurts ;)

>> Finally, bordering on bikeshed, weekdays' names are long and months' are
>> short. Having both short and long names for weekdays and months would
>> solve the inconsistency and satisfy everyone.
> 
> I hadn't thought about that. I'll think about it. I'm not sure that it
> really matters much though. I tend to prefer full names over short names,
> but that can become tedious when you use them a lot.

3-letter shorts, e.g. January-Jan, February-Feb, Monday-Mon, Tuesday-Tue are recognized by just about 
everyone. It makes sense to include both.

>> Are there any plans for a Calendar interface to allow user
>> implementations that distinguish business days and holidays?
> 
> I'm afraid that I have no clue what you're talking about. I mean, I know
> what a business day is and what a holiday is, but I'm not sure what you
> mean by a calendar interface in this context.

Sorry, was talking QuantLib, I meant something like this:
http://dsource.org/projects/quantlibd/browser/ql/time/calendars.d
(copy-pasting sucks, I know;))

> Are you looking for a way to
> query whether a particular day is a business day, weekend day, or holiday?
> That strikes me as being a function rather than an interface

An interface (or abstract class) makes sense. E.g. I may want to get the number of working days 
between this and this date. It may be implemented faster than walking the interval and pecking day 
by day.

> and it would
> be locale-dependent enough that I can't see it making into the standard
> library.

Designing the interface and, more importantly, solving how to store the holiday information to allow 
fast interval querying is not locale-specific. Plus, it is in common need for business, and it is not trivial 
-- ideal candidate for the standard library. Then everyone can write an implementation for their 
favorite country or stock exchange on their own.

>> Maybe I'm late on the 'pure' changes, but how come all the setters are
>> pure? I mean it modifies the (hidden) argument of the function, so it
>> shouldn't be, no?
> 
> They'd be weakly pure rather than strongly pure. Ultimately, I believe
> that the only functions in std.datetime which should be non-pure are the
> ones which access global variables or make a call whose potentially result
> changes every call (like getting the time) or functions who indirectly
> call such functions. Some of those will be strongly pure and some won't,
> but it's a royal pain get much in the way of strongly pure functions
> without weakly pure ones. That suggestion of Don's was fantastic and will
> quite possibly make pure useable.
> 
> Weakly pure functions are functions which don't access globals or return a
> different result with each call but which can't be optimized out, whereas
> strongly pure functions are the same except that all of their parameters
> are immutable or can be implicitly converted to immutable, and they _can_
> be optimized out in some cases. So, the getters in many cases would be
> strongly pure, whereas the setters would be weakly pure.

So it's in? Excellent!

-- 
Tomek


More information about the Digitalmars-d mailing list