November 01, 2018
On Thursday, 1 November 2018 at 14:17:13 UTC, Atila Neves wrote:
> On Monday, 29 October 2018 at 23:15:58 UTC, unprotected-entity wrote:
>> On Monday, 29 October 2018 at 15:50:56 UTC, Jonathan M Davis wrote:
>>>
>> It's not (just) that I don't like it, it's that I don't like not giving the programmer the tool to better encapsulate their code (specifically classes) *within* a module.
>
> You don't need to protect code in your module from other code in your module. If you do, put them in different modules.
That typically involves creation of files, which is not always ideal if you are working with code that is considerably small.

November 01, 2018
On Thu, Nov 01, 2018 at 04:19:57PM +0000, 12345swordy via Digitalmars-d wrote:
> On Thursday, 1 November 2018 at 14:17:13 UTC, Atila Neves wrote:
> > On Monday, 29 October 2018 at 23:15:58 UTC, unprotected-entity wrote:
> > > On Monday, 29 October 2018 at 15:50:56 UTC, Jonathan M Davis wrote: It's not (just) that I don't like it, it's that I don't like not giving the programmer the tool to better encapsulate their code (specifically classes) *within* a module.
> > 
> > You don't need to protect code in your module from other code in your module. If you do, put them in different modules.
>
> That typically involves creation of files, which is not always ideal if you are working with code that is considerably small.

Java also enforces, by policy, the creation of a separate file for every public class.  This is no different.


T

-- 
Genius may have its limitations, but stupidity is not thus handicapped. -- Elbert Hubbard
November 01, 2018
On Thursday, 1 November 2018 at 16:32:23 UTC, H. S. Teoh wrote:
> Java also enforces, by policy, the creation of a separate file for every public class.
So what? I thought this is D not Java.


November 01, 2018
On Thu, Nov 01, 2018 at 04:58:07PM +0000, 12345swordy via Digitalmars-d wrote:
> On Thursday, 1 November 2018 at 16:32:23 UTC, H. S. Teoh wrote:
> > Java also enforces, by policy, the creation of a separate file for every public class.
> So what? I thought this is D not Java.
[...]

Yes, and I'm glad I can (mostly) get away from Java in my current Android project, thanks to cross-compiling with LDC. :-P

But the point is that it's not all that onerous to have the file/module as the unit of encapsulation. It's not as if your modern filesystem would die or suffer severe performance problems if you have a couple of extra files in your source tree.  And any competent IDE / code editor / build system should have no problems dealing with an extra file or two, so I'm not sure I understand why this is such a big hangup for you.

Code in a module should be written to work nicely with each other in the first place, and doesn't need to be protected from each other.  If they do, then just put them in separate files, job done.

And if for whatever reason you absolutely MUST have everything in a single file yet insulated from each other, there's always the option of pre-processing your code with an external tool to split them up into temporary separate files and compile those instead of the file you edit, then you can have your cake and eat it too -- it will literally not compile if the code tries to call something it's not "supposed" to.

(Yes, I have no qualms about preprocessing / auto-generating code, even D code, in my projects. In my current project I have two .d files that are auto-generated from external data. I *could* have done it in CTFE with mixins, but that would consume a boatload more of RAM and slow down compilation by an order of magnitude, so it's just back to the trusty old writefln to print D code from a utility program and then compile the result.  Abstract all of that away in your build script, and you won't even notice it afterwards.  And if your build system can't reliably handle something like this, you need a new build system.)


T

-- 
Time flies like an arrow. Fruit flies like a banana.
November 01, 2018
On Thursday, 1 November 2018 at 16:19:57 UTC, 12345swordy wrote:
> On Thursday, 1 November 2018 at 14:17:13 UTC, Atila Neves wrote:
>> On Monday, 29 October 2018 at 23:15:58 UTC, unprotected-entity wrote:
>>> On Monday, 29 October 2018 at 15:50:56 UTC, Jonathan M Davis wrote:
>>>>
>>> It's not (just) that I don't like it, it's that I don't like not giving the programmer the tool to better encapsulate their code (specifically classes) *within* a module.
>>
>> You don't need to protect code in your module from other code in your module. If you do, put them in different modules.
> That typically involves creation of files, which is not always ideal if you are working with code that is considerably small.

If the code is considerably small you don't need private. You don't need any good engineering principles at all, use goto to your heart's content. It just doesn't matter.

That makes as much sense to me as introducing a keyword to protect a class from itself.

November 01, 2018
On 11/1/18 10:29 AM, Atila Neves wrote:
> On Wednesday, 31 October 2018 at 20:46:05 UTC, Zot wrote:
>> On Monday, 29 October 2018 at 09:25:07 UTC, unprotected-entity wrote:
>>> Just how often does one need to access the private members of a class, within a module?
>>
>> a lot actually. e.g. unittests
> 
> Unit tests should go through the public interface like anyone else. All private members and functions are implementation details that shouldn't matter and shouldn't break any tests if they're all removed.

So... don't test private functions? I do all the time. I want to test every single function I can.

I also look at internals, especially when I find bugs about them that can be caught with a peek at internal data.

Perhaps the internals implement some protocol, and you want to check it's in the right state part-way through a transaction.

However, I would *love* to be able to specify unit tests that *can't* access private internals for testing purposes. IIRC, it was proposed at some point to require this for documented unittests.

-Steve
November 01, 2018
On 11/1/18 10:28 AM, Atila Neves wrote:
> On Tuesday, 30 October 2018 at 08:18:57 UTC, Bastiaan Veelo wrote:
>> On Tuesday, 30 October 2018 at 00:01:18 UTC, unprotected-entity wrote:
>>> On Monday, 29 October 2018 at 22:24:22 UTC, Bastiaan Veelo wrote:
>>>>
>>>> I hear you and understand you, but personally I still prefer the D spec as it is in this regard, except for the confusing aspect that you shouldn’t `alias this` a private member; but that is rather a limitation of alias, not of encapsulation.
>>>>
>>>
>>> If your were sitting on a plane that was running the following D code, you might think differently ;-)
>>>
>>> --------
>>> class Plane
>>> {
>>>     private static int MAX_SPEED = 1000;
>>>
>>>     public void change_max_speed(int speed)
>>>     {
>>>         if(speed >= 1000)
>>>             MAX_SPEED = speed;
>>>     }
>>>
>>> }
>>>
>>> immutable Plane p = new Plane();
>>>
>>> // god no! why aren't you using the public interface of the class for this!
>>> void SetMaxSpeed() { p.MAX_SPEED = -1; }
>>>
>>> void Bar() { SetMaxSpeed(); } // mmm...trouble is about to begin...
>>>
>>> void main()
>>> {
>>>     import std.stdio;
>>>
>>>     Bar(); // oohps. thanks D module. we're all going to die!
>>>
>>>     // by the time you see this, it's too late for you, and your passengers.
>>>     writeln(p.MAX_SPEED);
>>>
>>> };
>>>
>>>
>>> -------
>>
>> :-) Why is MAX_SPEED mutable or even a runtime value, let alone signed?
> 
> Strictly my opinion below, but I believe wholeheartedly in this:
> 
> Using unsigned integers for anything except bit patterns and talking to hardware is an open invitation to bugs. The C++ community has recognised this and admitted that using size_t everywhere in the STL was a mistake.
> 
> "Ah, but I want type safety!". Uh-huh:
> 
> -----------------
> int[] ints;
> // indexing uses size_t, but...
> auto i = ints[-1];  // look ma, no errors or warnings!
> -----------------

It should throw an error, but actually, negative indexing is allowed in D or C, just on pointers only. And thanks to 2s complement math, it actually does index the right value.

Not saying this is preferable or good, just that it works, and does exactly what it should do, and what you expect it to do.

Where one generally gets into trouble is not specifying a negative number where an unsigned one is expected, but when one is comparing signed and unsigned numbers. The implicit casting definitely can make things more confusing than necessary. It's why I generally will avoid negative numbers in comparisons as much as possible. I.e. instead of if(x - 5 > y), I'll do if(x > y + 5).

> The problem in D and C++ is that they inherit behaviour from C, and in this case the important part of that inheritance is that integers of different types convert implicitly to each other. There is *no* type-safety when using unsigned integers. And because bit-patterns and actual integers share the same type now, people will invariably do something "they're not supposed to" and perform arithmetic with these values and usually wrap around. It's not pretty and it's not fun to debug.

I can see both sides. For instance Swift strictly forbids using signed to unsigned implicit casts, and the result is quite verbose. I write lots of code to find I have to add in lots of `bitPattern` and `truncatingBitPattern` etc. for things that are trivially obviously correct.

I find you develop a kind of numbness to it, where you reflexively add in your conversions without thinking about the consequences -- and you end up in the same place with worse-looking code.

-Steve
November 01, 2018
On Thursday, 1 November 2018 at 17:58:34 UTC, Atila Neves wrote:
> On Thursday, 1 November 2018 at 16:19:57 UTC, 12345swordy wrote:
>> On Thursday, 1 November 2018 at 14:17:13 UTC, Atila Neves wrote:
>>> On Monday, 29 October 2018 at 23:15:58 UTC, unprotected-entity wrote:
>>>> On Monday, 29 October 2018 at 15:50:56 UTC, Jonathan M Davis wrote:
>>>>>
>>>> It's not (just) that I don't like it, it's that I don't like not giving the programmer the tool to better encapsulate their code (specifically classes) *within* a module.
>>>
>>> You don't need to protect code in your module from other code in your module. If you do, put them in different modules.
>> That typically involves creation of files, which is not always ideal if you are working with code that is considerably small.
>
> If the code is considerably small you don't need private. You don't need any good engineering principles at all, use goto to your heart's content. It just doesn't matter.
Not the point. We talking about encapsulating code which involves creation of another modules which always involved in creation of another file. Which is not always good solution if your code is remarkably small.

> That makes as much sense to me as introducing a keyword to protect a class from itself.
It the equivalent of building another house to give your new child its own room, when you can simply assign a room in the house that you already have.


November 01, 2018
On Thursday, 1 November 2018 at 17:14:51 UTC, H. S. Teoh wrote:
> On Thu, Nov 01, 2018 at 04:58:07PM +0000, 12345swordy via Digitalmars-d wrote:
>> [...]
> [...]
>
> Yes, and I'm glad I can (mostly) get away from Java in my current Android project, thanks to cross-compiling with LDC. :-P
>
> [...]

I don't mind creating a tool to automatically copy past code in it's own module. Though I rather use attributes and create compile time instructions for it, but that is venturing into macro territory and we all know how difficult that is to persuade the two into accepting it.
November 01, 2018
On Thursday, 1 November 2018 at 14:28:27 UTC, Atila Neves wrote:
> On Tuesday, 30 October 2018 at 08:18:57 UTC, Bastiaan Veelo wrote:
>> On Tuesday, 30 October 2018 at 00:01:18 UTC, unprotected-entity wrote:
>>> On Monday, 29 October 2018 at 22:24:22 UTC, Bastiaan Veelo wrote:
>>>>
>>>> I hear you and understand you, but personally I still prefer the D spec as it is in this regard, except for the confusing aspect that you shouldn’t `alias this` a private member; but that is rather a limitation of alias, not of encapsulation.
>>>>
>>>
>>> If your were sitting on a plane that was running the following D code, you might think differently ;-)
>>>
>>> --------
>>> class Plane
>>> {
>>>     private static int MAX_SPEED = 1000;
>>>
>>>     public void change_max_speed(int speed)
>>>     {
>>>         if(speed >= 1000)
>>>             MAX_SPEED = speed;
>>>     }
>>>
>>> }
>>>
>>> immutable Plane p = new Plane();
>>>
>>> // god no! why aren't you using the public interface of the class for this!
>>> void SetMaxSpeed() { p.MAX_SPEED = -1; }
>>>
>>> void Bar() { SetMaxSpeed(); } // mmm...trouble is about to begin...
>>>
>>> void main()
>>> {
>>>     import std.stdio;
>>>
>>>     Bar(); // oohps. thanks D module. we're all going to die!
>>>
>>>     // by the time you see this, it's too late for you, and your passengers.
>>>     writeln(p.MAX_SPEED);
>>>
>>> };
>>>
>>>
>>> -------
>>
>> :-) Why is MAX_SPEED mutable or even a runtime value, let alone signed?
>
> Strictly my opinion below, but I believe wholeheartedly in this:
>
> Using unsigned integers for anything except bit patterns and talking to hardware is an open invitation to bugs. The C++ community has recognised this and admitted that using size_t everywhere in the STL was a mistake.
>
> "Ah, but I want type safety!". Uh-huh:
>
> -----------------
> int[] ints;
> // indexing uses size_t, but...
> auto i = ints[-1];  // look ma, no errors or warnings!
> -----------------
>
> The problem in D and C++ is that they inherit behaviour from C, and in this case the important part of that inheritance is that integers of different types convert implicitly to each other. There is *no* type-safety when using unsigned integers. And because bit-patterns and actual integers share the same type now, people will invariably do something "they're not supposed to" and perform arithmetic with these values and usually wrap around. It's not pretty and it's not fun to debug.
>
> I have literally lost count of how many bugs I've had to fix due to unsigned integers. `long` is large enough for anything you need, as Java has shown for 2 decades now.
>
> Friends don't let friends use unsigned types for counting.

My experience is exactly the opposite. I inherited a code base of ~200K lines of C written over 3 decades by several developers of varying skills. You can not imagine how many bugs I found thanks to replacing int and long by size_t and uint32_t/uint64_t.

int i = 0;
ints[--i];  // look ma, no errors or warnings! indeed

with size_t i at least you get segfault or a bus error.

The worst offense is using int on 64 bit machines when working on big datasets, overflows are really more common than people expect.

When using unsigned, it requires indeed to be careful when interacting with other variable, but since when is sloppiness a virtue?
The thing is, all the code that used int as a default was code that was not thought through concerning the range of values and limits of the used variables.