Thread overview
Can I create a package with friendly modules
Jun 12, 2022
forkit
Jun 12, 2022
forkit
Jun 12, 2022
Mike Parker
Jun 12, 2022
forkit
Jun 13, 2022
Mike Parker
Jun 12, 2022
Salih Dincer
Jun 13, 2022
Tejas
Jun 16, 2022
Salih Dincer
June 12, 2022
Is it possible to create a package.d, consisting of (for example), two modules, where each module can access private declarations within each other.

In essence, declaring 'a module level friendship', or a kind of 'extended module' if you want.

I might still want to add another module to the package, that is NOT part of that friendship between those other two modules, but is otherwise related to the solution.

June 12, 2022
On Sunday, 12 June 2022 at 05:05:46 UTC, forkit wrote:
>

e.g. If I could something like this:

// foo_1.d
module foo_1
private int a; // a is private to module foo_1

// foo_2.d
module foo_2
private int b; // b is private to module foo_2

// foo.d
module foo[dependencies:foo_1, foo_2];
import std;
writeln a; // can call foo_1.a directly even those its private to that module
writeln b; // can call foo_2.b directly even those its private to that module


June 12, 2022

On Sunday, 12 June 2022 at 05:05:46 UTC, forkit wrote:

>

Is it possible to create a package.d, consisting of (for example), two modules, where each module can access private declarations within each other.

In essence, declaring 'a module level friendship', or a kind of 'extended module' if you want.

I might still want to add another module to the package, that is NOT part of that friendship between those other two modules, but is otherwise related to the solution.

  • packagename
    -- package.d
    -- futuremodule.d
    --- subpackagename
    ---- friend1.d
    ---- friend2.d
// friend1.d
module packagename.subpackagename.friend1;

package void doSomethingFriendly();

///////
// friend2.d
module packagename.subpackagename.friend2;

import packagename.subpackagename.friend1;

void doSomething() { doSomethingFriendly(); }

///////
// package.d
module packagename;

public import
    packagename.subpackagename.friend1,
    packagename.subpackagename.friend2,
    packagename.futuremodule;
June 12, 2022

On Sunday, 12 June 2022 at 05:05:46 UTC, forkit wrote:

>

Is it possible to create a package.d, consisting of (for example), two modules, where each module can access private declarations within each other.

For this to be possible: You must first collect all modules in the directory with the same name as the module. Then you have to declare them with public import in package.d. If there are module specific things, you isolate them with package. Finally, compile it like this:

>

dmd main myproject/mymodule

main.d for example

import myproject.mymodule;

void main()
{
  S s;  // ok
  //P p // Error: undefined identifier `P`
  auto p = packageTest(); //ok
}

package.d for example

module myproject.mymodule;

public
{
  import myproject.mymodule.module1;
  import myproject.mymodule.module2;
  import myproject.mymodule.module3;
}

module1.d for example

module myproject.mymodule.module1;

struct S
{
  int i;
}

auto packageTest()
{
  return P();
}

package
{
  struct P
  {
    int i;
  }
}

SDB@79

June 12, 2022
On Sunday, 12 June 2022 at 05:46:17 UTC, Mike Parker wrote:
>

I don't get it.

How does this enable one module to access the private parts of another module?

Isn't 'private' *always* private to the module?

The idea I had, was to be able to spread a 'module' over more than one file - for the purpose of encapsulating this and that in different physical files, while *still* protecting the 'private is private to the module' concept.

e.g.

// main module
module myMainModule [extends: mod1, mod2, mod3];

when I compile this module myMainModule, the compiler brings the extensions of this module, and treats it as a single module.

similar to the concept of bringing in different modules into a package, only more fine-grained.

But if D has a one-to-one mapping between a module and a file, and if private is always private to the one module, then this could never work.

June 13, 2022
On Sunday, 12 June 2022 at 23:29:29 UTC, forkit wrote:

>
> I don't get it.
>
> How does this enable one module to access the private parts of another module?

It doesn't. But what you were describing in your post is package-level access. By keeping it the cross-module access in a subpackage, package is "private" to that subpackage.

>
> Isn't 'private' *always* private to the module?

Yes, which is why it doesn't allow cross-module access.

>
> The idea I had, was to be able to spread a 'module' over more than one file - for the purpose of encapsulating this and that in different physical files, while *still* protecting the 'private is private to the module' concept.

You can't spread modules across multiple files.

>
> But if D has a one-to-one mapping between a module and a file, and if private is always private to the one module, then this could never work.

Not with private. But what I described is the same effect.

June 13, 2022

On Sunday, 12 June 2022 at 05:05:46 UTC, forkit wrote:

>

Is it possible to create a package.d, consisting of (for example), two modules, where each module can access private declarations within each other.

In essence, declaring 'a module level friendship', or a kind of 'extended module' if you want.

I might still want to add another module to the package, that is NOT part of that friendship between those other two modules, but is otherwise related to the solution.

You can use package(qualifiedIdentifier) to satisfy this to a greater extent

Directory structure:


src
|
|--- main_file.d
|
|---parent
      |
      |--- driver.d
      |
      |--- package.d
      |
      |--- thing
             |
             |--- package.d
             |
             |--- first.d
             |
             |--- second.d
             |
             |--- third.d

Code :
src/main_file.d:

import parent;

void main()
{
	func();
}

src/parent/package.d:

module parent;

public import
	driver;

src/parent/driver.d:

module parent.driver;

import thing;

void func()
{
	S s;			// from third.d
	auto t = first.a;	// from second.d
	auto l = second.dbl;	// from first.d
}

src/parent/thing/package.d:

module parent.thing;

public import
	first,
	second,
	third;

src/parent/thing/first.d:

module thing.first;

import second;

static this()
{
	a = second.g; // can also access symbols within neighbouring modules
}
package(parent):
int a;
int b;
string c;

src/parent/thing/second.d:

module thing.second;

package(parent):

int g;
char p;
double dbl;

src/parent/thing/third.d:

module thing.third;

package(parent):

struct S
{
	int a;
	char c;
	string s;
}

private S private_struct; // can't access via parent package, since marked private

You run it via:
dmd -i -I=./parent -I=./parent/thing main_file.d
(I'm pretty sure it'll look far prettier using dub)

Here, all the symbols that are within package thing are visible to package parent as well, but not visible to any other package/module

June 16, 2022

On Monday, 13 June 2022 at 06:05:03 UTC, Tejas wrote:

>

Directory structure:


src
|
|--- main_file.d
|
|---parent
      |
      |--- driver.d
      |
      |--- package.d
      |
      |--- thing
             |
             |--- package.d
             |
             |--- first.d
             |
             |--- second.d
             |
             |--- third.d

Code :
src/main_file.d:

import parent;

void main()
{
	func();
}

src/parent/package.d:

module parent;

public import
	driver;

src/parent/driver.d:

module parent.driver;

import thing;

void func()
{
	S s;			// from third.d
	auto t = first.a;	// from second.d
	auto l = second.dbl;	// from first.d
}

src/parent/thing/package.d:

module parent.thing;

public import
	first,
	second,
	third;

src/parent/thing/first.d:

module thing.first;

import second;

static this()
{
	a = second.g; // can also access symbols within neighbouring modules
}
package(parent):
int a;
int b;
string c;

src/parent/thing/second.d:

module thing.second;

package(parent):

int g;
char p;
double dbl;

src/parent/thing/third.d:

module thing.third;

package(parent):

struct S
{
	int a;
	char c;
	string s;
}

private S private_struct; // can't access via parent package, since marked private

You run it via:
dmd -i -I=./parent -I=./parent/thing main_file.d
(I'm pretty sure it'll look far prettier using dub)

Here, all the symbols that are within package thing are visible to package parent as well, but not visible to any other package/module

Thanks, we all appreciate your efforts...

SDB@79