March 17, 2018
On Tuesday, 13 March 2018 at 05:11:48 UTC, psychoticRabbit wrote:
>> If you have access to the module source, you have access to the source of types inside it. Making the module the lowest level of encapsulation makes sense from that perspective.
>
> There are two problems I see:
>
> 1st - D has broken the concept of class encapsulation, simply for convenience at the module level. Not good in my opinion.

It's a language design decision as to whether a particular feature is worth supporting. I would like this feature too though. I'm not sure how much compiler complexity would be added by having another visibility modifier.

I'm surprised how many people here ignore the advantage of being able to modify your class/struct fields without the chance of breaking template code that might not even be instantiated by a unit test. (And no, the answer to this isn't fix your tests, because if that's your attitude, why bother with static typing, just use duck typing, the unit tests will catch any bugs). In theory this and other generic unit test issues could be comprehensively solved by having a Rust-like traits feature.

> 2nd - C++/C#/Java programmers will come to D, use the same syntax, but get very different semantics. Not good in my opinion. (i.e. I only realised private was not private, by accident).
>
> D has made many good design decisions. I do not see this as one of them.

+1, D should have used a different keyword, such as `module`. It is a classic source of confusion for programmers familiar with many statically typed languages, and it comes up regularly here. It is a syntax issue, semantically the feature is better than just having true private.
March 17, 2018
On Tuesday, 13 March 2018 at 13:59:00 UTC, Steven Schveighoffer wrote:
> If you limit to class members, then you have to do something like C++ friends, which are unnecessarily verbose.

Not if you also have a module-level visibility modifier, which could have been `module`.

> IMO, the module-level encapsulation is the right choice. It helps with a lot of key features:
>
> 1. IFTI factory methods

Aren't these mainly because constructors can't use IFTI, unlike C++17, and because nullary struct constructors are banned?

> 2. unittests

Documented unittests should not be allowed to use private symbols, I just filed this:
https://issues.dlang.org/show_bug.cgi?id=18623
March 17, 2018
On Saturday, 17 March 2018 at 09:18:13 UTC, Nick Treleaven wrote:
> It's a language design decision as to whether a particular feature is worth supporting. I would like this feature too though. I'm not sure how much compiler complexity would be added by having another visibility modifier.
>

D could add an new attribute to class members:  @deny

A @deny attribute can come before a classes private member, to indicate that the private member is to remain private, even within the module.

Cause sure, it nice to be among friends, but you don't want your friends knowing every thought that is going through your mind! Sometimes, somethings, just need to remain private.

@deny private string _userName;

now... _userName is no longer accessible at the module level, and class encapsulation is restored.

If had I any clue about compilers, I'd think this through more ;-)

March 17, 2018
On Saturday, 17 March 2018 at 11:08:27 UTC, psychoticRabbit wrote:
> On Saturday, 17 March 2018 at 09:18:13 UTC, Nick Treleaven wrote:
>> It's a language design decision as to whether a particular feature is worth supporting. I would like this feature too though. I'm not sure how much compiler complexity would be added by having another visibility modifier.
>>
>
> D could add an new attribute to class members:  @deny
>
> A @deny attribute can come before a classes private member, to indicate that the private member is to remain private, even within the module.
>
> Cause sure, it nice to be among friends, but you don't want your friends knowing every thought that is going through your mind! Sometimes, somethings, just need to remain private.
>
> @deny private string _userName;
>
> now... _userName is no longer accessible at the module level, and class encapsulation is restored.
>
> If had I any clue about compilers, I'd think this through more ;-)

I don't like the name @deny, personally I would rather see the private attribute changed to something like:

private(true) // The member is oly visible to its parent.

private(false) // Same as just "private", visible to whole module.

Could be specialized to something like:

private(this) // Same as private(true)

private(module) // Same as private(false)

That way it can be introduced without breaking changes and looks cleaner since it wouldn't be yet another attribute.

Really it's just an extension to the already existing attribute.

This feature should be relatively easy to implement since it's similar to the "package" attribute, which also takes a value as the module name.
March 17, 2018
On Saturday, 17 March 2018 at 14:16:19 UTC, bauss wrote:
>
> I don't like the name @deny .....

how about:

@reallyis private string firstName_;

mmm..perhaps not... then how about...

@strictly private string firstName_;


March 17, 2018
On Saturday, 17 March 2018 at 15:02:21 UTC, psychoticRabbit wrote:
> On Saturday, 17 March 2018 at 14:16:19 UTC, bauss wrote:
>>
>> I don't like the name @deny .....
>
> how about:
>
> @reallyis private string firstName_;
>
> mmm..perhaps not... then how about...
>
> @strictly private string firstName_;

Still introduces a new attribute. D already has a lot of attributes and it goes against how every other attribute for visibility works.

That's why my suggestion would work better, because the package attribute already works like that.
March 17, 2018
On Saturday, 17 March 2018 at 14:16:19 UTC, bauss wrote:
> I don't like the name @deny, personally I would rather see the private attribute changed to something like:
>
> private(true) // The member is oly visible to its parent.
>
> private(false) // Same as just "private", visible to whole module.
>
> Could be specialized to something like:
>
> private(this) // Same as private(true)
>
> private(module) // Same as private(false)
>

maybe extend that to a list of types?

private(typeof(this), Foo, Bar)

would mean only typeof(this), Foo and Bar from the same module have access.
March 17, 2018
On Saturday, 17 March 2018 at 21:22:44 UTC, arturg wrote:
> maybe extend that to a list of types?

this is basically what C++ friend does and D was trying to avoid the complexity of
March 17, 2018
On Saturday, 17 March 2018 at 21:33:01 UTC, Adam D. Ruppe wrote:
> On Saturday, 17 March 2018 at 21:22:44 UTC, arturg wrote:
>> maybe extend that to a list of types?
>
> this is basically what C++ friend does and D was trying to avoid the complexity of

Really, the complexity of 'friend' comes from people abusing it.

In D, I would prefer no breaking change here. Leave private as it is.

Just a simple attribute that only applies within a class, and only to private members within that class.

@strictly private string firstName_;

Nothing outside of the class, not even the module, can access this now. It's all encapsulated.

It breaks nothing (AFAIK).
It's very clear what the intention is here.
It's an easy attribute to remember.
It restores the principle of class enscapsulation within a module, for when it's really needed.

Now D programmers would have the best of both worlds.

March 18, 2018
On Saturday, 17 March 2018 at 23:54:22 UTC, psychoticRabbit wrote:
> In D, I would prefer no breaking change here. Leave private as it is.

My suggestion has no breaking change and it works just like the package attribute already works.

Also you shouldn't allow multiple types for it, that would defeat the purpose of private again and in that case you should just use as is, since module-level private can already ensure that.

If you need to share it with types outside of the module, then it's pointless, because you're essentially just duck-taping an issue of your program design and not the language design.