December 24, 2012
On 12/23/2012 4:03 AM, "Jérôme M. Berger" wrote:
> 	Because C++ *can* hide symbols from other modules with the
> anonymous namespace. D has no equivalent.

Everyone here has raised some good points. But this isn't a simple issue, so I suggest getting together and preparing a DIP. A DIP should address:

1. what access means at module scope
2. at class scope
3. at template mixin scope
4. backwards compatibility
5. overloading at each scope level and the interactions with access
6. I'd also throw in getting rid of the "protected" access attribute completely, as I've seen debate over that being a useless idea
7. there's also some debate about what "package" should mean

I.e. it should be a fairly comprehensive design addressing access, not just one aspect of it.

December 24, 2012
On Sunday, December 23, 2012 16:11:02 Walter Bright wrote:
> 6. I'd also throw in getting rid of the "protected" access attribute completely, as I've seen debate over that being a useless idea

Really? I'm shocked at that. It's necessary for stuff like NVI if private functions aren't virtual as well as any other case where you need to override internal functionality in derived classes.

> 7. there's also some debate about what "package" should mean
> 
> I.e. it should be a fairly comprehensive design addressing access, not just one aspect of it.

Sounds like a good idea.

- Jonathan M Davis
December 24, 2012
On 12/23/12 04:02, Jonathan M Davis wrote:
> In addition, in my experience, it's quite rare for classes to have public and
> private functions with the same name, meaning that you just don't hit this
> problem very often.

Having public and private constructors is a common idiom.
December 24, 2012
On 12/23/12 03:35, Walter Bright wrote:
> On 12/22/2012 8:03 AM, Andrei Alexandrescu wrote:
>> I think this is a fallacious argument because it concludes that apples
>> should be
>> peeled because oranges should.
>
> Given, in C++:
>
> struct S
> {
>    public:
>       void foo(int);
>    private:
>       void foo(float);
> }
>
> void bar()
> {
>      S s;
>      s.foo(1.0f);
> }
>
> This is an error in C++:

Yeah, and it must stay one for D overload sets too.
In my pull request I always used the most accessible protection for the visibility of an overload set without removing the access check after overload resolution.

http://dlang.org/hijack.html
https://github.com/D-Programming-Language/dmd/pull/739

December 24, 2012
On Monday, December 24, 2012 06:20:04 Martin Nowak wrote:
> On 12/23/12 03:35, Walter Bright wrote:
> > On 12/22/2012 8:03 AM, Andrei Alexandrescu wrote:
> >> I think this is a fallacious argument because it concludes that apples
> >> should be
> >> peeled because oranges should.
> > 
> > Given, in C++:
> > 
> > struct S
> > {
> > 
> >    public:
> >       void foo(int);
> > 
> >    private:
> >       void foo(float);
> > 
> > }
> > 
> > void bar()
> > {
> > 
> >      S s;
> >      s.foo(1.0f);
> > 
> > }
> 
> > This is an error in C++:
> Yeah, and it must stay one for D overload sets too.
> In my pull request I always used the most accessible protection for the
> visibility of an overload set without removing the access check after
> overload resolution.
> 
> http://dlang.org/hijack.html https://github.com/D-Programming-Language/dmd/pull/739

How is it hijacking if one of the overloads is private? It wouldn't even end up in the documentation. No one else would even know that the function existed unless they read the source code. I see _zero_ problem with making this use the public version, and it won't break any code in doing so, because it'll make _more_ code compile, not less.

Also, making the compiler take the most accessible function is _wrong_. In the example above, if bar were in the same module as S, it would then call the public foo, whereas if it were in another module, you'd get an error (assuming that inaccessible functions are still kept in overload sets). If multiple overloads of a function are accessible and they conflict, then they should conflict. It's definitely hijacking if you just grab the most accessible one.

So, unless I've misunderstood what you're suggesting, you're suggesting that the above code should continue to be broken out of fear of there being a hijacking issue (though I don't see how there could be one) but you've suggested _adding_ a hijacking issue by simply grabbing the most accessible function. That sounds like a really bad idea.

I'd propose that all accessible functions be put into overload sets, that no inaccessible functions be put into any overload sets, and that accessibility not have anything to do with overloading beyond that (so which function in the overload sets wins has _nothing_ to do with accessibility). And that's what most of us have been asking for. I find your stance to be very confusing.

- Jonathan M Davis
December 24, 2012
Andrei Alexandrescu:

Sorry for the late reply.

> I think this is a reframing we should shun because it switches the focus from "what is the usefulness of this" to "what is the difficulty of putting up with it".

Jonathan was (rightfully) presenting the implementation problems, so I have had the right to answer to those. I agree with you that the absence of implementation problems can't justify the introduction of a feature, but the presence of implementation problems can decrease the appealing of a new feature. So talking about implementation problems in such discussions is legitimate.


> The point here is demonstrating how helpful the feature is in writing good quality code.

Right. And unfortunately it's not easy to do.


> In my time I've seen this warning helping here and there, but I'd be hard pressed to convince myself or someone that it really adds value. It's one of the most frequent _innocuous_ warnings I see in third-party software when I compile it.

By itself the presence of such warning does not denote a bug. On the other hand in my C code sometimes I have put some variables that later I have forgotten to use. Such GCC warning has probably avoided me some mistakes. So I appreciate such warning in D too.


> Furthermore, I just googled ``go unused variables'' and guess what the first entry was: https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/OBsCksYHPG4

The situation is not exactly the same. This part of the discussion was about a warning (or two warnings, one for unused variables and one for unused last assignment to variables), while in Go that's an error and it can't be disabled.

I agree that in some cases, while you are writing the code, you sometimes want to introduce temporary debugging variables, that may or may not be really used. In such case you don't enable those warning(s). You enable them a little later when you polish the code.

Bye,
bearophile
December 24, 2012
On Sunday, December 23, 2012 23:41:35 Jonathan M Davis wrote:
> Also, making the compiler take the most accessible function is _wrong_. In the example above, if bar were in the same module as S, it would then call the public foo, whereas if it were in another module, you'd get an error (assuming that inaccessible functions are still kept in overload sets). If multiple overloads of a function are accessible and they conflict, then they should conflict. It's definitely hijacking if you just grab the most accessible one.

Okay. I didn't think that through enough. This analysis of the example is wrong. Rather, what would happen if the most accessible overload is taken first (as you (Martin) seem to be suggesting), then the private version would never be called, as the public one would win out, which _is_ very broken. And I wouldn't think that you'd be suggesting something that broken, so I must be misunderstanding what you're suggesting.

I don't think that accessibility should enter into function overloading at all beyond the fact that inaccessible functions are left out of overload sets.

- Jonathan M Davis
December 24, 2012
On 2012-12-24 01:11, Walter Bright wrote:

> 1. what access means at module scope
> 2. at class scope
> 3. at template mixin scope
> 4. backwards compatibility
> 5. overloading at each scope level and the interactions with access
> 6. I'd also throw in getting rid of the "protected" access attribute
> completely, as I've seen debate over that being a useless idea
> 7. there's also some debate about what "package" should mean

I also want to add:

8. Investigate the usefulness and possibility to combine multiple access attributes for more fine grained control, i.e. using "package" and "protected" on a single declaration

-- 
/Jacob Carlborg
December 24, 2012
Jonathan M Davis wrote:
> The plan is to have a lexer and parser for D in the standard library, which would greatly simplify creating tools that did this sort of thing. We'd probably already have the lexer portion (I was working on it earlier this year), but I got insanely busy in real life. I'm hoping to get back to it fairly soon here though.

Yeah, Compiler (or at least lexer/parser) as a library is definitely something I'm look forward to -- it opens up so many possibilities, not only for lints...
December 24, 2012
On Monday, December 24, 2012 12:20:35 Jacob Carlborg wrote:
> On 2012-12-24 01:11, Walter Bright wrote:
> > 1. what access means at module scope
> > 2. at class scope
> > 3. at template mixin scope
> > 4. backwards compatibility
> > 5. overloading at each scope level and the interactions with access
> > 6. I'd also throw in getting rid of the "protected" access attribute
> > completely, as I've seen debate over that being a useless idea
> > 7. there's also some debate about what "package" should mean
> 
> I also want to add:
> 
> 8. Investigate the usefulness and possibility to combine multiple access attributes for more fine grained control, i.e. using "package" and "protected" on a single declaration

I believe that C# did something similar. It would certainly solve the question of package's virtuality quite nicely and wouldn't change any existing code, just allow for those who want virtual package functions to have them.

- Jonathan M Davis