On Wednesday, 19 June 2013 at 07:12:30 UTC, Jonathan M Davis wrote:
On Wednesday, June 19, 2013 08:51:38 TommiT wrote:
I can't put a member function into a different file if it's
supposed to have access to private data of its enclosing
class/struct.

Then you can put the class in a different file. But even if
you can't, I don't think that it's worth it to complicate the
package attribute any further.

Let's now assume that we change the language specification so that 'package' access specifier allows access also to modules in nested packages. I'll show how difficult it can be to refactor your code in order to break it up into a package:

The file structure:
-------------------
/my_lib/mod_x.d
/my_lib/mod_y.d


File: /my_lib/mod_x.d
----------------------
module my_lib.mod_x;

import my_lib.mod_y;

void fun()
{
    my_lib.mod_y.S1 s1;
    s1.detail();
}


File: /my_lib/mod_y.d
----------------------
module my_lib.mod_y;

struct S1
{
    public void api()
    {
        S2 s2;
        s2.detail();
    }

    package void detail() { }
}

struct S2
{
    public void api() { }

    package void detail() { }
}

################################################################
Now, I want to break up both mod_x.d and mod_y.d into packages. I'll start by doing it naively and end up with this:

The file structure:
-------------------
/my_lib/mod_x/submod.d
/my_lib/mod_x/package.d
/my_lib/mod_y/submod_s1.d
/my_lib/mod_y/submod_s2.d
/my_lib/mod_y/package.d


File: /my_lib/mod_x/submod.d
-----------------------------
module my_lib.mod_x.submod;

import my_lib.mod_y;

void fun()
{
    my_lib.mod_y.S1 s1;
    s1.detail();
}


File: /my_lib/mod_x/package.d
------------------------------
module my_lib.mod_x;

public import my_lib.mod_x.submod;


File: /my_lib/mod_y/submod_s1.d
--------------------------------
module my_lib.mod_y.submod_s1;

import my_lib.mod_y.submod_s2;

struct S1
{
    public void api()
    {
        S2 s2;
        s2.detail();
    }

    package void detail() { }
}


File: /my_lib/mod_y/submod_s2.d
--------------------------------
module my_lib.mod_y.submod_s2;

struct S2
{
    public void api() { }

    package void detail() { }
}


File: /my_lib/mod_y/package.d
------------------------------
module my_lib.mod_y;

public import my_lib.mod_y.submod_s1;
public import my_lib.mod_y.submod_s2;

################################################################
At this point I notice this doesn't work because my_lib.mod_x.submod.fun tries to call my_lib.mod_y.S1.detail which is marked package and now in different package. In order to fix this without changing the public API, I'll create a new file called shared_s1.d, move the struct S1 there, and public import shared_s1.d back into the S1's original submod_s1.d file:

The file structure:
-------------------
/my_lib/mod_x/submod.d
/my_lib/mod_x/package.d
/my_lib/mod_y/submod_s1.d
/my_lib/mod_y/submod_s2.d
/my_lib/mod_y/package.d
/my_lib/shared_s1.d


File: /my_lib/shared_s1.d
--------------------------
module my_lib.shared_s1;

import my_lib.mod_y.submod_s2;

struct S1
{
    public void api()
    {
        S2 s2;
        s2.detail();
    }

    package void detail() { }
}


File: /my_lib/mod_y/submod_s1.d
--------------------------------
module my_lib.mod_y.submod_s1;

public import my_lib.shared_s1;


(other files stay the same)
################################################################
Now my_lib.mod_x.submod.fun has access rights and is able to call my_lib.mod_y.S1.detail because it's now an alias to my_lib.shared_s1.S1.detail. But then we notice that it doesn't work, because by moving the definition of S1 one folder up, we made it so that my_lib.shared_s1.S1.api isn't able to call my_lib.mod_y.submod_s2.S2.detail. So, we must do the same trick for the struct S2 now. Notice how viral this effect is. We end up with:

The file structure:
-------------------
/my_lib/mod_x/submod.d
/my_lib/mod_x/package.d
/my_lib/mod_y/submod_s1.d
/my_lib/mod_y/submod_s2.d
/my_lib/mod_y/package.d
/my_lib/shared_s1.d
/my_lib/shared_s2.d


File: /my_lib/shared_s2.d
--------------------------
module my_lib.shared_s2;

struct S2
{
    public void api() { }

    package void detail() { }
}


File: /my_lib/mod_y/submod_s2.d
--------------------------------
module my_lib.mod_y.submod_s2;

public import my_lib.shared_s2;


################################################################
And now it all works. But what did we learn from all this:

Your suggestion makes breaking modules into packages easier to understand but harder to do.

My suggestion makes breaking modules into packages harder to understand but easier to do.


On Wednesday, 19 June 2013 at 07:12:30 UTC, Jonathan M Davis wrote:
Even if we lose something in the process, we really don't lose
much, and since currently, package only applies to modules
directly in the same package and not nested packages, you'd
still be gaining over what we currently have.

I don't want 'package' symbols to give away access to nested packages.

Reply via email to