December 22, 2012
On 12/21/2012 8:38 PM, Jonathan M Davis wrote:
>> The reason it is that way is to avoid having it behave gratuitously
>> differently than how visibility works within classes and structs.
>
> ??? I don't see anything here that would become different between user-defined
> types and modules.
>
> All we're really asking for here is that inaccessible symbols not be put in
> overload sets.

But they are in structs in classes (following the way C++ does it).

December 22, 2012
Jonathan M Davis:

> but generally the worst that they'll do is create slight
> overhead because of the cost of default initializing them.

I don't care about that overhead, because the optimizer stages of compilers take care of removing it in many cases, that's not one of the main points of spotting unused variables:
- Removing unused variables makes the code tidier and more clean.
- Unused variables are noise that makes harder to understand code and algorithms.
- And most importantly, unused variables (or assigned and never read) are sometimes things that the programmers has forgotten to initialize or use, so they are sometimes associated with bugs.


> _especially_ if that means jumping through hoops to get
> to not complain about legitimate unused variables.

Legitimate uses of unused variables are mostly in library code, or user code similar to library code. Adding to those variable definitions a @used is fast and perfectly easy. It's not a "jumping through hoops".

Bye,
bearophile
December 22, 2012
On Saturday, December 22, 2012 09:30:15 bearophile wrote:
> Jonathan M Davis:
> > but generally the worst that they'll do is create slight overhead because of the cost of default initializing them.
> 
> I don't care about that overhead, because the optimizer stages of
> compilers take care of removing it in many cases, that's not one
> of the main points of spotting unused variables:
> - Removing unused variables makes the code tidier and more clean.
> - Unused variables are noise that makes harder to understand code
> and algorithms.
> - And most importantly, unused variables (or assigned and never
> read) are sometimes things that the programmers has forgotten to
> initialize or use, so they are sometimes associated with bugs.
> 
> > _especially_ if that means jumping through hoops to get
> > to not complain about legitimate unused variables.
> 
> Legitimate uses of unused variables are mostly in library code, or user code similar to library code. Adding to those variable definitions a @used is fast and perfectly easy. It's not a "jumping through hoops".

It requires extra work, making that code messier just because you want the compiler to help you point out places in your code where you failed to clean it up correctly by removing unused variables. You're basically asking for a feature to be added to the language so that the compiler will be able to tell you where your code is messy without complaining about legitimate code, _and_ your suggestion would make the legitimate code messier.

I really don't think that it's the compiler's job to tell you whether you have messy code or not. It's the compiler's job to tell you whether you have errors in your code or not. It's the job of a lint-like tool to find stuff like that.

And once we have a lexer and parser for D in the standard library (which I really need to get back to soon; life keeps getting in the way), creating lint-like tools will be much easier, and you can go mess around with one of those to get it to complain about every stray thing that you want your program to be examined for which isn't actually a question of whether the code is valid D or not. Let the compiler complain about code validity and leave the rest to other tools. Not to mention, if you work on such a tool, you have full control over whatever stray things it complains about, so you'll be free to get to complain about whatever you want without having to worry about convincing Walter Bright.

- Jonathan M Davis
December 22, 2012
On Saturday, December 22, 2012 00:21:33 Walter Bright wrote:
> On 12/21/2012 11:23 PM, Jonathan M Davis wrote:
> > But we _want_ that. The fact that inaccessible functions are even considered in overload sets is horrible. That's precisely the problem. No inaccessible functions should be in overload sets. Otherwise, simply adding a private function to a module can break code elsewhere. I don't see _any_ benefit in having inaccessible functions be in overload sets. It's leaking implementation details outside of the scope that they're in and breaking code elsewhere when changes are made. What do you think is so desirable about having inaccessible functions in overload sets?
> 
> It's that way in C++ mainly so that it doesn't make the already complex overloading system even more so. And in 25 years of working with C++, I've never seen this make anyone's list of horrible things about C++.

C++ doesn't have module-level access modifiers or UFCS, so it's completely unaffected by this. In C++, you can't add functions to classes from the outside, so there's no concern about adding private functions to a class breaking code using that class. And you can't add a private function to a module, because there are neither modules nor private, free functions, so you aren't going to get breakage from adding a private function, because you can't add a private function. Either you add what is effectively a public function (though technically, it has no access modifier at all, since it's not part of a class) and risk breakage that way, or you create a function which is only in the cpp file. In D, on the other hand, you can add private functions to modules, and you don't normally have separate implementation files. So, the situation is completely different.

We created this problem by adding modules and making it so that that the functions in them have access levels. We have extra layers of encapsulation which just don't exist in C++, and we made them leaky, because we made it so that the private functions affect overload sets. So, the fac that C++ doesn't get these complaints is pretty much irrelevant. It doesn't have the features which make this a problem. And regardless of whether you get complaints about this in C++, there have been plenty of complaints around here about it in D.

Pretty much every time that this issue comes up, people are surprised by the fact that private symbols aren't hidden and pretty much no one wants them to be in overload sets. I think that you're the only one that I've seen post that they thought that the current behavior is a good idea (certainly, anyone who agrees with you is in the minority or is silent on the issue). What we currently have leaks implementation detalis and thus causes code breakage when the implementation is changed. It needs to be fixed.

- Jonathan M Davis
December 22, 2012
Jonathan M Davis:

> You're basically asking for a feature to be added to the
> language so that the compiler will be able to tell you where
> your code is messy without complaining about legitimate code,
> _and_ your suggestion would make the legitimate code messier.

Here you are right only in principle, but not in practice: in general legitimate uses of unused variables is not common, so the total amount of noise added is not large. And most of such legitimate uses are in library code, that is usually not seen by programmers.


> I really don't think that it's the compiler's job to tell you whether you have messy code or not. It's the compiler's job to
> tell you whether you have errors in your code or not.

I think it depends on the specific cases and the specific definitions of "messy". If I disallow code patterns like "(!x & y)", they are not always bugs, but they are often cases of "messy" code, that I think it's worth disallowing.

Bye,
bearophile
December 22, 2012
On Saturday, December 22, 2012 09:53:48 bearophile wrote:
> Jonathan M Davis:
> > You're basically asking for a feature to be added to the language so that the compiler will be able to tell you where your code is messy without complaining about legitimate code, _and_ your suggestion would make the legitimate code messier.
> 
> Here you are right only in principle, but not in practice: in general legitimate uses of unused variables is not common, so the total amount of noise added is not large. And most of such legitimate uses are in library code, that is usually not seen by programmers.

I think that it's clear that we're just going to disagree here. Conditional compilation has unused variables fairly often, and RAII always does. Also, generated code can end up with unused variables in some cases and not in others depending on how its instantiated, making having to worry about unused variables that much worse. And I don't agree at all that those sorts of things are uncommon.

Of course, I can't even remember the last time that I had an unused variable, so I don't know what you're doing differently in your code that you think that it's really a problem in the first place. Cleraly, if you run into them often, you're doing something differently than I am.

Regardless, trying to warn about unused variables _will_ create additional complication in the language, and I really don' think that that's the sort of thing that the compiler should be worrying about anyway. The compiler should be complaining about things that are unequivocably wrong, not things that _might_ be wrong. If it were up to me, I'd remove warnings from the compiler entirely. Walter has completely convinced me with regards to how bad an idea compiler warnings are.

- Jonathan M Davis
December 22, 2012
Walter Bright wrote:
> On 12/21/2012 11:23 PM, Jonathan M Davis wrote:
>> But we _want_ that. The fact that inaccessible functions are even
>> considered
>> in overload sets is horrible. That's precisely the problem. No
>> inaccessible
>> functions should be in overload sets. Otherwise, simply adding a private
>> function to a module can break code elsewhere. I don't see _any_
>> benefit in
>> having inaccessible functions be in overload sets. It's leaking
>> implementation
>> details outside of the scope that they're in and breaking code
>> elsewhere when
>> changes are made. What do you think is so desirable about having
>> inaccessible
>> functions in overload sets?
> 
> 
> It's that way in C++ mainly so that it doesn't make the already complex overloading system even more so. And in 25 years of working with C++, I've never seen this make anyone's list of horrible things about C++.
> 
	Actually, it is *not* that way in C++ for "module-private"
functions. I know that C++ doesn't have true "modules" and a
fortiori true "module-private" functions (or types or variables),
but the C++ equivalent of module-private is file static (or the
anonymous namespace) and those do *not* make it into the overload
set and cannot affect user code.

		Jerome
-- 
mailto:jeberger@free.fr
http://jeberger.free.fr
Jabber: jeberger@jabber.fr



December 22, 2012
12/22/2012 12:21 PM, Walter Bright пишет:
> On 12/21/2012 11:23 PM, Jonathan M Davis wrote:
>> But we _want_ that. The fact that inaccessible functions are even
>> considered
>> in overload sets is horrible. That's precisely the problem. No
>> inaccessible
>> functions should be in overload sets. Otherwise, simply adding a private
>> function to a module can break code elsewhere. I don't see _any_
>> benefit in
>> having inaccessible functions be in overload sets. It's leaking
>> implementation
>> details outside of the scope that they're in and breaking code
>> elsewhere when
>> changes are made. What do you think is so desirable about having
>> inaccessible
>> functions in overload sets?
>
>
> It's that way in C++ mainly so that it doesn't make the already complex
> overloading system even more so. And in 25 years of working with C++,
> I've never seen this make anyone's list of horrible things about C++.
>

I was afraid you'd say that. Again the way C++ "solves it" is by hiding stuff behind header files or (for templates) using horrible internal namespaces.

They don't have access modifiers at the global scope but namespaces were a tool to solve name collisions. In the end it's still relies on convention e.g. some namespaces are not meant to be accessed outside of specific files.

See e.g. Boost c++, as an example of code using this _workaround_ everywhere.

-- 
Dmitry Olshansky
December 22, 2012
On 12/22/2012 09:21 AM, Walter Bright wrote:
> On 12/21/2012 8:38 PM, Jonathan M Davis wrote:
>>> The reason it is that way is to avoid having it behave gratuitously
>>> differently than how visibility works within classes and structs.
>>
>> ??? I don't see anything here that would become different between
>> user-defined
>> types and modules.
>>
>> All we're really asking for here is that inaccessible symbols not be
>> put in
>> overload sets.
>
> But they are in structs in classes (following the way C++ does it).
>

Actually this is not really what I am asking for. Maybe some terminology got mixed up?

A solution that is simple to understand and does not complicate the implementation a lot is the following:

Mandatory:

When resolving imported symbols, and there is a clash, ignore all private ones.

Optional:

Disallow overloading symbols with different accessibilities against each other.

December 22, 2012
On 12/22/12 3:30 AM, bearophile wrote:
> Legitimate uses of unused variables are mostly in library code, or user
> code similar to library code. Adding to those variable definitions a
> @used is fast and perfectly easy. It's not a "jumping through hoops".

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".

The point here is demonstrating how helpful the feature is in writing good quality code. 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.

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


Andrei