[phobos] datetime review

Andrei Alexandrescu andrei at erdani.com
Sun Oct 10 06:43:59 PDT 2010


On 10/10/10 5:59 CDT, Jonathan M Davis wrote:
> On Saturday 09 October 2010 12:27:26 Andrei Alexandrescu wrote:
>> * I suggest even experimenting with strings instead of TUnit. Really
>> TUnit is a vestige from C++ and Java, but we do accept string template
>> parameters so how about
>>
>> assert(convert!("years", "months")(2) == 24);
>>
>> etc. Opinions?
>
> One downside to this over TUnit is that it makes comparing time units harder
> (e.g. units<  TUnit.year), but that could be gotten around easily enough with a
> function that does the comparison for you, and not much code is going to care.
> It's primarily of interest in template constraints.

OK. Just mentioning the possibility.

> One issue that would arise from this is one which I'm beginning to think we need
> to address in the language somehow, and that is template constraint failures.
> When a template constraint fails, all the compiler tells you is that no version
> of the template matches the arguments that you're trying to instantiate with.
> That's highly uninformative. Ideally, it would tell you which portion of the
> constraint failed. For instance, by using strings instead of TUnit, you have the
> issue of getting the string exactly right. If the string had to be "year", and
> someone used "years" or "Year", then the template constraint would fail, and
> they would have no idea why. At least with the enum, the compiler will complain
> about the parameter that you're giving the template (though it complains that
> the mistyped value is not a property of int (e.g. that years is not a property
> of int if you used TUnit.years instead of TUnit.year), which isn't a very good
> message either - it's just that it's specific enough that it's easy to figure
> out). Using a string will result in worse error messages.

In fact that's not an issue. Template constraints were meant to avoid a 
template biting off more than it can chew. In this case, however, you 
want to cover the total set, so you can simply write:

long convert(string from, string to)(long) {
     static if (from == "seconds" && to == "minutes") {
     } else static if (...) {
     ...
     } else {
         static assert("Invalid duration specifiers. ...");
     }
}

> Still, I'm beginning to think that it's a good idea. If I do it, I'd likely
> change duration creation too. Right now, you'd do Dur.years() or Dur.months() or
> whatnot to create a duration, but it could become Dur!"year"() and Dur!"month"()
> (or something similar, since normally you wouldnt start a function with a
> capital letter - though it is specifically constructing a type in this case, so
> it's not completely off to use a capital letter) and you'd end up with fewer
> functions for creating durations, and could get rid of the Dur class (though in
> spite of your misgivings about it, I do quite like the idea of using classes for
> namespaces, at least in cases where a namespace would be useful). With TUnitConv
> removed, that would leave only Clock and IRange as namespace classes (and I
> really do think that it improves code readability to leave them that way).

Here's an unrelated suggestion that might simplify things a fair amount: 
drop the "months" and the "years" durations. They are the only ones that 
are irregular. Then you have only one duration type that's always 
precise and you can drop the interval type. If someone wants to figure 
out e.g. the number of months between two dates, we can provide specific 
functions.


Andrei


More information about the phobos mailing list