www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - Extending D's support for object-oriented design with private(this)

reply NotYouAgain <NotYouAgain gmail.com> writes:
TITLE: Extending D's support for object-oriented design with 
private(this)

NOTE: Only civil and well-informed discourse on this idea is 
welcome.

DIP forum guidelines are here: 
https://github.com/dlang/DIPs/blob/master/docs/guidelines-forums.md

BEGIN:

This DIP idea, relates to extending D's support for 
object-oriented design - by allowing private visibility to be 
attached to a class member.

The proposal creates no new limitations and no code breakage.

BACKGROUND:

The class type is the core building-block of class-based 
object-oriented design.

The facility for abstract, structured reasoning about a class 
type comes from its support for encapsulation.

D provides a class type, which in turn allows D to support 
class-based object-oriented design, with encapsulation, 
inheritance, and polymorphism.

see: https://dlang.org/spec/class.html

However, D's minimal encapsulation unit is actually a module, not 
a class.

That is, class private members are actually private module 
members, not private class members.

Although private class members cannot be interacted with from 
another module, they can be interacted with using code inside the 
same module (but outside of that class).

That's because (in D) the module, not the class, is the 
encapsulation unit.

Example (code in the same module - but outside of the class 
definition - accessing a private class member):

// --
module m;

     class C
     {
       private int _count; // visibilty of this member extends to 
the entire module.
     }

     unittest
     {
       C c = new C();
       c._count = 42;
     }

// ----

D also provides another form of encapsulation for 'a set of 
modules', when those modules all belong to the same package.

As such, a private class member cannot be interacted with from 
other modules that don't belong to the same package, but can be 
interacted with using code inside any of
the modules belonging to that package.

D's insistance (and apparent zealous protection) for having the 
module as the minimal encapsulation unit, is inconsistent with 
object-oriented design, where the class is itself a unit of 
encapsulation.

This has the following consequences:

(1) It makes it difficult to reason about a class definition in a 
module, when there is other code in the module, as all other code 
in the module is in essence a part of the class definition.

(2) It allows for accidental, unintended use of a private member 
by other code in the module, including unittests.

// --
module m;

     class C
     {
       private int _count; // visibilty of this member extends to 
the entire module.
       public void setCount(int c) { _count = c; }
     }

     unittest
     {
       C c = new C();
       c._count = 42; // Actually, this is a mistake, and the 
programmer should be testing the public method setCount(..)
     }

// ----

(3) One can only 'simulate' class-based encpasulation in D, by 
putting each class in its own module. This is, apparently, what 
is recommended whenever this topic is raised in the forums.

Both (1) (2) (3) can be fully resolved by adding private(this) 
functionality, as demonstrated here:

// --
module m;

     class C
     {
       private(this) int _count; // visibilty of this member is 
contained within this type
     }

     unittest
     {
       C c = new C();
       c._count = 42; // Error: data member _count is an 
inaccessible (private)property of type `m.C`
     }

// ----
Apr 24
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
Apart from literature review type content, there isn't much to discuss 
here. There is nothing to tune.

I suggest you start work on a draft DIP and move to development unless 
Walter or Atila have strong opinions against it.
Apr 24
next sibling parent reply Kagamin <spam here.lot> writes:
On Thursday, 25 April 2024 at 05:53:18 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 Apart from literature review type content, there isn't much to 
 discuss here. There is nothing to tune.
Nested classes.
Apr 25
parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 09:31:06 UTC, Kagamin wrote:
...
 Nested classes.
I believe that private(this) needs to always be consistent with its meaning. Altering its meaning for nested classes would not be appropriate. There is no code breakage. One simply can choose not to use private(this). class Outer { private(this) int m; class Inner { private int foo() { return m; // Error: class `test.Outer` variable `m` is not accessible } } }
Apr 25
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Friday, 26 April 2024 at 05:48:03 UTC, NotYouAgain wrote:
 On Thursday, 25 April 2024 at 09:31:06 UTC, Kagamin wrote:
...
 Nested classes.
And... class Outer { Inner newInner() { return new Inner(); } class Inner { private(this) this() // Error: class `EZ_Compiler_tmpfile.Outer.Inner` constructor `this` is not accessible { } } }
Apr 25
prev sibling next sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 05:53:18 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 Apart from literature review type content, there isn't much to 
 discuss here. There is nothing to tune.

 I suggest you start work on a draft DIP and move to development 
 unless Walter or Atila have strong opinions against it.
I'd like to see more discussion first. There are implications for derived classes (that are in the same module), and nested classes (which of course, are already in the same module). The feature would also open up the following 'new idiom' for creating and 'enforcing' pseudo static classes in D (which I like and use in OpenD). Some, I believe, may object to allowing such an idiom in D - but they should put forward their reasoning along with their objection. module m; safe: import std; final class C // final -> class cannot be derived from { private(this) this(){} // no instance of this class is possible // **not even by other code in the same module. private void test() {}; // although non-static members are allowed, but pointless, // since they can never be used - because of private(this) static: private(this) string message = "Hello!"; void sayHello() { writeln(message); } } unittest { C c = new C(); // Error: class `test.C` constructor `this` is not accessible writeln(C.message); // Error: property `message` is private to type `test.C` // static members are callable on a class even when no instance of the class exists. C.sayHello(); // ok }
Apr 25
prev sibling next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, April 24, 2024 11:53:18 PM MDT Richard (Rikki) Andrew Cattermole 
via dip.ideas wrote:
 Apart from literature review type content, there isn't much to discuss
 here. There is nothing to tune.

 I suggest you start work on a draft DIP and move to development unless
 Walter or Atila have strong opinions against it.
Well, Walter has consistently shot down requests for this kind of feature in the past (and there was a discussion in the newsgroup within just the past couple of months where it came up IIRC, and Walter shot it down then), so unless someone can come up with a really compelling reason why it's needed, it's going to be shot down. Unless something has changed quite recently, Walter's opinion on this has already been made quite clear, and it's been the same for years. The normal answer is that if you really need the other code in the module to not have access to the class' members, then that class should just go in another module. In practice, the current situation rarely causes problems. It seems more to be something that annoys some folks on principle rather than being an actual technical issue. I would be shocked if this DIP went anywhere. - Jonathan M Davis
Apr 25
next sibling parent bachmeier <no spam.net> writes:
On Thursday, 25 April 2024 at 19:48:11 UTC, Jonathan M Davis 
wrote:
 On Wednesday, April 24, 2024 11:53:18 PM MDT Richard (Rikki) 
 Andrew Cattermole via dip.ideas wrote:
 Apart from literature review type content, there isn't much to 
 discuss here. There is nothing to tune.

 I suggest you start work on a draft DIP and move to 
 development unless Walter or Atila have strong opinions 
 against it.
Well, Walter has consistently shot down requests for this kind of feature in the past (and there was a discussion in the newsgroup within just the past couple of months where it came up IIRC, and Walter shot it down then), so unless someone can come up with a really compelling reason why it's needed, it's going to be shot down. Unless something has changed quite recently, Walter's opinion on this has already been made quite clear, and it's been the same for years. The normal answer is that if you really need the other code in the module to not have access to the class' members, then that class should just go in another module. In practice, the current situation rarely causes problems. It seems more to be something that annoys some folks on principle rather than being an actual technical issue. I would be shocked if this DIP went anywhere. - Jonathan M Davis
My understanding of the difference with this proposal is that it would leave the module as the unit of encapsulation, but it would add a second type of privacy. I don't know if that would convince Walter, but AFAICT, this change wouldn't lead to requests to add friend to the language.
Apr 25
prev sibling next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 19:48:11 UTC, Jonathan M Davis 
wrote:
 On Wednesday, April 24, 2024 11:53:18 PM MDT Richard (Rikki) 
 Andrew Cattermole via dip.ideas wrote:
 Apart from literature review type content, there isn't much to 
 discuss here. There is nothing to tune.

 I suggest you start work on a draft DIP and move to 
 development unless Walter or Atila have strong opinions 
 against it.
Well, Walter has consistently shot down requests for this kind of feature in the past (and there was a discussion in the newsgroup within just the past couple of months where it came up IIRC, and Walter shot it down then), so unless someone can come up with a really compelling reason why it's needed, it's going to be shot down. Unless something has changed quite recently, Walter's opinion on this has already been made quite clear, and it's been the same for years. The normal answer is that if you really need the other code in the module to not have access to the class' members, then that class should just go in another module. In practice, the current situation rarely causes problems. It seems more to be something that annoys some folks on principle rather than being an actual technical issue. I would be shocked if this DIP went anywhere. - Jonathan M Davis
The requirement in D, that there be no other code in a module (including unittests), other than a class, in order to demonstrate to the compiler (and those that read the code) that the class is meant to be truly encapsulated, is a consequence of the module being the unit of encapsulation. Allowing a class to explicately define its encapsulated properties, seems to me, a much better solution, and consistent with what most people who use class-oriented oop would expect. It would also solve consequences (1) and (2) outline in my opening remark. (1) It makes it difficult to reason about a class definition in a module, when there is other code in the module, as all other code in the module is in essence a part of the class definition. (2) It allows for accidental, unintended use of a private member by other code in the module, including unittests. In the example below, neither the compiler nor someone reading the code, would know that the class is being used incorrectly in this unittest. Only by allowing the programmer of the class to be explicit about the encapsulated properties of the class, can the compiler and those reading this code below, identify the problem. Yes, you could say the programmer must put the unittest in a separate module to the class, and then the unitttest can be interpreted correctly. But this extra burden on the programmer in completely unnessecary if D has something like private(this). As for Walters opinion on this, I don't think I can recall ever seeing it, let alone any explanation for that opinion. But here and now seems like the best place to voice that, don't you think? I've already given reasons for why this feature would be useful. The reasons are valid. Objections to this idea should have there reasons as well, so we can test the validity of those objections. btw. The problem in the code below, is one of 'principle'. // -- module m; class C { private int _count; // visibilty of this member extends to the entire module. public void setCount(int c) { _count = c; } } unittest { C c = new C(); c._count = 42; // Actually, this is a mistake, and the programmer should be testing the public method setCount(..) } // ----
Apr 25
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 22:47:17 UTC, NotYouAgain wrote:
 ..
oops. that should have been: "btw. The problem in the code below, is NOT one of 'principle'."
Apr 25
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 19:48:11 UTC, Jonathan M Davis 
wrote:
 ..
 ...
 The normal answer is that if you really need the other code in 
 the module to not have access to the class' members, then that 
 class should just go in another module. In practice, the 
 current situation rarely causes problems. It seems more to be 
 something that annoys some folks on principle rather than being 
 an actual technical issue. I would be shocked if this DIP went 
 anywhere.

 - Jonathan M Davis
Another example, again, not on principle, but an actual issue. The class below is from: https://dlang.org/spec/class.html#invariants Sadly, the invariant here is ignored when I access the private member directly. The below will pass the unittest. However, by changing: private: int day; int hour; to: private(this): int day; int hour; not only has the author made their intent clear (as they have the tool to do it with private(this), but the compiler will now know the intent as well, and will rightly refuse to compile the code. // --------------- module m; safe: import std; class Date { this(int d, int h) { day = d; // days are 1..31 hour = h; // hours are 0..23 } invariant { assert(1 <= day && day <= 31); assert(0 <= hour && hour < 24); } private: int day; int hour; } unittest { Date d = new Date(1,1); d.day = 0; // invariant has no effect here. // day/hour really should not be accessible here anyway // - but there's no way in D to prevent this, // except by putting the unittest in a separate module to the class. } // -----------
Apr 26
prev sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 05:53:18 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 Apart from literature review type content, there isn't much to 
 discuss here. There is nothing to tune.
 ....
What literature review type content would you be expecting? If i say the earth is round, to I need to cite literature? If i say private class attributes are an important, widely used component for enhancing encapsulation, and all the benefits that flow from that; do I need to cite litereature for this? The very purpose of the idea for private(this) is to have an easier to use mechanism for having class attributes that are private to the class 'within' a module, and having those attributes enforced by the compiler. I don't think anyone is going to argue that class-oriented oop does not greatly benefit from having class attributes that can be private to the class ;-) So what would an argument against this idea be exactly? That D already offers you a harder way to do it, and you should just accept that? i.e never put other code in a module, if the module has a class in it. and never put a unittest in that module either. then...and only then.. is your problem solved. No. A harder way to do it, ensures programmers will not do it, and may not even both to use D. D needs an easier way. Please..please... someone come up with a different argument against this idea. But in regards to literature, this is interesting (especially the AHF findings): https://www.researchgate.net/publication/2478145_Toward_the_Design_Quality_Evaluation_of_Object-Oriented_Software
Apr 26
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 26/04/2024 11:36 PM, NotYouAgain wrote:
 On Thursday, 25 April 2024 at 05:53:18 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:
 
     Apart from literature review type content, there isn't much to
     discuss here. There is nothing to tune. ....
 
 What literature review type content would you be expecting?
Nothing for me personally. But yourself or others might have something interesting to share!
Apr 26
prev sibling next sibling parent reply zjh <fqbqrr 163.com> writes:
On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:
 TITLE: Extending D's support for object-oriented design with 
 private(this)
This improvement has no `side effects` on the `d` language. I really don't know why they `oppose` it?
Apr 24
parent reply Dom DiSc <dominikus scherkl.de> writes:
On Thursday, 25 April 2024 at 06:05:23 UTC, zjh wrote:
 This improvement has no `side effects` on the `d` language. I 
 really don't know why they `oppose` it?
Opposition was only because of "friend"s, which destroys encapsulation in an unpredictable manner. As long as no "friend" attribute is proposed, everything is fine. Already works without problems in OpenD.
Apr 25
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 08:08:40 UTC, Dom DiSc wrote:
 On Thursday, 25 April 2024 at 06:05:23 UTC, zjh wrote:
 This improvement has no `side effects` on the `d` language. I 
 really don't know why they `oppose` it?
Opposition was only because of "friend"s, which destroys encapsulation in an unpredictable manner. As long as no "friend" attribute is proposed, everything is fine. Already works without problems in OpenD.
If my understanding is correct, the concern was not about 'friends' but 'C++ like' friends. That is, friends that could essentially be anywhere.....and difficult to track down. But D also has a 'friends' notion, implicately. That is, all code in the module is essentially a friend of any class in the module, and within a package of modules, that notion extends further. It's implicit in D, because the module is the unit of encapsulation, not the class. So I'd say that D understands the necessity for a friend feature - it just restricts the borders of its use (i.e. to the module, or a package of modules). This idea never involved the concept of 'C++ like' friends, nor would it even be needed, since a more suitably 'constrained border' for friendship is already in D - i.e. the module (or modules within a package). And yes, I'm not aware of any problems using this feature that is already in OpenD ;-)
Apr 25
prev sibling next sibling parent reply Lance Bachmeier <no spam.net> writes:
On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:

 Both (1) (2) (3) can be fully resolved by adding private(this) 
 functionality, as demonstrated here:

 // --
 module m;

     class C
     {
       private(this) int _count; // visibilty of this member is 
 contained within this type
     }

     unittest
     {
       C c = new C();
       c._count = 42; // Error: data member _count is an 
 inaccessible (private)property of type `m.C`
     }

 // ----
This introduces a more restricted version of private. Overloading `private` to give it a second meaning is going to cause confusion for new users and really anyone that doesn't use D's OOP all the time. I recommend using something like `hidden` or `strongprivate`.
Apr 25
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 26/04/2024 12:55 AM, Lance Bachmeier wrote:
 This introduces a more restricted version of private. Overloading 
 `private` to give it a second meaning is going to cause confusion for 
 new users and really anyone that doesn't use D's OOP all the time. I 
 recommend using something like `hidden` or `strongprivate`.
Hidden is used as an attribute, defined as a UDA in ``core.attributes``. It is related to exportation, so that is already taken.
Apr 25
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 12:55:33 UTC, Lance Bachmeier wrote:
 This introduces a more restricted version of private. 
 Overloading `private` to give it a second meaning is going to 
 cause confusion for new users and really anyone that doesn't 
 use D's OOP all the time. I recommend using something like 
 `hidden` or `strongprivate`.
Yes, private(this) is more restricted, only in that it applies concept of private to the type - which is what the vast majority of class-oriented oo programmers would expect. And being able to 'explicetly' ensapsulate a member to the type itself, is a no-brainer to oop programmers. But they can't do that in D. In an ideal world, D would have done what Swift did - and have 'private' mean what most oop's would expect it to mean (that is, restricted to the enclosing declaration), and 'file-private' to mean what private means in D (that is, private to the module file). But its rarely and ideal world. A breaking change to fix this would *never* be accepted, *understandably*. this(this) is an already available construct in D. private(this) seems the best way to proceed I believe, since it *does* need to have the word 'private' in it, which is what any oop would expect. - 'strongprivate' suggest nothing really. - 'hidden' lacks clarity of its meaning. - 'private(this)' - private to 'this' (ie. this type) .. seems to me, to bring sufficient clarity to the construct, especially since the notion of 'this' is already clear in D classes. Therefore private(this) seems the most sensible way to implement this - at this stage, given the above points.
Apr 25
prev sibling next sibling parent reply Nick Treleaven <nick geany.org> writes:
It should say whether __traits(getMember), allMembers and 
.tupleof can access private(this) members.

private(this) maybe should be the default for synchronized 
classes.

BTW regarding unit tests, I would like to have `public unittest` 
disallow access to anything non public. Perhaps if accepted, 
there could later be private(this) to opt-in to accessing those 
fields. That is important when the class is a template and you 
don't want the test instantiated every time the template is 
instantiated.
Apr 25
next sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 13:35:29 UTC, Nick Treleaven wrote:
 It should say whether __traits(getMember), allMembers and 
 .tupleof can access private(this) members.
 ..
 ...
This unittest would pass: module m; safe: import std; class C { private(this): int x; } unittest { auto c = new C; static assert(__traits(getVisibility, C.x) == "private(this)"); static assert(__traits(hasMember, C, "x") == true); }
Apr 25
prev sibling next sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 13:35:29 UTC, Nick Treleaven wrote:
 It should say whether __traits(getMember), allMembers and 
 .tupleof can access private(this) members.
 ..
 ....
Yes, this would pass as well: (btw. you can test all this in OpenD, as it already has private(this) module m; safe: import std; class C { private(this): int x; } unittest { auto c = new C; foreach (i, ref part; c.tupleof) writeln(__traits(identifier, c.tupleof[i])); }
Apr 25
prev sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 13:35:29 UTC, Nick Treleaven wrote:
 It should say whether __traits(getMember), allMembers and 
 .tupleof can access private(this) members.

 private(this) maybe should be the default for synchronized 
 classes.
Does that mean, that 'private(this)' would solve: https://issues.dlang.org/show_bug.cgi?id=23158
Apr 26
parent Nick Treleaven <nick geany.org> writes:
On Friday, 26 April 2024 at 07:41:37 UTC, NotYouAgain wrote:
 On Thursday, 25 April 2024 at 13:35:29 UTC, Nick Treleaven 
 wrote:
 It should say whether __traits(getMember), allMembers and 
 .tupleof can access private(this) members.

 private(this) maybe should be the default for synchronized 
 classes.
Does that mean, that 'private(this)' would solve: https://issues.dlang.org/show_bug.cgi?id=23158
Yes, if synchronized class members are only allowed to be `private(this)`.
Apr 26
prev sibling next sibling parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:
 […]
I don’t know why, but I find `private(this)` looks weird. It makes me think I can put other things in the parentheses – which is not the case. How about `super private`? `super` is already a keyword. Yes, it’s a little bit tongue-in-cheek, but I honestly like it more than `private(this)`.
Apr 25
next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Thursday, 25 April 2024 at 16:40:30 UTC, Quirin Schroll wrote:
 On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:
 […]
I don’t know why, but I find `private(this)` looks weird. It makes me think I can put other things in the parentheses – which is not the case. How about `super private`? `super` is already a keyword. Yes, it’s a little bit tongue-in-cheek, but I honestly like it more than `private(this)`.
shouldnt it be `private alias this this;`
Apr 25
parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 17:14:23 UTC, monkyyy wrote:
 ..
 ...
 shouldnt it be `private alias this this;`
There are 2 ways I can interpret your contribution to this discussion. (1) You believe 'private alias this this;' is better that 'private(this)' (2) You are being derisive If it is the former, I don't agree. If it is the latter, I don't believe that derision is in the spirit of the guidelines for this forum group.
Apr 25
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 26 April 2024 at 00:36:37 UTC, NotYouAgain wrote:
 If it is the latter, I don't believe that derision is in the 
 spirit of the guidelines for this forum group.
I aint one for rules, but if your hall monitoring I would think accusing others of bad faith is worth twisting the knife. If I was being "derisive" I would be commenting on how oo should be removed from the language entirely; at minimum. oo-philes may not understand `alias this` statements, fine, but to break down `private alias this this`, `alias this` must use old fashioned alias statements so essentially its saying `private alias this=this`; given alias this is where the special case handling of a struct lives, and my understanding is `private` prepending statements is how to break otherwise perfectly good code for "safety" so I completely stand by my suggestion.
Apr 25
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Friday, 26 April 2024 at 02:27:49 UTC, monkyyy wrote:
 On Friday, 26 April 2024 at 00:36:37 UTC, NotYouAgain wrote:
 If it is the latter, I don't believe that derision is in the 
 spirit of the guidelines for this forum group.
I aint one for rules, but if your hall monitoring I would think accusing others of bad faith is worth twisting the knife. If I was being "derisive" I would be commenting on how oo should be removed from the language entirely; at minimum. oo-philes may not understand `alias this` statements, fine, but to break down `private alias this this`, `alias this` must use old fashioned alias statements so essentially its saying `private alias this=this`; given alias this is where the special case handling of a struct lives, and my understanding is `private` prepending statements is how to break otherwise perfectly good code for "safety" so I completely stand by my suggestion.
sorry. I still don't understand what your input to this discussion is (appart from that you don't like oop). Are you're saying you weren't being derisive, but you genuinely prefer 'private alias this this;' to 'private(this)'?
Apr 25
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 16:40:30 UTC, Quirin Schroll wrote:
 On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:
 […]
I don’t know why, but I find `private(this)` looks weird. It makes me think I can put other things in the parentheses – which is not the case. How about `super private`? `super` is already a keyword. Yes, it’s a little bit tongue-in-cheek, but I honestly like it more than `private(this)`.
Do I take it, that you're in agreement, that this is a solution to a problem, and that you're just uncomfortable with how private(this) looks? If so... you can already do things like this in D: struct A { this(this) {} }
Apr 25
prev sibling next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:

In anticipation of this new question (what happens it you use 
private(this) in global scope?

I can answer this below (in code):

module m;
 safe:

import std;

private(this) int x; // Error: visibility attribute 
`private(this)` cannot be used in global scope

void main(){}
Apr 25
parent Kagamin <spam here.lot> writes:
On Friday, 26 April 2024 at 06:39:31 UTC, NotYouAgain wrote:
 In anticipation of this new question (what happens it you use 
 private(this) in global scope?

 I can answer this below (in code):

 module m;
  safe:

 import std;

 private(this) int x; // Error: visibility attribute 
 `private(this)` cannot be used in global scope

 void main(){}
Conceptually module is a class, so its visibility design can follow nested class design.
Apr 26
prev sibling next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:

fyi.. for those interested in the source code changes that were 
needed to implement private(this):

https://github.com/dlang/dmd/compare/master...dkorpel:dmd:private-this#diff-8da4a723a20020bf5d1edf1a9f1344eb776c73a0ae35ccee95d3bc24cb0600a7R242
Apr 26
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Friday, 26 April 2024 at 10:44:11 UTC, NotYouAgain wrote:
 On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:

 fyi.. for those interested in the source code changes that were 
 needed to implement private(this):

 https://github.com/dlang/dmd/compare/master...dkorpel:dmd:private-this#diff-8da4a723a20020bf5d1edf1a9f1344eb776c73a0ae35ccee95d3bc24cb0600a7R242
oops: https://github.com/opendlang/opend/commit/3f77889a26043e1a0a82e27ace80b2d2285b4ad8
Apr 26
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:

 (2) It allows for accidental, unintended use of a private 
 member by other code in the module, including unittests.

 // --
 module m;

     class C
     {
       private int _count; // visibilty of this member extends 
 to the entire module.
       public void setCount(int c) { _count = c; }
     }

     unittest
     {
       C c = new C();
       c._count = 42; // Actually, this is a mistake, and the 
 programmer should be testing the public method setCount(..)
     }
```d module m; class C { private(this) int _count; public void setCount(int c) { _count = c; } unittest { C c = new C(); c._count = 42; // oops, this is still allowed } } ``` 1. unittests being able to examine/manipulate private data is *expected* and *desired*. How else do you plan to validate things are happening properly without having to expose more public functions than necessary? I'd expect a line such as `assert(c._count == 0);` to be a valid line in a unittest. 2. unittests generally are placed close to the things they test, and in fact are required to do so for documented unittests. This means they will be inside the class, and still have access to `private(this)` data. I don't find the arguments compelling enough to make this new feature. An entire module is as examinable as an entire class definition. It's already open in your editor even. -Steve
Apr 26
next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Friday, 26 April 2024 at 16:38:54 UTC, Steven Schveighoffer 
wrote:
 ..
 ...
 1. unittests being able to examine/manipulate private data is 
 *expected* and *desired*. How else do you plan to validate 
 things are happening properly without having to expose more 
 public functions than necessary? I'd expect a line such as 
 `assert(c._count == 0);` to be a valid line in a unittest.
 2. unittests generally are placed close to the things they 
 test, and in fact are required to do so for documented 
 unittests. This means they will be inside the class, and still 
 have access to `private(this)` data.

 I don't find the arguments compelling enough to make this new 
 feature. An entire module is as examinable as an entire class 
 definition. It's already open in your editor even.

 -Steve
I don't agree with any of those propositions. What value is there in allowing 'c._count == 0;' to be a valid part of a unittest when the class design implicitely (cause there is no explicit attribute available) makes c a private member to only be accessed through a public method? You say 'An entire module is as examinable as an entire class definition.' - I say, that is exactly the problem that 'private(this)' can fix! i.e. I want the class definition to be the class definition, and not the module definition to be the class definition. At the moment, a class definition inside a module that contains other code in the same module, is about as useful as: int foo(T* p); "Is p an array? is foo() going to mutate what it points to? Is foo() going to free() it? How would I know without reading the implementation?" - Walter Bright. It also makes the unittest in a module, an unreliable tool for testing - as you cannot rely upon the unittest to test what you think it should be testing. Only in D, can a class definition mean something completely different when there is other code nearby. I'm not aware of any other language where the same applies. It's worse than C++ friends. It's friendship galore... there is no way to control it inside a module, making classes difficult to reason about without taking into account all other code in the module. And using unittests in the same module as the class, as a tool for design verification tool, is just pointless - and prone to errors, as I've demonstrated - since the compiler cannot reason about the class intent either. D is different to many well known languages, in that it stems from pragmatism more than theory. But ignoring type theory has consequences. How can you reason about a class type, when that type has no means to control its own borders? Those borders are just as important 'inside' the module, as they are outside the module. This I think, is where any disagreement applies. All I'm asking for, is the tool to create those borders for use 'inside' the module. You see it as a 'new' feature' I see it as a feature that should already be there. There are clear benefits that arise from such a tool, as I've begun to demonstrate. If you're saying these benefits are not real, I have to disagree.
Apr 26
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Friday, 26 April 2024 at 23:42:48 UTC, NotYouAgain wrote:

 I don't agree with any of those propositions.
OK, and that is understandable. What I'm trying to convey is that *this is a design decision*. You may not agree with it, but it is not something that I think is "fundamental" to OO programming. I don't need to continue this, I've said my piece, and I'm not interested in further discussion on this. If you end up with a more formal proposal I likely will argue against it, but no hard feelings, I fully understand that there are certain points of view that I don't agree with but that reasonable people will think is correct or better. We can agree to disagree, and still be friends ;) -Steve
Apr 27
next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 22:59:29 UTC, Steven Schveighoffer 
wrote:
 On Friday, 26 April 2024 at 23:42:48 UTC, NotYouAgain wrote:

 I don't agree with any of those propositions.
OK, and that is understandable. What I'm trying to convey is that *this is a design decision*. You may not agree with it, but it is not something that I think is "fundamental" to OO programming. I don't need to continue this, I've said my piece, and I'm not interested in further discussion on this. If you end up with a more formal proposal I likely will argue against it, but no hard feelings, I fully understand that there are certain points of view that I don't agree with but that reasonable people will think is correct or better. We can agree to disagree, and still be friends ;) -Steve
Actually, here is the fundamental problem: D won't let me expression my intent in the code below. Had I wanted to express a const or an immutable (for example) I can express it - D won't stand in my way there. But if I want to something that the vast majority of class-oriented oop programmers would expect to, that is, declare a member in my class-type to 'actually' be private to that type, then D and all the usual naysayers that come out when this topic is raised, insist on standing in my way. No they say. You actually don't need to do that. But if you do, put the subclass in separate module. Put the unittest in their separate module as well. So do you see the 'actual' problem here, or just the one you want to see? That there is so much fierce opposition to such a simple proposition, has always been bewildering. The source of that opposition, is usually a hate for oop in general, a hate for oo programmers (e.g calling them oop..philes), a wish to see oop stripped complelely out of D, or an insistence that all class-oriented oo programmers change how they think, so that think the way D wants to them think (a form of mind coercion really). The idea is that a class should have an option to have truly private member, is sound. The oppostition is the fundamental problem.
Apr 27
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Sunday, 28 April 2024 at 00:07:22 UTC, NotYouAgain wrote:
 On Saturday, 27 April 2024 at 22:59:29 UTC, Steven 
 Schveighoffer wrote:
 On Friday, 26 April 2024 at 23:42:48 UTC, NotYouAgain wrote:

 I don't agree with any of those propositions.
OK, and that is understandable. What I'm trying to convey is that *this is a design decision*. You may not agree with it, but it is not something that I think is "fundamental" to OO programming. I don't need to continue this, I've said my piece, and I'm not interested in further discussion on this. If you end up with a more formal proposal I likely will argue against it, but no hard feelings, I fully understand that there are certain points of view that I don't agree with but that reasonable people will think is correct or better. We can agree to disagree, and still be friends ;) -Steve
Actually, here is the fundamental problem: D won't let me expression my intent in the code below. Had I wanted to express a const or an immutable (for example) I can express it - D won't stand in my way there. But if I want to something that the vast majority of class-oriented oop programmers would expect to, that is, declare a member in my class-type to 'actually' be private to that type, then D and all the usual naysayers that come out when this topic is raised, insist on standing in my way. No they say. You actually don't need to do that. But if you do, put the subclass in separate module. Put the unittest in their separate module as well. So do you see the 'actual' problem here, or just the one you want to see? That there is so much fierce opposition to such a simple proposition, has always been bewildering. The source of that opposition, is usually a hate for oop in general, a hate for oo programmers (e.g calling them oop..philes), a wish to see oop stripped complelely out of D, or an insistence that all class-oriented oo programmers change how they think, so that think the way D wants to them think (a form of mind coercion really). The idea is that a class should have an option to have truly private member, is sound. The oppostition is the fundamental problem.
class ClassWithPrivateField { private int privateField; // actually, my intent here is private(this), // but it cannot be expressed in D. // guess I better put the subclass in its own module // in the hope that someone thinks by doing that, // I've expressed that intent. this() { this.privateField = 42; } } class Subclass : ClassWithPrivateField { private int subPrivateField; this() { this.subPrivateField = 23; this.privateField = 52; // is this a mistake? The compiler has no way to know. } }
Apr 27
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 22:59:29 UTC, Steven Schveighoffer 
wrote:
 On Friday, 26 April 2024 at 23:42:48 UTC, NotYouAgain wrote:

 I don't agree with any of those propositions.
OK, and that is understandable. What I'm trying to convey is that *this is a design decision*. You may not agree with it, but it is not something that I think is "fundamental" to OO programming. I don't need to continue this, I've said my piece, and I'm not interested in further discussion on this. If you end up with a more formal proposal I likely will argue against it, but no hard feelings, I fully understand that there are certain points of view that I don't agree with but that reasonable people will think is correct or better. We can agree to disagree, and still be friends ;) -Steve
We can be friends, sure, but this unittest below is certainly not my friend ;-) Yes, I know the solution you will come up with. Put these two classes in separate modules, and make sure the unittest is not in the same module as Point; D really is module-oriented-programming, not object-oriented-programming. Its claim to support oop is rather dubious. One would need private(this) and protected(this), and then D could claim to support object-oriented-programming. module m; unittest { import std; ColoredPoint c = new ColoredPoint(2, 4); writefln("%s : %s", c.x, c.y); // 2 : 4 c.reset(); // actually this shouldn't even be allowed. It is not in the intent of the design. c.clear(); // only the clear() method should be using reset() writefln("%s : %s", c.x, c.y); // 0 : 0 } class Point { private int x, y; this(int x, int y) { this.x = x; this.y = y; }; // the intent here, is that reset() be only callable from ColoredPoint. // but because protected is also public inside a module, there is // no way in D to 'declare' that intent. protected void reset() { this.x = 0; this.y = 0; } } class ColoredPoint : Point { this(int x, int y) { super(x, y); }; void clear() { reset(); } }
Apr 28
prev sibling next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Friday, 26 April 2024 at 16:38:54 UTC, Steven Schveighoffer 
wrote:
...
 module m;

 class C
 {
    private(this) int _count;
    public void setCount(int c) { _count = c; }

    unittest
    {
       C c = new C();
       c._count = 42; // oops, this is still allowed
    }
 }
 ```
There is no 'oops' there. The unittest is a member of the class! It the unittest outside of the class that should not be allowed to compile.
Apr 26
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 27/04/2024 11:50 AM, NotYouAgain wrote:
 On Friday, 26 April 2024 at 16:38:54 UTC, Steven Schveighoffer wrote:
 ...
 module m;

 class C
 {
    private(this) int _count;
    public void setCount(int c) { _count = c; }

    unittest
    {
       C c = new C();
       c._count = 42; // oops, this is still allowed
    }
 }
 ```
There is no 'oops' there. The unittest is a member of the class! It the unittest outside of the class that should not be allowed to compile.
Based on the fact that a unittest block does not have a this pointer, Steven is correct. It isn't part of the scope. If you want this you have to be specific that it is included (and yes this is an example of why a DIP is needed to know what your assumptions are).
Apr 26
next sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 02:03:35 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 27/04/2024 11:50 AM, NotYouAgain wrote:
 On Friday, 26 April 2024 at 16:38:54 UTC, Steven Schveighoffer 
 wrote:
 ...
 module m;

 class C
 {
    private(this) int _count;
    public void setCount(int c) { _count = c; }

    unittest
    {
       C c = new C();
       c._count = 42; // oops, this is still allowed
    }
 }
 ```
There is no 'oops' there. The unittest is a member of the class! It the unittest outside of the class that should not be allowed to compile.
Based on the fact that a unittest block does not have a this pointer, Steven is correct. It isn't part of the scope. If you want this you have to be specific that it is included (and yes this is an example of why a DIP is needed to know what your assumptions are).
No I don't understand. The unittest is a special function being declared inside the scope of the class type. I would entirely expect it to have access to all private members of that type. When the unittest is declared outside the scope of the function, I would expect it to NOT have access to the private(this) members of the type. That's exactly what I expect and exactly how it works in OpenD. I presume it's a static function? Hence no this pointer? (I really don't know how its implemented, nor do I care. I can only care that it works as I expect it to work in OpenD.
Apr 26
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 02:03:35 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 If you want this you have to be specific that it is included 
 (and yes this is an example of why a DIP is needed to know what 
 your assumptions are).
But I prefer to discuss this first, as there are things I cleary do not know. Hence the discussion. The DIP process should incorporate what I've learned in the discusion, in order for the DIP to be worthy of the time and attention of those responsible for approving it. At the moment, the discusion is not revealing anything I don't alread know. That is, people 'seem' to accept that there are problems, by insisting that one just puts the class in a separate module, and a unittest for that class in yet another separate module. This discussion is about how to avoid putting the completely unnessary burden on programmers. I know. How about providnig the solution in the language instead? That's what's being discussed.
Apr 26
prev sibling parent reply zjh <fqbqrr 163.com> writes:
On Friday, 26 April 2024 at 16:38:54 UTC, Steven Schveighoffer 
wrote:

 I don't find the arguments compelling enough to make this new 
 feature. An entire module is as examinable as an entire class 
 definition. It's already open in your editor even.

 -Steve
Although `the feature` is small,but this feature is `harmless` and `many people` need it! Is this reason sufficient?
Apr 26
next sibling parent zjh <fqbqrr 163.com> writes:
On Saturday, 27 April 2024 at 01:18:38 UTC, zjh wrote:
 ..
A pure and harmless feature like this that helps developers, surprisingly, still needs to be discussed for a long time, and `'openD'` they just added it directly. It is very difficult for you to find such pure harmless feature.
Apr 26
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, April 26, 2024 7:18:38 PM MDT zjh via dip.ideas wrote:
 On Friday, 26 April 2024 at 16:38:54 UTC, Steven Schveighoffer

 wrote:
 I don't find the arguments compelling enough to make this new
 feature. An entire module is as examinable as an entire class
 definition. It's already open in your editor even.

 -Steve
Although `the feature` is small,but this feature is `harmless` and `many people` need it! Is this reason sufficient?
There is no question that some people want the feature, but a number of us do not buy the idea that anyone needs it. It adds further complication to the language (and personally, I don't want to see any more bugs related to visibility attributes), and the value that it adds is highly questionable. For many of us, experience has shown that something like private(this) is completely unnecessary and that private as it works now is plenty. If a struct or class really needs to keep its data private from any other piece of code, it (or the other code) can be put into a separate module. And if a module is large enough that you have to be worried about whether code accesses a type's private members when you don't want it to, that module is arguably too large anyway. Arguably, if someone feels the need for something like private(this), they're either doing something wrong, or they want it simply on the principle that types should be able to prevent all code that's external to them from accessing their private data. It really isn't an issue in practice, and if you really want to ensure that code can't access a type's private data, the workaround is simple. What usually seems to happen with private is that most people who use D for any real length of time have no problem with how it works, whereas folks who are new to the language are sometimes initially confused and annoyed that it doesn't work the way that they wanted or expected. They usually expect that it would work like it did in whatever language they came from. So, they either want private changed, or they want something like private(this) added. Some people do continue to be annoyed about private long term, but most developers seem to learn that it's really not an issue, and they're fine with it. If someone can come up with a particularly compelling argument such that it convinces Walter, then we may end up with private(this) (or something similar) at some point, but no one has yet come up with an argument that has convinced him that anything like it is necessary, and in general, the folks who have been around for a while tend to agree with him in this case. Obviously, not everyone will agree, and we'll see what Walter says about this proposal, but based on what he has said about this issue over the years (including fairly recently), I would be very surprised if he decided to make any changes to private or accepted a feature proposal like private(this). - Jonathan M Davis
Apr 26
next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 01:41:54 UTC, Jonathan M Davis 
wrote:
..
 ...
 - Jonathan M Davis
As usual, the only solution you can provide to the problems that I've very clear outline, are put the class in it's own module. That is the only solution to the problems. You say that all that D needs to do. I say, no, make it easier for me to solve my problems. A class already has a boundary outside of a module. Why you so determined to ensure a programmer never has the option of explicately declaring that boundary to other code in the class. I just don't get it. I can only presume you don't to oop, or you put every class in its own module, and every unittest for that class its own module as well. Well, no. There is an easier way -> private(this). No impact at all on existing code as far as I can tell. It's purely optin. But I think you're determined to think the same way - in the same way that you tell me that I'm determined to think the same way ; I've presented a number of examples now, where private(this) solves the problem identified. You're solution is one class per module, no unittest in the module either. No. I don't accept this as a good solution to the problems I've indentified.
Apr 26
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, April 26, 2024 11:44:15 PM MDT NotYouAgain via dip.ideas wrote:
 On Saturday, 27 April 2024 at 01:41:54 UTC, Jonathan M Davis

 wrote:
..

 ...
 - Jonathan M Davis
As usual, the only solution you can provide to the problems that I've very clear outline, are put the class in it's own module. That is the only solution to the problems. You say that all that D needs to do. I say, no, make it easier for me to solve my problems. A class already has a boundary outside of a module. Why you so determined to ensure a programmer never has the option of explicately declaring that boundary to other code in the class. I just don't get it. I can only presume you don't to oop, or you put every class in its own module, and every unittest for that class its own module as well. Well, no. There is an easier way -> private(this). No impact at all on existing code as far as I can tell. It's purely optin. But I think you're determined to think the same way - in the same way that you tell me that I'm determined to think the same way ; I've presented a number of examples now, where private(this) solves the problem identified. You're solution is one class per module, no unittest in the module either. No. I don't accept this as a good solution to the problems I've indentified.
No. I simply don't buy that any of the issues that private(this) is trying to solve are problems in practice. I have never found it to be difficult to reason about a class or struct just because there's other code in the module which could access the private members of that class or struct. And accessing private members by accident is not something that happens often if ever in my experience. If anything, it's usually a complete non-issue even if the code does access private members, because it's all code under the control of the maintainers of the module and has no effect on the public API. And in plenty of cases (especially unit tests), it's actually desirable that other code within the module be able to access the private members. The whole point is to prevent code from outside the module from accessing the private data, and it usually doesn't matter if other code within the module does. And if it is actually a problem, then you can put the code in another module, much as that's obviously not the answer that you want. But in my experience, I simply don't have problems with code accessing private data when I don't want it to. Maybe that's in part due to the fact that I typically name private members differently from public ones by prepending them with an underscore, so it's very obvious which I'm using, making it rather hard to use the wrong one by accident, but I simply don't run into problems where having member variables be private to a module instead of to the class or struct is the cause. So, I don't disagree with you that private(this) solves the issues that you're worried about. I disagree that the issues are significant enough that a language change is required. I routinely put several types and functions within a module and put the unit tests in the same module right next to the code that they're testing, and I don't run into issues with private as a result of that. Plenty of other D developers have the same experience. So, from my perspective, you're trying to solve a problem that isn't even a problem in the first place. In addition, mucking around with the implementation for private will almost certainly result in bugs added to the compiler, because that happens pretty much every time that the visibility attributes get mucked with. It also raises issues of what happens with __traits(getVisibility, ...), and it would presumably mean adding another string to the list, making it yet another thing that code doing type introspection potentially has to take into account. I'd rather not have to deal with that either. Now, you clearly feel that there's a problem that needs solving and that private(this) will solve it. Some folks agree with you. And there's nothing wrong with bringing up the idea and trying to talk Walter into it. But I don't personally think that there's a problem that needs solving here or that adding the extra complication to the language that it would entail would be worth it. So, that's really our disagreement here rather than whether private(this) solves what you're trying to solve. I'm also quite sure that unless something you say manages to change Walter's mind, he will have a similar opinion to mine, because that has consistently been his opinion on this topic for years now. But we'll see what he says when he voices his opinion about your specific proposal. Much as I expect him to reject it, I would say that your odds are probably slightly better with adding private(this) than they would be with trying to get him to change what private means. - Jonathan M Davis
Apr 26
next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 06:48:47 UTC, Jonathan M Davis 
wrote:
 ..
 ...
 ... So, from my perspective, you're trying to solve a problem 
 that isn't even a problem in the first place.
Mmm. This is where you don't understand my motivation. I'm not saying that it's causing widespread problems and that it needs to be addressed. I'm saying, I want to prevent the problem from even occuring. Almost any newcomer to D, will experience this problem. There is no solution to them, other than to 'be more careful', or put the class in a module by itself, and ensure any unittest testing it, is also in another separate module. In that is solution being proposed to 'prevent' the problem'. My proposal is more likely be used, as it's so much easier. You present the hard solution to preventing the problems, I present the easy solution. If I understand correctly, that seems to be where we differ. You saying -> be careful not to do it so that it doesn't cause problems, or put use separate modules for everything. Me saying -> use private(this) A class is 'a type' of a particular thing, describing its properties and how it is to be interacted with, just like anyother type. If people come to D with that mindset, they will make mistakes, just like most newcomers make that mistake. Forcing them to think of the class as a subtype of the module, is not going to work. They'll just go elsewhere (which may well me the desriable outcome for some ;-)
Apr 27
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, April 27, 2024 1:12:16 AM MDT NotYouAgain via dip.ideas wrote:
 On Saturday, 27 April 2024 at 06:48:47 UTC, Jonathan M Davis

 wrote:
 ..
 ...
 ... So, from my perspective, you're trying to solve a problem
 that isn't even a problem in the first place.
Mmm. This is where you don't understand my motivation. I'm not saying that it's causing widespread problems and that it needs to be addressed. I'm saying, I want to prevent the problem from even occuring. Almost any newcomer to D, will experience this problem. There is no solution to them, other than to 'be more careful', or put the class in a module by itself, and ensure any unittest testing it, is also in another separate module. In that is solution being proposed to 'prevent' the problem'. My proposal is more likely be used, as it's so much easier. You present the hard solution to preventing the problems, I present the easy solution. If I understand correctly, that seems to be where we differ. You saying -> be careful not to do it so that it doesn't cause problems, or put use separate modules for everything. Me saying -> use private(this) A class is 'a type' of a particular thing, describing its properties and how it is to be interacted with, just like anyother type. If people come to D with that mindset, they will make mistakes, just like most newcomers make that mistake. Forcing them to think of the class as a subtype of the module, is not going to work. They'll just go elsewhere (which may well me the desriable outcome for some ;-)
What I'm saying is that there isn't actually a problem that needs solving. It's a theoretical issue and not one in reality. Programmers routinely program in D without running into any issues with private. Some of them even think that private is private to the class or struct and are surprised years later to find out that it isn't, because they never have problems with it. Visibility attributes are necessary for controlling the public API, which D's private does just fine. From what I've seen, the only problem that we actually get from it is people being surprised that D's private is private to the module and then who want it to work differently (or who want something like private(this) in addition to private), because they think that it's good OO programming to have that and that it's dirty otherwise. But from a practical standpoint, I'm not sure that I've ever seen a bug reported that happened because private was for the module and not the type. If anything, the odds have been much higher that there's a compiler bug that has accidentally made something public or private when it shouldn't be (particularly since the change from private, public, etc. being protection attributes to visibility attributes seems to have been tricky enough that a number of subtle bugs were introduced in the process). In my experience, there simply isn't anything to worry about here, and usually, the folks who are worried about it are worried about it because it's not what they're used to or because it doesn't fit in with their ideal view of OO programming. It is a topic that I've seen come up periodically over the nearly twenty years that I've been using D, so it's far from new, and it will probably never go away as long as things stay the way that they are, but it's almost always newcomers complaining because it's different and not people who have actually had problems who complain. And in general, folks who program with D the way that it is find that private works just fine as-is. Other aspects of the language may cause problems, but private being private to the module really hasn't been causing problems in general. So, yes, I bring up moving code to other modules as a solution if you actually want to guarantee that it doesn't have access to the code in the module that it was in, because that will give you that guarantee. But it's not something that I'm arguing that folks should be doing as best practice, because it simply isn't necessary in practice. And because I have not seen anything that private(this) is trying to solve as something that's actually causing problems, I don't see any reason to add a language feature to try to solve those problems. - Jonathan M Davis
Apr 27
next sibling parent reply Arafel <er.krali gmail.com> writes:
On 27/4/24 9:39, Jonathan M Davis wrote:
 What I'm saying is that there isn't actually a problem that needs solving.
 It's a theoretical issue and not one in reality. Programmers routinely
 program in D without running into any issues with private. Some of them even
 think that private is private to the class or struct and are surprised years
 later to find out that it isn't, because they never have problems with it.
Well, I'm one of these programmers that was bitten by this issue. Coming from Java, though, the idea of keeping a class per file / module didn't seem so alien, so I just went with it. That being said, I would have very much preferred to have this feature available. Another aspect not being discussed here are synchronized classes [1]. Note that:
 Member fields of a synchronized class cannot be public
This breaks apart in very subtle and hard to detect ways when you allow other code in the same module to access private members, even if it looks innocuous. Concurrency bugs are notably hard to detect and even harder to debug, and introducing backdoors like this doesn't exactly help. And "just don't do it" seems quite a bit like "you're holding it wrong". That's just enforcing by convention, and at that point why not go with the python "private" way? Just tell people that they shouldn't do it, and done. Note how this is totally opposite as how `const` is treated: no more "logical const", but hard const. Now, you can argue that synchronized classes are a mistake, shouldn't exist in the first place, are misleading, whatever... but I also disagree here: they have their usage for simple use cases with POD-like objects that _need_ to be a class (for whatever the reason). And the fact is that they exist, so unless and until you deprecate them, why not try to make them at least somewhat useful? FWIW, in my view they should also implicitly cast to / from shared as needed, just like immutable. Anyway, I digress. So this is another real benefit of having private(this). If the only drawback is the hypothetical "complexity" that it could add (which, while not being a compiler expert, I very much doubt it would be too big), why not check the already existing implementation and see what corner cases really appear? I mean, the feature is literally already implemented, can be tested, and some people must be already using it without big issues. Why not at least put it behind a preview switch? [1]: https://dlang.org/spec/class.html#synchronized-classes
Apr 27
next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 08:29:46 UTC, Arafel wrote:
 ..
 ....
 That being said, I would have very much preferred to have this 
 feature available.
It's great that this idea is attracting some support ;-) Sadly, it's usually just those against it that voice their opinions.
 Another aspect not being discussed here are synchronized 
 classes...
so, it seems, at least 2 problems indentified in this discussion, can now be solved with private(this). 1 - It can (apparently) resolve an issue with synchronized classes (I' don't pretend to understand them) 2 - It can prevent private(this) members from being accessible in a unittest (where the unittest is outside the scope of the class - which is how i always do them anyway). That is, the unittest can be made to only be able to test the public interface now. The compiler itself will enforce this constraint. I expect there are alternative solutions to both 1 and 2. But I expect any alternative solution would only solve one of them, and a different alternative solution would be needed to solve the other. But private(this) can solve both ? Wow. One solution, to multiple problems. How cool is that!
Apr 27
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 27/04/2024 9:18 PM, NotYouAgain wrote:
 so, it seems, at least 2 problems indentified in this discussion, can 
 now be solved with private(this).
 
 1 - It can (apparently) resolve an issue with synchronized classes (I' 
 don't pretend to understand them)
It does not resolve them. It enables a programmer who knows that an issue exists to prevent it. The same programmer who wrote that module. It could be solved by doing something like this internally and automatically. No need for a DIP exposing this capability.
Apr 27
parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 12:41:55 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 27/04/2024 9:18 PM, NotYouAgain wrote:
 so, it seems, at least 2 problems indentified in this 
 discussion, can now be solved with private(this).
 
 1 - It can (apparently) resolve an issue with synchronized 
 classes (I' don't pretend to understand them)
It does not resolve them. It enables a programmer who knows that an issue exists to prevent it. The same programmer who wrote that module. It could be solved by doing something like this internally and automatically. No need for a DIP exposing this capability.
but with private(this), the issue wouldn't exist in the first place. Am I correct? (I'm not saying I am, I'm asking the question, since i don't know what synchronized classes are). private(this) is for preventing issues from arising in the first place, not fixing them after they arise.
Apr 27
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 28/04/2024 1:02 AM, NotYouAgain wrote:
 On Saturday, 27 April 2024 at 12:41:55 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:
 
     On 27/04/2024 9:18 PM, NotYouAgain wrote:
 
         so, it seems, at least 2 problems indentified in this
         discussion, can now be solved with private(this).
 
         1 - It can (apparently) resolve an issue with synchronized
         classes (I' don't pretend to understand them)
 
     It does not resolve them.
 
     It enables a programmer who knows that an issue exists to prevent
     it. The same programmer who wrote that module.
 
     It could be solved by doing something like this internally and
     automatically. No need for a DIP exposing this capability.
 
 but with private(this), the issue wouldn't exist in the first place.
If you use it. There is plenty of code in existence that doesn't and the default isn't being suggested to be changed to require it (and would affect all classes, not just synchronized due to all having monitor objects). In other words, it's not a fix.
Apr 27
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 13:11:22 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 28/04/2024 1:02 AM, NotYouAgain wrote:
 On Saturday, 27 April 2024 at 12:41:55 UTC, Richard (Rikki) 
 Andrew Cattermole wrote:
 
     On 27/04/2024 9:18 PM, NotYouAgain wrote:
 
         so, it seems, at least 2 problems indentified in this
         discussion, can now be solved with private(this).
 
         1 - It can (apparently) resolve an issue with 
 synchronized
         classes (I' don't pretend to understand them)
 
     It does not resolve them.
 
     It enables a programmer who knows that an issue exists to 
 prevent
     it. The same programmer who wrote that module.
 
     It could be solved by doing something like this internally 
 and
     automatically. No need for a DIP exposing this capability.
 
 but with private(this), the issue wouldn't exist in the first 
 place.
If you use it. There is plenty of code in existence that doesn't and the default isn't being suggested to be changed to require it (and would affect all classes, not just synchronized due to all having monitor objects). In other words, it's not a fix.
ok. thanks for explaining. I would not a promote a change this will break existing code. The point of private(this) is the option to use it, not to enforce it on anyone. So in this case, we are in 'agreement' then ;-) Still, if it were available, as an option, the programmer could then fix it themselves.
Apr 27
prev sibling parent reply Kagamin <spam here.lot> writes:
On Saturday, 27 April 2024 at 08:29:46 UTC, Arafel wrote:
 And "just don't do it" seems quite a bit like "you're holding 
 it wrong". That's just enforcing by convention, and at that 
 point why not go with the python "private" way? Just tell 
 people that they shouldn't do it, and done.
In OOP world you enforce contracts with interfaces, not with access attributes. Do you really come from java?
Apr 27
parent reply Arafel <er.krali gmail.com> writes:
On 27/4/24 12:22, Kagamin wrote:
 In OOP world you enforce contracts with interfaces, not with access 
 attributes. Do you really come from java?
I don't understand you. Are you arguing that we don't need `private`, or even visibility, at all, because we should just use interfaces? Because otherwise, once you accept the need for `private`, then the question is what the limits should be. D chose "module", which I can understand, but don't share, at least not as the only option. I think the class / scope is a much more natural boundary, as it is for visibility.
Apr 27
parent reply Kagamin <spam here.lot> writes:
On Saturday, 27 April 2024 at 10:58:17 UTC, Arafel wrote:
 On 27/4/24 12:22, Kagamin wrote:
 In OOP world you enforce contracts with interfaces, not with 
 access attributes. Do you really come from java?
I don't understand you. Are you arguing that we don't need `private`, or even visibility, at all, because we should just use interfaces?
If you prefer hardcore OOP, yes. Interfaces for contracts is OOP best practice.
Apr 27
parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 11:16:08 UTC, Kagamin wrote:
 On Saturday, 27 April 2024 at 10:58:17 UTC, Arafel wrote:
 On 27/4/24 12:22, Kagamin wrote:
 In OOP world you enforce contracts with interfaces, not with 
 access attributes. Do you really come from java?
I don't understand you. Are you arguing that we don't need `private`, or even visibility, at all, because we should just use interfaces?
If you prefer hardcore OOP, yes. Interfaces for contracts is OOP best practice.
For me, type integrity is the most important thing. Well, type integrity is important for any type really, not just a class type. Imagine if you could put "hello" into an int, simply because the int was in a module with other code, and therefore lost the ability to protect its integrity. private already exists, and provides the **necessary** support for enscapsulation of the class type from code *outside* the module. This discussion is really just about a new access modifier => private(this), to provide better support for encapsulation of the class type from code *within* the module. There is no argument that the class should not have, or does need to have, the means to protect its type integrity. D has knows it needs this, but only allows it in relation to code outside the module. I'm saying, I need it in the module, because the one-class per module is not my thing. If there's disagreement, its because some don't think I need that, and that the one-class per module is all their willing to offer me. They believe a class-type should be a sub-type of a non-type (i.e. the module). That's where I firmly disagree. Ensuring that operations on a class type are compatible with its design, could be left to 'software engineering', sure, but a tool like private(this) provides a mechanism to express that intent 'explicately', which makes the class-type a strong type again. At the moment, its a pretty weak type when other code is in the module with it. "A strong type is the software engineering superstructure for programs". That is where I begin my programming. With a strong type, not a weak one, that lacks any real border. As such, whenever I code my class-type, I want the means to protect its type integrity, regardless of where the surrounding code exists. More importantly, I want the compiler to understand and enforce that integrity. If I didn't need that as well, I could use 'convention', and then ... hope for the best... But even Javascript learnt, that convention is not enough.. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties If there is any disagreement to the idea of private(this), it needs to be on the basis that a weak type is fine, and that I should just accept that. 'Pretending' its a strong type by ensuring no other code is the module with it, is a pretty poor solution for a programming language. I need this tool so that I can explicately declare intended meaning in my type *and* have the compiler on my side enforcing that. The proof of a type, is in the type of its proof.
Apr 27
parent reply Kagamin <spam here.lot> writes:
Javascript doesn't indicate much, it had no protection at all.
Apr 27
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 12:45:27 UTC, Kagamin wrote:
 Javascript doesn't indicate much, it had no protection at all.
ok sure. how about almost every other major language in use then. but back to D... class ClassWithPrivateField { private int privateField; // actually, my intent here is private(this), // but it cannot be expressed in D. // guess I better put the subclass in its own module // in the hope that someone thinks by doing that, // I've expressed that intent. this() { this.privateField = 42; } } class Subclass : ClassWithPrivateField { private int subPrivateField; this() { this.subPrivateField = 23; this.privateField = 52; // is this a mistake? The compiler has no way to know. } }
Apr 27
prev sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 07:39:19 UTC, Jonathan M Davis 
wrote:
 What I'm saying is that there isn't actually a problem that 
 needs solving. It's a theoretical issue and not one in reality.
That's nonsense. Almost every oop that looks at D, will discover the problem themselves. The compiler won't help them. You assume that oop will comes to D not expecting private to mean private to the type? They will come to D expecting private to be private to the type. They will discover the same issue that I've uncovered, and will need to adjust their thinking to that a class is no longer considered a type in oop in D, but a subtype of the module. Again, Swift done it right. D done it wrong. oo programmers coming to D will have to live with a programming langauge that does it wrong.
 Programmers routinely program in D without running into any 
 issues with private. Some of them even think that private is 
 private to the class or struct and are surprised years later to 
 find out that it isn't, because they never have problems with 
 it.
They haven't developed an extensive library using class-oriented oop style then ;-) Most likely, they're using D for its C like capabilities.
 Visibility attributes are necessary for controlling the public 
 API, which D's private does just fine.
No. Visibility is related to the type as well. This is where D got it wrong. Swift got it right.
 From what I've seen, the only problem that we actually get from 
 it is people being surprised that D's private is private to the 
 module and then who want it to work differently (or who want 
 something like private(this) in addition to private), because 
 they think that it's good OO programming to have that and that 
 it's dirty otherwise.
Why would they be surprised do you think? Yes, it is good OOp programming to have private attributes. And 'dirty'? wtf does that mean?
 But from a practical standpoint, I'm not sure that I've ever 
 seen a bug reported that happened because private was for the 
 module and not the type.
private(this) is not about fixing bugs. It's about fixing type design. It's about fixing unittest so that they actually test the design of the type.
 In my experience, there simply isn't anything to worry about 
 here, and usually, the folks who are worried about it are 
 worried about it because it's not what they're used to or 
 because it doesn't fit in with their ideal view of OO 
 programming.
It's about an ideal language in which to do oop. D claims to support oop. but then insist that they rethink what oop is. No, I want to do what I know to work. D claims I can do that, but it doesn't live up to that claim.
 It is a topic that I've seen come up periodically over the 
 nearly twenty years that I've been using D, so it's far from 
 new, and it will probably never go away as long as things stay 
 the way that they are...
Enter 'private(this)' .. and you'll never ever have to here about it, ever again ;-)
 but it's almost always newcomers complaining...
And why do you think that is? Would they be making the same complaint if they used Swift? Not likely. Serious oo programmers will likely go elsehwere once they discover how D insists they conform to the way D want them to think.
 problems, but private being private to the module really hasn't 
 been causing problems in general.
And yet, so say its a topic that keeps coming up, and will continue to keep coming up. If it's not causing a problem, perhaps its because to the people to whom it was causing a problem, have gone elsewhere... so it's no longer a problem for D.
 So, yes, I bring up moving code to other modules as a solution 
 if you actually want to guarantee that it doesn't have access 
 to the code in the module that it was in, because that will 
 give you that guarantee. But it's not something that I'm 
 arguing that folks should be doing as best practice, because it 
 simply isn't necessary in practice.
I want that guarantee. In fact, I insist that any language I use provides that guarantee. I also insist that it doesn't require more effort than what it should. adding (this) to private, is the less effort possible. I don't want to see the bugs arise, I want to prevent them from arising, with the least effort possible, from me. The module is not a type, and the class should not be a subtype of it. The class itself is the type. It should be able to assert control over itself, like other types.
 And because I have not seen anything that private(this) is 
 trying to solve as something that's actually causing problems, 
 I don't see any reason to add a language feature to try to 
 solve those problems.

 - Jonathan M Davis
You (and others) provide alternatives to private(this) when people discover those problems, but you (and others) don't see what the problem identified, as a problem, but as a non-problem, but still, one requiring a solution? I don't get the logic in that. If there is no problem, why propose the one class per module, one unittest per module, solution? Haskell...etc. programmers are the actual problem, not D. They come to D expecting the wrong thing..It's their thinking that is the problem, not D. That's not a convincing argument. Never has been. Never will be. private(this) and the problem is no longer there. All those programmers will not be required to change how they think. D might even become popular then.
Apr 27
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, April 27, 2024 2:39:50 AM MDT NotYouAgain via dip.ideas wrote:
 You (and others) provide alternatives to private(this) when
 people discover those problems, but you (and others) don't see
 what the problem identified, as a problem, but as a non-problem,
 but still, one requiring a solution? I don't get the logic in
 that.

 If there is no problem, why propose the one class per module, one
 unittest per module, solution?
No, all we're saying is that if you think that it's a problem for the module to be treated as the unit of encapsulation, you can have one class per module to get around that. We're not arguing that that's actually how you should be writing your code. How you organize it is up to you. Many of us put quite a few types and functions in the same module and have no problem with it, but we're also not determined to view the class as the unit of encapsulation.

 Haskell...etc. programmers are the actual problem, not D. They
 come to D expecting the wrong thing..It's their thinking that is
 the problem, not D.

 That's not a convincing argument. Never has been. Never will be.

 private(this) and the problem is no longer there. All those
 programmers will not be required to change how they think. D
 might even become popular then.
Ultimately, D chose to go the route of making the module the unit of encapsulation. Some people don't like that (usually because that doesn't fit with how they want to view OOP), but it's served us well overall, and it's allowed us to have a simpler situation with regards to visibility attributes than some other languages have. Adding an extra layer to it to allow classes to be treated as a unit of encapsulation might satisfy those who want to insist that the unit of encapsulation should be the class for proper OOP, but in practice, it hasn't been necessary for D. Obviously, it's a design decision with tradeoffs, as most design decisions are, and some people aren't going to agree with it, but it is one that has worked quite well for us overall. You're free to hate that decision. You're free to propose a change to the language like you're doing to try to get the situation to change. Sometimes, Walter agrees to make a change, and sometimes he doesn't. So, if you're convincing enough, maybe the situation will change, but based on what he's said about this in the past, I fully expect that it will be rejected. When learning any language, it's bound to be the case that some design decisions of the language do not match what you expect or want. Sometimes, it's because those decisions are bad. Sometimes, it's simply because it's not what you're used to or because it doesn't fit how you want things to work. In some cases, it's something that you ultimately come to agree with and like, whereas in other cases, it's just a part of the language that's permanently annoying. You (and anyone else coming to D) will come to your own conclusions about where D's view on private and the unit of encapsulation falls on that scale. just going to say that D made a different design decision, and it's one that's worked well for us. And assuming that you don't convince Walter to change the language, you'll have to figure out how to best work with how private works in D for as long as you choose to use D. Ultimately, whether D did it better or not, D did it differently, and everyone using D has to deal with how it works. For anyone who insists on treating the class as the unit of encapsulation, it's likely to be annoying, whereas for anyone who's willing to treat the module as the unit of encapsulation, it works quite well. - Jonathan M Davis
Apr 27
next sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 09:32:00 UTC, Jonathan M Davis 
wrote:
..
..
Can I suggest we both get off this merry-go-round ;-) It's not a productive use of my time, nor yours, nor anyone elses who have to read through all this nonsense. If I understand correctly, you think it's pretty pointless. Fine. Let's leave it at that. I believe that has been your position for...well.. forever. I like to hear from others, in regards to what benefits they think private(this) might provide, because if a DIP were to be presented, I can assure you, it wouldn't be saying how pointless this DIP is. Perhaps Walter could express his opinion, since I really have no idea what it is. I only ever get told that Walter would completely reject any DIP with private(this). If he says he won't even consider it, then even this discussion is pointless. People should just move to openD instead I guess.
Apr 27
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 09:32:00 UTC, Jonathan M Davis 
wrote:
 .. .. - Jonathan M Davis
"but programmers can choose what makes the most sense for that particular class hierarchy, whereas we cannot possibly make that decision for all classes and not screw over developers in the process, because it's not one size fits all." https://forum.dlang.org/post/mailman.1555.1714097812.3719.digitalmars-d puremagic.com It would be great if that same reasoning of yours could be directed to this idea.
Apr 27
prev sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 06:48:47 UTC, Jonathan M Davis 
wrote:
 ...
What is your solution to the problem below? Let me guess: (1) don't make the mistake of bypassing the public interface in the unittest. (2) put the unittest in a separate module. My solution: (1) make x and y private(this) and you cannot make a mistake, since the compiler will not let you make that mistake. // --- module m; safe: class C { private int x, y; invariant() { assert(x == y); } void modifyX(int val) { x = val; } void modifyY(int val) { y = val; } } unittest { C c = new C(); c.x = 10; // incorrect use of the type. } // ---
Apr 27
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, April 27, 2024 1:31:10 AM MDT NotYouAgain via dip.ideas wrote:
 On Saturday, 27 April 2024 at 06:48:47 UTC, Jonathan M Davis

 wrote:
 ...
What is your solution to the problem below? Let me guess: (1) don't make the mistake of bypassing the public interface in the unittest. (2) put the unittest in a separate module. My solution: (1) make x and y private(this) and you cannot make a mistake, since the compiler will not let you make that mistake. // --- module m; safe: class C { private int x, y; invariant() { assert(x == y); } void modifyX(int val) { x = val; } void modifyY(int val) { y = val; } } unittest { C c = new C(); c.x = 10; // incorrect use of the type. } // ---
Why is that an incorrect use of the type? Why should I care whether code within the same module is accessing a private member? It doesn't cause problems with the public API if code does that. And if I don't want code within the module to access the private data then I simply won't write code that does, and if I accidentally write code that does, it's all part of the code that's internal to the module rather than part of the public API, so it's an implementation detail. It won't matter to the code that's using my module whether I have code in there using a type's private members or not. It might go against some concept that the programmer has of what OO is supposed to look like, but ultimately, it's an implementation detail of the module and irrelevant to any code outside of the module. What matters to the code using your module is whether it works, not how its internals are organized. You could even have whole sections of your class' implementation be private functions that are free functions within the module instead of within the class itself, and it wouldn't matter to anyone using your class. Is the issue that the code is bypassing the invariant? If your code screws up when accessing private members and doesn't make sure that the invariant is correct before any public member functions are called, then you'll catch it then, because the invariant will fail. So, it's not like this is going to result in your code having bugs. And if the code does ensure that the invariant is correct before any public member functions are called, then it's doing the right thing with regards to the state of the object, and there shouldn't be a problem. And for most unit tests, accessing the private state of an object is a non-issue (in fact, it's often useful). They need to test that that type and its functions are working correctly, and for most tests, the fact that they have access to the private members either helps them do their job, or it's irrelevant. It's certainly true that if you want to write a test that is guaranteed to only be able to access the public API of a type that you can't currently put that in the module itself, but that's usually only a concern when writing samples for the documentation (since it's obviously a problem if examples use private members given that users of your code can't do that), and if those are documented unit tests, then they have to follow immediately after the symbol that they're documenting, meaning that private(this) wouldn't help anyway. Those unittest blocks would have to be in a position where they would have access to the private members whether you wanted them to or not in order for the compiler to associate them with the symbols that they're supposed to document and test. Similarly, private(this) wouldn't help at all with a documented unittest block accidentally using a private member of the module rather than of a particular class or struct. So, if documentation is the concern (and that's usually the place where it would make sense to actually be worried about using private symbols in a test), private(this) is not a solution. And if you really want to prevent tests that aren't documented unit tests from accessing private members for some reason, to do that with private(this), you're forced to move them outside of the type, making it so that they can't be next to what they're testing, making it a somewhat awkward solution even if it's not as bad as having to move the unit tests into another module. So, if there's any feature that might be useful here, it isn't a way to lock away your class' private members from the rest of the module; it's a way to tell the compiler that a particular unittest block should be treated as if it were not within the module with regards to which symbols it can access. Then you could write documented unit tests where you had to use imports and the public API rather than having them have access to everything within the module, and you could then be completely sure that none of your examples used anything private (whether it was part of the class or not). And if you really wanted other tests to then not have access to private members for some reason, you could mark those unittest blocks with the same attribute or pragma or whatever it is that that feature used to mark the unittest block as not having access. But for most code within a module, whether it uses a private member or a public one is just an implementation detail and is irrelevant to any code outside of that module. All that the code outside cares about is that the code works properly, not whether its internals use public or private members. Now, using a member that you didn't intend to would definitely be a problem if it behaved differently, but that really doesn't have anything to do with public vs private, since it could happen with any symbol, and proper testing will catch that. - Jonathan M Davis
Apr 27
prev sibling parent Atila Neves <atila.neves gmail.com> writes:
On Saturday, 27 April 2024 at 05:44:15 UTC, NotYouAgain wrote:
 On Saturday, 27 April 2024 at 01:41:54 UTC, Jonathan M Davis 
 wrote:
..
 ...
 - Jonathan M Davis
As usual, the only solution you can provide to the problems that I've very clear outline, are put the class in it's own module.
Yes, that's the solution. It works right now. Adding a feature to the language requires justifying its cost, and I haven't seen anything in this thread that does, *especially* since the user always has the option of creating a module for every class if they so wish.
Apr 30
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 01:41:54 UTC, Jonathan M Davis 
wrote:
 Arguably, if someone feels the need for something like 
 private(this), they're either doing something wrong, or they 
 want it simply on the principle that types should be able to 
 prevent all code that's external to them from accessing their 
 private data. It really isn't an issue in practice, and if you 
 really want to ensure that code can't access a type's private 
 data, the workaround is simple.
I'm not doing anything wrong! I'm declaring a user-defined class type, and I want it to have private members, that I don't want to be accessed outside of the scope in which the class is being defined. How am I doing anything wrong here? The class type can already prevent access to its private members - but only to code outside the module. Are you saying this isn't necessary? Just make it all public and no problems will arise? Well, problems WILL arise. Just as problems 'can' arise with code inside the module. I'm trying to provide a strong type here, but D won't let me. It has no mechanism to do that, as it doesn't consider a class type to be a true type (but nontheless, declares itself to support OO programming). To code 'outside' the module, I can present the class as a true type - 'private'. To code 'inside' the module, I cannot. It simply cannot be done. Inside the module, 'private' means nothing. The only solution you and others put forward, in order to ensure private really is private in a module, is to ensure no other code is in the module. Really?!? You may as well tell me to f$$$ off. Cause they both mean the same to me. Also, I'm not insisting that private be changed, only that private(this) be added. *Both* have their use. In OpenD, **I** can choose between private and private(this). That's exactly what I would expect from any language I chose to program in. Why would anyone *insist* on preventing me from doing that? You cannot reason around a class type in D, when other code is in the module. You have to take all that other code into account - and there lies the problem. The compiler will never know, and a code revievwer will have to review all code in the module, just to understand the intent in the desing of the class.. if they're lucky. From the code in the class-type, I should be able to extract a proof or its correct usage. In D, a proof is not possible when there is other code in the module. And 'the workaround' is not simple! I want to make it simple, by integrating into D, an optional ......), so that the programmer can make the class contain 'proof-carrying code' - code that explicately declares how this type can be used. private(this) is what would make it simple. My motivations could not be clearer.
Apr 26
prev sibling next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:
 This DIP idea, relates to extending D's support for 
 object-oriented design - by allowing private visibility to be 
 attached to a class member.

 The proposal creates no new limitations and no code breakage.
About the idea itself - I don't feel strongly either way. I would personally likely not use this feature, but it's easy enough to understand that it wouldn't bother me either if others use it. I need to stress though, that you need to approach this subject with utmost diplomacy and humblety. Class-level `private` has been the very subject of more than one flame war in these forums. You will quickly become shunned if you're seen as instigating another one. The disclaimers you included at beginning of your post hint that you're already aware of that. In any case, please don't attempt to get your viewpoints through by arguing with those who disagree. You need to accept that it's better to agree to disagree, or you won't be taken seriously in a delicate subject like this.
Apr 27
next sibling parent reply Arafel <er.krali gmail.com> writes:
On 27/4/24 15:10, Dukc wrote:
 I need to stress though, that you need to approach this subject with 
 utmost diplomacy and humblety. Class-level |private| has been the very 
 subject of more than one flame war in these forums. You will quickly 
 become shunned if you're seen as instigating another one. The 
 disclaimers you included at beginning of your post hint that you're 
 already aware of that.
I have to say I have been surprised at how strongly some people react. I started by saying that I think it's a minor issue, has a workaround, and the workaround doesn't even feel too unusual to me. In short: I don't think it's worth raising a fuss, it's just one of those odd quirks that you learn to live with. Still, I think it makes sense as a feature, and, honestly, I see it as a low-hanging fruit: it's an addition to the language, fully opt-in, it doesn't interact with pretty much anything else*, and has an already working implementation with even some real-life exposure to find out the rough edges. So given that there are few drawbacks (I would dare say none beyond a very much hypothetical "complexity" in the language), and acknowledged, even if minor, benefits, the question for me becomes: "why not?". "Because that's how things are" is something I can happily accept, as I have been doing so far, but not agree with. *: Assuming you define it as: "for `private(this)` members or methods, code outside the class (or eventually struct) behaves as if it were in a different module".
Apr 27
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 15:47:50 UTC, Arafel wrote:
 On 27/4/24 15:10, Dukc wrote:
 I need to stress though, that you need to approach this 
 subject with utmost diplomacy and humblety. Class-level 
 |private| has been the very subject of more than one flame war 
 in these forums. You will quickly become shunned if you're 
 seen as instigating another one. The disclaimers you included 
 at beginning of your post hint that you're already aware of 
 that.
I have to say I have been surprised at how strongly some people react. I started by saying that I think it's a minor issue, has a workaround, and the workaround doesn't even feel too unusual to me. In short: I don't think it's worth raising a fuss, it's just one of those odd quirks that you learn to live with. Still, I think it makes sense as a feature, and, honestly, I see it as a low-hanging fruit: it's an addition to the language, fully opt-in, it doesn't interact with pretty much anything else*, and has an already working implementation with even some real-life exposure to find out the rough edges. So given that there are few drawbacks (I would dare say none beyond a very much hypothetical "complexity" in the language), and acknowledged, even if minor, benefits, the question for me becomes: "why not?". "Because that's how things are" is something I can happily accept, as I have been doing so far, but not agree with. *: Assuming you define it as: "for `private(this)` members or methods, code outside the class (or eventually struct) behaves as if it were in a different module".
You are not the first to be 'surprised' by the reaction to such a simple, and sound idea. Apart from the usual flamewares instigated by people in D who hate oop, think oo programmers are oop..philes, etc...etc.... the only real objection that I can fathom, is that in D, the module is the unit of encapsulation, not the class, and therefore if i use D, i need to think like that, and if I don't want to, then to bad for me. I think that is the objection to which a debate is warranted. Ignore all the other crap that always accompany's this idea. It has always been there, and will always be there. The question is, does private(this) fundamentally change anything about D, or is it a minor change that would allow something that anyone who has ever written a class, be able to do in D. Or, do we accept that the class type must takes second place to the module (a non-type). Swift is a great example of how both options (private and fileprivate) work together to solve programmers problems. They don't work against each other. The programmer can choose the option 'they think' is best for them. Swift does not try to coerce the programmer into thinking differently, unlike D. Again, the idea is sound. It exists in practically all of the most widely used oo capable languages - even in OpenD. The change is simple. But the opposition is really fierce. So anyone wanting or supporting this feature must be prepared to deal with that fierce opposition. Most are not prepared to do that, hence the idea never progresses.... I am very comfortable challenging the statusquo ;-) Some are (understandably), not. Fortunately, we now have a forum group where the idea itself can be discussed. But even that is already proving to be difficult. Remember, the opposition to this is very fierce. So it really should not come as much of surprise ;-) The D module is the unit of encapsulation, but it is NOT a type. A class IS a type, and should have the necessary 'explicit' means to encapsulation those properties it wants to encapsulate. That is my argument. It really could not be simpler. It is certainly not an argument designed to provoke flame wars, as other would have you believe. The most fundamental argument against it, is no, in D, a class doesn't need that option. .. because D already provides a means of encapsulation, the module, and that is sufficient... but if you really want a class that can have its own encapsulation properties, then put it in a module by itself. So that last paragraph is the only opposition to it that is worthy of your attention. Ignore all the other stuff ;-)
Apr 27
prev sibling next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 13:10:08 UTC, Dukc wrote:
 .. ..
 You need to accept that it's better to agree to disagree, or 
 you won't be taken seriously in a delicate subject like this.
A programmer being able to declare a private member in a class is a 'delicate' subject. It inflames war? Really? Yes I know this is all true actually. But the idea is fundamentally sound. I simply cannot agree to those that say it is not sound. The motivations for such fierce opposition to it, is the problem. By discussing it, their motivations become clearer. My motiviation could not be simpler. I just want to declare a private member in my class - that is all I want.
Apr 27
parent reply Dukc <ajieskola gmail.com> writes:
On Sunday, 28 April 2024 at 00:16:37 UTC, NotYouAgain wrote:
 On Saturday, 27 April 2024 at 13:10:08 UTC, Dukc wrote:

 A programmer being able to declare a private member in a class 
 is a 'delicate' subject.

 It inflames war? Really?
It's not so much that the subject itself would be touchy, bar for one person who just couldn't stop complaining over the status quo, to the point of resorting to sockpuppetry. It's that the arguments about it went so badly and fruitlessly, that I'm pretty sure people would hate to go over all that once again. Therefore, please don't start arguments on this.
 But the idea is fundamentally sound.

 I simply cannot agree to those that say it is not sound.

 The motivations for such fierce opposition to it, is the 
 problem.
Unfortunately, you're doing the exact mistake I'm warning you about. By the time you're questioning motivations of others it's a sure sign you're not getting anywhere with this. This is the case *even if their motivations are actually problematic*. People aren't perfect. Maybe they deserve chastising about their attitudes, but it will still annoy them and destroy their respect for you and you proposal. It's not worth it. Anyone thinking it is should not be here in the first place.
Apr 28
next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Sunday, 28 April 2024 at 20:49:37 UTC, Dukc wrote:
 On Sunday, 28 April 2024 at 00:16:37 UTC, NotYouAgain wrote:
 On Saturday, 27 April 2024 at 13:10:08 UTC, Dukc wrote:

 A programmer being able to declare a private member in a class 
 is a 'delicate' subject.

 It inflames war? Really?
It's not so much that the subject itself would be touchy, bar for one person who just couldn't stop complaining over the status quo, to the point of resorting to sockpuppetry. It's that the arguments about it went so badly and fruitlessly, that I'm pretty sure people would hate to go over all that once again. Therefore, please don't start arguments on this.
 But the idea is fundamentally sound.

 I simply cannot agree to those that say it is not sound.

 The motivations for such fierce opposition to it, is the 
 problem.
Unfortunately, you're doing the exact mistake I'm warning you about. By the time you're questioning motivations of others it's a sure sign you're not getting anywhere with this. This is the case *even if their motivations are actually problematic*. People aren't perfect. Maybe they deserve chastising about their attitudes, but it will still annoy them and destroy their respect for you and you proposal. It's not worth it. Anyone thinking it is should not be here in the first place.
Well I was clearly talking about the motivations of those people who hate oop and hate oop programmers and think they are oop..philes. They need to be called out! My motivation is clear and very simple. Let D have the equivalant of Swift's 'private' and 'fileprivate'. Currently D can only offer fileprivate (i.e. private). Swift designers have already made the case for needing a distinction here. At the moment, in D, every class if a module is effecitvely annotated with this hidden attribute: anything_else_in_this_module_is_a_c++_like_friend_to_this_class class { } I don't like it. I want to change it. People objecting to the change simply because they hate oop and oop programmers, are the problem for why this idea can never be discuss in a civil manner. The only valid objection relevant to the idea (so far), is that one can put each class and each unit test, all in their own module. That's a valid objection to be tackled in this discussion. My objection to that is clear. First, it only creates an illusion for oop. Second, it enforces a design constraint that should be left up to developers, and not the language. Walters justification for fileprivate (ie. private), was to avoid the necessity for C++ friends. Fine. But now everything is a friend. I just want the explicit means to unfriend. The idea is only controversial, because many in the D community are genuiely oop haters. Once you understand that, you understand the pushback that is needed against them, when this idea is raised. Also, the suggestion that idea should not be raised except once, is silly. It should be raised as often as required, to determine whether it can gain necessary support to proceed to a DIP. And calling me a socketpuppet because you think I'm the only one pursuing this idea, if not correct. Other people like the idea as well. Their posts are not my posts. But thanks for distracting the discussion, once again.
Apr 28
parent reply Dukc <ajieskola gmail.com> writes:
On Sunday, 28 April 2024 at 23:32:45 UTC, NotYouAgain wrote:
 The idea is only controversial, because many in the D community 
 are genuiely oop haters.

 Once you understand that, you understand the pushback that is 
 needed against them, when this idea is raised.

 Also, the suggestion that idea should not be raised except 
 once, is silly.

 It should be raised as often as required, to determine whether 
 it can gain necessary support to proceed to a DIP.
This reads like you're going to disregard my advice. If so, I don't think anything I could write would turn your head. Too bad, as it leads me to the conclusion you're not worth debating the DIP with until you learn to be less combative. Sooner or later other people will conclude the same - probably some have done so already.
 And calling me a socketpuppet because you think I'm the only 
 one pursuing this idea, if not correct. Other people like the 
 idea as well. Their posts are not my posts.
To be clear, whoever instigated those former flame wars I wrote about is who I meant falling into sockpuppetry.
Apr 29
parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Monday, 29 April 2024 at 08:34:21 UTC, Dukc wrote:
 On Sunday, 28 April 2024 at 23:32:45 UTC, NotYouAgain wrote:
 The idea is only controversial, because many in the D 
 community are genuiely oop haters.

 Once you understand that, you understand the pushback that is 
 needed against them, when this idea is raised.

 Also, the suggestion that idea should not be raised except 
 once, is silly.

 It should be raised as often as required, to determine whether 
 it can gain necessary support to proceed to a DIP.
This reads like you're going to disregard my advice. If so, I don't think anything I could write would turn your head. Too bad, as it leads me to the conclusion you're not worth debating the DIP with until you learn to be less combative. Sooner or later other people will conclude the same - probably some have done so already.
 And calling me a socketpuppet because you think I'm the only 
 one pursuing this idea, if not correct. Other people like the 
 idea as well. Their posts are not my posts.
To be clear, whoever instigated those former flame wars I wrote about is who I meant falling into sockpuppetry.
No, I know Walter will never approve this, no matter want. He even wanted to get of protected as well. But the battle is ongoing... At least in the Swift community, someone was willing to listen: https://forum.dlang.org/post/tgjilaffuybvpkksmane forum.dlang.org
Apr 29
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Monday, 29 April 2024 at 09:12:12 UTC, NotYouAgain wrote:
..
and: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160404/014116.html Swift made the decision to fix private more than 8 years ago!
Apr 29
prev sibling next sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Sunday, 28 April 2024 at 20:49:37 UTC, Dukc wrote:
 ..
 ...
and as you can see, this confusion over D mis-use of the concept of oop private, has been around for a very long time ... long before I discovered D. "One thing that is confusing in D is that private members of a type are accessible by the module that includes that type." (2012) https://forum.dlang.org/post/ka1i21$29ac$1 digitalmars.com
Apr 28
prev sibling next sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Sunday, 28 April 2024 at 20:49:37 UTC, Dukc wrote:
 ..
 ...
and look at the lengths one has to go to, to explain, and understand, what private in D means: https://dlang.org/blog/2018/11/06/lost-in-translation-encapsulation/ But if D has private(this), that article could have just been a one liner: "If you need private to the class, use private(this)". Done. Decades of confusion, useless converstations about it, all done away with. You won't need that article for OpenD ;-) .. just tell people to use private(this). Now if anyone has the programming skills to submit a PR to OpenD for protected(this), please feel free to do so ;-) And yes, this is 'campaign' - a campaign to be able to think about objects as being a unit of encapsulation (in addition to the module being a unit of encapsulation). Then programmers can finally take control over D's mistake (to take that control away from them), and they can decide what is best for them .. just like they can do in Swift.
Apr 28
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Sunday, 28 April 2024 at 20:49:37 UTC, Dukc wrote:
 ..
 ....
anyway... long live oop! and see ya' all next time. p.s - just remember to annotate your class types in D, like this... anything_else_in_this_module_is_a_c++_like_friend_to_this_class class { }
Apr 28
prev sibling parent NotYouAgain <NotYouAgain gmail.com> writes:
On Saturday, 27 April 2024 at 23:47:59 UTC, Warin Kempf wrote:
 On Saturday, 27 April 2024 at 13:10:08 UTC, Dukc wrote:
 On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:
 I need to stress though, that you need to approach this 
 subject with utmost diplomacy and humblety. Class-level 
 `private` has been the very subject of more than one flame war 
 in these forums. You will quickly become shunned if you're 
 seen as instigating another one. The disclaimers you included 
 at beginning of your post hint that you're already aware of 
 that.
Yes because he instigated the last few wars. Its the only reason I hope Walter rejects this idea, seeing this guy lose his mind every 12 months is oddly amusing.
Actually, if you look at this post from Walter (on a seperate idea), well, I'm fundamentlly using the same logic as he is. https://forum.dlang.org/post/v0h23q$1b89$1 digitalmars.com That is, you can still programmer well with out private(this), sure, but ..and then I'd use all most the exact logic in his arguements....
Apr 27
prev sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Thursday, 25 April 2024 at 05:37:24 UTC, NotYouAgain wrote:
 TITLE: Extending D's support for object-oriented design with 
 private(this)

 NOTE: Only civil and well-informed discourse on this idea is 
 welcome.

 [...]
The D solution is to encourage splitting modules. However this has for side effect more syscalls (to load the files) and more parsers instances. Maybe this aspect could be studied in order to propose arguments. Also splitting may encourage to create several modules that finally can only work together (i.e that makes sense to put everything together so the split can be seen as "absurd"). So far the discussion is getting less and less serious and ressembles to what we've already seen in the past, in the "general" NG. Personally I casually use FPC, which has `strict private` (i.e `private(this)`) and `strict protected` (i.e `protected(this)`. I dont find them essential but as a matter of discpline I have used them a couple of time and found them to be useful, in certain cases. For example presentation and logic implemented in the same module, but be sure that the presentation will only use the getters/setters of the logic and not the fields.
Apr 29
next sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Monday, 29 April 2024 at 13:39:17 UTC, Basile B. wrote:
 The D solution is to encourage splitting modules. ...
You could it that way, I guess. I prefer to say, that D puts the burden of correctness, fully on the programmer. The Swift community already went through this issue over 8 years ago, and the decided a fix was warranted (and I mean the very, very experienced people who design Swift). You can see some of those discussion here (and note how professional those discussions are too) - https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160321/013261.html That any oo programmer that comes to D should have to explain to anyone in the D community the value of an option to declare a private class member and have to argue it for years...no decades.. is just pathetic. I cannot describe it any other way. Yes, I know people in D disagree. Fine. That doesn't make them right. Does it make me right...well..one can just look at what Java, Haskell....have by design ... and I can go on and on.... As I said before, the proof of a type is in the type of its proof. Not just each class, but each unittest has to go in its own module. It's a totally uncessary burden to place on programmers in order to the design contraint they want on their class type, and appropriate enforcement of that design by the compiler. If people disagree, fine. I don't accept that they are a correct, and the proof is in all the languages I just mentioned. I think those languages represent the vast majority of programmers in the world. D represents less than atom of that amount. But just remember to annotate your class types with the annotation below, and I'm sure everything will work out just fine for you..and your users, and those who have to maintain your code. ------ module test; BEWARE_all_code_in_this_class_is_a_c++_like_friend_of_this_class_including_unittests. class Firefighter { private void DoSomethingATraineeShouldNotDo() {} } class TraineeFirefighter : Firefighter {} unittest { TraineeFirefighter joe = new TraineeFirefighter(); joe.DoSomethingATraineeShouldNotDo(); } ----------
Apr 29
parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Monday, 29 April 2024 at 23:21:46 UTC, NotYouAgain wrote:
 ..
 ----------
"I have become more and more convinced that the key to code reusability and scalability is encapsulation — having subsystems communicate through small, well-defined interfaces and letting them hide their own implementation details." - Walter Bright http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394?queryText=Scott%2BMeyers
Apr 29
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Monday, 29 April 2024 at 23:31:55 UTC, NotYouAgain wrote:
..
"The goal is to give the programmer the tools to do what he needs to do, rather than a bunch of red tape to dictate what he cannot do. That's why we have trusted, system, and even asm. The programmer is responsible for making sane architectural decisions with the tools he is given, rather than being told what (not) to do within the confines of his cell. " - H. S. Teoh https://forum.dlang.org/post/mailman.4716.1541041974.29801.digitalmars-d-announce puremagic.com private(this) is a tool for the programmer - a tool the D designers seems to insist he never gets his hands on. (or her, .., ...., if the case may be). Why *so many* are **so strongly** against this particular tool, is rather bewildering. Surely its not just because there is an alternative, but very burdensome tool available (the one-module per ..everything.. thing? I think its more likely, there is some philosophical, principled postion they want to hang on to. Perhaps even something they really hate (like those that hate oop in general, and despise the fact the D says it supports it - I can point out some of those people if you want - one even inserted himself in this discuss, which ensured this discussion would go off track..yet again). I cannot think of any other reasons for such strong, consistent, opposition.
Apr 29
prev sibling parent reply NotYouAgain <NotYouAgain gmail.com> writes:
On Monday, 29 April 2024 at 13:39:17 UTC, Basile B. wrote:
 ..
 ..
 Personally I casually use FPC, which has `strict private` (i.e 
 `private(this)`) and `strict protected` (i.e `protected(this)`. 
 I dont find them essential but as a matter of discpline I have 
 used them a couple of time and found them to be useful, in 
 certain cases. For example presentation and logic implemented 
 in the same module, but be sure that the presentation will only 
 use the getters/setters of the logic and not the fields.
The source of all this, can be trace back to the D designer who decided to change the "right and obvious" meaning of private. That was a mistake. It's not the the moduleprivate is wrong, that certainly has a place, but changing the meaning of private, was a mistake that D has to live with. As Chris Lattner (of Apple) said (in their discussions on fixing the exact same problem they had in Swift): (1) "We keep public and private meaning the “right” and “obvious” things." https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160321/013261.html It's time (a decade overdue actaully) for the D community to have this discussion. Swift was already used widely when they made this change 8 years ago. D is not in even widespread use today. D could make the same change, and restore private to what everyone knows it to mean, and use moduleprivate or fileprivate as meaning private to this module. Yes, I know the opposition to this idea. I do not need to here from them again. I'd rather here from those who support change, not those who are totally against it (as their views are already known). That was the whole point of presenting this idea in the DIP ideas group, instead of the General group, where everyone piles onto you if you raise this idea.
Apr 29
next sibling parent reply Lance Bachmeier <no spam.net> writes:
On Tuesday, 30 April 2024 at 00:01:00 UTC, NotYouAgain wrote:

 Yes, I know the opposition to this idea. I do not need to here 
 from them again. I'd rather here from those who support change, 
 not those who are totally against it (as their views are 
 already known).
That would be pointless. There's discussion so that the downsides can be raised and addressed. I don't see any reason to keep this going further. Write a DIP and see what happens. If you restate your opinions about how OOP should be done and how people here don't understand OOP, it'll be a waste of your time. Everybody knows those arguments. Whether you want to accept it or not, many people have found that things work well as they are, so you're not likely to convince anyone in power by going down that road. If you make the case that this does not lead to a demand for friends, which I see as a strong argument, then maybe it'll have a chance. I think it's a reasonable addition to the language, but I'm not the one that makes those decisions (and that's a good thing, because I can't claim to know much about designing a big language like D).
Apr 29
parent NotYouAgain <NotYouAgain gmail.com> writes:
On Tuesday, 30 April 2024 at 06:08:52 UTC, NotYouAgain wrote:

Interesting take on access (visibility) controls in Swift prior 
to Swift fixing this.

https://blog.human-friendly.com/swift-access-controls-are-like-cs-and-that-isnt-necessarily-a-bad-thing

The above blog was written before Swift 3 came out, which fixed 
private to mean what everyone had always expected it to mean.

D has the same problem. C like access control. .. and it's not 
surprising that Walter chose this, due to his very strong 
affinity with C.

But many Swift oop developers didn't like the C like access 
controls.

Swift designers fully understood and accepted the argument, the 
ack. the mistake they made, and they just fixed it.

Everyone is still happy using Swift, and Swift is a better 
language after the fix, than before it.
Apr 30
prev sibling parent reply Dom DiSc <dominikus scherkl.de> writes:
On Tuesday, 30 April 2024 at 00:01:00 UTC, NotYouAgain wrote:
 The source of all this, can be trace back to the D designer who 
 decided to change the "right and obvious" meaning of private.

 That was a mistake. It's not that the module private is wrong, 
 that certainly has a place, but changing the meaning of 
 private, was a mistake that D has to live with.
It's not "wrong". It's just a different philosophy, like with transitive const. You can claim something is "logical const" but still modify internal state, or you enforce that something that is claimed const can really not be modified whatsoever. Neither of the two is "wrong", it's just different and you can not easily translate between the two. With private you can claim something is not accessed by other stuff within the same file (by declaring it "private to the class"), but this is only "logical private", because effectively if you have access to a file, you can access everything in that file, no matter how "private" it is. But if something is in a different file, you can enforce that someone cannot access (aka modify) what is in there. Maybe simply by making the file readonly, but there are also stronger protection measures possible. As I said in the other thread: A black-box test (for example something that tests the encapsulation of an object) shall not have the possibility to modify the object under test. So it cannot be in the same file. If you implement it in the same file and claim privacy, you are lying to yourself. It is simply not true. In both cases (const and private) C++ allows the programmer to lie to himself (which is convenient, I confess) and D enforce correct behaviour (which is inconvenient at times). I prefer the D philosophy. I have nothing against private(this), it's convenient, you are right. But I hate it if someone insist to call the other philosophy "wrong". That is what provoces so much resistence in these threads. Your chances to get the feature you want so much will become much higher, if you refreign from insulting others.
Apr 30
parent Mike Parker <aldacron gmail.com> writes:
I've refrained so far from deleting any posts in this thread that 
still had on-topic content. However, I've had to delete several 
now, and I've had enough complaints about the tenor of this 
thread that I can declare it's been disruptive, so let's shut it 
down here.

Given Atila's comment, the idea doesn't have a chance of approval 
anyway. If anyone wants to submit a DIP for it, feel free. But if 
you do it, you're pretty much tilting at windmills.

I welcome anyone who wants to discuss the idea civilly to start a 
new thread.
Apr 30