Thread overview
Multiple modules per file
Jun 20, 2022
Dennis
Jun 20, 2022
Paul Backus
Jun 20, 2022
Paul Backus
Jun 20, 2022
kinke
Jun 21, 2022
rikki cattermole
June 20, 2022

What if you could just concatenate .d files?

You could write a file pkg.d that looks like this:

/// Helper module
module pkg.sub;

string name;

/// Main application module
module pkg.app;

import pkg.sub;
void main()
{
    writeln("hello ", name);
}

/// My package
module pkg;

public import pkg.app;
public import pkg.sub;

And then this works:

dmd pkg.g

No new syntax like module {} or fancy tricks like mixin("module x;"), it would be as if the compiler splits up the file into multiple files as a preprocessing step.

Other files can only import pkg, since the compiler can't find e.g. pkg/sub.d.

Why?

It's best practice to keep modules small, but it's not always fun to deal with many small files.

In many text editors/IDEs it's easier to scan through a file than a file tree.

It's also easier to distribute. Notice how some libraries use stand alone files for convenience: arsd, stb, the SQLite Amalgamation. Sometimes, your code has to be condensed to one string of text for a web IDE, like codingame, godbolt, run.dlang.io, or when just posting in the forums / bugzilla.

And, of course, the recent discussion about private to the class, where putting a class in its own file is rejected as a solution.

Thoughts?

June 20, 2022

On Monday, 20 June 2022 at 15:48:08 UTC, Dennis wrote:

>

What if you could just concatenate .d files?

[...]

>

Other files can only import pkg, since the compiler can't find e.g. pkg/sub.d.

Well, presumably you could do it if you passed pkg.d explicitly on the command line. But it wouldn't work with dmd -i (and probably not with dub either).

This seems to me like a feature where the number of ways to use it right (e.g., for package-internal modules that aren't intended for outside use) is much smaller than the number of ways you could potentially shoot yourself in the foot with it. If we adopt this feature, I expect we'll end up getting a regular stream of questions in the Learn forum where someone asks "why doesn't my project build?", and the answer is "you need to put your modules in separate files."

You could mitigate the issue by requiring that all modules in a file belong to the same package, but then you lose out on some of the desirable godbolt/run.dlang.io use cases, so it's not a clear win.

June 20, 2022

On 6/20/22 11:48 AM, Dennis wrote:

>

Other files can only import pkg, since the compiler can't find e.g. pkg/sub.d.

This one thing might make it unsavory. But I still like it as a starting point.

-Steve

June 20, 2022

On Monday, 20 June 2022 at 15:48:08 UTC, Dennis wrote:

>

Thoughts?

Terrible. ;) - run.dlang.io supports something called HAR:

--- foo.d
void bla() {}

--- bar.d
import foo;
void main() { bla(); }
June 20, 2022

On 6/20/22 12:34 PM, Paul Backus wrote:

>

On Monday, 20 June 2022 at 15:48:08 UTC, Dennis wrote:

>

What if you could just concatenate .d files?

[...]

>

Other files can only import pkg, since the compiler can't find e.g. pkg/sub.d.

Well, presumably you could do it if you passed pkg.d explicitly on the command line. But it wouldn't work with dmd -i (and probably not with dub either).

Another option is to use a different filename for such "package modules", like .dp for "d package"?

>

This seems to me like a feature where the number of ways to use it right (e.g., for package-internal modules that aren't intended for outside use) is much smaller than the number of ways you could potentially shoot yourself in the foot with it. If we adopt this feature, I expect we'll end up getting a regular stream of questions in the Learn forum where someone asks "why doesn't my project build?", and the answer is "you need to put your modules in separate files."

Well, we already get messages because of the terrible error message you get when it can't find your module file (module object is in object.d which cannot be read). In this case, it might be even worse, suggesting that it can't read your module, when it's obviously in the right place.

In any case, I think the idea is worth exploring, but I don't know that it's a necessary addition.

-Steve

June 20, 2022

On Monday, 20 June 2022 at 17:15:07 UTC, Steven Schveighoffer wrote:

>

Another option is to use a different filename for such "package modules", like .dp for "d package"?

Yeah, this could work if you restrict it to one package per file.

>

Well, we already get messages because of the terrible error message you get when it can't find your module file (module object is in object.d which cannot be read). In this case, it might be even worse, suggesting that it can't read your module, when it's obviously in the right place.

That message has actually been improved in DMD 2.100:

$ cat test.d
import no_such_module;
$ dmd -c test.d
test.d(1): Error: unable to read module `no_such_module`
test.d(1):        Expected 'no_such_module.d' or 'no_such_module/package.d' in one of the following import paths:
import path[0] = /usr/include/dmd/phobos
import path[1] = /usr/include/dmd/druntime/import
June 21, 2022
For reference:

ML modules which I think are closer to the origin of the feature, did support multiple to a file. They were a little bit like a struct.

Of course they were paired with signatures, which as we all know are now in deep demand for a large range of reasons ;)