June 23, 2022

On Thursday, 23 June 2022 at 09:49:25 UTC, Dom Disc wrote:

>

No, but this whole discussion is only about coding style (putting each class in its own module or not). And from style guide perspective having more options is always bad. It reduces the readability.

From a readability perspective and an educational cost perspective having «private» mean anything but the conventional class-private is a mistake. So that has clearly not been the main consideration when landing on the current setup. It is by and large a personal opinion design. Much of the D design is personal/opinionated.

Anyway, if you look at Phobos then you'll realize that the language does not affect module structure to a significant degree. Having more constraints, will not make people make create more disorganized code. If anything you get more structure, better documentation using language means and more opportunities to clearly organize your code.

(But as noted before, this is not D's biggest issue…)

June 23, 2022
On Thursday, 23 June 2022 at 09:49:25 UTC, Dom Disc wrote:
>
> ...
> No, but this whole discussion is only about coding style (putting each class in its own module or not). And from style guide perspective having more options is always bad. It reduces the readability.

Coding style?

Ummm .. no.

Why is it, that some people ***still*** don't get it.

It's about being able to declare, as strongly typed, abstract data object, that is responsible for declaring and maintaining its own invariants, and where the compiler can enforce those invariants.

It is perhaps, the single most important concept for good, scalable, software engineering.

Sure, D has a 'workaround' where you can 'simulate' this. But it's deficient. As soon as you add any code whatsover to the module, the simulation dissolves.

The only solution to not having a strongly typed abstract data object, is to have one.

It makes software engineering better, not worse.

But more importantly, you get to decide whether to use it or not.

Like it's completely up to you. You don't like it? Don't use it. Simple.

If it's the thing you've waiting for, for years, then woohoo!

At least someone had the balls (or otherwise), to take this to the next level and actually try putting it in as a preview, so people can try it.

Again, totally up to you to try it or not.

want to try it: '-preview=privateThis'

don't want to try it: ''

It's up to **you**

C has it's million dollar mistake.

I think missing this important feature was D's million 'user' mistake (a million missing users because of it).
June 23, 2022

On Thursday, 23 June 2022 at 09:42:59 UTC, Ola Fosheim Grøstad wrote:

>

On Thursday, 23 June 2022 at 09:30:49 UTC, deadalnix wrote:

>

Usually, while you increase things on one axis, you also diminish them on another.

I don't see how providing more expressive constraints diminish anything on a semantic level if sound.

There is an implementation/design/educational cost, but history suggests that languages over time add more expressive constraints: C++ concepts/consteval, Python typing module, TypeScript, JavaScript classes/private.

Then you see how providing more has a cost, at least and implementation/design/educational one. So there is a point at wish adding that expressivness is counter productive, it is at the point when the value of the extra things that you can express is lower than the cost incurred by implementing the change required for that extra expressivness to be possible.

There are other costs:

  • Tooling will not support that feature initially. D tends to be cavalier with that, and as a result, has worse tooling than pretty much any other language out there.
  • There are now many ways to express the same thing (put things in different module and use private or put thing in the same module and use private(this)). This has an adverse effect on readability by providing ways to subvert the expectations of the reader.

I'm also convinced that there are costs I cannot really pinpoint, but that are real. The existing landscape clearly demonstrate this. For instance, while Java provides class level visibility, it is actually commonplace to have one Java class per file in numerous projects. Amongst the top languages, more than half have little to no visibility constraints, and these who do like Java tend to have idioms to map visibility with files.

There is something there that remains under explored.

June 23, 2022

On Wednesday, 22 June 2022 at 23:31:28 UTC, user1234 wrote:

>

On Wednesday, 22 June 2022 at 23:08:38 UTC, deadalnix wrote:

>

On Wednesday, 22 June 2022 at 21:30:07 UTC, forkit wrote:

>

I refer maxhaton back to the seminal paper on the benefits of abstract data types:

Programming with abstract data types - Liskov and Zilles 1974

https://dl.acm.org/doi/pdf/10.1145/942572.807045

I wish you understood that every comment that you make where you fail to present any concrete instance of the problem caused weakens your case.

Assuming the people you are talking to are not well versed in the concept of asbtract data types is somewhat amusing, but I'm afraid, also playing against your case.

to be fair, I think that, to any example presented here, the answer will be "put the aggregate declaration in its own module". But let's try something simple:

struct VLA {
private:
    void* ptr;
    size_t length;
public:
    void setLength(size_t value);
}

struct Other {
    VLA vla;
    void imBad() {
        length += 1; // now I may have faults or not when reading the vla
    }
}

It's about being strict with yourself. What if I'm not really good, make stupid mistakes ? Now I have a security barrier, I can use private(this), the compiler helps me with an error.

there's no practical difference to this:

struct VLA {
private:
    void* ptr;
    size_t length;
public:
    void setLength(size_t value);
    void imBad() {
        vla.length += 1; // now I may have faults or not when reading the vla
    }
}

struct Other {
    VLA vla;
    void breaktheworld() {vla.imBad();}
}

in both cases your function breaks any invariants VLA might have. The real question is, why is VLA declared in the module scope in the first place? This is a prime example of why class private encourages bad code design.

June 23, 2022

On Thursday, 23 June 2022 at 10:18:29 UTC, deadalnix wrote:

>

So there is a point at wish adding that expressivness is counter productive, it is at the point when the value of the extra things that you can express is lower than the cost incurred by implementing the change required for that extra expressivness to be possible.

Yes, there is a cost if the syntax is messed up or if there is a breaking change.

The cost for adding the feature is higher now than if one at a later stage choose to clean up the syntax (and thus get a breaking change anyway). So it probably should wait for a more general syntax cleanup.

June 23, 2022
On Thursday, 23 June 2022 at 10:16:42 UTC, forkit wrote:

> strongly typed, abstract data object is perhaps, the single most
> important concept for good, scalable, software engineering.
>
> Sure, D has a 'workaround' where you can 'simulate' this.
This is no workaround. It's one of Ds basic design choices, and done so for reasons (the friend-problem), not accidentally.

> it's deficient. As soon as you add any code whatsover to the module, the simulation dissolves.
You can prevent that from happening (supported by the OS!). Much better as you can prevent someone who has access to a module from changing one of the classes within it (there you have no chance at all).

I call that strong typed. Much, much stronger than with multiple classes within one file!

> I think missing this important feature was D's million 'user' mistake (a million missing users because of it).
There is no feature missing.
And I still find the way D realizes the same as other languages do with class private much better. Far from a mistake.

June 23, 2022
On Thursday, 23 June 2022 at 10:16:42 UTC, forkit wrote:
>
> Coding style?
>
> Ummm .. no.
>
> Why is it, that some people ***still*** don't get it.

I think that all people here get it. They don't agree on making an elephant out of mosquito.


June 23, 2022
On Thursday, 23 June 2022 at 10:18:29 UTC, deadalnix wrote:
>
> ..
> Then you see how providing more has a cost, at least and `implementation/design/educational` one. So there is a point at wish adding that expressivness is counter productive, it is at the point when the value of the extra things that you can express is lower than the cost incurred by implementing the change required for that extra expressivness to be possible.
>
> There are other costs:
>  - Tooling will not support that feature initially. D tends to be cavalier with that, and as a result, has worse tooling than pretty much any other language out there.
>  - There are now many ways to express the same thing (put things in different module and use `private` or put thing in the same module and use `private(this)`). This has an adverse effect on readability by providing ways to subvert the expectations of the reader.
>
> I'm also convinced that there are costs I cannot really pinpoint, but that are real. The existing landscape clearly demonstrate this. For instance, while Java provides class level visibility, it is actually commonplace to have one Java class per file in numerous projects.  Amongst the top languages, more than half have little to no visibility constraints, and these who do like Java tend to have idioms to map visibility with files.
>
> There is something there that remains under explored.

There's always a cost in giving people choice.

In C++, C#, Java, Swift, .... I have this choice, and my choice is to use it, and my software engineering is better because i make that choice. If it was useless, i wouldn't use it.

In D, I don't have that choice.

Nor do the millions of C++, C#, Java and Swift programmers.

I mean this is something you need to take seriously.

This is not an argument over bracing preferences.

This is an argument for, a programming language to provide proper support for strongly typed abstract objects. That's all there is to this. All the other nonsense in these threads, is just distracting noise to confuse people, and to ensure they never get to make that choice, in D.

June 23, 2022
On Thursday, 23 June 2022 at 03:10:46 UTC, Mike Parker wrote:
> On Thursday, 23 June 2022 at 01:45:22 UTC, Paul Backus wrote:
>
>> Your proposal would lead to the following situation:
>>
>>     struct EvenNumber
>>     {
>>         private int n;
>>         invariant (n & 1 == 0);
>>
>>         this(int n) { this.n = n; }
>>
>>         void addTwoMethod() { this.n++; this.n++; } // ok
>>     }
>>
>>     void addTwoUFCS(ref EvenNumber this_)
>>     {
>>         this_.n++; this_.n++; // error - violates invariant
>>     }
>
> I could live with that particular inconsistency. The bigger downside I see is that you'd potentially have multiple invariant checks for the same class on a single function call. And whether that's acceptable depends on how common this is in practice.
>
>>
>> IMO the correct way to view this is that code in the same module as a class is part of the class's implementation, just as much as code in the actual class body. (Or if you prefer, they are both part of the module's implementation, since the module is the fundamental unit of decomposition here, not the class.)
>>
>
> As long as the invariant checks only run on those functions that actually touch a private member. There would potentially be checks for multiple classes running before and after each function call, so doing it on every function call in the module is overkill.
>
> And that would also have to include any public member functions of any classes that access any private members of other classes in the same module. It seems more complex to implement than just doing a rewrite to getters/setters.
>
> An even simpler option would be to disallow access to any private members in a module on classes that have invariants. Not something I'd advocate, but a possibility.


Another idea would be to force the programmer to specify _when_ the invariant checks happen. :
```
     struct EvenNumber
     {
         private int n;
         invariant (n & 1 == 0);

         this(int n) { this.n = n; }

         void addTwoMethod() { this.n++; this.n++; } // ok
     }

     void addTwoUFCS(ref EvenNumber this_)
     {
         invariant(enter) { // invariant is checked here
            this_.n++; this_.n++;
         }

         invariant(exit) {
            this_.n++; this_.n++;
         } // invariant is checked here

         invariant(access) {
            this_.n++; // invariant is checked here
            this_.n++; // invariant is checked here
         }
     }
```
June 23, 2022
On Thursday, 23 June 2022 at 10:34:50 UTC, Alexandru Ermicioi wrote:
> On Thursday, 23 June 2022 at 10:16:42 UTC, forkit wrote:
>>
>> Coding style?
>>
>> Ummm .. no.
>>
>> Why is it, that some people ***still*** don't get it.
>
> I think that all people here get it. They don't agree on making an elephant out of mosquito.

But it is an elehpant, not a mosquito.

That's the point I've been trying to make - which it seems, is still not getting across to some.