Jump to page: 1 221  
Page
Thread overview
Using closure in function scope to make "real" private class members
Jun 01, 2022
H. S. Teoh
Jun 01, 2022
rikki cattermole
Jun 01, 2022
Dukc
Jun 01, 2022
12345swordy
Jun 03, 2022
forkit
Jun 03, 2022
Mike Parker
Jun 03, 2022
forkit
Jun 03, 2022
Guillaume Piolat
Jun 03, 2022
forkit
Jun 03, 2022
Mike Parker
Jun 03, 2022
forkit
Jun 03, 2022
Mike Parker
Jun 03, 2022
12345swordy
Jun 03, 2022
forkit
Jun 04, 2022
forkit
Jun 04, 2022
forkit
Jun 04, 2022
monkyyy
Jun 04, 2022
Mike Parker
Jun 04, 2022
forkit
Jun 04, 2022
Mike Parker
Jun 04, 2022
forkit
Jun 04, 2022
matheus
Jun 04, 2022
forkit
Jun 04, 2022
zjh
Jun 04, 2022
Ali Çehreli
Jun 04, 2022
forkit
Jun 04, 2022
Adam D Ruppe
Jun 04, 2022
Mike Parker
Jun 04, 2022
zjh
Jun 04, 2022
zjh
Jun 04, 2022
forkit
Jun 04, 2022
Ali Çehreli
Jun 05, 2022
forkit
Jun 05, 2022
forkit
Jun 05, 2022
Ali Çehreli
Jun 05, 2022
forkit
Jun 05, 2022
forkit
Jun 05, 2022
forkit
Jun 06, 2022
Commander Zot
Jun 04, 2022
Dukc
Jun 04, 2022
Nick Treleaven
Jun 04, 2022
Nick Treleaven
Jun 09, 2022
forkit
Jun 03, 2022
Ali Çehreli
Jun 03, 2022
forkit
Jun 03, 2022
forkit
Jun 03, 2022
bauss
Jun 03, 2022
bauss
Jun 03, 2022
zjh
Jun 04, 2022
Commander Zot
Jun 04, 2022
zjh
Jun 04, 2022
zjh
Jun 04, 2022
zjh
Jun 04, 2022
zjh
Jun 04, 2022
Commander Zot
Jun 04, 2022
zjh
Jun 05, 2022
Dom Disc
Jun 05, 2022
Dom Disc
Jun 05, 2022
Dom Disc
Jun 05, 2022
forkit
Jun 06, 2022
zjh
Jun 06, 2022
forkit
Jun 06, 2022
zjh
Jun 06, 2022
forkit
Jun 06, 2022
forkit
Jun 06, 2022
forkit
Jun 06, 2022
Dom Disc
Jun 08, 2022
forkit
Jun 08, 2022
Commander Zot
Jun 06, 2022
norm
Jun 06, 2022
forkit
Jun 06, 2022
Basile B.
Jun 06, 2022
rikki cattermole
Jun 06, 2022
zjh
Jun 06, 2022
zjh
Jun 06, 2022
mee6
Jun 06, 2022
zjh
Jun 07, 2022
zjh
Jun 07, 2022
zjh
Jun 07, 2022
Dom Disc
Jun 07, 2022
zjh
Jun 07, 2022
zjh
Jun 07, 2022
zjh
Jun 07, 2022
zjh
Jun 07, 2022
zjh
Jun 07, 2022
zjh
Jun 07, 2022
zjh
Jun 07, 2022
Basile B.
Jun 07, 2022
Nick Treleaven
Jun 07, 2022
forkit
Jun 07, 2022
Andrey Zherikov
Jun 07, 2022
forkit
Jun 08, 2022
forkit
Jun 08, 2022
forkit
Jun 08, 2022
zjh
Jun 08, 2022
forkit
Jun 08, 2022
zjh
Jun 08, 2022
zjh
Jun 08, 2022
zjh
Jun 08, 2022
zjh
Jun 08, 2022
forkit
Jun 08, 2022
Max Samukha
Jun 08, 2022
forkit
Jun 08, 2022
Dom Disc
Jun 08, 2022
forkit
Jun 08, 2022
bauss
Jun 08, 2022
bauss
Jun 08, 2022
zjh
Jun 08, 2022
bauss
Jun 08, 2022
forkit
Jun 08, 2022
forkit
Jun 08, 2022
Piotr Duda
Jun 08, 2022
forkit
Jun 08, 2022
forkit
Jun 08, 2022
forkit
Jun 08, 2022
bauss
Jun 08, 2022
forkit
Jun 08, 2022
Max Samukha
Jun 08, 2022
Max Samukha
Jun 08, 2022
zjh
Jun 08, 2022
bauss
Jun 08, 2022
forkit
Jun 08, 2022
zjh
Jun 08, 2022
forkit
Jun 08, 2022
bauss
Jun 08, 2022
Arafel
Jun 08, 2022
bauss
Jun 08, 2022
Arafel
Jun 07, 2022
forkit
Jun 08, 2022
forkit
Jun 08, 2022
Walter Bright
Jun 08, 2022
forkit
Jun 08, 2022
zjh
Jun 08, 2022
Walter Bright
Jun 08, 2022
bauss
Jun 08, 2022
forkit
Jun 09, 2022
Mike Parker
Jun 09, 2022
forkit
Jun 09, 2022
forkit
Jun 09, 2022
Adam Ruppe
Jun 09, 2022
forkit
Jun 09, 2022
Mike Parker
Jun 09, 2022
Mike Parker
Jun 09, 2022
forkit
Jun 09, 2022
forkit
Jun 09, 2022
rikki cattermole
Jun 09, 2022
forkit
Jun 09, 2022
forkit
Jun 09, 2022
bauss
Jun 09, 2022
bauss
Jun 09, 2022
zjh
Jun 09, 2022
zjh
Jun 08, 2022
Max Samukha
Jun 08, 2022
Dom Disc
Jun 08, 2022
zjh
Jun 08, 2022
zjh
Jun 08, 2022
Walter Bright
Jun 09, 2022
Max Samukha
Jun 09, 2022
forkit
Jun 10, 2022
Tejas
Jun 06, 2022
Dom Disc
Jun 03, 2022
forkit
Jun 06, 2022
forkit
May 31, 2022
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(dmd.dsymbol.Dsymbol) [0x55672d7ea933]
??:? void dmd.dsymbol.foreachDsymbol(dmd.root.array.Array!(dmd.dsymbol.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.
June 01, 2022
https://issues.dlang.org/show_bug.cgi?id=23151
June 01, 2022
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.
June 01, 2022
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

June 03, 2022
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.

June 03, 2022

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:

struct Foo {
    private int _x;

    void x(int val) { _x = val; }
}

vs. this:

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.

June 02, 2022
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

June 03, 2022

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.

June 03, 2022
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.

June 03, 2022
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 ;-)
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11