November 10, 2005
Regan Heath wrote:
> On Thu, 10 Nov 2005 02:34:36 +0200, Jari-Matti Mäkelä  <jmjmak@invalid_utu.fi> wrote:
> 
>> Regan Heath wrote:
>>
>>> So, does Java have something like "friend" in C++? Does a class ever  gain  access to another classes 'private' data? If so, how? If not, why  has it  never been required? (as it was in C++? debatable?)
>>
>>
>> Yes, all classes in the same package (Java package = D module) share  their private data. This is no problem (unless you run out of inodes ;))  since all non-friendly classes can be split into separate packages.
> 
> 
> Ahh, so that works like it does in D... only D calls them modules to  Java's packages and D have another thing called a "package" and a  protection attribute for that too.
> 
Actually it's a bit more complex. Although packages in Java have many similarities with the modules in D, Java packages are physically (file system) like D packages. Actually Java packages may consist of multiple source files. Confusing, eh?
November 10, 2005
Tomás Rossi wrote:
> I agree, but i think i understood what Regan was trying to explain. Suppose you
> have something like this:
> 
> --------------------------------------------------------------
> module some_module;
> 
> class A { protected char[] name="class A"; } // Base class.
> class B : A { public this() { name="class B"; } // Derived.
> class C : A { public this() { name="class C"; } // Derived.
> 
> // Don't wanna let X gain access to protected member 'name' nor to any
> // other member of A, B or C that is not public, etc.
> class X { ... bla bla bla ... }
> --------------------------------------------------------------
> 
> Clearly, if you want to let 'B' and 'C' gain access to 'name', you cannot
> declare it 'local' you'll have rather declare it 'protected'. But this will
> leave it visible to the other classes of the module.

Why do you have to keep the class X in the same module with classes A,B and C? It seems to me that class X is definitely not a friend class of any of the first three. You can minimize the abuse of D modules by doing:

module some_module;

class A { protected char[] name="class A"; } // Base class.
class B : A { public this() { name="class B"; } // Derived.
class C : A { public this() { name="class C"; } // Derived.

module x_module;
class X { ... bla bla bla ... }
November 10, 2005
Regan Heath wrote:
> On Thu, 10 Nov 2005 08:53:50 +1100, Derek Parnell <derek@psych.ward> wrote:
> 
>> On Thu, 10 Nov 2005 10:13:00 +1300, Regan Heath wrote:
>>
>>> On Wed, 9 Nov 2005 16:41:55 +1100, Derek Parnell <derek@psych.ward>  wrote:
>>>
>>>> I think I'd prefer a new protection attribute to limit scope to within  a
>>>> class or struct. Something like ...
>>>>
>>>>  class Aux
>>>>  {
>>>>  local:
>>>>  static int invisible_outside_class = 8;
>>>>  private:
>>>>  static int n = 5;
>>>>  static float f = 3.14;
>>>>  }
>>>>
>>>> And even rename "private" to "module" to make it more clear as to its
>>>> scope.
>>>
>>>
>>> I think to make changes you first have to remove the "constantly in
>>> effect" module-friend-public access which is applied, this effect  modifies
>>> all the existing protection attributes, making them all "public" for  code
>>> in the same module.
>>>
>>> Once removed "private", "protected", and of course "public" would have  the
>>> same meaning as in C++. Then, you could add "module" which would be
>>> "private" for code exterior to this module and "public" for code within
>>> the module. This would be the least confusing for a C++ developer coming
>>> to D I believe.
>>>
>>> But, the problem with this idea is that it isn't flexible enough. Say  you
>>> have a class:
>>>
>>> class Foo
>>> {
>>>    private int a;
>>>    protected int b;
>>>    public int c;
>>> }
>>>
>>> and you need access to 'b' in this module? you can't use "module" as  that
>>> makes it "private" outside the module, not "protected". So, the next
>>> logical step is to make "module" a modifier for the other 3 protection
>>> attributes.
>>>
>>> That eventuality is worse than the C++ "friend" situation I feel, it  does
>>> give more fine grained control but it's more verbose and fiddly as a
>>> result. In comparison the current D way is less fine grained but also  much
>>> easier to use.
>>
>>
>> Huh? You seem to be trying to complicate this to make it look silly.I  disagree that one needs to do all the twisting and mashing of keywords  and concepts you just described.
>> Simply leave everything as it is now, and add a "local" attribute to
>> designate those members whose scope is only the enclosing class/struct.
>> That's it! You then get all the benefits of current D philosophy plus the
>> added concept of reduced bonding amongst class in the same module.
> 
> 
> If your intention is to stop confusing C++ developers then this isn't  going to work IMO. They're going to continue to use "private" and expect  C++ behaviour. Sure, now they have "local" to achieve C++ private, but the  problem remains how do they get C++ protected within a module?

I think the C++ -users are fully able to RTFM whenever they need some guidance. To simplify the D visibility keywords, I've created some nice charts [1] based on [2]. You don't need a local-keyword since you can limit the visibility of private members using the module system (actually this requires Walter to fix the pending visibility bug)

[1] http://users.utu.fi/jmjmak/d/
[2] http://www.digitalmars.com/d/attribute.html
November 10, 2005
On Thu, 10 Nov 2005 13:09:33 +1300, Regan Heath wrote:


[snip]
> If your intention is to stop confusing C++ developers then this isn't going to work IMO.

LOL! You are very correct, but I'm not regarding C++ coders as a "protected" species. My position is that if you want to learn a new language then learn it, and don't expect it to be the same as what you already know. So I don't care if some C++ coders find it hard to adapt to a new language. I realize that Walter and most others here are not of this opinion.

> They're going to continue to use "private" and expect C++ behaviour.

Are you implying that C++ coders innately find it hard to learn new languages? ;-)

>Sure, now they have "local" to achieve C++ private, but the
> problem remains how do they get C++ protected within a module?

I haven't really talked about 'protected' behaviour, just lexical scope so far. I'm not sure that I see 'private' and 'protected' as mutually exclusive. One deals with lexical scope and the other deals with inheritance scope. Is there any reason (conceptually) why a member cannot have both attributes? That is, a member could be designated as invisible outside the module *and* invisible to derived classes. I know that's not how D works now, but I'm talking conceptually.

> If your suggestion is just an idea to get C++ private behaviour and to get it with a _different_ keyword, fine, I just see no merit in that, personally.

Repeat after me ... D is not C++ ... D is not Java ... D is not C++ ... D is not Java ... D is not C++ ... D is not Java ... <G>

> My suggestion was based on the way I see the D system working, in my opinion "private" etc work exactly how they work in C++ _except_ there is a blanket effect "friend" for all code within a module. You can make it the same as C++ by removing that blanket effect.
> 
> Your suggestion creates an exception to the blanket effect, one that is essentially "private" minus the blanket effect.
> 
> That is how I see it operating, perhaps you see it differently?

Conceptually, without prejudice to any specific keyword, I see lexical scoping thusly ...

  (A)  Limited to enclosing block.
  (B)  Limited to enclosing container, i.e. class or struct.
  (C)  Limited to enclosing file, i.e. module.
  (D)  Limited to enclosing directory, i.e. package.
  (E)  Limited to enclosing application, i.e. the executable.
  (F)  Not limited to anything.

Currently the D language supports all but (B).

Now another type of scoping, which is orthogonal to the above, is inheritance scoping. This is just see as making a member 'visible' to derived classes or not.

>>> The current D way offers no less control than "friend" in C++ but it offers it in a different way, instead of adding friend to a class you place it in the same module.

I do find D's restriction that a module is the same as a source file is a problem. If somehow you could have multiple files comprise a single module then the 'friend' concept might be easier to implement.

>> Yes, exactly. And that is the problem. It forces one to place 'friend' classes into the same module, but by doing that one also increases the cost of maintenance by implicitly increasing the binding between such classes.
> 
> Explain how it "implicitly increas(es) the binding between such classes"?

If you have two classes in the same file, then all the code in either class can see all the members in the other class, implicitly. You don't have to make them explicitly visible to each other. (Not sure how nested/inner classes effect this).

> I am assuming here we're comparing 2 C++ friend classes and 2 D classes in the same module, how is the D method "increased binding"?

It doesn't increase it in D more than in C++. The increase is the same in both languages. I'm not comparing C++ with D here. The increase I'm talking about is just there because the class members are there.

For example, imagine that I have a file with one class. I later come along an add another class to the same file. Currently, just be doing that, I bind (conceptually) the two classes together because each can see the internals of the other. However, further imagine that the default behaviour was that each class in a module does *not* expose its internals to other classes in the module. In that case, the classes are not bound to each other. If you then explicitly exposes selected members, you can control the limits of the binding, and thus control maintenance concerns.

>Further, how
> does it increase the cost of maintenance?

The computer science literature has for many years noted that 'module' binding is proportional to the complexity of the code. If you reduce the bindings you reduce the complexity, and reducing complexity can reduce maintenance costs.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
10/11/2005 11:38:51 AM
November 10, 2005
In article <opszz0bk0623k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>On Wed, 9 Nov 2005 21:50:19 +0000 (UTC), Tomás Rossi <Tomás_member@pathlink.com> wrote:
>> In article <opszzrvyj923k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>> The current D way offers no less control than "friend" in C++ but it offers it in a different way, instead of adding friend to a class you place it in the same module.
>>
>> What about if you have no access to the module source where lies the
>> class to
>> which you want your class to be friend with? (I know, my english sucks).
>
>It's pretty good, that sentence is going to be confusing no matter how you say it.
>
>> The
>> friend approach gives you the advantage that you do not have to modify
>> the
>> source file of the class to which you want YOUR class to be friend (that
>> could
>> be a class not written by you or you may even just not have the source,
>> maybe
>> just the .obj or .lib (is this not possible?)).
>> Correct me if i'm wrong please.
>
>I admin I am no C++ nor "friend" expert, it was my understanding that friend operates like so:
>
>class A {
>   private static int a;
>   friend class B;
>};
>
>class B {
>   void foo() { a = 5; }
>};
>
>class A specifies the friend who is allowed to access the private int 'a' and modify it. Without access to class A you cannot become a friend and access it's private members.

For an example of what I mean, take a look of iostreams << and >> operator overloading. That was to what i was referring to.

Tom
November 10, 2005
In article <dku4mo$2p0o$1@digitaldaemon.com>, =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= says...
>
>Tomás Rossi wrote:
>>>I disagree. Private is a standard keyword in many oo-languages. You don't need these "local"-members anywhere.

Uh? Why are you so sure?

>>>The idea behind "friends" and D modules is not that you'll put all your classes in the same module.

UUHhh?! I thought that "friends" concept of D was to put all the "friend" classes in the same module. I don't know how to do it if not.

>>>If the classes are somehow internally related, you can have them in the same module, otherwise keep them in separate modules. That way there's no need the make things more complex than they really are.
>>>
>> I dont understand? How do you achieve "friend" behavior between two classes in different modules?
>Actually I think I'm not following your train of thought. You can't have both "local"- and "friend"-functionality at the same time.

I know and I didn't mean that.

>Friend-relationship means that the private members are accessible, this local-visibility seems the mean that the private members are inaccessible inside the "friend" class.

Local means: THAT MEMBER (the local one), can´t be accessed by another class in
the same module.

Regards

Hope you catched my train of thought this time :)

Tom
November 10, 2005
On Thu, 10 Nov 2005 12:06:02 +1100, Derek Parnell <derek@psych.ward> wrote:
> On Thu, 10 Nov 2005 13:09:33 +1300, Regan Heath wrote:
> [snip]
>> If your intention is to stop confusing C++ developers then this isn't
>> going to work IMO.
>
> LOL! You are very correct, but I'm not regarding C++ coders as a
> "protected" species. My position is that if you want to learn a new
> language then learn it, and don't expect it to be the same as what you
> already know. So I don't care if some C++ coders find it hard to adapt to a
> new language. I realize that Walter and most others here are not of this
> opinion.

Don't go putting me into a basket just yet!

The reason I mention C++ is not because I think we need to protect anyone, rather the OP is a C++ programmer (I believe) and mentioned they found the D system confusing, I quote:
  "I personally think that this behavior is useless and confusing."

Aside: Realistically, the easier D is to adopt, the more people will do it. The 2 or perhaps 3 big groups which could adopt are C++, Java and C# programmers.

>> Sure, now they have "local" to achieve C++ private, but the
>> problem remains how do they get C++ protected within a module?
>
> I haven't really talked about 'protected' behaviour, just lexical scope so far. I'm not sure that I see 'private' and 'protected' as mutually
> exclusive. One deals with lexical scope

I dont think it's "lexical" scope. The symbol is still visible outside that scope, access to it is simply prevented so it's more like "access" scope. If the symbol were not visible outside the scope you'd get a symbol not found error as opposed to the access denied style error you actually get.

> and the other deals with
> inheritance scope.

In both cases I believe it's "access" scope.

This is the reason applying private to a class definition doesn't work, I believe, because it is a slightly different concept, you're actually hiding something as opposed to restricting access to something which isn't actually hidden.

The D documentation does state that private replaces the C/C++ static, now, I believe static actually hides the variable, which in turn prevents access. I'm not sure D's private covers all of static yet.

> Is there any reason (conceptually) why a member cannot
> have both attributes? That is, a member could be designated as invisible
> outside the module *and* invisible to derived classes. I know that's not
> how D works now, but I'm talking conceptually.

Sure, but I think there is a difference between "invisible" and "inaccessable".

<snip>

>>>> The current D way offers no less control than "friend" in C++ but it
>>>> offers it in a different way, instead of adding friend to a class you
>>>> place it in the same module.
>
> I do find D's restriction that a module is the same as a source file is a
> problem. If somehow you could have multiple files comprise a single module then the 'friend' concept might be easier to implement.

This is a seperate topic, doesn't "package" help here?
(lets no take this further in this thread, it's large enough as is)

>>> Yes, exactly. And that is the problem. It forces one to place 'friend'
>>> classes into the same module, but by doing that one also increases the
>>> cost of maintenance by implicitly increasing the binding between such
>>> classes.
>>
>> Explain how it "implicitly increas(es) the binding between such classes"?
>
> If you have two classes in the same file, then all the code in either class can see all the members in the other class, implicitly.

Here is the root of the disagreement, IMO placing classes in the same module _is_ explicitly asking for them to be visible to each other, by definition.

> You don't have to
> make them explicitly visible to each other. (Not sure how nested/inner
> classes effect this).
>
>> I am assuming here we're comparing 2 C++ friend classes and 2 D classes in
>> the same module, how is the D method "increased binding"?
>
> It doesn't increase it in D more than in C++. The increase is the same in
> both languages. I'm not comparing C++ with D here. The increase I'm talking about is just there because the class members are there.
>
> For example, imagine that I have a file with one class. I later come along
> an add another class to the same file. Currently, just be doing that, I
> bind (conceptually) the two classes together because each can see the
> internals of the other.
> However, further imagine that the default behaviour
> was that each class in a module does *not* expose its internals to other
> classes in the module. In that case, the classes are not bound to each
> other. If you then explicitly exposes selected members, you can control the limits of the binding, and thus control maintenance concerns.
>
>> Further, how
>> does it increase the cost of maintenance?
>
> The computer science literature has for many years noted that 'module'
> binding is proportional to the complexity of the code. If you reduce the
> bindings you reduce the complexity, and reducing complexity can reduce
> maintenance costs.

What exactly are you comparing here? You seem to be comparing "classes bound by D's module system" with "classes not bound by D's module system". I think that comparison is pointless, aren't we assuming the binding is required in some case, and if so shouldn't we be comparing different methods to achieve that binding?

If so, aren't we comparing D's module method with C++'s "friend" method, Java's (just like D) package method and your suggested "local" method.

I've already shown how your suggestion lacks a solution for 'protected' members, and then I suggested a change (which you thought was overly complicated).

I prefer D's method for it's simplicity.

Regan
November 10, 2005
On Thu, 10 Nov 2005 01:48:56 +0000 (UTC), Tomás Rossi <Tomás_member@pathlink.com> wrote:
> In article <opszz0bk0623k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> On Wed, 9 Nov 2005 21:50:19 +0000 (UTC), Tomás Rossi
>> <Tomás_member@pathlink.com> wrote:
>>> In article <opszzrvyj923k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>> The current D way offers no less control than "friend" in C++ but it
>>>> offers it in a different way, instead of adding friend to a class you
>>>> place it in the same module.
>>>
>>> What about if you have no access to the module source where lies the
>>> class to
>>> which you want your class to be friend with? (I know, my english sucks).
>>
>> It's pretty good, that sentence is going to be confusing no matter how you
>> say it.
>>
>>> The
>>> friend approach gives you the advantage that you do not have to modify
>>> the
>>> source file of the class to which you want YOUR class to be friend (that
>>> could
>>> be a class not written by you or you may even just not have the source,
>>> maybe
>>> just the .obj or .lib (is this not possible?)).
>>> Correct me if i'm wrong please.
>>
>> I admin I am no C++ nor "friend" expert, it was my understanding that
>> friend operates like so:
>>
>> class A {
>>   private static int a;
>>   friend class B;
>> };
>>
>> class B {
>>   void foo() { a = 5; }
>> };
>>
>> class A specifies the friend who is allowed to access the private int 'a'
>> and modify it. Without access to class A you cannot become a friend and
>> access it's private members.
>
> For an example of what I mean, take a look of iostreams << and >> operator
> overloading. That was to what i was referring to.

Take a look at what? the source code? (I assume you mean C++'s iostreams << and >> operators)

I'm not that well versed in C++ (mostly a C programmer) so I haven't used these, nor do I know how they're constructed. Can you give a simplified example?

Regan
November 10, 2005
On Thu, 10 Nov 2005 03:05:20 +0200, Jari-Matti Mäkelä <jmjmak@invalid_utu.fi> wrote:
> Regan Heath wrote:
>> On Thu, 10 Nov 2005 08:53:50 +1100, Derek Parnell <derek@psych.ward> wrote:
>>
>>> On Thu, 10 Nov 2005 10:13:00 +1300, Regan Heath wrote:
>>>
>>>> On Wed, 9 Nov 2005 16:41:55 +1100, Derek Parnell <derek@psych.ward>  wrote:
>>>>
>>>>> I think I'd prefer a new protection attribute to limit scope to within  a
>>>>> class or struct. Something like ...
>>>>>
>>>>>  class Aux
>>>>>  {
>>>>>  local:
>>>>>  static int invisible_outside_class = 8;
>>>>>  private:
>>>>>  static int n = 5;
>>>>>  static float f = 3.14;
>>>>>  }
>>>>>
>>>>> And even rename "private" to "module" to make it more clear as to its
>>>>> scope.
>>>>
>>>>
>>>> I think to make changes you first have to remove the "constantly in
>>>> effect" module-friend-public access which is applied, this effect  modifies
>>>> all the existing protection attributes, making them all "public" for  code
>>>> in the same module.
>>>>
>>>> Once removed "private", "protected", and of course "public" would have  the
>>>> same meaning as in C++. Then, you could add "module" which would be
>>>> "private" for code exterior to this module and "public" for code within
>>>> the module. This would be the least confusing for a C++ developer coming
>>>> to D I believe.
>>>>
>>>> But, the problem with this idea is that it isn't flexible enough. Say  you
>>>> have a class:
>>>>
>>>> class Foo
>>>> {
>>>>    private int a;
>>>>    protected int b;
>>>>    public int c;
>>>> }
>>>>
>>>> and you need access to 'b' in this module? you can't use "module" as  that
>>>> makes it "private" outside the module, not "protected". So, the next
>>>> logical step is to make "module" a modifier for the other 3 protection
>>>> attributes.
>>>>
>>>> That eventuality is worse than the C++ "friend" situation I feel, it  does
>>>> give more fine grained control but it's more verbose and fiddly as a
>>>> result. In comparison the current D way is less fine grained but also  much
>>>> easier to use.
>>>
>>>
>>> Huh? You seem to be trying to complicate this to make it look silly.I  disagree that one needs to do all the twisting and mashing of keywords  and concepts you just described.
>>> Simply leave everything as it is now, and add a "local" attribute to
>>> designate those members whose scope is only the enclosing class/struct.
>>> That's it! You then get all the benefits of current D philosophy plus the
>>> added concept of reduced bonding amongst class in the same module.
>>   If your intention is to stop confusing C++ developers then this isn't  going to work IMO. They're going to continue to use "private" and expect  C++ behaviour. Sure, now they have "local" to achieve C++ private, but the  problem remains how do they get C++ protected within a module?
>
> I think the C++ -users are fully able to RTFM whenever they need some guidance.

Sure, but they will still have to rewire their brains to adopt the new system. To be clear I wasn't suggesting we change it, I was just re-working Derek's solution to be more useful (as I saw it).

> To simplify the D visibility keywords, I've created some nice charts [1] based on [2]. You don't need a local-keyword since you can limit the visibility of private members using the module system (actually this requires Walter to fix the pending visibility bug)
>
> [1] http://users.utu.fi/jmjmak/d/
> [2] http://www.digitalmars.com/d/attribute.html

I like it.

One point however. Is there a difference between "visible" and "accessable"? It seems "private" makes an instance (not a definition, yet?) "inaccessable" but not "invisible", this is shown by the sort of error message given when you try to access a "private" instance.

D's docs say that "private" replaces "static" but doesn't "static" actually make an instance or declaration "invisible" as opposed to simply making it "inaccessable", it seems "private" in D does not cover everything that "static" did and that is why we're arguing about it ;)

Regan


Regan
November 10, 2005
In article <dku5ps$2pp7$2@digitaldaemon.com>, =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= says...
>
>Tomás Rossi wrote:
>> I agree, but i think i understood what Regan was trying to explain. Suppose you have something like this:
>> 
>> --------------------------------------------------------------
>> module some_module;
>> 
>> class A { protected char[] name="class A"; } // Base class.
>> class B : A { public this() { name="class B"; } // Derived.
>> class C : A { public this() { name="class C"; } // Derived.
>> 
>> // Don't wanna let X gain access to protected member 'name' nor to any
>> // other member of A, B or C that is not public, etc.
>> class X { ... bla bla bla ... }
>> --------------------------------------------------------------
>> 
>> Clearly, if you want to let 'B' and 'C' gain access to 'name', you cannot declare it 'local' you'll have rather declare it 'protected'. But this will leave it visible to the other classes of the module.
>
>Why do you have to keep the class X in the same module with classes A,B and C? It seems to me that class X is definitely not a friend class of any of the first three.

I think no one could assure that X should (or shouldn't) be friend of A, B or C, because they are just generic examples and incomplete one´s as well. Meaningless objects wouldn't give you a clue for if they should be friends or not. Besides, this was not a piece of code to justify the "local" or "module" attribute proposal.

>You can minimize the abuse of D modules by doing:
>
>module some_module;
>
>class A { protected char[] name="class A"; } // Base class.
>class B : A { public this() { name="class B"; } // Derived.
>class C : A { public this() { name="class C"; } // Derived.
>
>module x_module;
>class X { ... bla bla bla ... }

This is a nice thing and was a good thing to mention.

Regards

Tom