June 14, 2022

On Tuesday, 14 June 2022 at 13:49:30 UTC, Ola Fosheim Grøstad wrote:

>

It isn't necessarily through a different path unless you think that Bar is cloaking Foo, basically redoing everything that is Foo.

D encourages me to think about it as being similar to 'alias this', which seems to behave differently:

module a;

import b;

struct Foo
{
    private int _c;
}

void foo(Bar b)
{
    b._c = 1; // passes, to Mike's and my surprise
}

void main()
{
}
module b;

import a;

struct Bar
{
    Foo foo;
    alias foo this;
}
June 14, 2022

On Tuesday, 14 June 2022 at 16:33:10 UTC, Max Samukha wrote:

>

On Tuesday, 14 June 2022 at 13:49:30 UTC, Ola Fosheim Grøstad wrote:

>

It isn't necessarily through a different path unless you think that Bar is cloaking Foo, basically redoing everything that is Foo.

D encourages me to think about it as being similar to 'alias this', which seems to behave differently:

module a;

import b;

struct Foo
{
    private int _c;
}

void foo(Bar b)
{
    b._c = 1; // passes, to Mike's and my surprise
}

void main()
{
}
module b;

import a;

struct Bar
{
    Foo foo;
    alias foo this;
}

that looks like a bug too

June 14, 2022

On Tuesday, 14 June 2022 at 16:33:10 UTC, Max Samukha wrote:

>

On Tuesday, 14 June 2022 at 13:49:30 UTC, Ola Fosheim Grøstad wrote:

>

It isn't necessarily through a different path unless you think that Bar is cloaking Foo, basically redoing everything that is Foo.

D encourages me to think about it as being similar to 'alias this', which seems to behave differently:

alias this is a weird special case. It doesn't really behave like anything else in the language. You probably shouldn't draw any broad conclusions based on the behavior of alias this.

June 14, 2022
On Tuesday, 14 June 2022 at 10:47:18 UTC, forkit wrote:
> The decision to friend or unfriend should be a design consideration, and not a design constraint enforced onto you by the language.
>
> D has removed the need to use C++ like friend.

Yes, but it reached this by making the module the encapsulation unit.
If you want something to be a friend, put it in the same file.
If you want it to be no friend, put it in a different file.
If it's a member, you can do nothing about it - not with module level nor with class level privacy. Also not in C++ or Java or any other language I know about.

> Now I need a suitable, enforcable, design constraint, so i can unfriend.

Yes, now we're talking. What we need is no new level of privacy, we need a method to unfriend something - especially applicable also to member functions. THIS would give us some real new benefit.

This could be realized by a new UDA (adding to the attribute soup): @noPrivateAccess or likewise. Add this to a function and the compiler will error out if you try to use any module private variable within this function.
The problem is: This may not be useful very often, because there may be a lot of private things, and you would like only some of them to be not accessible by this function. So you can add a list of variables that should not be usable: @noPrivateAccess(bla, blubb)
Now this becomes really ugly. Maybe vice versa would be better: give it a list of private stuff it is allowed to access: @limitPrivateAccess(x)
I would think this is the best solution, because most of the time a single function will need only access to very few private variables. Of course without annotation a function can access everything within the module as always, to not breaking any existing code.
June 14, 2022

On Tuesday, 14 June 2022 at 17:16:04 UTC, Dom Disc wrote:

>

If it's a member, you can do nothing about it - not with module level nor with class level privacy. Also not in C++ or Java or any other language I know about.

Not sure what you meant by this. You can make the member a class that has its own privacy with a selective set of friends.

June 14, 2022

On Tuesday, 14 June 2022 at 16:57:34 UTC, Paul Backus wrote:

>

alias this is a weird special case. It doesn't really behave like anything else in the language. You probably shouldn't draw any broad conclusions based on the behavior of alias this.

In this simple case scoping rules should be exactly the same as those for class inheritance. Otherwise, we failed (or D is fundamentally incompatible with the way I think).

June 14, 2022
On Tuesday, 14 June 2022 at 17:16:04 UTC, Dom Disc wrote:
> On Tuesday, 14 June 2022 at 10:47:18 UTC, forkit wrote:
>> Now I need a suitable, enforcable, design constraint, so i can unfriend.
>
> Yes, now we're talking. What we need is no new level of privacy, we need a method to unfriend something - especially applicable also to member functions. THIS would give us some real new benefit.

If a function doesn't need access to private member variables, don't implement it as a member function. Instead, put it in a separate module and call it using UFCS.

https://www.ddj.com/cpp/how-non-member-functions-improve-encapsu/184401197
June 14, 2022

On Tuesday, 14 June 2022 at 17:24:31 UTC, Ola Fosheim Grøstad wrote:

>

On Tuesday, 14 June 2022 at 17:16:04 UTC, Dom Disc wrote:

>

If it's a member, you can do nothing about it - not with module level nor with class level privacy. Also not in C++ or Java or any other language I know about.

Not sure what you meant by this. You can make the member a class that has its own privacy with a selective set of friends.

What I mean is: You cannot prevent a member function from having access to the private variables of the class. Even if it should not touch them.

June 14, 2022
On Tuesday, 14 June 2022 at 19:39:40 UTC, Paul Backus wrote:
> If a function doesn't need access to private member variables, don't implement it as a member function. Instead, put it in a separate module and call it using UFCS.
Yes, that is nice.
But the most common usecase is that the class has multiple private variables, and each member function needs only access to some of them.
Today there is no way to express to which of them a function should have access and to which not.
My idea was the following:

class C
{
   private int _hidden_x;
   private int _hidden_y;
   @limitPrivateAccess(_hidden_x) foo(x)
   {
      _hidden_x = x;
      _hidden_y = 0; // error: foo has no access to _hidden_y
   }
}

So foo would normally have access to _hidden_y although the developer doesn't want that. That is so because today _all_ member functions (and friends) have access to _all_ private variables. The new UDA @limitPrivateAccess restrict this to only those private variables given as its parameters.
Together with a new privacy-level "@hidden" we could even have variables that no-one has access to, except those functions that are explicitly allowed to access them via the UDA. This would be the ultimate restriction level.
June 14, 2022
On Tuesday, 14 June 2022 at 05:43:49 UTC, forkit wrote:
> What do you think the cost of adding such a feature is?

Any cost above 0 is a no go here.

The feature is useless. If things shouldn't see each other's private, they don't belong in the same module.

Done, thanks for coming to my TED talk.