www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Using closure in function scope to make "real" private class members

reply "H. S. Teoh" <hsteoh qfbox.info> writes:
So today, I thought I wanted to explore how far I can push the idea of
using closures over local variables in function scope to simulate
class-private field, i.e.:

--------
auto makeObj() {
	int realPrivateX;
	class C {
		int modulePrivateX;
		void func() {
			realPrivateX++;
		}
	}
	return new C;
}
void main() {
	auto obj = makeObj();
	obj.modulePrivateX++; // OK
	obj.realPrivateX++; // NG
}
--------

So far so good.  Next, I wondered if this could actually be extended to
handle an inheritance hierarchy too.  Here was my attempt:

------
interface I {
	void intfunc(int x);
}

auto makeBaseObj() {
	int realPrivateX;
	class Base : I {
		private int modulePrivateX;
		int publicX;
		override void intfunc(int x) {
			realPrivateX++; // expected OK
		}
	}
	return new Base;
}

auto makeDerivedObj() {
	int realPrivateY;
	class Derived : typeof(makeBaseObj()) {
		private int modulePrivateY;
		int publicY;
		override void intfunc(int x) {
			realPrivateX++; // expected NG
			modulePrivateX++;
		}
	}
	return new Derived;
}
------


When I tried to compile this, however, the compiler said:

------
/tmp/test.d(20): Error: class `test.makeDerivedObj.Derived` is nested within
`makeDerivedObj`, but super class `Base` is nested within `makeBaseObj`
---
ERROR: This is a compiler bug.
Please report it via https://issues.dlang.org/enter_bug.cgi
with, preferably, a reduced, reproducible example and the information below.
DustMite (https://github.com/CyberShadow/DustMite/wiki) can help with the
reduction.
---
DMD v2.098.1-1176-g005d97cb4
predefs   DigitalMars LittleEndian D_Version2 all D_SIMD Posix ELFv1 linux
CRuntime_Glibc CppRuntime_Gcc D_InlineAsm_X86_64 X86_64 D_LP64 D_PIC assert
D_PreConditions D_PostConditions D_Invariants D_ModuleInfo D_Exceptions
D_TypeInfo D_HardFloat
binary    dmd
version   v2.098.1-1176-g005d97cb4
config    /usr/src/d/bin/dmd.conf
DFLAGS    -I/usr/src/d/druntime/import -I/usr/src/d/druntime/src
-I/usr/src/d/phobos -L-L/usr/src/d/phobos/generated/linux/release/32
-L-L/usr/src/d/phobos/generated/linux/release/64 -L--no-warn-search-mismatch
-L--export-dynamic -fPIC
---
core.exception.AssertError src/dmd/aggregate.d(678): Assertion failure
----------------
??:? _d_assertp [0x55672da66de1]
??:? void dmd.aggregate.AggregateDeclaration.makeNested() [0x55672d752f64]
??:? _ZN22DsymbolSemanticVisitor23funcDeclarationSemanticEP15FuncDeclaration
[0x55672d7e2c80]
??:? _ZN22DsymbolSemanticVisitor5visitEP15FuncDeclaration [0x55672d7e5d78]
??:? _ZN15FuncDeclaration6acceptEP7Visitor [0x55672d857f61]
??:? _Z15dsymbolSemanticP7DsymbolP5Scope [0x55672d7d9b09]
??:? void dmd.dsymbolsem.DsymbolSemanticVisitor.visit(dmd.dclass.ClassDeclaration).__lambda9!(dmd.dsymbol.Dsymbol).__lambda9(
md.dsymbol.Dsymbol) [0x55672d7ea933]
??:? void dmd.dsymbol.foreachDsymbol(dmd.root.array.Array!(dmd.dsym
ol.Dsymbol).Array*, void delegate(dmd.dsymbol.Dsymbol)) [0x55672d7d3293]
??:? _ZN22DsymbolSemanticVisitor5visitEP16ClassDeclaration [0x55672d7e9e04]
??:? _ZN16ClassDeclaration6acceptEP7Visitor [0x55672d794b85]
??:? _Z15dsymbolSemanticP7DsymbolP5Scope [0x55672d7d9b09]
??:? _ZN25ExpressionSemanticVisitor5visitEP14DeclarationExp [0x55672d837165]
??:? _ZN14DeclarationExp6acceptEP7Visitor [0x55672d81ca21]
??:? _Z18expressionSemanticP10ExpressionP5Scope [0x55672d84d50f]
??:? _ZN24StatementSemanticVisitor5visitEP12ExpStatement [0x55672d8ce49f]
??:? _ZN12ExpStatement6acceptEP7Visitor [0x55672d8caad5]
??:? _Z17statementSemanticP9StatementP5Scope [0x55672d8ce383]
??:? _ZN24StatementSemanticVisitor5visitEP17CompoundStatement [0x55672d8ce766]
??:? _ZN17CompoundStatement6acceptEP7Visitor [0x55672d8cafd1]
??:? _Z17statementSemanticP9StatementP5Scope [0x55672d8ce383]
??:? _ZN16Semantic3Visitor5visitEP15FuncDeclaration [0x55672d8c5206]
??:? _ZN15FuncDeclaration6acceptEP7Visitor [0x55672d857f61]
??:? _Z9semantic3P7DsymbolP5Scope [0x55672d8c3c4d]
??:? _ZN16Semantic3Visitor5visitEP6Module [0x55672d8c404e]
??:? _ZN6Module6acceptEP7Visitor [0x55672d7bb6d9]
??:? _Z9semantic3P7DsymbolP5Scope [0x55672d8c3c4d]
??:? int dmd.mars.tryMain(ulong, const(char)**, ref dmd.globals.Param)
[0x55672d7441f8]
??:? _Dmain [0x55672d745e35]
------

Oops. :-D


T

-- 
If it's green, it's biology, If it stinks, it's chemistry, If it has numbers
it's math, If it doesn't work, it's technology.
May 31 2022
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
https://issues.dlang.org/show_bug.cgi?id=23151
May 31 2022
prev sibling next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Wednesday, 1 June 2022 at 01:54:52 UTC, H. S. Teoh wrote:
 So today, I thought I wanted to explore how far I can push the 
 idea of using closures over local variables in function scope 
 to simulate class-private field, i.e.:

 --------
 auto makeObj() {
 	int realPrivateX;
 	class C {
 		int modulePrivateX;
 		void func() {
 			realPrivateX++;
 		}
 	}
 	return new C;
 }
 void main() {
 	auto obj = makeObj();
 	obj.modulePrivateX++; // OK
 	obj.realPrivateX++; // NG
 }
 --------
Frankly, I don't think this thing is worth doing any hacks for. Controlling the scope of encapsulation is rarely that critical, and if it is, it's easier to just put the class to it's own file.
Jun 01 2022
next sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Wed, Jun 01, 2022 at 12:24:23PM +0000, Dukc via Digitalmars-d wrote:
 On Wednesday, 1 June 2022 at 01:54:52 UTC, H. S. Teoh wrote:
 So today, I thought I wanted to explore how far I can push the idea
 of using closures over local variables in function scope to simulate
 class-private field, i.e.:
[...]
 Frankly, I don't think this thing is worth doing any hacks for.
 Controlling the scope of encapsulation is rarely that critical, and if
 it is, it's easier to just put the class to it's own file.
I know, I wouldn't actually do this myself in a real project. But I was just curious how far I could go with the current language. T -- If it tastes good, it's probably bad for you.
Jun 01 2022
prev sibling next sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Wednesday, 1 June 2022 at 12:24:23 UTC, Dukc wrote:
 On Wednesday, 1 June 2022 at 01:54:52 UTC, H. S. Teoh wrote:
 So today, I thought I wanted to explore how far I can push the 
 idea of using closures over local variables in function scope 
 to simulate class-private field, i.e.:

 --------
 auto makeObj() {
 	int realPrivateX;
 	class C {
 		int modulePrivateX;
 		void func() {
 			realPrivateX++;
 		}
 	}
 	return new C;
 }
 void main() {
 	auto obj = makeObj();
 	obj.modulePrivateX++; // OK
 	obj.realPrivateX++; // NG
 }
 --------
Frankly, I don't think this thing is worth doing any hacks for. Controlling the scope of encapsulation is rarely that critical, and if it is, it's easier to just put the class to it's own file.
It is critical if you working with other people and you want the code to be self evident. - Alex
Jun 01 2022
prev sibling next sibling parent reply forkit <forkit gmail.com> writes:
On Wednesday, 1 June 2022 at 12:24:23 UTC, Dukc wrote:
 Frankly, I don't think this thing is worth doing any hacks for. 
 Controlling the scope of encapsulation is rarely that critical, 
 and if it is, it's easier to just put the class to it's own 
 file.
That only option available to me in D, to ensure that my class has truly 'private' members (so that no other code within the same module can access them), is to put it in it's own module. That's so sad.
Jun 02 2022
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 3 June 2022 at 05:34:48 UTC, forkit wrote:

 That only option available to me in D, to ensure that my class 
 has truly 'private' members (so that no other code within the 
 same module can access them), is to put it in it's own module.

 That's so sad.
No, it's not sad. Just, please consider this: ```d struct Foo { private int _x; void x(int val) { _x = val; } } ``` vs. this: ```d struct Foo { private int _x; } void x(Foo f} { f._x = x; } ``` The only difference here is that in one case, the function manipulating `_x` is above the brace that terminates `Foo`, and in the other case it's below it. In practical terms, the person editing the module has access to the function in both cases. You can argue that the module might have many lines of code. I can argue that a class or struct definition can have manly lines of code. How is one case different from the other? Any argument about encapsulation here is purely ideological. If you have access to the source file, you have access to the private members, period. The practical problem that arises is when you directly manipulate `_x` at multiple points in the file and then one day decide to rename it to `_y`. Ignoring the fact things like `Find and Replace` and `Ctrl + D` exist, and that the worst case resulting from such a change should be compilation errors, this problem exists whether you're accessing the field from within the class or from elsewhere in the module. But yeah, this can be an issue on teams, sure. Java, where you almost always have one class per file, has exactly the same issue. The common recommendation in Java for people concerned about it is to only access private members via their getters and setters, even within the class. In D, given module `mymod`, you can split your aggregates into individual files and make a package module: ``` - mymod -- package.d -- classA.d -- classB.d -- freefuncs.d ``` Then clients can still treat `mymod` as a single module, and you get your ideological purity. But your problem of programmers having access to the private memvers of `ClassA` if they have access to `classA.d` doesn't go away. It's just been moved to a different module.
Jun 02 2022
next sibling parent forkit <forkit gmail.com> writes:
On Friday, 3 June 2022 at 05:58:06 UTC, Mike Parker wrote:
 ...
 Any argument about encapsulation here is purely ideological. If 
 you have access to the source file, you have access to the 
 private members, period.
 ...
No. Not really. It's more than ideological. As long as the module contains one, and only one class, and only contains code that manipulates that one class, then encapsulation is maintained within that module - regardless of where in the module that code is. The problem, is that a module can contain all sorts of code, and any of the code can alter the way you think that class might operate (i.e. the interface of that class cannot be relied upon, witin a module, that contains any code unrelated to that class. For the person who has access to the module, this 'might' not be a problem (as long as they extra careful not to let code in the module alter the properties of the class, where the class definition did not account for that. The other problem, where code in the module may exist, that doesn't relate directly to the manipulation of the class, is that someone reading the code in that module cannot be assured the interface of that class is being used correctly, unless they audit ALL the code in that module. I'll say that again - they need to audit ALL the code in that module. For these reasons, the programmer must ensure that every class is contained in it's owm module, and that any code in that module directly relates to the properties/functionality of that class. While this might be considered best practice, an option to make a property of class truly private within the module, would provide some flexibiltiy to this requirement.
Jun 03 2022
prev sibling next sibling parent reply Guillaume Piolat <first.last gmail.com> writes:
On Friday, 3 June 2022 at 05:58:06 UTC, Mike Parker wrote:
 No, it's not sad.
+1, not everything has to be decoupled. Being in the same file means you want those things to be coupled, and thus you get that. I much prefer that to the "friend" thing in C++.
Jun 03 2022
parent reply forkit <forkit gmail.com> writes:
On Friday, 3 June 2022 at 10:12:04 UTC, Guillaume Piolat wrote:
 On Friday, 3 June 2022 at 05:58:06 UTC, Mike Parker wrote:
 No, it's not sad.
+1, not everything has to be decoupled. Being in the same file means you want those things to be coupled, and thus you get that. I much prefer that to the "friend" thing in C++.
Hey, it's fine that the D module is in effect 'the owner' of the representation of a class, rather than the class itself. While suprising to some, that's just how it is. It's not a bad thing. There are benefits in that approach, and I am not arguing against that approach. But in D, if you want to statically enforce class encapsulation, the *only* way you can do this, is by putting every every class in its own file. That is what's sad.
 +1, not everything has to be decoupled.
+1 ;-)
 Being in the same file means you want those things to be 
 coupled, and thus you get that.
Not necessarily. The overall goal should be encapsulation (hence in D, the one class per module recommendation). But the goal of encapsulation is to manage complexity and support local reasoning. It's not an excuse to force programmers to put each class in its own module, in order to statically enforce its represenation.
Jun 03 2022
parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 3 June 2022 at 10:37:28 UTC, forkit wrote:

 Not necessarily. The overall goal should be encapsulation 
 (hence in D, the one class per module recommendation). But the 
 goal of encapsulation is to manage complexity and support local 
 reasoning. It's not an excuse to force programmers to put each 
 class in its own module, in order to statically enforce its 
 represenation.
And in D you encapsulate at the module level. We don't need another keyword for more fine-grained encapsulation, because we already have a solution in the form of the package module.
Jun 03 2022
parent reply forkit <forkit gmail.com> writes:
On Friday, 3 June 2022 at 11:50:22 UTC, Mike Parker wrote:
 On Friday, 3 June 2022 at 10:37:28 UTC, forkit wrote:

 Not necessarily. The overall goal should be encapsulation 
 (hence in D, the one class per module recommendation). But the 
 goal of encapsulation is to manage complexity and support 
 local reasoning. It's not an excuse to force programmers to 
 put each class in its own module, in order to statically 
 enforce its represenation.
And in D you encapsulate at the module level. We don't need another keyword for more fine-grained encapsulation, because we already have a solution in the form of the package module.
That's fine, if a module that contains a class, is nice and short, and only contains code that directly acts on that class, and no other code, whatsoever. Otherwise the encapsulation 'could' be broken (i.e. mutations maybe occuring outside of your encapsulated representation), and you won't know unless you know ALL the code in that module (as it cannot be enforced statically by the compiler). It's up to the human to verify the correctness. To just say the programmer owns the module, and therefore everything will be fine.. is naive. Practically speaking, anyone that uses a class in D, must be put it in its own module - no exceptions.
Jun 03 2022
parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 3 June 2022 at 12:13:47 UTC, forkit wrote:

 Practically speaking, anyone that uses a class in D, must be 
 put it in its own module - no exceptions.
That's just nonsense.
Jun 03 2022
next sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Friday, 3 June 2022 at 15:41:04 UTC, Mike Parker wrote:
 On Friday, 3 June 2022 at 12:13:47 UTC, forkit wrote:

 Practically speaking, anyone that uses a class in D, must be 
 put it in its own module - no exceptions.
That's just nonsense.
It isn't nonsense if you want private to encapsulate to the class only and not the entire module file. That the technique that you *HAVE* to use in D. Unless you don't mind removing the one module per file restriction. -Alex
Jun 03 2022
prev sibling parent reply forkit <forkit gmail.com> writes:
On Friday, 3 June 2022 at 15:41:04 UTC, Mike Parker wrote:
 On Friday, 3 June 2022 at 12:13:47 UTC, forkit wrote:

 Practically speaking, anyone that uses a class in D, must be 
 put it in its own module - no exceptions.
That's just nonsense.
How is it nonsense? I don't get it. If you want the compiler to statically ensure there are no unsafe mutations (from other code within the same module) on the encapsulated represenation of a class, then you have no choice (apart from *manually* inspecting and verifying all the code in the module). You cannot get this static ensurance from the compiler otherwise. The aim of class abstraction is to support encapsulation and local reasoning. The best way to achieve this aim in D, is one-class-per-file. It's nonsense to suggest that this is nonsense. It's just fact. I do not see why their would be such a strong objection to giving the programmer an alternative approach. That seems 'ideological' to me.
Jun 03 2022
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/3/22 6:50 PM, forkit wrote:
 On Friday, 3 June 2022 at 15:41:04 UTC, Mike Parker wrote:
 On Friday, 3 June 2022 at 12:13:47 UTC, forkit wrote:

 Practically speaking, anyone that uses a class in D, must be put it 
 in its own module - no exceptions.
That's just nonsense.
How is it nonsense? I don't get it.
I think he means the "no exceptions" is nonsense. There are valid reasons to want to access private data from outside types. -Steve
Jun 03 2022
parent reply forkit <forkit gmail.com> writes:
On Friday, 3 June 2022 at 23:30:58 UTC, Steven Schveighoffer 
wrote:
 On 6/3/22 6:50 PM, forkit wrote:
 On Friday, 3 June 2022 at 15:41:04 UTC, Mike Parker wrote:
 On Friday, 3 June 2022 at 12:13:47 UTC, forkit wrote:

 Practically speaking, anyone that uses a class in D, must be 
 put it in its own module - no exceptions.
That's just nonsense.
How is it nonsense? I don't get it.
I think he means the "no exceptions" is nonsense. There are valid reasons to want to access private data from outside types. -Steve
First, this is not something I've argued against. I'm made no such argument that attempts to invalidate that point of view. But his comment is very selective then, if that's what he meant, because my comments have been within the context of wanting static, compiler enforced, safety of the class. Which can only be done by putting every class in its own file. No exceptions. I'm arguing to give the programmer another option, not take an option way.
Jun 03 2022
parent forkit <forkit gmail.com> writes:
On Saturday, 4 June 2022 at 00:41:24 UTC, forkit wrote:

I'd like it, if I had 'the option', to do something like this in 
D:

(where the attribute  sealed, results in static, compiler 
enforced, protection of the interface of that class, from any 
code outside of that class (i.e. code in the same module).

 sealed
 final
 orWhatever... it's irrelevant at this stage as to what the 
attribute could be called.


// --- some module file

 sealed class A
{

}


 sealed class B
{

}

// ------------
Jun 03 2022
prev sibling next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 3 June 2022 at 22:50:06 UTC, forkit wrote:
 The aim of class abstraction is to support encapsulation and 
 local reasoning. The best way to achieve this aim in D, is 
 one-class-per-file.

 It's nonsense to suggest that this is nonsense. It's just fact.
your code must be enterprise-grade https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition
Jun 03 2022
prev sibling next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 3 June 2022 at 22:50:06 UTC, forkit wrote:
 On Friday, 3 June 2022 at 15:41:04 UTC, Mike Parker wrote:
 On Friday, 3 June 2022 at 12:13:47 UTC, forkit wrote:

 Practically speaking, anyone that uses a class in D, must be 
 put it in its own module - no exceptions.
That's just nonsense.
How is it nonsense? I don't get it.
"anyone that uses a class in D...no exceptions" Change that to "anyone who wants class-level encapsulation" and remove the "no exceptions" and it's sensible.
 I do not see why their would be such a strong objection to 
 giving the programmer an alternative approach. That seems 
 'ideological' to me.
It would require adding a new protection keyword to the language. The general policy for that is that there must be a strong benefit. Given that we already have a way to achieve the same goal (putting classes in their own modules), then the benefit of such a keyword is extremely weak.
Jun 03 2022
parent reply forkit <forkit gmail.com> writes:
On Saturday, 4 June 2022 at 01:41:52 UTC, Mike Parker wrote:
 ....
 It would require adding a new protection keyword to the 
 language. The general policy for that is that there must be a 
 strong benefit. Given that we already have a way to achieve the 
 same goal (putting classes in their own modules), then the 
 benefit of such a keyword is extremely weak.
Well, I've never encounted as much resistance to change, as what occurs when someone brings this topic up in a discussion. I really do think there is idealogical resistance to such a change, and it's this that brings about these strong reactions. Cause D has plenty of completely useless attributes. I don't think another one is going to make much difference. In the meantime, if a D programmer wants static, compile time verification that that the encapsulation of a class is not broken, then they MUST put that class in a separate module (one module per class). No exceptions.
Jun 03 2022
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Saturday, 4 June 2022 at 05:07:10 UTC, forkit wrote:
 On Saturday, 4 June 2022 at 01:41:52 UTC, Mike Parker wrote:
 ....
 It would require adding a new protection keyword to the 
 language. The general policy for that is that there must be a 
 strong benefit. Given that we already have a way to achieve 
 the same goal (putting classes in their own modules), then the 
 benefit of such a keyword is extremely weak.
Well, I've never encounted as much resistance to change, as what occurs when someone brings this topic up in a discussion.
I'm just expressing my thoughts on the topic. I think it would be a pointless addition to the language. But if you feel strongly enough about it, submit a DIP and see how it goes. I'm fairly confident it will be rejected since we already have a solution, but I could be wrong. A DIP that's persuasive enough to convince Walter and Atila is all you need.
Jun 03 2022
parent forkit <forkit gmail.com> writes:
On Saturday, 4 June 2022 at 05:13:25 UTC, Mike Parker wrote:
 I'm just expressing my thoughts on the topic. I think it would 
 be a pointless addition to the language. But if you feel 
 strongly enough about it, submit a DIP and see how it goes. I'm 
 fairly confident it will be rejected since we already have a 
 solution, but I could be wrong. A DIP that's persuasive enough 
 to convince Walter and Atila is all you need.
But a DIP is the one sure way, of it never, ever...ever.. happening. So I'm not surprised at your suggestion, to DIP it ;-)
Jun 03 2022
prev sibling next sibling parent reply matheus <matheus gmail.com> writes:
On Saturday, 4 June 2022 at 05:07:10 UTC, forkit wrote:
 ...
 Cause D has plenty of completely useless attributes. I don't 
 think another one is going to make much difference.
 ...
I have no opinion on the merit being discussed except this part, because I do think that keep adding more attributes will hurt D in a long term, in fact this is becoming a pattern in this language... there is a problem? -Let's add this attribute to solve. If possible this should be thought in a way to be solved without adding new attributes. Matheus.
Jun 03 2022
next sibling parent forkit <forkit gmail.com> writes:
On Saturday, 4 June 2022 at 05:20:58 UTC, matheus wrote:
 On Saturday, 4 June 2022 at 05:07:10 UTC, forkit wrote:
 ...
 Cause D has plenty of completely useless attributes. I don't 
 think another one is going to make much difference.
 ...
I have no opinion on the merit being discussed except this part, because I do think that keep adding more attributes will hurt D in a long term, in fact this is becoming a pattern in this language... there is a problem? -Let's add this attribute to solve. If possible this should be thought in a way to be solved without adding new attributes. Matheus.
I don't agree. The increased use of attributes is really the best way to accomodate change, rather than keywords or syntax changes. D is more of a hobby language to me anyway, so I couldn't care less what it does. But to the extent it allows me to do things -> the way I want to do them, then and only then, does it maintain my interest.
Jun 03 2022
prev sibling parent zjh <fqbqrr 163.com> writes:
On Saturday, 4 June 2022 at 05:20:58 UTC, matheus wrote:

 If possible this should be thought in a way to be solved 
 without adding new attributes.

 Matheus.
The important thing is that there is `demand` now, It is important that we have a way to `solve` it.
Jun 03 2022
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/3/22 22:07, forkit wrote:
 On Saturday, 4 June 2022 at 01:41:52 UTC, Mike Parker wrote:
 ....
 It would require adding a new protection keyword to the language. The
 general policy for that is that there must be a strong benefit. Given
 that we already have a way to achieve the same goal (putting classes
 in their own modules), then the benefit of such a keyword is extremely
 weak.
Well, I've never encounted as much resistance to change, as what occurs when someone brings this topic up in a discussion.
I think the reason is there is no strong argument for one way or the other. There are two options: a) 'private' means "private to the class", which necessitates the equivalent of the keyword 'friend'. This option is what C++ chose. b) 'private' means "private to the module", which frees 'friend' as a user symbol. This option is what D chose.
 I really do think there is idealogical resistance to such a change, and
 it's this that brings about these strong reactions.
Since D came after C++, it is clear that option b was seen to be superior. Let's hear arguments why option a is better than b.
 Cause D has plenty of completely useless attributes. I don't think
 another one is going to make much difference.
It will make N+1.
 In the meantime, if a D programmer wants
Ah!
 static, compile time
 verification that that the encapsulation of a class
Ah!
 is not broken, then
 they MUST put that class in a separate module (one module per class).
Where did "wants" and "encapsulation of class" come from? Why would a D programmer not "need" "encapsulation of module"? Let's hear arguments about why one is better than the other. Which text book are we following? Why are you stopping at class level? Why would one member function of a class access members that were supposed to be touched only by another member function? Where is that abstraction? Why don't we "want" that? Is it because other languages don't provide that? This whole discussion of encapsulation levels is arbitrary.
 No exceptions.
I am not going to contribute to your projects. Life is too short to follow "core guidelines". How about actually getting things done? Ali
Jun 04 2022
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Saturday, 4 June 2022 at 07:04:35 UTC, Ali Çehreli wrote:
 Since D came after C++, it is clear that option b was seen to 
 be superior. Let's hear arguments why option a is better than b.
As already stated, when changing the model you want encapsulation to be tight. Stronger typing is always better in this setting. «Friend» is useful in larger apps when you need access on another layer for performance or concurrency reasons. It documents exactly what you need to look at when changing invariants. But D has other stuff to fix, so there is no reason to fix this one. Most D programs are not so large that it matters all that much.
Jun 04 2022
prev sibling parent reply forkit <forkit gmail.com> writes:
On Saturday, 4 June 2022 at 07:04:35 UTC, Ali Çehreli wrote:
 ...
 I think the reason is there is no strong argument for one way 
 or the other. There are two options:

 a) 'private' means "private to the class", which necessitates 
 the equivalent of the keyword 'friend'. This option is what C++ 
 chose.

 b) 'private' means "private to the module", which frees 
 'friend' as a user symbol. This option is what D chose.

 I really do think there is idealogical resistance to such a
change, and
 it's this that brings about these strong reactions.
Since D came after C++, it is clear that option b was seen to be superior. Let's hear arguments why option a is better than b.
It's interesting that whenever this topic is brought up, that people in the D community (like you, for example), try to rephrase it as if we're all being forced to make a choice between A *or* B. I'd like to have A *and* B. You normally come up with ideas to issues that people raise (even ideas that to me see pretty ordinary), except, when it is this issue?? Why this idea encounters sooo.. much resistance, is..well. interesting. The rest of your response I couldn't make any sense of.. so I'll ignore it. In the end though, encapsulation of a class, in D, is broken, and cannot be statically verified by the compiler, unless you put that class in it's own file (which is what you're expected to do anyway, based on the reponses this idea always provoke). Since there is no option B, to do otherwise, is what I would consider unsound programming, as it is not possible to reason about the code of the class contained within a module, without understanding ALL the code in that module. It's also not possible to prove (again, without human intervention) that other code in the module does not violate the modular requirements of the class. A possible counter agrument to the above, is that there is no encapsulation of a class in D. The module provides all the encapsulation anyone will ever need. I'm not sure I'd want to be on that side of the argument ;-)
Jun 04 2022
next sibling parent Adam D Ruppe <destructionator gmail.com> writes:
On Saturday, 4 June 2022 at 11:15:13 UTC, forkit wrote:
 In the end though, encapsulation of a class, in D, is broken, 
 and cannot be statically verified by the compiler
Good OOP code accesses objects through interfaces anyway. The class itself ought only be used to construct it.
Jun 04 2022
prev sibling next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Saturday, 4 June 2022 at 11:15:13 UTC, forkit wrote:

 Why this idea encounters sooo.. much resistance, is..well. 
 interesting.
As I see it, this is a matter of "thinking in D" vs "thinking in something else". When you think in the language you're using, you organize your code to best take advantage of that language's features. D gives you the tools you need to have the strict encapsulation you want--classes can go in their own module; package modules present a single module interface to the world; package protection allows internal access within the package where necessary. What I don't understand is, what's so hard about that?
 In the end though, encapsulation of a class, in D, is broken,
Two things here. 1) There's a fundamental disagreement that encapsulation is broken. As I see it, it isn't broken. Any class I implement in a module is encapsulated from outside that module. I don't have any need for encapsulation inside the module, anymore than I would have any need for encapsulation inside the class (i.e., restricting access to a private member to a single member function). Since they're all in the same file, there's no difference whatsoever outside of a conceptual one. If you have access to the module's source, you have access to the private members. 2) A solution exists for anyone who cares about that conceptual difference. We don't need a new keyword/attribute to do something you can already do.
 A possible counter agrument to the above, is that there is no 
 encapsulation of a class in D. The module provides all the 
 encapsulation anyone will ever need.
I would almost say "Exactly!" to this, if not for the "all the encapsulation anyone will ever need". The module is the unit of encapsulation in D. But, as you demonstrate, some people just aren't comfortable with that. So they have the option to put their classes in separate modules.
Jun 04 2022
next sibling parent reply zjh <fqbqrr 163.com> writes:
On Saturday, 4 June 2022 at 12:28:41 UTC, Mike Parker wrote:


Obviously, adding a little code can make it convenient for all 
kinds of `'d'` programmers.
Is there no difference between `class level` encapsulation and 
`module level` encapsulation?
Jun 04 2022
parent zjh <fqbqrr 163.com> writes:
On Saturday, 4 June 2022 at 12:57:16 UTC, zjh wrote:

 Is there no difference between `class level` encapsulation and 
 `module level` encapsulation?
`Encapsulation` is `very very` important, At any level. you don't want `class encapsulation` and don't think it's worth it?
Jun 04 2022
prev sibling parent forkit <forkit gmail.com> writes:
On Saturday, 4 June 2022 at 12:28:41 UTC, Mike Parker wrote:
 2) A solution exists for anyone who cares about that conceptual 
 difference. We don't need a new keyword/attribute to do 
 something you can already do.
Umm..no. Once again, you're rephrasing my argument to suit you're agenda ( of sprouting the 'superior' approach of D). If I could aready do what i want to do, I would not be discussing it. I'd like the option to improve type soundness of a class, so that I can confidently have other code in the module, and thereby have the assurance that other code does not violate my class invariants. I cannot currently do that in D. It's a bit like having an invariant near the top of the module, that says x must not equal 0. But 85 lines down in the code, someone has set x to 0. An you're argument would be, hey, just put x in its own module then.
Jun 04 2022
prev sibling next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/4/22 04:15, forkit wrote:
 On Saturday, 4 June 2022 at 07:04:35 UTC, Ali Çehreli wrote:
 ...
 I think the reason is there is no strong argument for one way or the
 other. There are two options:

 a) 'private' means "private to the class", which necessitates the
 equivalent of the keyword 'friend'. This option is what C++ chose.

 b) 'private' means "private to the module", which frees 'friend' as a
 user symbol. This option is what D chose.

 I really do think there is idealogical resistance to such a
change, and
 it's this that brings about these strong reactions.
Since D came after C++, it is clear that option b was seen to be superior. Let's hear arguments why option a is better than b.
It's interesting that whenever this topic is brought up, that people in the D community (like you, for example), try to rephrase it as if we're all being forced to make a choice between A *or* B. I'd like to have A *and* B.
Languages don't provide every want without weighing pros of cons. It may very well be good to have both A and B but I am not convinced.
 You normally come up with ideas to issues that people raise (even ideas
 that to me see pretty ordinary)
I am happy to be simple and happily finding ways to become more so.
 , except, when it is this issue??
I am not going to come up with ideas for non-issues. I asked whether you've seen a single case where somebody forgot to mark a variable 'private' and there was an issue. I seriously doubt it. People are not crazy creatures that change members willy nilly. In fact, encapsulation can be achieved purely by convention: Name all members in a special way e.g. with a leading underscore and let it mean "this is private" and you have encapsulation. Nobody will access those members. If they ever do access, that's because they have a business case to do so. I gave the real-world example of how one company did access D runtime's GC statistics, which happened to be marked as 'private' when it was first designed.
 Why this idea encounters sooo.. much resistance, is..well. interesting.
I man not resisting this idea but your presentation of it. You present it as if D is broken. I asked for your arguments for favoring per-class encapsulation vs. per-module encapsulation. I haven't seen those arguments yet but I suspect you favor class because other languages do so. My "text book" reference was related: Is there a computer science consensus on class should be the unit of encapsulation? I gave another example where your favoring per-class encapsulation comes short: What about private members that are accessed only by a subset of the member functions of a class. That pattern emerges a lot in my types. Does not the same logic apply to that case? Member function foo() can access array _buffer even though _buffer should be accessed only by bar() and zar(). I know one can put _buffer, bar(), and zar() in a different class and get lower level encapsulation but that's not different from moving code to another module to get lower level of encapsulation.
 The rest of your response I couldn't make any sense of.. so I'll 
ignore it. I tried to explain above: - Why do you favor 'class' over module? - If you stop at 'class', you will come up short.
 In the end though, encapsulation of a class, in D, is broken
That is wrong. And exactly that kind of mistaken but so-sure statement moves me to so much resistence. The encapsulation point is merely arbitrary. Please you explain why you are so strong on where you stop encapsulation. Why class? Is there a computer science theory behind it?
 and cannot
 be statically verified by the compiler
As I said, since nobody will reach private members willy nilly, static verification of it is overkill. Encapsulation can be achieved by a convention. I will go further and note that private does not add any value to the program: Replace all with 'public' and the program will run in exactly the same way with exactly the same level of safety.
 Since there is no option B, to do otherwise, is what I would consider
 unsound programming, as it is not possible to reason about the code of
 the class contained within a module, without understanding ALL the code
 in that module.
Really? That does not make sense at all. Why would e.g. Vector's code have anything to do with List's code? How does one get a hold of an object of the other to access its private members? This kind of statement is misguided. I am afraid people new to programming will take those and be concerned. There is no such problem at all. I haven't seen a single case of such violation of encapsulation. None.
 It's also not possible to prove (again, without human intervention) that
 other code in the module does not violate the modular requirements of
 the class.
My example above holds: List's code does not even receive a Vector object. I don't know what kind of projects you work with but I am happy to never have encountered such violations of modular requirements. (?)
 A possible counter agrument to the above, is that there is no
 encapsulation of a class in D. The module provides all the encapsulation
 anyone will ever need.

 I'm not sure I'd want to be on that side of the argument ;-)
You clearly are not and I proudly am. Besides, there are other ways of providing encapsulation when really needed. The reason I don't hear the pimpl idiom in D circles is because nobody really needs it. Ali
Jun 04 2022
parent reply forkit <forkit gmail.com> writes:
On Saturday, 4 June 2022 at 23:11:24 UTC, Ali Çehreli wrote:
 I man not resisting this idea but your presentation of it. You 
 present it as if D is broken. I asked for your arguments for 
 favoring per-class encapsulation vs. per-module encapsulation. 
 I haven't seen those arguments yet but I suspect you favor 
 class because other languages do so.
Again (how many time do I have to say this??), my argument is not favouring one or the other. It's favouring the 'option' to have both.
 - Why do you favor 'class' over module?
Again, I don't. How many times do I have to say this??
 (me) In the end though, encapsulation of a class, in D, is 
 broken

 (you) That is wrong.
Again, you pick only part of my argument so that it suits your agenda. Here is what I actually wrote: "In the end though, encapsulation of a class, in D, is broken, and cannot be statically verified by the compiler, unless you put that class in it's own file (which is what you're expected to do anyway, based on the reponses this idea always provoke)." It's pointless for me to discuss an issue with people who are clearly ideologically opposed to it. So I won't ;-)
Jun 04 2022
parent forkit <forkit gmail.com> writes:
On Sunday, 5 June 2022 at 00:30:14 UTC, forkit wrote:
 Again (how many time do I have to say this??), my argument is 
 not favouring one or the other. It's favouring the 'option' to 
 have both.
Well, to be clear, both exist already (i.e. one class per module, and it's done). But my argument is to have both in the context of a module that contains a class, as well as other code (as I've made very clear from the beginning). I don't want to have to manually audit a whole module, just becasue it contains code other than a class, and therefore, there is no way to ensure the invariants of that class are being upheld, without manually inspecting all code in that module. This is my point. I should not have to do this manually, and I do not want to 'forced' by the language to put each class in its own module, because of this. That's the end of my discussion on this topic ;-)
Jun 04 2022
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/4/22 04:15, forkit wrote:

 You normally come up with ideas to issues that people raise
Has anyone suggested the following syntax yet? class C { private class: // really private private module: // module-level as today private: // same as 'private module' } If there are syntax issues, perhaps paranthesis can work: private(class): Ali
Jun 04 2022
next sibling parent forkit <forkit gmail.com> writes:
On Sunday, 5 June 2022 at 01:32:45 UTC, Ali Çehreli wrote:
 On 6/4/22 04:15, forkit wrote:

 You normally come up with ideas to issues that people raise
Has anyone suggested the following syntax yet? class C { private class: // really private private module: // module-level as today private: // same as 'private module' } If there are syntax issues, perhaps paranthesis can work: private(class): Ali
See. I knew you could do it ;-) All it takes is an open mind -> not wanting to be forced into thinking the way a language wants you to think.
Jun 04 2022
prev sibling parent reply forkit <forkit gmail.com> writes:
On Sunday, 5 June 2022 at 01:32:45 UTC, Ali Çehreli wrote:

btw. Has anyone ever conducted a code review into representation 
exposure in phobos, at the intra-module level (within a module, 
including unit-tests)?

It would be interesting to see, if, and where, invariants are not 
being preserved, and why.
Jun 04 2022
parent reply forkit <forkit gmail.com> writes:
On Sunday, 5 June 2022 at 04:49:44 UTC, forkit wrote:

btw.

here is a simple example, for demonstration purposes only, of the 
change that I'd like to see in D:

It's benefit seems very obvious to me ;-)

First, the invariants of the class are now upheld by the compiler.

Second, those of us who expect invariants to be upheld, can now 
have it.

Third, it's completely optional. Nobody has to change anything 
they currently do. If you don't want it, don't use it.


// ----
module test;

// example:  private is an access specifier, that works just as 
private does,
// except, that  private is encapsulated to the class (or struct).

class ID
{
     import std.string;

      private:
         string _id;

     public
         void setID(string id)
         {
             assert(isNumeric(id));
             _id = id;
         }
}

unittest
{
     import std.stdio;

     ID id = new ID();

     id.setID("123"); // Fine. The invariant is maintained.
     writeln(id._id);

     id._id = "dsa"; // This would violate the invariant.
                     // The compiler would never allow this with 
 private
     writeln(id._id);
}

// -----
Jun 04 2022
parent Commander Zot <no no.no> writes:
On Sunday, 5 June 2022 at 06:08:10 UTC, forkit wrote:
 On Sunday, 5 June 2022 at 04:49:44 UTC, forkit wrote:
[...]
btw. here is a simple example, for demonstration purposes only, of the change that I'd like to see in D: [...]
may I suggest you just use the proper tools for enforcing invariants? https://dlang.org/spec/class.html#invariants
Jun 06 2022
prev sibling parent Dukc <ajieskola gmail.com> writes:
On Friday, 3 June 2022 at 22:50:06 UTC, forkit wrote:
 On Friday, 3 June 2022 at 15:41:04 UTC, Mike Parker wrote:
 On Friday, 3 June 2022 at 12:13:47 UTC, forkit wrote:

 Practically speaking, anyone that uses a class in D, must be 
 put it in its own module - no exceptions.
That's just nonsense.
How is it nonsense? I don't get it.
Because practical experience - at least mine - suggests almost the complete opposite of what you're saying. Let's take a practical example. Imagine I'm making a GUI label struct. ```D struct Label { private ubyte[] content; string text() { //whatever... } string text(string arg) { //assign arg to content...; } Tuple(Font, size_t)[] getFonts { //Get list of fonts used, along //with their usage starting //points... } //and other members... } ``` I'm marking `content` private because I want to keep myself free to change that to some other internal represenataion in the future. Let's say this struct is not the only thing in the module. A realistic scenario would be that there are 2000 other lines that can access `content` if they really want to. That's not a big problem. Others will usually instead use the public functions of `Label`. If I someday decide to change the internal representation, it's possible that one or two things in the module depend on it if I'm unlucky. Those are quick and easy to fix, and I can fix them myself since they are in the same module. I probably won't bother to put `Label` to it's own file just to avoid such an insignificant risk, and I'm pretty sure an average D programmer would agree with me in this.
Jun 04 2022
prev sibling next sibling parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 3 June 2022 at 05:58:06 UTC, Mike Parker wrote:
 The only difference here is that in one case, the function 
 manipulating `_x` is above the brace that terminates `Foo`, and 
 in the other case it's below it. In practical terms, the person 
 editing the module has access to the function in both cases.
I like private in D, but there is a big problem with synchronized members: ```d synchronized class C { private int i; } public void foo(C c) { c.i++; } ``` ``` $ dmd -vasm -c old/syncclass.d _D9syncclass3fooFCQq1CZv: 0000: FF 40 08 inc dword ptr 8[EAX] 0003: C3 ret ``` `foo` just incremented `i` without locking `c`.
Jun 04 2022
parent Nick Treleaven <nick geany.org> writes:
On Saturday, 4 June 2022 at 16:53:45 UTC, Nick Treleaven wrote:
 I like private in D, but there is a big problem with 
 synchronized members:
Filed: https://issues.dlang.org/show_bug.cgi?id=23158
Jun 04 2022
prev sibling parent forkit <forkit gmail.com> writes:
On Friday, 3 June 2022 at 05:58:06 UTC, Mike Parker wrote:
 ...
 In D, given module `mymod`, you can split your aggregates into 
 individual files and make a package module:

 ```
 - mymod
 -- package.d
 -- classA.d
 -- classB.d
 -- freefuncs.d
 ```

 Then clients can still treat `mymod` as a single module, and 
 you get your ideological purity. But your problem of 
 programmers having access to the private memvers of `ClassA` if 
 they have access to `classA.d` doesn't go away. It's just been 
 moved to a different module.
Those last two lines of your response, is 'my justification'. i.e. none of the workarounds make the problem go away. All they do is add totally unnecessary cognitive load, to what should be a really simple, straightforward, design decision - I want this to be private to this class. Access control decisions should not be dictated to me by D. Access control is a decision I (the designer) have the right to make, and also the right to expect the compiler to enforce. Claiming this right to be just 'ideological purity' is a nice distraction ;-)
Jun 08 2022
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/2/22 22:34, forkit wrote:

 That's so sad.
I don't feel sad at all. I stopped my response after seeing Mike's. But I will add that I am surprised that this issue comes up from time to time. Have you ever been bitten by the fact that you forgot to mark a member private and that was a cause of some kind of trouble? (I don't think so.) I can't believe other programmers would use that should-be-private member and started abusing it. Note that for it to be a cause of trouble, it would have been abused, not used. From that point of view, if others found the member useful, it actually means that it was a mistake to mark it private, right? Contrary to the other case, I do have examples of this sort though: D runtime used to mark GC stats private and people had to copy/paste that private struct to their code and access GC stats. (Real story.) See? private was wrong there. There are other cases where Phobos marks features private and I can't use them easily. Truly private members are not needed and as Mike explained, they don't exist anyway. I obviously agree with the language preventing me from making mistakes but in the private case, it would merely be reducing usability. I don't want that. D's view on private was strange to me at first but now I see that what I was accustomed to was wrong. I was using a feature without thinking about it. I find this sort of usability of D... very useful... :) Ali
Jun 02 2022
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 3 June 2022 at 06:17:57 UTC, Ali Çehreli wrote:
 Have you ever been bitten by the fact that you forgot to mark a 
 member private and that was a cause of some kind of trouble?
I am not going to say that this is an issue D should focus on (more important challenges exits), but knowing exactly who has access to what in a class is very useful when your program grows and you need to restructure the model. So yes, I would say so, but D should focus on other things… not worth a breaking change.
Jun 03 2022
prev sibling parent reply forkit <forkit gmail.com> writes:
On Friday, 3 June 2022 at 06:17:57 UTC, Ali Çehreli wrote:
 ...
 D's view on private was strange to me at first but now I see 
 that what I was accustomed to was wrong. I was using a feature 
 without thinking about it. I find this sort of usability of 
 D... very useful... :)

 Ali
So do I. I'm not arguing against it. But see my response to Mike Parker, as to my reasoning for why I think programmers need to take a cautious approach to this aspect of the D programming language. 'An option' to make it truly private, even from other code within the module, should the programmer require this, doesn't sound like such an evil idea - as some would like to make it out to be ;-)
Jun 03 2022
parent reply forkit <forkit gmail.com> writes:
On Friday, 3 June 2022 at 08:53:08 UTC, forkit wrote:

class myClass
{
     _really_private string _ID;
}
Jun 03 2022
parent reply bauss <jj_1337 live.dk> writes:
On Friday, 3 June 2022 at 09:02:17 UTC, forkit wrote:
 On Friday, 3 June 2022 at 08:53:08 UTC, forkit wrote:

 class myClass
 {
     _really_private string _ID;
 }
Perhaps something like: ``` class Foo { private class string _id; // Private to the class } ``` ``` class Foo { private module string _id; // Private to the module private int _number; // Same as "private module" since that's the default } ``` Of course an equivalent to structs "private struct" could be added as well.
Jun 03 2022
next sibling parent bauss <jj_1337 live.dk> writes:
On Friday, 3 June 2022 at 10:20:08 UTC, bauss wrote:
 On Friday, 3 June 2022 at 09:02:17 UTC, forkit wrote:
 On Friday, 3 June 2022 at 08:53:08 UTC, forkit wrote:

 class myClass
 {
     _really_private string _ID;
 }
Perhaps something like: ``` class Foo { private class string _id; // Private to the class } ``` ``` class Foo { private module string _id; // Private to the module private int _number; // Same as "private module" since that's the default } ``` Of course an equivalent to structs "private struct" could be added as well.
To add onto this: This also has the advantage of having no breaking-changes, since old code will work just the same, but new code can leverage the control of what is private and to what. There's no reason to change the default behavior of private, BUT having the ability to change the behavior when necessary is nice. Some of D's decisions are far too black and white and forgot that there are nuances to programming.
Jun 03 2022
prev sibling parent reply zjh <fqbqrr 163.com> writes:
On Friday, 3 June 2022 at 10:20:08 UTC, bauss wrote:

 class Foo
 {
     private class string _id; // Private to the class
 }
 class Foo
 {
     private module string _id; // Private to the module
     private int _number; // Same as "private module" since 
 that's the default
 }
 ```
I think it is `worth adding`. Simply adding some code can distinguish between `class` level and `module` level. It is very friendly for those familiar with `C++'s` class level encapsulation.
Jun 03 2022
parent reply Commander Zot <no no.no> writes:
On Friday, 3 June 2022 at 12:06:01 UTC, zjh wrote:
 On Friday, 3 June 2022 at 10:20:08 UTC, bauss wrote:

 class Foo
 {
     private class string _id; // Private to the class
 }
 class Foo
 {
     private module string _id; // Private to the module
     private int _number; // Same as "private module" since 
 that's the default
 }
 ```
I think it is `worth adding`. Simply adding some code can distinguish between `class` level and `module` level. It is very friendly for those familiar with `C++'s` class level encapsulation.
it adds more special cases to metaprogramming for practically no benefit.
Jun 04 2022
parent reply zjh <fqbqrr 163.com> writes:
On Saturday, 4 June 2022 at 13:37:18 UTC, Commander Zot wrote:
 On Friday, 3 June 2022 at 12:06:01 UTC, zjh wrote:
Language is inherently `complex`.Obviously, d did not distinguish between `module level` encapsulation and `class encapsulation`. Finally, you told me that this will added `"special cases"`.
Jun 04 2022
next sibling parent zjh <fqbqrr 163.com> writes:
On Saturday, 4 June 2022 at 13:41:43 UTC, zjh wrote:
 Finally, you told me that this will added `"special cases"`.
If you dare not `face` the problem directly, you will only get `more and more` problems.
Jun 04 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Saturday, 4 June 2022 at 13:41:43 UTC, zjh wrote:
 Language is inherently `complex`.
Well, that is a problem, as the main selling point is to be simpler than C++!!
Jun 04 2022
parent reply zjh <fqbqrr 163.com> writes:
On Saturday, 4 June 2022 at 13:56:07 UTC, Ola Fosheim Grøstad 
wrote:
 On Saturday, 4 June 2022 at 13:41:43 UTC, zjh wrote:
 Language is inherently `complex`.
Well, that is a problem, as the main selling point is to be simpler than C++!!
If you want to meet the needs of `more and more` users, you must be `complex`. Otherwise, you are cheating.
Jun 04 2022
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Saturday, 4 June 2022 at 14:08:24 UTC, zjh wrote:
 If you want to meet the needs of `more and more` users, you 
 must be `complex`.
 Otherwise, you are cheating.
More and more users are using Python… Cheating pays off!
Jun 04 2022
parent reply zjh <fqbqrr 163.com> writes:
On Saturday, 4 June 2022 at 14:21:41 UTC, Ola Fosheim Grøstad 
wrote:

 More and more users are using Python… Cheating pays off!
Cheating first feel good, but then it all fell into `bad luck`.
Jun 04 2022
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Saturday, 4 June 2022 at 14:29:58 UTC, zjh wrote:
 On Saturday, 4 June 2022 at 14:21:41 UTC, Ola Fosheim Grøstad 
 wrote:

 More and more users are using Python… Cheating pays off!
Cheating first feel good, but then it all fell into `bad luck`.
Adding one little feature here and one little feature there is just a distraction that takes the focus off completing and streamlining what is already in the language.
Jun 04 2022
prev sibling parent reply Commander Zot <no no.no> writes:
On Saturday, 4 June 2022 at 14:08:24 UTC, zjh wrote:
 On Saturday, 4 June 2022 at 13:56:07 UTC, Ola Fosheim Grøstad 
 wrote:
 On Saturday, 4 June 2022 at 13:41:43 UTC, zjh wrote:
 Language is inherently `complex`.
Well, that is a problem, as the main selling point is to be simpler than C++!!
If you want to meet the needs of `more and more` users, you must be `complex`. Otherwise, you are cheating.
class private does not provide anything you can not already express in D. if you don't want access to you class, put it in it's own module where it belongs. but really this problem should not arise in the first place, because you should use interfaces anyway. a class should be an implementation detail. if anything we could add the ability to declare multiple modules in one file, but i'm not a fan of that either.
Jun 04 2022
parent reply zjh <fqbqrr 163.com> writes:
On Saturday, 4 June 2022 at 14:23:42 UTC, Commander Zot wrote:

 because you should use interfaces anyway. a class should be an 
 implementation detail.
For me, it would be better ,if I could encapsulate at `class level`.In any case, I don't want the `outside` to affect `my class inside`.
Jun 04 2022
parent reply Dom Disc <dominikus scherkl.de> writes:
On Saturday, 4 June 2022 at 14:40:10 UTC, zjh wrote:
 For me, it would be better ,if I could encapsulate at `class 
 level`.In any case, I don't want the `outside` to affect `my 
 class inside`.
C++ "class level privacy" needs to have "friends", else you cannot create top-level functions that have access to the private members. But these "friends" destroy the whole purpose of "private": Anybody can declare friends, without even touching the file where the class is defined, and thereby access things that shouldn't even be visible to them (implementation details or even security relevant things)! In D you need to change the file where a class is defined if you need to access its privates - this is much easier visible and in a larger team can't be hidden from the person responsible for that class. forkit wrote:
 my argument is not favouring one or the other. It's favouring 
 the
 'option' to have both.
But C++ private is just working by convention - it doesn't enforce anything (because it can be circumvented with friends, same problem as with const which can be circumvented with mutable). By adding this broken thing to D it will be less save and can't guarantee any privacy anymore, just like with C++ now.
Jun 05 2022
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Sunday, 5 June 2022 at 19:41:36 UTC, Dom Disc wrote:
 Anybody can declare friends, without even touching the file 
 where the class is defined, and thereby access things that 
 shouldn't even be visible to them (implementation details or 
 even security relevant things)!
No, I don't think so: «If a program contains more than one definition of a type, then each definition must be equivalent.» https://en.wikipedia.org/wiki/One_Definition_Rule Whether compiler check for it, or not, is another issue.
Jun 05 2022
parent reply Dom Disc <dominikus scherkl.de> writes:
On Sunday, 5 June 2022 at 19:48:03 UTC, Ola Fosheim Grøstad wrote:
 On Sunday, 5 June 2022 at 19:41:36 UTC, Dom Disc wrote:
 Anybody can declare friends, without even touching the file 
 where the class is defined, and thereby access things that 
 shouldn't even be visible to them (implementation details or 
 even security relevant things)!
No, I don't think so: «If a program contains more than one definition of a type, then each definition must be equivalent.»
?!? You don't need to re-declare the class. You can simply overwrite a friend function. Ok, if the class don't have any friends, this doesn't work. But most of the time there are some...
Jun 05 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Sunday, 5 June 2022 at 20:42:59 UTC, Dom Disc wrote:
 You don't need to re-declare the class. You can simply 
 overwrite a friend function.
Not exactly sure by what you mean by overwrite, you mean defining the function twice? Encapsulation does not protect against sabotage, only against mistakes.
Jun 05 2022
next sibling parent Dom Disc <dominikus scherkl.de> writes:
On Sunday, 5 June 2022 at 21:40:18 UTC, Ola Fosheim Grøstad wrote:
 Encapsulation does not protect against sabotage, only against 
 mistakes.
Fair enough.
Jun 05 2022
prev sibling parent forkit <forkit gmail.com> writes:
On Sunday, 5 June 2022 at 21:40:18 UTC, Ola Fosheim Grøstad wrote:
 On Sunday, 5 June 2022 at 20:42:59 UTC, Dom Disc wrote:
 You don't need to re-declare the class. You can simply 
 overwrite a friend function.
Not exactly sure by what you mean by overwrite, you mean defining the function twice? Encapsulation does not protect against sabotage, only against mistakes.
+1 .. although the benefits of encapsulation are much greater than that. Encapsulation, along with the concepts of decompostion and abstraction, are the three most important concepts in programming. None of which are there to protect against sabotage. Because of the limitation of the human capacity for dealing with complexity, we must organise our code into chunks, in this case, a class, so that we can capture common properties 'in one place'. Now we can reason about it locally. Also now, even with our limited human capacity for managing complexity, we can begin to build up a complex system. Horray for the class! It's hard to have an object in D (and instantiation of a class) that has well defined behaviour, when there is no mechanism to protect that behaviour (from mistakes -> from surrounding code in the same module). My example with the unit-test demonstrates that. One class per module does not solve that problem either btw. D's approach *includes* the module as an abstraction by which you can manage complexity. But it seems to me, that it has come at the expense of the class abstaction -> by that I mean, as long as there is no way to enforce the invariants of the abstraction -> from any surrounding code in same module, then mistakes will be made. Even in unit-test code! And whether or not mistake are in fact made, is irrelevant. The fact that mistakes can be made, requires one to audit ALL the surrounding code in the module! So just the option to have a really private property would be nice. It takes nothing away from anyone, and doesn't force anything on anyone. It's purely opt-in, and will no doubt, contribute to better encapsulation, and hence better software. Ideally, you'd choose to default to private in your programming guidelines, and only when this doesn't work for you, should you remove the . This would encourage better encapsulation I believe. Some of those D modules in phobos.. grr...!! On what basis (other than an idealogical objection to 'change'), would someone object to such an 'option'? Just imagine if D had a leaky module abstraction - but you were told to deal with that, by avoiding making mistakes ;-)
Jun 05 2022
prev sibling next sibling parent reply zjh <fqbqrr 163.com> writes:
On Sunday, 5 June 2022 at 19:41:36 UTC, Dom Disc wrote:
 [...]
I usually don't use the `pointer` very much, and haven't used `friend`. I'm not that complicated. I directly expose the `'members'` . If the `'private members'` related to realization .They are of course `private`, avoid unintentional use . Class only needs to expose a few `'functions + members'`, and everything is OK Class is the smallest unit of encapsulation. `D` but do not add it. You do not know which code has changed your `private variables` in the same module . It's so interesting.
 Anybody can declare friends, without even touching the file
I don't know .I haven't use `friend'.
Jun 05 2022
parent reply forkit <forkit gmail.com> writes:
On Monday, 6 June 2022 at 00:07:53 UTC, zjh wrote:
 On Sunday, 5 June 2022 at 19:41:36 UTC, Dom Disc wrote:
 [...]
I usually don't use the `pointer` very much, and haven't used `friend`. I'm not that complicated. I directly expose the `'members'` . If the `'private members'` related to realization .They are of course `private`, avoid unintentional use . Class only needs to expose a few `'functions + members'`, and everything is OK Class is the smallest unit of encapsulation. `D` but do not add it. You do not know which code has changed your `private variables` in the same module . It's so interesting.
 Anybody can declare friends, without even touching the file
I don't know .I haven't use `friend'.
Well, if you use D, then you do ;-) Cause the module is the friend you will always have, no matter what ;-)
Jun 05 2022
parent zjh <fqbqrr 163.com> writes:
On Monday, 6 June 2022 at 00:33:30 UTC, forkit wrote:

 Well, if you use D, then you do ;-)

 Cause the module is the friend you will always have, no matter 
 what ;-)
You're `right`.
Jun 05 2022
prev sibling parent reply forkit <forkit gmail.com> writes:
On Sunday, 5 June 2022 at 19:41:36 UTC, Dom Disc wrote:
 On Saturday, 4 June 2022 at 14:40:10 UTC, zjh wrote:
 For me, it would be better ,if I could encapsulate at `class 
 level`.In any case, I don't want the `outside` to affect `my 
 class inside`.
C++ "class level privacy" needs to have "friends", else you cannot create top-level functions that have access to the private members. But these "friends" destroy the whole purpose of "private": Anybody can declare friends, without even touching the file where the class is defined, and thereby access things that shouldn't even be visible to them (implementation details or even security relevant things)! In D you need to change the file where a class is defined if you need to access its privates - this is much easier visible and in a larger team can't be hidden from the person responsible for that class.
What I like about C++ friend concept, is that you explicately know who is a friend and who isn't. It's declared right there in the class. In a D module, everything could be a friend. Everything! You'll have to look at ALL the code in the module to determine that - as opposed to C++, where you can find this information right there in the class declaration. Imagine if everyone in your street was your friend, and they could come around willy nilly and do as they please, in your nice, encapsulated home. Now, to be fair, it's nice to have a friend around. But all the time!!! Doing whatever the %F#V they want!!!
Jun 05 2022
next sibling parent reply forkit <forkit gmail.com> writes:
On Monday, 6 June 2022 at 01:05:44 UTC, forkit wrote:

I think this statement differentiates the C++ approach, to D's 
approach:

C++ approach: "Use a member when you can, and a friend when you 
have to."
https://isocpp.org/wiki/faq/friends

D approach: What nonsense! Why keep private things private! Just 
make everything a friend.
Jun 05 2022
parent reply forkit <forkit gmail.com> writes:
On Monday, 6 June 2022 at 01:23:41 UTC, forkit wrote:

when your boss isn't really your friend:

// ----

module test;
 safe :

class Employee
{
   private:
     double salary;

   public:
     double getSalary()
     {
         return salary;
     }

     void setSalary(double amount)
     {
         try
         {
             if (amount < 100_000 )
                 throw new Exception("msg");

             salary = amount;
         }
         catch (Exception e)
         {
             import std.stdio;
             writeln("No. Don't be an ass! Try again.");
         }
     }

}

class Boss
{
   private:
     Employee e;
}

// compile with: -main -unittest
unittest
{
     Boss boss = new Boss();
     boss.e = new Employee();

     //boss.e.setSalary(100_000.0); // The objects invariant WILL 
be upheld (at runtime).


                          // If only D had  private - or, if I had 
'remembered' to use the member function

     import std.stdio : writefln;
     import std.math;
     writefln("The employees salary is: %s", 
(isNaN(boss.e.getSalary())) ? (0) : (boss.e.getSalary()));
}

// -----
Jun 05 2022
parent reply Dom Disc <dominikus scherkl.de> writes:
On Monday, 6 June 2022 at 02:35:11 UTC, forkit wrote:
 On Monday, 6 June 2022 at 01:23:41 UTC, forkit wrote:

 when your boss isn't really your friend:

 // ----

 module test;
  safe :

 class Employee
 {
 }

 class Boss
 {
 }
Now that is real nonsense! Why should those two classes ever be within the same file?!? Not everything is a friend - only what is in the same file! And unlike C++ you can have friends *only within the same file* and not also in whatever file belonging to some other developer. Yes, unlike in Java you can have more than one class or other stuff in one file. But you should only put things in one file that really belong together (need access to implementation details). And that is really easy to keep under control. In my opinion much easier than in C++.
Jun 06 2022
parent reply forkit <forkit gmail.com> writes:
On Monday, 6 June 2022 at 11:45:31 UTC, Dom Disc wrote:
 On Monday, 6 June 2022 at 02:35:11 UTC, forkit wrote:
 On Monday, 6 June 2022 at 01:23:41 UTC, forkit wrote:

 when your boss isn't really your friend:

 // ----

 module test;
  safe :

 class Employee
 {
 }

 class Boss
 {
 }
Now that is real nonsense! Why should those two classes ever be within the same file?!?
The two classes were clearly concocted for the example - actually, after a discussion with a friend about problems they were having with their boss - who pretended to be friend to them, until one day .... But that aside, it is often that one object cannot exist, unless the other object already exists. It's not unusual, to want to keep this code together - even, god forbid, in the same module!
 Not everything is a friend - only what is in the same file!
Precisely. That's my whole point. Everything in the same file is your friend. Although, that is not the actual problem, since friends are useful. The actual problem is there is 'no option to unfriend'. There are no encapsulated components in a module. The D language doesn't provide the means to do that. It's all just one big... thing.
Jun 07 2022
parent Commander Zot <no no.no> writes:
On Wednesday, 8 June 2022 at 00:12:28 UTC, forkit wrote:
 On Monday, 6 June 2022 at 11:45:31 UTC, Dom Disc wrote:
 On Monday, 6 June 2022 at 02:35:11 UTC, forkit wrote:
 On Monday, 6 June 2022 at 01:23:41 UTC, forkit wrote:

 when your boss isn't really your friend:

 // ----

 module test;
  safe :

 class Employee
 {
 }

 class Boss
 {
 }
Now that is real nonsense! Why should those two classes ever be within the same file?!?
The two classes were clearly concocted for the example - actually, after a discussion with a friend about problems they were having with their boss - who pretended to be friend to them, until one day .... But that aside, it is often that one object cannot exist, unless the other object already exists. It's not unusual, to want to keep this code together - even, god forbid, in the same module!
 Not everything is a friend - only what is in the same file!
Precisely. That's my whole point. Everything in the same file is your friend. Although, that is not the actual problem, since friends are useful. The actual problem is there is 'no option to unfriend'. There are no encapsulated components in a module. The D language doesn't provide the means to do that. It's all just one big... thing.
interface Foo { int itWorks(); static Foo _new() { static class PrivateFoo : Foo { int _b; override int itWorks() { return _b; } } auto pfoo = new PrivateFoo; pfoo._b = 42; //only accessible in this function scope return pfoo; } } int main() { auto foo = Foo._new; writeln(foo.itWorks); return 0; }
Jun 08 2022
prev sibling parent reply norm <norm.rowtree gmail.com> writes:
On Monday, 6 June 2022 at 01:05:44 UTC, forkit wrote:
 On Sunday, 5 June 2022 at 19:41:36 UTC, Dom Disc wrote:
 On Saturday, 4 June 2022 at 14:40:10 UTC, zjh wrote:
 For me, it would be better ,if I could encapsulate at `class 
 level`.In any case, I don't want the `outside` to affect `my 
 class inside`.
C++ "class level privacy" needs to have "friends", else you cannot create top-level functions that have access to the private members. But these "friends" destroy the whole purpose of "private": Anybody can declare friends, without even touching the file where the class is defined, and thereby access things that shouldn't even be visible to them (implementation details or even security relevant things)! In D you need to change the file where a class is defined if you need to access its privates - this is much easier visible and in a larger team can't be hidden from the person responsible for that class.
What I like about C++ friend concept, is that you explicately know who is a friend and who isn't. It's declared right there in the class. In a D module, everything could be a friend. Everything! You'll have to look at ALL the code in the module to determine that - as opposed to C++, where you can find this information right there in the class declaration. Imagine if everyone in your street was your friend, and they could come around willy nilly and do as they please, in your nice, encapsulated home. Now, to be fair, it's nice to have a friend around. But all the time!!! Doing whatever the %F#V they want!!!
This is such a non-issue, the mindset in D simply needs to be encapsulation boundary is at the module level. All this huff and puff of wasted of energy goes away at that point and your designs will actually be much cleaner than in C++. This is a pure ideological debate and it is actually very useful to have module level encapsulation. It is even more of a non-issue when D has thread-local variables by default.
Jun 05 2022
parent reply forkit <forkit gmail.com> writes:
On Monday, 6 June 2022 at 04:01:27 UTC, norm wrote:
 This is such a non-issue, the mindset in D simply needs to be 
 encapsulation boundary is at the module level. All this huff 
 and puff of wasted of energy goes away at that point and your 
 designs will actually be much cleaner than in C++. This is a 
 pure ideological debate and it is actually very useful to have 
 module level encapsulation.
I agree that it's a non-issue, in that I haven't argued that isn't very useful to have module level encapsulation. Why ya'll always twist my argument to suit your own? My argument is clear. It would be 'nice to have' 'an option' for there to be a genuine private component of a class. Not pseudo 'private', but genuine private. An option to bring back an actual class type. And can I remind everyone, yet again, my argument is NOT that we shouldn't have module level encapsulation! Also, please don't tell me that I need to think like D wants me to think. Cause, no, I don't. And I won't.
Jun 05 2022
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 6 June 2022 at 04:34:23 UTC, forkit wrote:
 An option to bring back an actual class type.
What do you mean here? Btw, one advantage of having module-level private is that D classes have "invariant checks". If you can prove that all the functions in the module uphold the class-invariant, and if the invariant only touches private fields, then you can remove the invariant check. There is nothing wrong with having private in addition, but the main issues is that the complexity of D source code is going in the wrong direction. Having 4 protection levels is perhaps more of a disadvantage than an advantage. The problem is not this "one addition". The problem is the 100 other "one additions". Everybody has their own "just this one" and that is how D is accumulating more and more complexity.
Jun 06 2022
parent reply Basile B. <b2.temp gmx.com> writes:
On Monday, 6 June 2022 at 08:51:44 UTC, Ola Fosheim Grøstad wrote:
 On Monday, 6 June 2022 at 04:34:23 UTC, forkit wrote:
 An option to bring back an actual class type.
What do you mean here? Btw, one advantage of having module-level private is that D classes have "invariant checks". If you can prove that all the functions in the module uphold the class-invariant, and if the invariant only touches private fields, then you can remove the invariant check. There is nothing wrong with having private in addition, but the main issues is that the complexity of D source code is going in the wrong direction. Having 4 protection levels is perhaps more of a disadvantage than an advantage.
reminder: we have [already 5]
 The problem is not this "one addition". The problem is the 100 
 other "one additions". Everybody has their own "just this one" 
 and that is how D is accumulating more and more complexity.
[already 5]: https://dlang.org/spec/attribute.html#visibility_attributes
Jun 06 2022
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 06/06/2022 9:39 PM, Basile B. wrote:
 reminder: we have [already 5]
Lets remove the linker directive, export :D
Jun 06 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 6 June 2022 at 09:39:30 UTC, Basile B. wrote:
 reminder: we have [already 5]
There you go! I tend to stick to public and private, and protected only on occasion. Too many details to remember…
Jun 06 2022
parent reply zjh <fqbqrr 163.com> writes:
On Monday, 6 June 2022 at 09:58:44 UTC, Ola Fosheim Grøstad wrote:

 Too many details to remember…
You don't need remember it at all, because only those who need it use it .Like `C++'s` `friend`, I don't use it at all .I don't care.
Jun 06 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 6 June 2022 at 11:17:39 UTC, zjh wrote:
 You don't need remember it at all, because only those who need 
 it use it .
Doesn't work, you need to read other people's code. Rarely used things should usually not be in the language.
 Like `C++'s` `friend`, I don't use it at all. I don't care.
Oh, but I remember most of C++'s language features! The C++ language itself is not so big. The complexity in C++ is elsewhere (what to do where if you want to avoid such and such problem, how to solve this and that issue, etc).
Jun 06 2022
parent reply zjh <fqbqrr 163.com> writes:
On Monday, 6 June 2022 at 11:26:35 UTC, Ola Fosheim Grøstad wrote:

You need to learn more complicated things about` 'd'`. Add a 
small `'private'`, in fact, you don't need to remember something 
at all.You can get familiar with it after looking at it `several 
times`.
`Small things`, to solve big problems, but you are blocking them 
,it's `so funny`.
Jun 06 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 6 June 2022 at 12:25:51 UTC, zjh wrote:
 `Small things`, to solve big problems, but you are blocking 
 them ,it's `so funny`.
(I am not blocking anything, how could I?) A large number of *insignificant and random additions* won't solve any big problems related to D projects. They will just make it more difficult to get to a good place, both in terms of language comprehension and in terms of compiler quality. Language additions should only come as a consequence of a targeted strategy that takes the *whole language* into consideration. The wishing-well approach does not work well for language design. How many pointless keywords do you want on your screen?
Jun 06 2022
parent reply mee6 <mee6 lookat.me> writes:
On Monday, 6 June 2022 at 12:59:04 UTC, Ola Fosheim Grøstad wrote:
 Language additions should only come as a consequence of a 
 targeted strategy that takes the *whole language* into 
 consideration.

 The wishing-well approach does not work well for language 
 design. How many pointless  keywords do you want on your screen?
live is the latest addition. Just one more optional attribute and it'll fix all of D's problems.
Jun 06 2022
parent reply zjh <fqbqrr 163.com> writes:
On Monday, 6 June 2022 at 15:46:35 UTC, mee6 wrote:

  live is the latest addition. Just one more optional attribute 
 and it'll fix all of D's problems.
As long as `attributes` can solve my problem, I don't care how many `attributes` there are. I `like` `attributes`.
Jun 06 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 6 June 2022 at 23:05:29 UTC, zjh wrote:
 As long as `attributes` can solve my problem, I don't care how 
 many `attributes` there are.
 I `like` `attributes`.
Adding many variations of the same just makes code harder to read and mistakes easier to make. In most languages «private» has the same meaning. In D it has a slightly different meaning. That is ok, but somewhat annoying. If you now add « private», which means the same as «private» in other languages, then experienced programmers will be confused and demand an explanation. In other words they will ask «what the hell went wrong in the design process, this is a mess». A well designed language has a small and expressive core. Adding special cases is not good, especially not if you have generic programming features. These are well established facts that all scholars agree upon. More mostly redundant stuff makes things worse, not better. If there are issues, go back to the drawing board and fix the core language.
Jun 06 2022
parent reply zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 05:05:53 UTC, Ola Fosheim Grøstad 
wrote:


wheather it's annoying, people have solved the problem.
It's funny that you didn't solve the problem.
If you don't need it. You don't have to worry about it at all.
It's so easy,
We solve small problems before solving big ones. It is easy to 
`make mistakes` if you try big ones first.
Jun 07 2022
next sibling parent reply zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 07:17:29 UTC, zjh wrote:

 `private`
In addition, adding `class encapsulation` is to make up for the deficiency . It's not that you said adding `special cases`! Just like there are `men and women`, you have to say that there are only `men`, there is not `women`. `woman` is `special cases`! Then others just can't help you.
Jun 07 2022
parent reply Dom Disc <dominikus scherkl.de> writes:
On Tuesday, 7 June 2022 at 07:23:27 UTC, zjh wrote:
 adding `class encapsulation` is to make up for the deficiency.
There is no deficiency. What we have is already capable of doing what is needed. private would only add a new way to do the same in a sightly different (and worse) way. Just because that different way is more like C++ (and less like Java or other languages) is not enough benefit to compensate for the increase in mental burden. And no, ignoring new features if you don't need them is _not_ working, as often you need to read or even work with code written by others. So you need to understand all features they use and cope with different styles if there is more than one way to do a thing. So it is always better to have only one way to do something, even if that doesn't please everybody. Think of it like coding style guides: you may not like them because you would prefer a different style, but they increase the readability by large, so learn to live with them!
Jun 07 2022
parent reply zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 07:56:30 UTC, Dom Disc wrote:

 Think of it like coding style guides: you may not like them 
 because you would prefer a different style, but they increase 
 the readability by large, so learn to live with them!
This is not `style` at all, because the changes are `very small`! It does not destroy `readability`, but adds a `keyword or attribute` . `Small changes` and great improvements in `class encapsulation` .and are well worth it.
Jun 07 2022
parent zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 08:49:17 UTC, zjh wrote:

 `Small changes` and great improvements in `class encapsulation` 
 .and are well worth it.
The `'really advantage'` of D is to achieve `'small changes'` and complete `'big features'` with the help of `'attributes'`! So, I like `'attributes'`! This Point, but nobody is blowing!
Jun 07 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 7 June 2022 at 07:17:29 UTC, zjh wrote:
 We solve small problems before solving big ones. It is easy to 
 `make mistakes` if you try big ones first.
D should solve its «big» problems and ignore «small problems». The alternative is to start over from scratch. If you want «private» to be class only, then change the semantics. You could just make «protected» mean access by inheritance and module. No need for an endless stream of additions. If it matters, adjust what you've got, don't pile on more pointless details. (In this case it doesn't matter much, so leave it as it is.)
Jun 07 2022
parent reply zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 07:50:27 UTC, Ola Fosheim Grøstad 
wrote:

 D should solve its «big» problems and ignore «small problems».
`Hard core` programmers are responsible for `difficult problems`, and ordinary people are responsible for `simple problems`. This is not an unimportant issue. It will destroy the `encapsulation`. As long as it is `' reasonable '` and can meet the `' needs'` of different people, it is no big deal to add it. `'d '` needs to meet people's `needs` first, and then slowly solve `big or difficult` problems. `Class privacy` is an important and simple problem. If you solve it, you can attract `c++ users` easily. `Encapsulation of classes` is essential for me. if `D` don't provide it, it just makes me `unhappy `. If `c++` programmers think so, why do they use d? Obviously, just adding a piece of code solves the `user's` needs. The `success` of c++ is to constantly meet the `needs` of different people. Look at the latest `rust` and `other languages`. Which is not `complicated`? Even `'go'` has added 'generic'.
Jun 07 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 7 June 2022 at 08:45:49 UTC, zjh wrote:
 `Class privacy` is an important and simple problem.
 If you solve it, you can attract `c++ users` easily.
There are many approaches to encapsulation. Beta, the successor to Simula (the first OOP language) did it on a syntactical level which in some ways is more elegant. There are many takes on encapsulation, most follow Simula, but there is nothing particularly wrong with what D has chosen here. Maybe «package» and «external» should not have been added! Think about generic programming first, how many cases do you need to deal with? 2 is ok, but annoying. 3 is a bit much. 4, 5, 6++ is way too much. And you are wrong about C++ programmers. I am a C++ programmer. This is not what makes them complain. Go through the forum archives and you'll see what they complain about.
 The `success` of c++ is to constantly meet the `needs` of 
 different people.
The success of C++ comes down to it being the first OO-language suitable for desktop applications that made it big, then add performance and being compatible with C.
 Look at the latest `rust` and `other languages`. Which is not 
 `complicated`? Even `'go'` has added 'generic'.
Rust and Go are not complicated. Rust makes memory management complicated by requiring a tree-structure. The language itself isn't complicated. Go is not complicated. Go makes error-handling complicated by not having proper exceptions. The first batch of Rust users complained about it being too complicated and they have put a serious amount of effort into making memory management annotations less cumbersome. Go was released as a rather minimal language and has only made marginal additions. Their take on generics is minimal. TLDR; I strongly disagree.
Jun 07 2022
parent reply zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 09:05:36 UTC, Ola Fosheim Grøstad 
wrote:

 TLDR; I strongly disagree.
`Class encapsulation` is a must for ordinary `c++ people`! I am not an expert. I only know that `class encapsulation` is very cool, at least more comfortable than `module encapsulation`.
Jun 07 2022
next sibling parent zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 09:09:52 UTC, zjh wrote:

 `Class encapsulation` is a must for ordinary `c++ people`!
C++ developers are used to `class encapsulation`. Moreover, this kind of `"minimal" encapsulation`, the "c++" developers, has been deeply rooted in the `hearts` of the people, and no one complains,like it doesn't exist! But in `'d'`, there is no `'class encapsulation' `, which is unthinkable!
Jun 07 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 7 June 2022 at 09:09:52 UTC, zjh wrote:
 On Tuesday, 7 June 2022 at 09:05:36 UTC, Ola Fosheim Grøstad 
 wrote:

 TLDR; I strongly disagree.
`Class encapsulation` is a must for ordinary `c++ people`!
I am «ordinary C++ people». I also learned OOP from the people who created OOP! I should be terribly biased towards Simula's take on «private», but I am not. Why? Encapsulation is just a reminder. Encapsulation has no effect on the final executable. This is why Beta could take encapsulation out of the language semantics and do it on the level of the language grammar through what they called «the fragment system» (or something like that).
 I am not an expert. I only know that `class encapsulation` is 
 very cool, at least more comfortable than `module 
 encapsulation`.
Pick up a book on language design, it is fun to read about, and you seem interested! Then we can talk more. (Without basic knowledge about language design principles it is easy to reach conclusion that has proven to be not so good).
Jun 07 2022
parent reply zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 09:17:17 UTC, Ola Fosheim Grøstad 
wrote:
 Pick up a book on language design, it is fun to read about, and 
 you seem interested! Then we can talk more. (Without basic 
 knowledge about language design principles it is easy to reach 
 conclusion that has proven to be not so good).
What I care about is that the code will not `inadvertently` destroy `my class code` . This is the meaning of `encapsulation` . I don't care about other `designs`.
Jun 07 2022
parent reply zjh <fqbqrr 163.com> writes:
On Tuesday, 7 June 2022 at 09:22:13 UTC, zjh wrote:

 What I care about is that the code will not `inadvertently` 
 destroy `my class code` .
 This is the meaning of `encapsulation` .
 I don't care about other `designs`.
For me, `'minimum encapsulation'` is a matter of `principle` and cannot be changed! But `'d'` does not encourage `'minimum encapsulation'`! Then you talk with me about `designing language`?
Jun 07 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 7 June 2022 at 09:31:20 UTC, zjh wrote:
 For me, `'minimum encapsulation'` is a matter of `principle` 
 and cannot be changed!
I see. If you have lots of principles then D will be a challenge for you. It is not a very principled language.
 But `'d'` does not encourage `'minimum encapsulation'`!
 Then you talk with me about `designing language`?
Not exactly sure what you mean. You can do fine without any formal encapsulation using conventions. A common convention in languages without encapsulation is to prefix private variables with underscore, then let the IDE provide warnings when "encapsulation" is broken. This works perfectly well in practice. I've never had a problem with it. The reason is that encapsulation is «just a reminder» and that works well unless you insist on being stupid. Stronger encapsulation is only essential if you redesign larger programs or have teams with disloyal programmers who are taking shortcuts. Encapsulation is not absolute in D, and can never be. You can just cast the pointer to a different type and you'1l get full access to everything from anywhere.
Jun 07 2022
next sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Tuesday, 7 June 2022 at 10:13:35 UTC, Ola Fosheim Grøstad 
wrote:
 Encapsulation is not absolute in D, and can never be. You can 
 just cast the pointer to a different type and you'1l get full 
 access to everything from anywhere.
Also interfaces break visibility with joy. If an interface implementer implements one of the func as private, you can still use it, whatever is the call site.
Jun 07 2022
parent Nick Treleaven <nick geany.org> writes:
On Tuesday, 7 June 2022 at 10:40:41 UTC, Basile B. wrote:
 Also interfaces break visibility with joy. If an interface 
 implementer implements one of the func as private, you can 
 still use it, whatever is the call site.
Example? This gives an error: ```d interface I { void f(); } class C : I // error { private void f(){} } ``` privifaceimp.d(4): Error: class `privifaceimp.C` interface function `void f()` is not implemented
Jun 07 2022
prev sibling parent reply forkit <forkit gmail.com> writes:
On Tuesday, 7 June 2022 at 10:13:35 UTC, Ola Fosheim Grøstad 
wrote:
 This works perfectly well in practice. I've never had a problem 
 with it. The reason is that encapsulation is «just a reminder» 
 and that works well unless you insist on being stupid. Stronger 
 encapsulation is only essential if you redesign larger programs 
 or have teams with disloyal programmers who are taking 
 shortcuts.
I disagree with your assertions here. I don't think you've fully grasped the benefits of encapsulation in terms of decomoposition. In any case, you simply cannot encapsulate the semantics of an object (within a class definition) in D, since code surrounding it can get at any part of its specification. But wait. There's more. D 'insists' on not giving you the means to protect that encapsulation. D just does not have the language construct to do that - intentionaly, by design even! Putting the class in its own module does not change this fact - i.e. you still need to ensure there is no other code surrounding it (including unit test), for it to have a kind of pseudo encapsulation. The simple fact is, that a class in D is a weak type, since violations of its contract from other code in the module, cannot be detected during compilation. Instead, it deliberately, intentionally, proudly, leaves this important aspect in software development to the programmer(s).
Jun 07 2022
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 7 June 2022 at 12:47:36 UTC, forkit wrote:
 I disagree with your assertions here. I don't think you've 
 fully grasped the benefits of encapsulation in terms of 
 decomoposition.
Hi, the benfits of encapsulation is obvious, but you can encapsulate without having language support. If you want class-private, just choose the convention that "_fieldname" means class-private. Every time you see "obj._fieldname" you will realize that this is not what you want to do. If that is not enough, use static analysis. The reality is, encapsulation does not have to be in the language at all in order for you to have encapsulation. It can be a mental thing/code review thing, it can be a grammar thing, it can be a linter issue. Python does not provide in-language encapsulation at all. Yet I encapsulate my classes in Python all the time. And I have external tools to check for it if I want. Beta did not provide in-language encapsulation at all, but the fragment system for source code composistion did. This aspect of D does not limit you as a programmer. Memory management issues do, however. How about focusing on stuff that truly matters and that is likely to change?
 D 'insists' on not giving you the means to protect that 
 encapsulation. D just does not have the language construct to 
 do that - intentionaly, by design even!
There are lots of things D insists on, and this is the least problematic one… How about focusing on things that you cannot fix yourself with an external tool? If this was to change then the only sensible thing would be to adopt what is common in other languages, but allow "protected" access to module members. This is unlikely to happen, and the last thing D needs is more noise in the syntax. So the least problematic choice is to keep it as is.
 The simple fact is, that a class in D is a weak type, since 
 violations of its contract from other code in the module, 
 cannot be detected during compilation.
All C derivatives have weak type systems across the board.
Jun 07 2022
parent reply Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Tuesday, 7 June 2022 at 14:04:27 UTC, Ola Fosheim Grøstad 
wrote:
 Hi, the benfits of encapsulation is obvious, but you can 
 encapsulate without having language support. If you want 
 class-private, just choose the convention that "_fieldname" 
 means class-private. Every time you see "obj._fieldname" you 
 will realize that this is not what you want to do. If that is 
 not enough, use static analysis.

 The reality is, encapsulation does not have to be in the 
 language at all in order for you to have encapsulation. It can 
 be a mental thing/code review thing, it can be a grammar thing, 
 it can be a linter issue.

 Python does not provide in-language encapsulation at all. Yet I 
 encapsulate my classes in Python all the time. And I have 
 external tools to check for it if I want.
What you are speaking here about is encapsulation by convention (naming rules for the members). This is good approach especially when everyone follows it. Unfortunately people don't. They tend to code their own way. As a result, for the languages that don't provide encapsulation (like Python), people started adding corresponding checks to static analyzers/linters to force the encapsulation. So the convention became more complex: in addition to naming rules, now you should also run static analyzer/linter. This means that the code that violates encapsulation is valid but breaks some convention rules. For the languages that have encapsulation forced by compiler, you have a guarantee that it's not broken. In this case the code that violates encapsulation is not valid and must be fixed. Just to summarize, both approaches (no encapsulation and forced encapsulation) are equally good. We all have our habits in coding and it doesn't mean that everyone should do the things in the only one way. As for me, I'd like to see class/struct level encapsulation in D. Let me share my D experience to clarify the benefit. I started writing a (single module) library that can be used by others. At that point I wanted to separate public API from internal code so I used `private` for everything internal and `public` for public API. At some point during active development, the module became so large so I decided to convert it to a package and split into logical components (modules). So I can easily enforce clear interaction between logical components by `package` and `private`. Now I want to enforce clear interaction between physical components (structs and classes) within a logical component. Ideally, I want to be able to mark specific members as "real" private so nothing else except struct/class itself can access them. This is what I see as a benefit of this feature for me. Unfortunately, D gives me two options: put every struct/class into its own module (sub module of a logical component), or leave it as is. Since I am not a fan of having dozens of small files (one per struct/class), I decided to leave it as is. Regarding implementation. I don't like ` private` as people will be confused a lot with ` private`<->`private`. IMHO the ideal solution would be having `module` to mark module privates and `private` for real privates but this is not backward compatible. So the better solution might be extending syntax for `private` having something like `private(symbol[, symbol ...])` where `symbol` is a symbol that has access to the member For example: `this` means current struct/class; `this.foo` or `<typeof(this)>.foo` means foo member in the current struct/class.
Jun 07 2022
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 7 June 2022 at 18:07:34 UTC, Andrey Zherikov wrote:
 What you are speaking here about is encapsulation by convention 
 (naming rules for the members). This is good approach 
 especially when everyone follows it. Unfortunately people 
 don't. They tend to code their own way. As a result, for the 
 languages that don't provide encapsulation (like Python), 
 people started adding corresponding checks to static 
 analyzers/linters to force the encapsulation.
The general convention is to use underscore as a prefix for internals, that is pretty universal across languages and has been so for many decades. I believe even PyCharm will recognize this. But it is easier to build a linter for D than for Python, so if you want it, then you can build it. You can also use user defined attributes in D if you don't like underscores? Having a linter-eco system is something all languages will benefit from, so having something worthwhile to trigger people to build their own linters is not necessarily a disadvantage. If people want " private" badly then it is great if they build a linter that they share with others. If enough people use it then that can trigger inclusion in the language. This is how languages ought to evolve: 1a. First try a library solution (like OP), if you cannot do it… 1b. …try to build a generator of some sort, if you cannot do it… 1c. …try to build an analyzer of some sort etc… 2. Collect feedback from users of your solution. 3. Consider writing a DIP if the solution is working, but would benefit greatly from compiler support. 4. Find a compiler dev willing to cowrite the DIP. Then use that as a proof of concept for the DIP. If enough people use your solution when the DIP is evaluated then it obviously will be a much stronger candidate for inclusion!
 compatible. So the better solution might be extending syntax 
 for `private` having something like `private(symbol[, symbol 
 ...])` where `symbol` is a symbol that has access to the member
How would users know that this `private` means something different? It is very difficult to get good usability as long as most users coming from other languages have a rather firm interpretation of what `private` means. With the current setup `private` means «the strongest encapsulation» which at least is somewhat consistent with other languages. You could introduce `internal` as a keyword, but that doesn't overcome the confusion of D'internal = C++'private and D'private ≈ C++private&friend. So no matter what you do, usability will suffer. Thus a breaking change is the only good alternative from a usability POV. And that won't happen in D2.
Jun 07 2022
parent reply forkit <forkit gmail.com> writes:
On Tuesday, 7 June 2022 at 19:42:00 UTC, Ola Fosheim Grøstad 
wrote:
 It is very difficult to get good usability as long as most 
 users coming from other languages have a rather firm 
 interpretation of what `private` means.
No, they (we) come with a firm interpretation of what encapsulation means, because they (we) can actually make things private, and that contract can be enforced at compile time - they (we) don't have to 'remember' not to make mistakes. C++ friend is not something you should be using all the time. It breaks encapsulation. It does not enhance it, in any way, whatsoever. But there are situations where it makes things a lot easier, that's for sure. But it comes at the expense of encapsulation (just as inheritance does). But at least I can choose to inherit, or not. In D, encapsulation is non-existent (from other code within a module). There is no option to encapsulate it either. You're forced to do silly work arounds to just get a pseudo encapsulation. But more importantly, the language they're 'most likely' coming from, if they do object-based, or object-oriented programming, the options available to the progrommer to obtain, to obtain greater encapsulation, to various degrees - but D sought to weaken it, intentionally, by making *everything* your friend. You got no choice in D. D's approach (without an option like private), encourages less encapsulation, by design, because you 'by default' consider everything your friend. There is no need to think about encapsulating components within a module. Some argue this is the whole point. But just go look at some of the modules in phobos ;-) Faced with the choice of using an object-based, or object-oriented approach to the design of a solution, without a private option, D would NOT ever be my choice of language. Other langauges are already better suited for such a design.
Jun 07 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 7 June 2022 at 23:50:55 UTC, forkit wrote:
 On Tuesday, 7 June 2022 at 19:42:00 UTC, Ola Fosheim Grøstad 
 wrote:
 It is very difficult to get good usability as long as most 
 users coming from other languages have a rather firm 
 interpretation of what `private` means.
No, they (we) come with a firm interpretation of what encapsulation means, because they (we) can actually make things private,
That is a weird take. The word can mean private to the file or module, whatever the language defines as the basic unit. Nothing wrong with that, just unusual in language design to use that word inside a class with that meaning.
 C++ friend is not something you should be using all the time. 
 It breaks encapsulation. It does not enhance it,
Actually, it often does in my code. I use it to prevent creation of the class outside the factory.
Jun 07 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 03:52:05 UTC, Ola Fosheim Grøstad 
wrote:
 That is a weird take. The word can mean private to the file or 
 module, whatever the language defines as the basic unit. 
 Nothing wrong with that, just unusual in language design to use 
 that word inside a class with that meaning.
What the language does, is what the language does. I accept that different languages take different decisions around these ideas. But an ability to put up a barrier around some aspect of a class, using 'private' for example, is clearly a benefit. Where is the downside? I don't get it. If you can put up a barrier, you should also be able to take it down of course (hence 'friend'). language want to intentionally, take that away, and even go so far as bragging about it? Even worse, refuse to even consider an option to put if back? I just don't get it. It makes no sense to me, whatsoever. It's truly beyond what I'd expect for a language that wants to compete I like D's module system cause its convenient and easy to use, and it lets you group logically related abstractions together, in one place. Yey! I really like this. I can even get used to everything being a friend. It doesn't take much cognitive effort to do that ;-) But not even having the option to put up a barrier around my abstraction to ensure some parts are hidden from surrounding code in the module, is too much. A module containing a large number of related, but potentially leaky abstractions, doesn't sound that great to me ;-) As you mentioned in a previous post - no I have to go build a static analyser, cause the compiler is completely useless here. D has really taken something away. Something I've always had. Something I need, and something I rely upon. Something I want.
 C++ friend is not something you should be using all the time. 
 It breaks encapsulation. It does not enhance it,
Actually, it often does in my code. I use it to prevent creation of the class outside the factory.
Nonsense. When you break the barrier, you've broken the encapsulation. Full stop. No if and buts about it ;-) I accept that by breaking the barrier, you might have made your job easier. That's fine also. I'd like to make my job easier too, by being able to put that barrier back up.
Jun 07 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 05:42:10 UTC, forkit wrote:
 But an ability to put up a barrier around some aspect of a 
 class, using 'private' for example, is clearly a benefit. Where 
 is the downside?
There would be no downside if D was willing to take a breaking change, but that is unlikely.
 A module containing a large number of related, but potentially 
 leaky abstractions, doesn't sound that great to me ;-)
Then write a linter that does what you want. If nobody cared enough about this to write and use a linter then that suggests that not enough people care about it enough to warrant a language change. Ooor just prefix internals with underscore and be disciplined within the module. Not too hard actually.
 Something I need, and something I rely upon.
Just write the linter, if it gains traction then that is proof that a language change should be considered.
 Actually, it often does in my code. I use it to prevent 
 creation of the class outside the factory.
Nonsense. When you break the barrier, you've broken the encapsulation. Full stop. No if and buts about it ;-)
This is not correct. Private constructor+one friend gives tighter control than public constructor and no friend. If you use one factory for many classes then that gives MUCH tighter control.
 I accept that by breaking the barrier, you might have made your 
 job easier. That's fine also.
Not easier. There is no other way to tighten control. Hence better encapsulation.
Jun 07 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 06:14:58 UTC, Ola Fosheim Grøstad 
wrote:
 There would be no downside if D was willing to take a breaking 
 change, but that is unlikely.
Huh? private(this) ..(for example) is not a 'breaking' change. It's completly opt-in. It provides a choice; Including a choice to just keep doing what you've always been doing. The only argument against it, that would be worthwhile considering, is the cognitive effort in adapting to such a change. private int myInt; private(this) int myInt; Not much cognitive effort required here ;-)
 A module containing a large number of related, but potentially 
 leaky abstractions, doesn't sound that great to me ;-)
Then write a linter that does what you want.
That's my point. It's sad that you even have consider the need to do this. compilers do it for me. But not the D compiler.
 If nobody cared enough about this to write and use a linter 
 then that suggests that not enough people care about it enough 
 to warrant a language change.
That's cause, perhaps, to those whom it matters, they end up deciding not to use D. What is their alternative course of action? Spend a year tring to get a DIP through that nobody in the D admin (Walter specifically) even wants.
 Just write the linter, if it gains traction then that is proof 
 that a language change should be considered.
already use and rely upon this feature. Imagine if those lanaguages took it away. "Sorry folks. We decided to take that feature that you've relied upon for so long, and dump it. Why don't you go write a linter instead." I'm sure that would go over really well ;-)
Jun 07 2022
next sibling parent reply zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 06:45:24 UTC, forkit wrote:

You need to submit `bugzilla`, or you need a `dip`.
Or convince the stubborn Walter.
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 07:03:10 UTC, zjh wrote:
 On Wednesday, 8 June 2022 at 06:45:24 UTC, forkit wrote:

 You need to submit `bugzilla`, or you need a `dip`.
 Or convince the stubborn Walter.
Life is too short ;-) Walter almost certainly gets the last say in this particular matter anyway - and I'm certainly not ignorant of this fact ;-) compiler, all already does this, for me. So the case for using D for anything other than simple console apps, at least in my case, is diminished. I don't want to be told I have to do the one-class-per-file thing, and I don't want to have to go off and write a linter/static-analyser. I just want the compiler to ensure my code is doing what I expected it to be doing, and not tell me, 'bugger off, go do it yourself'.
Jun 08 2022
next sibling parent zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 07:30:43 UTC, forkit wrote:

 'bugger off, go do it yourself'.
The source code is all there. Even, you can `fork` it and make your `own compiler`!
Jun 08 2022
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 07:30:43 UTC, forkit wrote:
 I don't want to be told I have to do the one-class-per-file 
 thing, and I don't want to have to go off and write a 
 linter/static-analyser.
Writing a linter is no more work than making the compiler do it. You've got the DMD source. So what you basically say is that you don't want to write the linter, you want somebody else to do it for you. In other words you don't nobody cares enough about this issue to put in the work. Which isn't particularly surprising since this is one of the minor issues in the language.
Jun 08 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 06:45:24 UTC, forkit wrote:
 On Wednesday, 8 June 2022 at 06:14:58 UTC, Ola Fosheim Grøstad 
 wrote:
 There would be no downside if D was willing to take a breaking 
 change, but that is unlikely.
Huh? private(this) ..(for example) is not a 'breaking' change. It's completly opt-in.
D should stop adding more ugly complexity. it is dying from 1000 well-meaning cuts
 That's cause, perhaps, to those whom it matters, they end up 
 deciding not to use D.
If this one thing is the reason they leave then they would have left anyway!!

 already use and rely upon this feature. Imagine if those 
 lanaguages took it away.
Imagine if you took features away from Haskell, clearly D must have everything Haskell has! Not to mention Rust or Php!! Proof failed, but your line of reasoning does explain why D is bleeding from 1000 well-meaning cuts...
Jun 08 2022
next sibling parent reply zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 07:04:48 UTC, Ola Fosheim Grøstad 
wrote:

I don't care about attributes. I can add them if I want .
You add so much yourself!
Attribute can be deduced!!!
A simple problem , you have made it so complicated.
Jun 08 2022
parent reply zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 07:08:54 UTC, zjh wrote:

 A simple problem , you have made it so complicated.
Isn't it `out of the box`? Why `linter`?
Jun 08 2022
parent zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 07:15:18 UTC, zjh wrote:
 On Wednesday, 8 June 2022 at 07:08:54 UTC, zjh wrote:

 A simple problem , you have made it so complicated.
Isn't it `out of the box`? Why `linter`?
Module without `class` as `encapsulation`, is there only `'d'` in the world? Yes, we are the first!
Jun 08 2022
prev sibling next sibling parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 07:04:48 UTC, Ola Fosheim Grøstad 
wrote:
 Imagine if you took features away from Haskell, clearly D must 
 have everything Haskell has!  Not to mention Rust or Php!!

 Proof failed, but your line of reasoning does explain why D  is 
  bleeding  from  1000  well-meaning  cuts...
Sorry, but what percentage of programmers in the world programmer in Haskell? Is that even a language? ;-) i.e. The vast majority of the worlds programmers have compile time enforcement of the hidden part of their abstraction. If it provides little or no benefit, why is it there? if 'private(this)' is too much for the D community to handle, then ya'll got bigger problems for sure ;-)
Jun 08 2022
parent reply Max Samukha <maxsamukha gmail.com> writes:
On Wednesday, 8 June 2022 at 07:14:32 UTC, forkit wrote:

 Is that even a language? ;-)
Haskell is The Language!
Jun 08 2022
parent forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 07:54:11 UTC, Max Samukha wrote:
 On Wednesday, 8 June 2022 at 07:14:32 UTC, forkit wrote:

 Is that even a language? ;-)
Haskell is The Language!
Well if Haskell can do it, why can't D? "..and we can make fields private if we want. " https://mmhaskell.com/blog/2019/1/7/why-haskell-i-simple-data-types
Jun 08 2022
prev sibling parent reply Dom Disc <dominikus scherkl.de> writes:
On Wednesday, 8 June 2022 at 06:45:24 UTC, forkit wrote:

 already use and rely upon this feature. Imagine if those 
 languages took it away.
Ok, you don't get why I (and D) like it to not conflate things that don't need access to the innards of a class within the same file. I on the other side don't get why you think forbidding access from outside of one file is _not_ encapsulation. It is. And it is easy to control: you put all friends in the same file, and nothing else. You don't have to search where all the friends may be implemented. And if you want something to have no access to the privates, just move it to some other file. Don't tell me this is error-prone or hard to review. It's much easier than to look for all friends in the whole project. I personally *hate* it if I should review a file and then need to look into dozends of other files to do this. And C++ tend to always require this. One of my main reasons to drop C++. Java doesn't even allow friends or subclasses to reside within the same file, and nobody complains about that or claims that this is not encapsulation.
Jun 08 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 08:11:41 UTC, Dom Disc wrote:
 look for all friends in the whole project. I personally *hate* 
 it if I should review a file and then need to look into dozends 
 of other files to do this. And C++ tend to always require this. 
 One of my main reasons to drop C++.
I think many such issues actually are tooling issues and architecture issues just as much as language issues. It is very difficult to talk of C++ being this or that since the language itself doesn't impose much structure. You can have a good or bad structure, and it really comes down to modelling, design patterns, software architecture choices and discipline. Other languages impose more firm structure and that can be good, or bad, depending on what you try to achieve, but you can also use tooling to establish a structure so… Is the language dominating the strucuture? Or is the structure a result of the culture of the people using it? Most of the time it is the latter, it is the culture and the people.
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 08:36:10 UTC, Ola Fosheim Grøstad 
wrote:
 Is the language dominating the strucuture?

 Or is the structure a result of the culture of the people using 
 it?

 Most of the time it is the latter, it is the culture and the 
 people.
In D, it's certainly the language that is dominating the structure here. 4 facts: (1) A class is THE 'central' notion to OO programming. (2) A class implements a type. (3) The OO features in D, all come from the class. (4) In D, classes are (also) programmer defined types. A module should not have ownership over the specification of a type. That ownership should belong to the person writing that specification. It's the language that is enforcing a different structure (in terms of OO design) here. Fine. D has decided that module will make the decision, by making everthing within a module a friend of any type declared within that module. If this was a design decision because of the problems of 'friend' in C++, fine. That makes sense. I get it. But does it really make sense that you cannot unfriend? This should be a decision the programmer at least has the 'option' of making. In my 'perfect world' view of D, the module should only have ownership of 'the aggregation' of the related abstractions that are contained within it, thus providing a nice barrier to the outside world for that 'aggregation'. When the module owns the specifications of all the abstractions contained within it, there are consequences. How can type conformance be enforced within a module? It can't. Imagine if I could, accidently, willy nilly, put a "wtf!" into an int, and not even know about it, till it was too late. Walter has his firm view. I have mine.
Jun 08 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 09:34:09 UTC, forkit wrote:
 Walter has his firm view. I have mine.
Sure, your viewpoint would make sense for D3, but then there would be many such adjustments to make. To make all those adjustments in D2 with no breaking change would lead to a mess.
Jun 08 2022
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 8 June 2022 at 09:38:24 UTC, Ola Fosheim Grøstad 
wrote:
 On Wednesday, 8 June 2022 at 09:34:09 UTC, forkit wrote:
 Walter has his firm view. I have mine.
Sure, your viewpoint would make sense for D3, but then there would be many such adjustments to make. To make all those adjustments in D2 with no breaking change would lead to a mess.
Not in this case. I already proposed something that can work without providing attribute soup. Just extend the private access modifier to allow an optional specifier such as class/struct. https://forum.dlang.org/post/wmamhwkfdqgzaqndgaus forum.dlang.org Ex. ``` class Foo { private int a; // private to module private class int b; // private to class } ```
Jun 08 2022
next sibling parent bauss <jj_1337 live.dk> writes:
On Wednesday, 8 June 2022 at 09:55:00 UTC, bauss wrote:
 On Wednesday, 8 June 2022 at 09:38:24 UTC, Ola Fosheim Grøstad 
 wrote:
 On Wednesday, 8 June 2022 at 09:34:09 UTC, forkit wrote:
 Walter has his firm view. I have mine.
Sure, your viewpoint would make sense for D3, but then there would be many such adjustments to make. To make all those adjustments in D2 with no breaking change would lead to a mess.
Not in this case. I already proposed something that can work without providing attribute soup. Just extend the private access modifier to allow an optional specifier such as class/struct. https://forum.dlang.org/post/wmamhwkfdqgzaqndgaus forum.dlang.org Ex. ``` class Foo { private int a; // private to module private class int b; // private to class } ```
Could also be like this instead: ``` class Foo { private int a; // private to module private this int b; // private to class } ``` Thinking about it using this instead of class/struct is probably better, since it doesn't make sense to restrict to anything else other than itself.
Jun 08 2022
prev sibling next sibling parent zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 09:55:00 UTC, bauss wrote:

 ```d
 class Foo
 {
   private int a; // private to module
   private class int b; // private to class
 }
 ```
Right,No damage at all!
Jun 08 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 09:55:00 UTC, bauss wrote:
 Just extend the private access modifier to allow an optional 
 specifier such as class/struct.
I guess this is where ideas about aesthetics, consistency and usability differ. My view is that all of the proposed syntaxes are bad and would be confusing to people coming to the language. All proposal signal that something went wrong and somebody patched it up with band-aid and duct-tape. And you still get one more case to deal with if you want to reason about this in meta programming.
Jun 08 2022
parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 8 June 2022 at 10:00:37 UTC, Ola Fosheim Grøstad 
wrote:
 My view is that all of the proposed syntaxes are bad and would 
 be confusing to people coming to the language.
But so is the current behavior to people that come to the language. I see people asking every other week about why something isn't "private". I think a lot of other people can testify to that too. The solutions where at least allow one to opt-out of something, it's completely optional and it won't confuse anyone who don't use it. In fact it might make it more understandable since you will realize that what you thought was private wasn't really private and that if you want it private to something then you specify "this". It's much better than the current system where you have to move your classes to a new module, because then you lose __all__ friend capabilities. In some cases you might want both and D does not give you that. You have to pick either friends only or privates only.
Jun 08 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 10:20:37 UTC, bauss wrote:
 On Wednesday, 8 June 2022 at 10:00:37 UTC, Ola Fosheim Grøstad 
 wrote:
 My view is that all of the proposed syntaxes are bad and would 
 be confusing to people coming to the language.
But so is the current behavior to people that come to the language. I see people asking every other week about why something isn't "private".
They would also ask what "private class" means. If you are gonna do it, do at least propose a proper keyword for it: local, hidden, internal… Anything simple is better than keyword, private(this), private class etc. Such syntax screams "amateur project" and I wouldn't even consider downloading a language like that. When I first tried D it was because the syntax looked clean (way before the madness caught on).
Jun 08 2022
next sibling parent forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 10:30:59 UTC, Ola Fosheim Grøstad 
wrote:
 They would also ask what "private class" means.
That's easy to solve ;-) It's simple. People will know if its documented (I mean how else do they know, that private is not really private - cause it says so in the documentation - or they discover it by mistake (more likely). A really minor change to the existing documentation, as such, and it's done: https://dlang.org/spec/attribute.html#visibility_attributes 1. Visibility is an attribute that is one of private, private (this), package, protected, public, or export. They may be referred to as protection attributes in documents predating DIP22. 2. Symbols with private visibility can only be accessed from within the same module. Symbols with private (this) visibility can only be accessed from within the abstraction in which it is defined, and can be applied to a class or struct only.
Jun 08 2022
prev sibling next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 10:30:59 UTC, Ola Fosheim Grøstad 
wrote:
 They would also ask what "private class" means. If you are 
 gonna do it, do at least propose a proper keyword for it: 
 local, hidden, internal…
Btw, the original OOP syntax from Simula is **HIDDEN** and **PROTECTED**. So there is some precedent for this.
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 11:02:45 UTC, Ola Fosheim Grøstad 
wrote:
 On Wednesday, 8 June 2022 at 10:30:59 UTC, Ola Fosheim Grøstad 
 wrote:
 They would also ask what "private class" means. If you are 
 gonna do it, do at least propose a proper keyword for it: 
 local, hidden, internal…
Btw, the original OOP syntax from Simula is **HIDDEN** and **PROTECTED**. So there is some precedent for this.
I wouldn't object to 'hidden int x'. This would solve the problem of 'private (this)' and 'private this()' being too close syntactically.
Jun 08 2022
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 11:07:39 UTC, forkit wrote:
 I wouldn't object to 'hidden int x'.
It is at least easy to understand. (Simula had "hidden", "protected" and "hidden protected" (private), but that doesn't matter ;-)
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 11:18:42 UTC, Ola Fosheim Grøstad 
wrote:
 On Wednesday, 8 June 2022 at 11:07:39 UTC, forkit wrote:
 I wouldn't object to 'hidden int x'.
It is at least easy to understand. (Simula had "hidden", "protected" and "hidden protected" (private), but that doesn't matter ;-)
Interesting that Scala has 'private[this]' https://stackoverflow.com/questions/9698677/privatethis-vs-private Still, I think I'd prefer 'hidden' actually. It's pretty clear what you're stating here with that word. And, you can't confuse it with a contructor like 'this()'. But it would require the addition of a new keyword, which takes the idea to a whole new level :-( The addition of new keyword is really something I'd want to avoid, if at all possible. perhaps 'private class' and 'private struct' makes more sense after all.
Jun 08 2022
next sibling parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 11:25:46 UTC, forkit wrote:
 Interesting that Scala has 'private[this]'

 https://stackoverflow.com/questions/9698677/privatethis-vs-private
oh. https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 11:32:48 UTC, forkit wrote:

Another option is:

class myClass
{
     private[myClass] int x; // private to this abstraction.
     private int y; // private to the module
}

same for a struct:

struct myStruct
{
     private[myStruct] int x;
     private int y;
}


I kinda like this.
Jun 08 2022
parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 8 June 2022 at 11:38:15 UTC, forkit wrote:
 On Wednesday, 8 June 2022 at 11:32:48 UTC, forkit wrote:

 Another option is:

 class myClass
 {
     private[myClass] int x; // private to this abstraction.
     private int y; // private to the module
 }

 same for a struct:

 struct myStruct
 {
     private[myStruct] int x;
     private int y;
 }


 I kinda like this.
I don't like it, it seems to add much more clutter, like imagine some long generic type name.
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 11:49:26 UTC, bauss wrote:
 I don't like it, it seems to add much more clutter, like 
 imagine some long generic type name.
Yes, I agree. Too much typing ;-) .. and what happens if you mistype?? Forget that idea ;-) btw. interesting (but old) discussion in the scala commmunity around this idea: I think they ended up dropping private[this] in scala 3 anyway, despite this proposal to keep it. but the conversation is interesting. https://contributors.scala-lang.org/t/proposal-to-retain-private-this-in-scala-3/3829
Jun 08 2022
parent reply Max Samukha <maxsamukha gmail.com> writes:
On Wednesday, 8 June 2022 at 11:52:32 UTC, forkit wrote:

 Yes, I agree. Too much typing ;-)
To me, it's not as much about typing as about unnecessarily using a concrete name for an abstract concept. For example, 'this' as the name for constructors/destructors is an improvement over C++. At the same time, 'eponymous' members of templates is a regression.
Jun 08 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 12:49:27 UTC, Max Samukha wrote:
 For example, 'this' as the name for constructors/destructors is 
 an improvement over C++.
I dislike the reuse of terminology for different concepts, so I prefer «constructor» like in TypeScript, although I guess the C++ solution makes sense because you can conceptualize it as a call to function with the same name as the class. Anyway it is possible to create a parser/grammar without reserving so many keywords (or reusing them). I don't think there is a good reason for having " safe" and " pure", the grammar ought to be unambiguous with "safe" and "pure" without making them keywords.
Jun 08 2022
next sibling parent Max Samukha <maxsamukha gmail.com> writes:
On Wednesday, 8 June 2022 at 13:14:43 UTC, Ola Fosheim Grøstad 
wrote:
 On Wednesday, 8 June 2022 at 12:49:27 UTC, Max Samukha wrote:
 For example, 'this' as the name for constructors/destructors 
 is an improvement over C++.
I dislike the reuse of terminology for different concepts, so I prefer «constructor» like in TypeScript,
It is still 'constructor' and not a different name every time.
 although I guess the C++ solution makes sense because you can 
 conceptualize it as a call to function with the same name as 
 the class.
Yes, but when the name is used in the context of that class, it is redundant.
 Anyway it is possible to create a parser/grammar without 
 reserving so many keywords (or reusing them). I don't think 
 there is a good reason for having " safe" and " pure", the 
 grammar ought to be unambiguous with "safe" and "pure" without 
 making them keywords.
Jun 08 2022
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 13:14:43 UTC, Ola Fosheim Grøstad 
wrote:
 there is a good reason for having " safe" and " pure", the 
 grammar ought to be unambiguous with "safe" and "pure" without 
 making them keywords.
Ack, it is "pure" (I never use it) but " nogc", " trusted" etc. Maybe it is possible to add «hidden» without making it a keyword? I guess one will have to look at the productions for the internals of a class body. I suspect a lot of the keywords could go if one wrote a new parser from scratch.
Jun 08 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 11:25:46 UTC, forkit wrote:
 Still, I think I'd prefer 'hidden' actually. It's pretty clear 
 what you're stating here with that word.
It is important that it sounds like it is less accessible than "private", I guess "hidden" sends that message. «hidden from module» «private to module»
Jun 08 2022
next sibling parent zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 11:37:53 UTC, Ola Fosheim Grøstad 
wrote:

 It is important that it sounds like it is less accessible than 
 "private", I guess "hidden" sends that message.

 «hidden from module»

 «private to module»
`hidden` looks better!
Jun 08 2022
prev sibling parent bauss <jj_1337 live.dk> writes:
On Wednesday, 8 June 2022 at 11:37:53 UTC, Ola Fosheim Grøstad 
wrote:
 On Wednesday, 8 June 2022 at 11:25:46 UTC, forkit wrote:
 Still, I think I'd prefer 'hidden' actually. It's pretty clear 
 what you're stating here with that word.
It is important that it sounds like it is less accessible than "private", I guess "hidden" sends that message. «hidden from module» «private to module»
Sounds good to me.
Jun 08 2022
prev sibling parent Piotr Duda <duda.piotr gmail.com> writes:
On Wednesday, 8 June 2022 at 13:11 forkit via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Wednesday, 8 June 2022 at 11:02:45 UTC, Ola Fosheim Grøstad
 wrote:
 On Wednesday, 8 June 2022 at 10:30:59 UTC, Ola Fosheim Grøstad
 wrote:
 They would also ask what "private class" means. If you are
 gonna do it, do at least propose a proper keyword for it:
 local, hidden, internal…
Btw, the original OOP syntax from Simula is **HIDDEN** and **PROTECTED**. So there is some precedent for this.
I wouldn't object to 'hidden int x'. This would solve the problem of 'private (this)' and 'private this()' being too close syntactically.
Or copy delphi and use 'strict private' (and 'strict protected').
Jun 08 2022
prev sibling parent forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 10:30:59 UTC, Ola Fosheim Grøstad 
wrote:
 Anything simple is better than  keyword, private(this), private 
 class etc. Such syntax screams "amateur project" and I wouldn't 
 even consider downloading a language like that. When I first 
 tried D it was because the syntax looked clean (way before the 
  madness caught on).
It can't be: 'private this()' because that conflicts with the use of the word 'this' that is associated with a constructor. 'private (this)' makes perfect sense to me. First, the word 'this' is already associated "to the object, class, or other entity of which the currently running code is a part." - https://en.wikipedia.org/wiki/This_(computer_programming) Second. The exact same syntax can be used for class or struct. One could argue that 'private (this)' and 'private this()' are too close syntactically, and could cause confusion. I wouldn't disagree. But I'd be fine with it, since I'd be using it so often, it'll be programmed into my muscle memory ;-)
Jun 08 2022
prev sibling next sibling parent zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 09:38:24 UTC, Ola Fosheim Grøstad 
wrote:
  but then there
 would be many such adjustments to make.

 To make all those adjustments in D2 with no breaking change 
 would  lead  to  a  mess.
Will it be so `troublesome` if it is `well encapsulation`?
Jun 08 2022
prev sibling parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 09:38:24 UTC, Ola Fosheim Grøstad 
wrote:
 On Wednesday, 8 June 2022 at 09:34:09 UTC, forkit wrote:
 Walter has his firm view. I have mine.
Sure, your viewpoint would make sense for D3, but then there would be many such adjustments to make. To make all those adjustments in D2 with no breaking change would lead to a mess.
I still don't get it. I'm not advocating for my 'perfect world view' for D. just: private(this) That is not a breaking change. It would purely opt-in. Everyone gets what they want (except those who don't want any change).
Jun 08 2022
parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 8 June 2022 at 09:57:49 UTC, forkit wrote:
 On Wednesday, 8 June 2022 at 09:38:24 UTC, Ola Fosheim Grøstad 
 wrote:
 On Wednesday, 8 June 2022 at 09:34:09 UTC, forkit wrote:
 Walter has his firm view. I have mine.
Sure, your viewpoint would make sense for D3, but then there would be many such adjustments to make. To make all those adjustments in D2 with no breaking change would lead to a mess.
I still don't get it. I'm not advocating for my 'perfect world view' for D. just: private(this) That is not a breaking change. It would purely opt-in. Everyone gets what they want (except those who don't want any change).
I completely agree. I really hate the current design, because I have been in situations where I have separated classes because they needed private fields, but then later I actually needed some of the fields shared and had to share those fields public. So either you have to share all fields as friends or you share none. It's too black/white.
Jun 08 2022
parent reply Arafel <er.krali gmail.com> writes:
On 8/6/22 12:00, bauss wrote:
 
 I completely agree. I really hate the current design, because I have 
 been in situations where I have separated classes because they needed 
 private fields, but then later I actually needed some of the fields 
 shared and had to share those fields public.
Out of curiosity, why wasn't `package` or eventually `package(foo)` [1] an option? It seems to have been designed for this very purpose. Of course the classes could be in packages with no common ancestor, but then it would perhaps be worth questioning how so closely coupled classes end up so far away in the hierarchy. [1]: https://dlang.org/spec/attribute.html#VisibilityAttribute
Jun 08 2022
parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 8 June 2022 at 10:49:58 UTC, Arafel wrote:
 On 8/6/22 12:00, bauss wrote:
 
 I completely agree. I really hate the current design, because 
 I have been in situations where I have separated classes 
 because they needed private fields, but then later I actually 
 needed some of the fields shared and had to share those fields 
 public.
Out of curiosity, why wasn't `package` or eventually `package(foo)` [1] an option? It seems to have been designed for this very purpose. Of course the classes could be in packages with no common ancestor, but then it would perhaps be worth questioning how so closely coupled classes end up so far away in the hierarchy. [1]: https://dlang.org/spec/attribute.html#VisibilityAttribute
Because functions cannot be package __and__ virtual.
Jun 08 2022
parent Arafel <er.krali gmail.com> writes:
On 8/6/22 12:58, bauss wrote:
 Because functions cannot be package __and__ virtual.
Good reason, indeed. Well, I guess it technically can, if all your subclasses are in the same package (or at least branch). Agreed, not too useful in the general case, though. Would it make sense however to make `protected` behave like it does in java [1], and include `package` visibility? Given that AFAIK D took most of its OOP ideas from Java, I think it wouldn't be too far-fetched. Perhaps another option would be to add an optional parameter like `package` already does to activate this functionality, or to just allow both keywords: `protected package`. [1]: https://docs.oracle.com/javase/specs/jls/se18/html/jls-6.html#jls-6.6.2
Jun 08 2022
prev sibling parent reply forkit <forkit gmail.com> writes:
On Tuesday, 7 June 2022 at 18:07:34 UTC, Andrey Zherikov wrote:
 Regarding implementation. I don't like ` private` as people 
 will be confused a lot with ` private`<->`private`. IMHO the 
 ideal solution would be having `module` to mark module privates 
 and `private` for real privates but this is not backward 
 compatible. So the better solution might be extending syntax 
 for `private` having something like `private(symbol[, symbol 
 ...])` where `symbol` is a symbol that has access to the member 
 For example: `this` means current struct/class; `this.foo` or 
 `<typeof(this)>.foo` means foo member in the current 
 struct/class.
Yes. I agree. private is not descriptive enough. private(module) on the otherhand, states its purpose very clearly.
Jun 07 2022
parent forkit <forkit gmail.com> writes:
On Tuesday, 7 June 2022 at 23:59:42 UTC, forkit wrote:
 Yes. I agree.  private is not descriptive enough.

 private(module) on the otherhand, states its purpose very 
 clearly.
On second thoughts - even private(module) is confusing. Does it mean private to the module? It's too confusing also. Perhaps: private(this) .. since 'this' is already traditionally associated with the abstraction it's referring to.
Jun 07 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/7/2022 5:47 AM, forkit wrote:
 Instead, it deliberately, intentionally, proudly, leaves this important aspect 
 in software development to the programmer(s).
Yeah, well, the alternative is "friend" classes, which are an abomination. The unit of encapsulation in D is the module, not the class.
Jun 07 2022
next sibling parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 06:56:50 UTC, Walter Bright wrote:
 On 6/7/2022 5:47 AM, forkit wrote:
 Instead, it deliberately, intentionally, proudly, leaves this 
 important aspect in software development to the programmer(s).
Yeah, well, the alternative is "friend" classes, which are an abomination. The unit of encapsulation in D is the module, not the class.
But the abomination, is what you already have ;-) Cause *everything* is a friend. It can't get much worse than that. But wait, it does get worse ... you (the programmer) got no say it. You cannot unfriend in D (except through a series of silly workarounds, that even then, just give you 'the appearance' that you've unfriended - they still your friends, should they ever show up on the scene. You got not say it. That's the real 'abomination'.
Jun 08 2022
next sibling parent zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 07:07:45 UTC, forkit wrote:
  they still your friends, should they
 ever show up on the scene.
With these friends, what enemies do you need!
Jun 08 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
My experience with C++ and the "friend" class concept is it is necessary for
C++ 
because it has no notion of a module.

D is much simplified by making the module the fence for encapsulation. C++ 
favors a smaller number of large files, D is designed around a larger number of 
small files.

I understand that you don't prefer that approach, but I suspect if you've used 
"friend" classes much in C++ you'd change your mind. Most people find D's way a 
relief.
Jun 08 2022
parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 8 June 2022 at 18:53:35 UTC, Walter Bright wrote:
 My experience with C++ and the "friend" class concept is it is 
 necessary for C++ because it has no notion of a module.

 D is much simplified by making the module the fence for 
 encapsulation. C++ favors a smaller number of large files, D is 
 designed around a larger number of small files.

 I understand that you don't prefer that approach, but I suspect 
 if you've used "friend" classes much in C++ you'd change your 
 mind. Most people find D's way a relief.
I think there are two sides of the coin. Also I don't think it's necessarily that people have a problem with how D wants it, it's just that some of us would like the option to opt-out of it when needed.
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Wednesday, 8 June 2022 at 19:12:33 UTC, bauss wrote:
 On Wednesday, 8 June 2022 at 18:53:35 UTC, Walter Bright wrote:
 My experience with C++ and the "friend" class concept is it is 
 necessary for C++ because it has no notion of a module.

 D is much simplified by making the module the fence for 
 encapsulation. C++ favors a smaller number of large files, D 
 is designed around a larger number of small files.

 I understand that you don't prefer that approach, but I 
 suspect if you've used "friend" classes much in C++ you'd 
 change your mind. Most people find D's way a relief.
I think there are two sides of the coin. Also I don't think it's necessarily that people have a problem with how D wants it, it's just that some of us would like the option to opt-out of it when needed.
+1 why is so hard for people to get this point? I don't get it. It seems like such a simple concept -> an option to have a member of a class that is private to that class. C'mon everyone. It's simple to get your head around. There is no part of this idea that requires anyone to change what they currently do in D. It's pure opt-in.
Jun 08 2022
parent reply Mike Parker <aldacron gmail.com> writes:
On Wednesday, 8 June 2022 at 21:38:24 UTC, forkit wrote:

 why is so hard for people to get this point? I don't get it.

 It seems like such a simple concept -> an option to have a 
 member of a class that is private to that class.

 C'mon everyone. It's simple to get your head around.

 There is no part of this idea that requires anyone to change 
 what they currently do in D.

 It's  pure opt-in.
We get your point just fine. That's not where the pushback is coming from. Like I've already told you, any new language feature has to justify its existence. New features add complexity to the language implementation and the cognitive load. There has to be a compelling reason to add it. You haven't demonstrated one in this thread from what I've seen. You can achieve what you want by splitting things out into separate files, and that's what you have to overcome in order to sell this idea. You keep insisting this isn't good enough, because even then one can always add something to a module that accesses private class members. But that's not really a compelling reason, because the solution to that exists: don't do it. You keep mentioning Java. Every method in a Java class has access to private member variables, even when the intention is for only one method to modify each member variable. How do they handle it? By convention. It's the exact same issue you're complaining about here. In D, that the functions access the private members can be outside of the brace closing the class definition makes no practical difference. If you move to class per file, you've solved your conceptual problem of encapsulation at the class boundary, and as long as you never add a function to the module that accesses those variables from outside of the closing brace you're golden. But you still have to contend with multiple member functions having access to the private variables, so you still have to go by convention if you want to keep access to the minimum. Or should we also have a level of encapsulation to allow access only from a single function? If you can demonstrate that the benefit of adding a new level of protection to the language outweighs the cost, then you'll have a leg to stand on. But it's a tough sell since we already have a way to handle it.
Jun 08 2022
next sibling parent forkit <forkit gmail.com> writes:
On Thursday, 9 June 2022 at 00:38:56 UTC, Mike Parker wrote:
 ...the solution to that exists: don't do it.
Mmm. Why didn't I think of that. Now my problem has gone away.
Jun 08 2022
prev sibling next sibling parent reply forkit <forkit gmail.com> writes:
On Thursday, 9 June 2022 at 00:38:56 UTC, Mike Parker wrote:
 We get your point just fine. That's not where the pushback is 
 coming from. Like I've already told you, any new language 
 feature has to justify its existence. New features add 
 complexity to the language implementation and the cognitive 
 load....
The cognitive load is put onto me, when I come to D. That becasue the D module system decides my specification for me, by making private, public within the module. I have no say in this, other than these 'work arounds' that you insist I follow - including the best one yet 'just don't do it'. Work-arounds is not a feature that D should be proud of. I do not have to make the case for there being a need to make a part of a specification of an abstraction, truly private to that abstraction. That argument has been made decades ago, and proven to be a valid, and a highly useful, and highly used, design feature - even more so, when the compiler is able to enforce those invariants, which D cannot do. So without an 'option' like I've suggested, the actual 'cognitive load' is put on to those that come to D. IMO, without justification.
Jun 08 2022
next sibling parent reply Adam Ruppe <destructionator gmail.com> writes:
On Thursday, 9 June 2022 at 01:04:26 UTC, forkit wrote:
 IMO, without justification.
Maybe you should fork it.
Jun 08 2022
parent forkit <forkit gmail.com> writes:
On Thursday, 9 June 2022 at 01:09:14 UTC, Adam Ruppe wrote:
 On Thursday, 9 June 2022 at 01:04:26 UTC, forkit wrote:
 IMO, without justification.
Maybe you should fork it.
when I win the lotto, that's what I'll do (cause i'd need a team of pretty good compiler developers to get anywhere, and they hard to find, and kinda expensive to employ ;-) Their very first project would be: private - private, as it should be. private[module] - private as it currently is. Then, no need to do 'workarounds' anymore. Co-operative mutablity will no longer be the default. You'll have to opt-in to it. Now, the compiler will tell you when you're invariants are being compromised. You won't have to ever 'remember' to 'just not do it'.
Jun 08 2022
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 9 June 2022 at 01:04:26 UTC, forkit wrote:
 On Thursday, 9 June 2022 at 00:38:56 UTC, Mike Parker wrote:
 I have no say in this, other than these 'work arounds' that you 
 insist I follow - including the best one yet 'just don't do it'.
I explained that. Here's some code since it apparently wasn't clear what I meant: ```d class Foo { int specialSauce; void onlyModifySauceHere(int newVal) { assert(newVal > someMin && newVal <= someMax); specialSauce = newVal; } void functionAddedByCluelessTeamMember() { specialSauce *= 100; } } ``` How is this problem solved in Java? Don't do it. C++? Don't do it. In D, if you don't want functions in the module accessing private class members, don't do it. There is no practical difference whatsoever if the offending function is above or below the closing brace.
 I do not have to make the case
You're the one who wants the feature, so yeah, the onus is on you or someone who agrees with you to convince the maintainers of the language that it's a feature worth having. Otherwise, it isn't going to happen. You've said enough about this topic in this thread and others that you could have written a DIP by now. And both of us are repeating the same points over and over, so I'm done with it.
Jun 08 2022
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Thursday, 9 June 2022 at 01:54:22 UTC, Mike Parker wrote:

     int specialSauce;
That was supposed to be private, of course.
Jun 08 2022
prev sibling next sibling parent forkit <forkit gmail.com> writes:
On Thursday, 9 June 2022 at 01:54:22 UTC, Mike Parker wrote:
 You've said enough about this topic in this thread and others 
 that you could have written a DIP by now. And both of us are 
 repeating the same points over and over, so I'm done with it.
In Australian politics, you don't bring a measure to the floor, unless you already have good insight into how that measure will be accepted, or not. I'd take the same approach with a DIP. i.e first ascertain what level of support there might be. If the indication is very little support, don't bother bring the measure to the floor - cause you already know it's going nowhere. Clearly there is so little support for this simple idea, that it's pointless discussing any further. Good luck in the contstant explaining to new comers, as to why private doesn't really mean private, and why you have to do various workarounds to simulate it, and why the compiler will never (can never) enforce those decisions, and why D will not even consider an option to let the designer make the decision. You'll need to provide better arguments though. Cause you're current arguments are not persuasive enough, IMO, to quickly shutdown the discussion of this issue, when it inevitably arises again.
Jun 08 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 9 June 2022 at 01:54:22 UTC, Mike Parker wrote:
 On Thursday, 9 June 2022 at 01:04:26 UTC, forkit wrote:
 You've said enough about this topic in this thread and others 
 that you could have written a DIP by now. And both of us are 
 repeating the same points over and over, so I'm done with it.
Just create a separate forum fo discussing new features right under «General». forkit has to engage with other users to convince them, and to find a solution that msny can agree on, no point in writing a DIP if nobody on the core team wants to be a sponsor. So he first needs a large group of people to agree, then they need to find someone on the core team to sponsor it. This is how it ought to work. The real problem is lack if focus, e.g. the memory management issue that has cost D the loss of so much talent is still at the experimental stage and is digging itself into a usability nightmare that only a tiny core of die hard fans would use. Yet it should have been known over a decade ago, if a the process was reasonable this would have been completed before Rust hit 1.0. What forkit asks for isn’t unreasonable, the syntax was unreasonable. Since D seems to have gotten onto a track where usability is increasingly ignored then it is better to have no change. The process ought to be: Need -> usability requirements -> design... Instead it is: Need -> fancy idea -> 70% implementation -> usability issues -> justified whining. Or people writing really poorly thought out DIPs because they have no background or education that could make them good language designers. Most DIPs should not have been written. You need to engage with others to write a half decent DIP. How many good DIPs can you point to? One or two? Certainly not three!!! So the best D can do is stop adding stuff and just fix flaws until people start believing that the core team takes an interest in shipping completed polished solutions. Then D can add forkit’s suggested idea.
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Thursday, 9 June 2022 at 04:52:13 UTC, Ola Fosheim Grøstad 
wrote:
 ....
 What forkit asks for isn’t unreasonable, the syntax was 
 unreasonable.
putting aside the idea of this every being accepted.... as far as syntax goes... i still think an annotation, rather than a word, or a new word, is the best approach. An annotation seems very consistent with the D style to me. class myClass { self private string secret; }
Jun 08 2022
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
private(scope)

Nice and simple, if you know what private and scope does, you can 
probably guess what it does here.
Jun 08 2022
parent reply forkit <forkit gmail.com> writes:
On Thursday, 9 June 2022 at 05:52:10 UTC, rikki cattermole wrote:
 private(scope)

 Nice and simple, if you know what private and scope does, you 
 can probably guess what it does here.
It's just those brackets that bother me. Something doesn't seem right with them there like that. Consider where else in the language () is used, for example. btw. In swift (where they seem to have actually thought this out sensibly): 'fileprivate' -> means an entity that is accessible anywhere in that file. 'private' -> means an entity that cannot be accessed anywhere except for the enclosing type, such as a class so here's yet another idea: - just an idea, not a proposal ;-) private -> no change. means an entity that is accessible anywhere in that file. scopeprivate -> means an entity that cannot be accessed anywhere except for the enclosing type, such as a class
Jun 08 2022
next sibling parent forkit <forkit gmail.com> writes:
On Thursday, 9 June 2022 at 06:21:08 UTC, forkit wrote:

another example, where I think swift done it better:

i.e. you know exactly what the designers intentions were when 
this was written.

(in Swift 4, an class extension can now access a private member)

-- some file --
class A { private var name = "First Letter" }

extension A
{
   func printName()
  {
    print(name) // you may access it here from swift 4. Swift 3 
will throw error.
  }
}
-- end file --
Jun 08 2022
prev sibling parent reply bauss <jj_1337 live.dk> writes:
On Thursday, 9 June 2022 at 06:21:08 UTC, forkit wrote:
 On Thursday, 9 June 2022 at 05:52:10 UTC, rikki cattermole 
 wrote:
 private(scope)

 Nice and simple, if you know what private and scope does, you 
 can probably guess what it does here.
It's just those brackets that bother me. Something doesn't seem right with them there like that. Consider where else in the language () is used, for example. btw. In swift (where they seem to have actually thought this out sensibly): 'fileprivate' -> means an entity that is accessible anywhere in that file. 'private' -> means an entity that cannot be accessed anywhere except for the enclosing type, such as a class so here's yet another idea: - just an idea, not a proposal ;-) private -> no change. means an entity that is accessible anywhere in that file. scopeprivate -> means an entity that cannot be accessed anywhere except for the enclosing type, such as a class
Couldn't it be `private scope` or `scope private` then if the brackets bother you? I think scopeprivate as a keyword is really long. Maybe it could just be `scope` and nothing else, since `scope` as it is now cannot be used in the same context and thus it won't conflict with how it currently is. But perhaps it's better to have `hidden` then anyway since it's much more clear.
Jun 09 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 9 June 2022 at 09:47:54 UTC, bauss wrote:
 But perhaps it's better to have `hidden` then anyway since it's 
 much more clear.
You might as well, adding a new protection level might be a breaking change thanks to meta-programming. It is probably possible to write the parser in such a way that "hidden" isn't a keyword. At worst it will impact people who use a type called "hidden".
Jun 09 2022
parent bauss <jj_1337 live.dk> writes:
On Thursday, 9 June 2022 at 10:16:06 UTC, Ola Fosheim Grøstad 
wrote:
 On Thursday, 9 June 2022 at 09:47:54 UTC, bauss wrote:
 But perhaps it's better to have `hidden` then anyway since 
 it's much more clear.
You might as well, adding a new protection level might be a breaking change thanks to meta-programming. It is probably possible to write the parser in such a way that "hidden" isn't a keyword. At worst it will impact people who use a type called "hidden".
Could make it an error when used directly, but a warning when accessed through traits. Then deprecate it over time, allowing people to fix their code to support it.
Jun 09 2022
prev sibling parent reply zjh <fqbqrr 163.com> writes:
On Thursday, 9 June 2022 at 00:38:56 UTC, Mike Parker wrote:
New features add
 complexity to the language implementation and the cognitive 
 load. There has to be a compelling reason to add it.
There is no `cognitive load` at all! Only the `"module"` encapsulation extends to the `"minimum class"` encapsulation that should exist. If this is a `cognitive load`,then please don't `write a program`. `C++23's` "`corutine`" is so `troublesome` ,but people are still learning it.
Jun 08 2022
parent zjh <fqbqrr 163.com> writes:
On Thursday, 9 June 2022 at 01:28:28 UTC, zjh wrote:

 There is no `cognitive load` at all!
 Only the `"module"` encapsulation extends to the `"minimum 
 class"` encapsulation that should exist.
`One sentence` can explains it,there is no `cognitive burden`!!!
Jun 08 2022
prev sibling parent reply Max Samukha <maxsamukha gmail.com> writes:
On Wednesday, 8 June 2022 at 06:56:50 UTC, Walter Bright wrote:
 The unit of encapsulation in D is the module, not the class.
Why is it less of an abomination? Class is the unit of encapsulation by the very definition of OOP. D just forces you into the class-per-module paradigm, basically redefining modules as classes. That is just as abominable, given friends are rare in "properly" designed OOP code.
Jun 08 2022
next sibling parent reply Dom Disc <dominikus scherkl.de> writes:
On Wednesday, 8 June 2022 at 08:23:31 UTC, Max Samukha wrote:
 That is just as abominable, given friends are rare in 
 "properly" designed OOP code.
Not in C++. E.g. operator overloads with the class as second operand but some basic type as first operand _can't_ be member functions (because C++ doesn't have op_right). But operators tend to really need access to the innards, so most of the time they have to be friends. And there are many operators, hence many friends...
Jun 08 2022
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 08:41:36 UTC, Dom Disc wrote:
 But operators tend to really need access to the innards, so 
 most of the time they have to be friends. And there are many 
 operators, hence many friends...
This is something that can be fixed by a dedicated IDE though. So this is just syntax. What you might want to do in C++ is to implement "*=", "+=" etc inside the class and then the external operators can be created without access to the internals.
Jun 08 2022
prev sibling next sibling parent reply zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 08:23:31 UTC, Max Samukha wrote:
 On Wednesday, 8 June 2022 at 06:56:50 UTC, Walter Bright wrote:

That is just as abominable, given friends
 are rare in "properly" designed OOP code.
Right!
Jun 08 2022
parent zjh <fqbqrr 163.com> writes:
On Wednesday, 8 June 2022 at 08:45:54 UTC, zjh wrote:

  That is just as abominable, given friends
 are rare in "properly" designed OOP code.
Right!
I even forgot `friend`. I don't need `friend`.
Jun 08 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/8/2022 1:23 AM, Max Samukha wrote:
 Why is it less of an abomination?
Because "friend" classes are a mess. They can be spread all over your code. Modules are physically co-located in the same file, making them easy to manage.
Jun 08 2022
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 8 June 2022 at 20:35:30 UTC, Walter Bright wrote:
 On 6/8/2022 1:23 AM, Max Samukha wrote:
 Why is it less of an abomination?
Because "friend" classes are a mess. They can be spread all over your code.
Friend functions are useful when you want tight encapsulation without performance issues. It can help reducing the exposed public API to a minimum. It can also be useful for concurrency, to make the write-api nonpublic etc. It is useful for restricting the creation of objects. And you get an explicit list. I like it. But there is no reason for D to become like C++. D should focus on simplicity and ease of use.
Jun 08 2022
prev sibling parent reply Max Samukha <maxsamukha gmail.com> writes:
On Wednesday, 8 June 2022 at 20:35:30 UTC, Walter Bright wrote:
 On 6/8/2022 1:23 AM, Max Samukha wrote:
 Why is it less of an abomination?
Because "friend" classes are a mess. They can be spread all over your code. Modules are physically co-located in the same file, making them easy to manage.
To me, mandating a certain codebase structure is not an advantage. Also, you can always misuse 'package' to make a mess out of a D codebase. 'friend' is abominable for a different reason - it breaks encapsulation by exposing the entire state instead of selected members, and D is no different in this respect.
Jun 09 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 9 June 2022 at 13:05:46 UTC, Max Samukha wrote:
 'friend' is abominable for a different reason - it breaks 
 encapsulation by exposing the entire state instead of selected 
 members, and D is no different in this respect.
Not necessarily. You can put all the members you want to expose in a separate C++ class inside the other class and only expose this one. You usually don't want to make another class a friend, just some specified functions. The tools for improved encapsulation are there even if most C++ programmers don't care enough to use them. And I guess that also is the situation for D, most D users care more about convenience than strictness. You see this in D code bases by the tendency to «abuse» string mixins! At the end of the day, culture has a massive impact…
Jun 09 2022
parent reply forkit <forkit gmail.com> writes:
On Thursday, 9 June 2022 at 13:15:14 UTC, Ola Fosheim Grøstad 
wrote:
 And I guess that also is the situation for D, most D users care 
 more about convenience than strictness...
I think this is true, particulary for 'core'. I think this is why private is considered as a restrictive move, instead of an enhancement ;-) But whatever.... I'm going to spend some time on Swift now (having never used it before). It looks really interesting - and already has proper access modifiers ;-) It also has what initially attracted me to D too (which was the convenience of using arrays with the [..] magic. This too looks interesting: // array of any items let anything: [Any] = [1, "a", 3.14] https://theswiftdev.com/beginners-guide-to-swift-arrays/
Jun 09 2022
next sibling parent Tejas <notrealemail gmail.com> writes:
On Thursday, 9 June 2022 at 21:44:51 UTC, forkit wrote:
 On Thursday, 9 June 2022 at 13:15:14 UTC, Ola Fosheim Grøstad 
 wrote:
 And I guess that also is the situation for D, most D users 
 care more about convenience than strictness...
I think this is true, particulary for 'core'. I think this is why private is considered as a restrictive move, instead of an enhancement ;-) But whatever.... I'm going to spend some time on Swift now (having never used it before). It looks really interesting - and already has proper access modifiers ;-) It also has what initially attracted me to D too (which was the convenience of using arrays with the [..] magic. This too looks interesting: // array of any items let anything: [Any] = [1, "a", 3.14] https://theswiftdev.com/beginners-guide-to-swift-arrays/
We also have those: https://dlang.org/library/std/variant/variant_array.html
Jun 09 2022
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 9 June 2022 at 21:44:51 UTC, forkit wrote:
 I'm going to spend some time on Swift now (having never used it 
 before).

 It looks really interesting
It is ok, but they have some slightly annoying things to stay compatible with Objective-C.
Jun 09 2022
prev sibling parent Dom Disc <dominikus scherkl.de> writes:
On Monday, 6 June 2022 at 04:34:23 UTC, forkit wrote:
 My argument is clear. It would be 'nice to have' 'an option' 
 for there to be a genuine private component of a class. Not 
 pseudo 'private', but genuine  private.
I would be ok with this, if it comes WITHOUT friends. Else it would destroy encapsulation like it does in C++. And friends wouldn't be necessary, as we have the real D encapsulation as fallback, so why not. It's useless, but if you want it this urgently...
Jun 06 2022
prev sibling parent forkit <forkit gmail.com> writes:
On Wednesday, 1 June 2022 at 12:24:23 UTC, Dukc wrote:
 ...
 Controlling the scope of encapsulation is rarely that critical, 
 and if it is, it's easier to just put the class to it's own 
 file.
Actually, controlling the scope of encapsulation is *critical* to managing complexity. Due to everything within a module being a (C++ like) 'friend' to any class within that module, the ONLY way to manage the complexity of a D module, in the case where object oriented design is in play, is by doing what you say - put each class in it's own module. Fine. I'd like to audit the D source code, to see if that is actually what happens when programmers have access to the flexible, friendly, D module ;-) Otherwise, encapsulation is compromised.
Jun 03 2022
prev sibling parent forkit <forkit gmail.com> writes:
On Wednesday, 1 June 2022 at 01:54:52 UTC, H. S. Teoh wrote:

btw. if seems we've higjacked your thread.

sorry about that.

Seems like I raised a very provocative idea, indeed.

I'll refrain from any more posts.

However, I'd still like to know *your* motivation for the code 
you presented.

(unless you also think it is 'too provocative an idea' to comment 
on any further).
Jun 05 2022