Thread overview
Is it bad form to put code in package.d other than imports?
Jan 03, 2018
Soulsbane
Jan 03, 2018
Jonathan M Davis
Jan 03, 2018
Soulsbane
Jan 03, 2018
H. S. Teoh
January 03, 2018
I've only understood that imports should go in package.d. I'm seeing more and more packages on code.dlang.org using it for the packages primary code. Is this alright? As far as I can tell it's just bad form. It would be nice to have one of the maintainers higher up the food chain comment on this!

Thanks!
January 03, 2018
On Wednesday, January 03, 2018 06:10:10 Soulsbane via Digitalmars-d-learn wrote:
> I've only understood that imports should go in package.d. I'm seeing more and more packages on code.dlang.org using it for the packages primary code. Is this alright? As far as I can tell it's just bad form. It would be nice to have one of the maintainers higher up the food chain comment on this!
>
> Thanks!

The entire reason that the package.d feature was added was so that it would be possible to split a module into a package without breaking code. Anything beyond that was beyond the scope of the purpose of the feature, albeit not necessarily in conflict with its original purpose.

For better or worse, a number of folks like being able to just import an entire package at once using it, so it's not uncommon for folks to set it up to do that, though personally, I'm not a fan of that.

All Phobos has done with package.d thus far is split modules into packages, not add it for importing packages that already exist. As for leaving code in package.d, the only package in Phobos that I'm aware of doing that on a permanent basis is std.range, and I have no idea why that was done. When std.algorithm and std.container were split, package.d was used for documentation purposes (which makes a lot of sense), but there's no real code in there. std.datetime's package.d has some now-deprecated functionality that was left in there rather than being put in a module when std.datetime was split, because there was no point in putting it in a module. In the long run though, all of that will be gone from std.datetime's package.d, and it too will only be used for documentation. I have no idea what folks have been doing on code.dlang.org.

In terms of functionality, there really isn't much special about package.d. If there were, we probably wouldn't have been able to talk Walter into it. We were able to precisely because public imports already worked in a way that allowed package.d to work. We just needed the feature to be added to make it possible to import a package. So, package.d allows that, but beyond that, it's just a normal module. It typically containts public imports for the rest of the package, but it doesn't have to, and it can contain whatever code you want to put in there. You can do whatever you want with it, though really, using it for much of anything at all beyond splitting up a package in place is beyond the scope of why it was introduced. But ultimately, there's nothing really special about package.d, and different folks have different ideas about it and how it should be used.

Personally, I don't think that it's very clean to be putting stuff other than documentation in package.d, and I don't really like the idea of setting it up to import the entire package under normal circumstances; I see it simply as a way to split up a module in place without breaking code, but that's just how I feel about it. I don't know that there are much in the way of objective arguments about package.d and how it should be used.

However, at this point, the trend in best practices is towards using scoped, selective imports as much as possible (since that reduces compilation times and more closely associates the imports with what's using them), and that pretty much flies in the face of the idea of importing an entire package at once. You _can_ use selective imports and package.d together, but it also makes the compiler do more work than if you just selectively imported from the module that the symbol is actually in. And if you're putting code directly in package.d, then it's not possible to import just that module unless it doesn't have any public imports in it. So, from a flexibility standpoint, it makes more sense to avoid putting symbols directly in package.d.

However, AFAIK, there really isn't much in the way of best practices with regards to package.d. All Phobos has done with it has been to split modules into packages like it was originally intended, and beyond that, folks have kind of done whatever they want. You may find a bunch of people agreeing with you that folks shouldn't be putting normal code in package.d, but AFAIK, there's no real general agreement on the matter one way or the other. There isn't really even agreement about whether package.d should be used when it isn't needed (and it's pretty much only needed when splitting up a module in-place).

- Jonathan M Davis

January 03, 2018
On Wednesday, 3 January 2018 at 07:43:52 UTC, Jonathan M Davis wrote:
> On Wednesday, January 03, 2018 06:10:10 Soulsbane via Digitalmars-d-learn wrote:
>> [...]
>
> The entire reason that the package.d feature was added was so that it would be possible to split a module into a package without breaking code. Anything beyond that was beyond the scope of the purpose of the feature, albeit not necessarily in conflict with its original purpose.
>
> [...]

Wow! Thanks Johnathan for the thorough explanation!
January 03, 2018
On Wed, Jan 03, 2018 at 12:43:52AM -0700, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Wednesday, January 03, 2018 06:10:10 Soulsbane via Digitalmars-d-learn wrote:
> > I've only understood that imports should go in package.d. I'm seeing more and more packages on code.dlang.org using it for the packages primary code. Is this alright? As far as I can tell it's just bad form. It would be nice to have one of the maintainers higher up the food chain comment on this!
[...]
> In terms of functionality, there really isn't much special about package.d.  If there were, we probably wouldn't have been able to talk Walter into it.  We were able to precisely because public imports already worked in a way that allowed package.d to work. We just needed the feature to be added to make it possible to import a package. So, package.d allows that, but beyond that, it's just a normal module. It typically containts public imports for the rest of the package, but it doesn't have to, and it can contain whatever code you want to put in there. You can do whatever you want with it, though really, using it for much of anything at all beyond splitting up a package in place is beyond the scope of why it was introduced. But ultimately, there's nothing really special about package.d, and different folks have different ideas about it and how it should be used.
[...]

I personally have used package.d to put declarations that are common to a particular package, e.g., package-global enums, constants, that sort of thing. This is particular the case when the package's submodules aren't usually directly imported by outside code, in which case I tend to think of package.d as the "baseline, common declarations", and if outside code demands, it can import a more specific submodule that exposes a more specific API for that package.

As Jonathan said, you can use package.d pretty much for whatever you want.


T

-- 
Claiming that your operating system is the best in the world because more people use it is like saying McDonalds makes the best food in the world. -- Carl B. Constantine