October 08, 2010
On Friday 08 October 2010 22:00:50 Walter Bright wrote:
> Jonathan M Davis wrote:
> > I should probably add that the seven modules aren't exactly equal in size. In particular datetime.all only has its module documentation and public imports for all of the other modules, and datetime.other is quite small. I didn't necessarily split the code into modules in the best manner. I split it more on concepts than the amount of code in them (so datetime.timepoint probably has close to half of the code in it). I'm open to suggestions if someone has a better way to split the code up. Ideally, it would all be in one module, but it was too much for one.
> 
> I agree that modules should be organized by concept rather than size. But also, I don't know of a rule that says a module is "too large", unless that module contains concepts that are independent of each other and that users will rarely require both at the same time.
> 
> Remember, if a module's implementation code is large, it can be split into a .di/implementation pair, rather than into multiple modules.

That I was not aware of. I'm certainly open to doing that instead. It's just that the file was around 40,000 lines, which was getting to be a bit much to deal with in one file (I don't believe that any of the current Phobos modules even hit 10,000). Splitting the interface out like that would move the documentation out of the source file (for better or worse), which would definitely cut down on its size, though it's the unit tests that take up the most space.

Really, the ideal would be to have all of it in one module but have the code split up into several files. The closest way that I was aware to do that was to use a single module which publicly imported the others. I'll look at splitting it into an interface file and source file though.

- Jonathan M Davis
October 08, 2010

Jonathan M Davis wrote:
> On Friday, October 08, 2010 14:58:35 Walter Bright wrote:
> 
>>
>> It bothers me that there are so many types, i.e. "various duration types", "various interval types", etc.
>>
>> Now that I read that again, why is there both a "duration" and an
>> "interval"?
>> 
>
> A duration is a length of time with units while an interval is two time points (or a time point and a duration) which therefore designate a duration which is fixed in time.

Ok, makes sense.

>  So, they are distinct (the concepts are from Boost). There are
> multiple duration types primarily because you can't convert between months and
> small units without a specific date, so you can't convert something like 5 months
> to days without knowing which months you're dealing with.

True, but why would a month be a type other than int?

>  However, I have
> definite worked on making it so that you don't have to worry about the multiple
> duration types in most cases. You'd do something like Dur.years(5) + Dur.days(2)
> to create a duration of 5 years and 2 days, and you don't have to know or care
> what the duration types are.
> 

Ok, but I don't see that requires more than one duration type.

> There are multiple interval types only to deal with infinity. You have Interval,
> with a definite begin and end, PosInfInterval which goes from a specific time
> point to infinity, and NegInfInterval which goes from negative infinity to a
> specific time point. The infinite intervals are primarily of interest in creating
> infinite ranges. A lot of user code could simpler ignore them.
> 

Ok.

> 
>> Why are there multiple "various time zone classes" instead of "a" time
>> zone class?
>> 
>
> There are multiple time zone classes because it uses polymorphism to deal with the rules for a given time zone. The really basic LocalTime and UTC deal with most cases, but for anyone who really needs to deal with multiple time zones, PosixTimeZone and WindowsTimeZone will be invaluable (I'd love to only have one of those, but Windows just doesn't deal with time zones like the Posix world does).
>
> 

I agree some kind of polymorphism for time zones is necessary. [rant] Timezones should be an operating system service, if for no other reason than it sucks to have all your apps break when some tinhorn country decides to change their daylight savings time, etc.[/rant]


October 08, 2010
On Friday 08 October 2010 22:30:02 Walter Bright wrote:
> >  So, they are distinct (the concepts are from Boost). There are
> > 
> > multiple duration types primarily because you can't convert between months and small units without a specific date, so you can't convert something like 5 months to days without knowing which months you're dealing with.
> 
> True, but why would a month be a type other than int?

Sure, a MonthDuration holds the number of months internally as an integral value, but if you have an int floating around by itself, it doesn't have any units, and the programmer has to worry about what the int actually means. They'd then have to worry about the conversions between various units of time (month, day, hour, etc.). The duration structs deal with that for you.

Even worse, what would it mean to add a naked number to a time point? If you add 7 to a date, what does that mean? And even if everyone agreed that it was clear that adding 7 to a date meant adding 7 days to it, adding 7 to a time of day wouldn't mean the same thing, so that naked number could mean very different things when added to two different types of time point. By having a duration type which includes the units, it's taken care of for you. You won't try and add months to time of day, because it won't compile. And if you try and add days to it, it will mean exactly the same thing as if you added days to a date (much as adding days to a time of day is relatively pointless). Overall, it should make the programmer's life easier rather than harder.

> >  However, I have
> > definite worked on making it so that you don't have to worry about the
> > multiple duration types in most cases. You'd do something like
> > Dur.years(5) + Dur.days(2) to create a duration of 5 years and 2 days,
> > and you don't have to know or care what the duration types are.
> 
> Ok, but I don't see that requires more than one duration type.

The problem with month vs smaller units is that you can't do _any_ conversion between them without a specific date. So, you can't have a duration that holds both months and days. Sure, when you subtract two dates, you have the information to do the conversion to smaller units, so you can have their difference be in days or seconds or whatever. But if you create durations directly - e.g. Dur.months(5) - then you have no way of converting the number of months to smaller units in order to be able to add the two durations together.

MonthDuration holds months and HNSecDuration holds hecto-nanoseconds (100 ns). There is no way to take those two and turn them into one type or to add the two of them together and result in a duration of either type (which is why JointDuration holds both rather than actually trying to add them together). There's no conversion. Once you add them to a specific time point, _then_ it's possible, but free-floating months and days can't be added together.

> > There are multiple time zone classes because it uses polymorphism to deal with the rules for a given time zone. The really basic LocalTime and UTC deal with most cases, but for anyone who really needs to deal with multiple time zones, PosixTimeZone and WindowsTimeZone will be invaluable (I'd love to only have one of those, but Windows just doesn't deal with time zones like the Posix world does).
> 
> I agree some kind of polymorphism for time zones is necessary. [rant] Timezones should be an operating system service, if for no other reason than it sucks to have all your apps break when some tinhorn country decides to change their daylight savings time, etc.[/rant]

Which is why PosixTimeZone and WindowsTimeZone will be getting that information from the OS, but the OS does not make it easy. On Posix, you have to actually read in the time zone files from disk, and on Windows, you have to read the registry. No system calls are provided to properly deal with time zones. Honestly, time zone support for anything other than the local time zone is very poor on both Posix and Windows systems. And Windows won't even let you set the time zone for your program without setting for the whole OS. It's not a pleasant situation really, but I hope to be able to overcome it well enough that D programmers won't have to worry about it.

- Jonathan M Davis
October 08, 2010

Jonathan M Davis wrote:
>
> Really, the ideal would be to have all of it in one module but have the code split up into several files. The closest way that I was aware to do that was to use a single module which publicly imported the others. I'll look at splitting it into an interface file and source file though.
>
> 

druntime does it for several modules, and can serve as an example.
October 08, 2010

Jonathan M Davis wrote:
>
>
> Sure, a MonthDuration holds the number of months internally as an integral value, but if you have an int floating around by itself, it doesn't have any units, and the programmer has to worry about what the int actually means. They'd then have to worry about the conversions between various units of time (month, day, hour, etc.). The duration structs deal with that for you.
>
> Even worse, what would it mean to add a naked number to a time point? If you add
> 7 to a date, what does that mean? And even if everyone agreed that it was clear
> that adding 7 to a date meant adding 7 days to it, adding 7 to a time of day
> wouldn't mean the same thing, so that naked number could mean very different
> things when added to two different types of time point. By having a duration type
> which includes the units, it's taken care of for you. You won't try and add
> months to time of day, because it won't compile. And if you try and add days to
> it, it will mean exactly the same thing as if you added days to a date (much as
> adding days to a time of day is relatively pointless). Overall, it should make
> the programmer's life easier rather than harder.
> 

Ok, I can see that.

>
> Which is why PosixTimeZone and WindowsTimeZone will be getting that information from the OS, but the OS does not make it easy. On Posix, you have to actually read in the time zone files from disk, and on Windows, you have to read the registry. No system calls are provided to properly deal with time zones. Honestly, time zone support for anything other than the local time zone is very poor on both Posix and Windows systems. And Windows won't even let you set the time zone for your program without setting for the whole OS. It's not a pleasant situation really, but I hope to be able to overcome it well enough that D programmers won't have to worry about it.
>
> 

I know it's a miserable job (I failed at it, despite spending a great deal of time on it), and since the OS falls down on it, it's a great service to have it in the standard library.
October 09, 2010
 On 09.10.2010 07:29, Jonathan M Davis wrote:
> Really, the ideal would be to have all of it in one module but have the code split up into several files. The closest way that I was aware to do that was to use a single module which publicly imported the others.
You could also use multiple files and combine those in one module using string mixins and import:

module std.datetime;

mixin(import("std/datetime_core.d"));
mixin(import("std/datetime_duration.d"));
mixin(import("std/datetime_interval.d"));

But this also brings lots of problems. I don't know whether it produces one ddoc file, line information for compile errors will be useless (maybe the #line directive could help by using #line 1 "datetime_core.d" in the implementation files)

-- 
Johannes Pfau

October 09, 2010
On 9 okt 2010, at 11:22, Johannes Pfau wrote:

> On 09.10.2010 07:29, Jonathan M Davis wrote:
>> Really, the ideal would be to have all of it in one module but have the code split up into several files. The closest way that I was aware to do that was to use a single module which publicly imported the others.
> You could also use multiple files and combine those in one module using string mixins and import:
> 
> module std.datetime;
> 
> mixin(import("std/datetime_core.d"));
> mixin(import("std/datetime_duration.d"));
> mixin(import("std/datetime_interval.d"));
> 
> But this also brings lots of problems. I don't know whether it produces one ddoc file, line information for compile errors will be useless (maybe the #line directive could help by using #line 1 "datetime_core.d" in the implementation files)
> 
> -- 
> Johannes Pfau
> 
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos


I think it would be better with multiple modules and one module which publicly imports the other modules. Then in the main module one can have a version(D_Ddoc) statement containing declarations of all the classes and functions from the other modules and the corresponding documentation as well. But I guess this is something similar to the .di/implementation approach suggested by Walter.

-- 
/Jacob Carlborg

October 09, 2010
This is an interesting discussion that I personally find very important.

One of the most annoying things in Phobos is that modules are too large and by too large I mean they contain lots and lots of stuff that are loosely related to each other.

I'm strongly against design like that. As a programmer I've been grown with idea of module separation in mind. At work, we are spending tens of hours discussing the same problem: code dependency reduction. In Phobos, it's just a disaster - every module is a monster that heavily depends or other monsters alike.

I've heard an opinion that it's hard for people to remember too many modules names. However, they know that you need to import std.array to use Appender, or std.algorithm to use sort etc. As such, it shouldn't be any harder for them to import std.algorithm.sort; or import std.array.appender; Alternatively, they may import std.algorithm.all and have the whole bulk of features at their disposal, but from my experience, that's not what is needed anyway. Here is a random import snippet from my code:

import core.memory : GC;
import core.atomic : cas;
import core.stdc.string : memcpy;
import core.sync.semaphore : Semaphore;

In ddmd, I have

module dmd.expression.Add;
module dmd.expression.And;
module dmd.expression.ArrayLength;
etc

each declaring just *one* method and only imports stuff that that particular module needs. It helps reducing module dependencies *a lot*.
October 09, 2010
I completely agree.

On 9 okt 2010, at 12:46, Denis wrote:

> This is an interesting discussion that I personally find very important.
> 
> One of the most annoying things in Phobos is that modules are too large and by too large I mean they contain lots and lots of stuff that are loosely related to each other.
> 
> I'm strongly against design like that. As a programmer I've been grown with idea of module separation in mind. At work, we are spending tens of hours discussing the same problem: code dependency reduction. In Phobos, it's just a disaster - every module is a monster that heavily depends or other monsters alike.
> 
> I've heard an opinion that it's hard for people to remember too many modules names. However, they know that you need to import std.array to use Appender, or std.algorithm to use sort etc. As such, it shouldn't be any harder for them to import std.algorithm.sort; or import std.array.appender; Alternatively, they may import std.algorithm.all and have the whole bulk of features at their disposal, but from my experience, that's not what is needed anyway. Here is a random import snippet from my code:
> 
> import core.memory : GC;
> import core.atomic : cas;
> import core.stdc.string : memcpy;
> import core.sync.semaphore : Semaphore;
> 
> In ddmd, I have
> 
> module dmd.expression.Add;
> module dmd.expression.And;
> module dmd.expression.ArrayLength;
> etc
> 
> each declaring just *one* method and only imports stuff that that
> particular module needs. It helps reducing module dependencies *a
> lot*.
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos

-- 
/Jacob Carlborg

October 09, 2010
Le 2010-10-09 ? 1:47, Jonathan M Davis a ?crit :

> Which is why PosixTimeZone and WindowsTimeZone will be getting that information from the OS, but the OS does not make it easy. On Posix, you have to actually read in the time zone files from disk, and on Windows, you have to read the registry. No system calls are provided to properly deal with time zones. Honestly, time zone support for anything other than the local time zone is very poor on both Posix and Windows systems. And Windows won't even let you set the time zone for your program without setting for the whole OS. It's not a pleasant situation really, but I hope to be able to overcome it well enough that D programmers won't have to worry about it.

I had the "pleasure" to work with time zones on Windows once, what a mess!

On OSX, Cocoa has an API for that, but you can probably get it the posix way too.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/