www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - About Go, D module naming

reply "bearophile" <bearophileHUGS lycos.com> writes:
An article about many of the design decisions behind the Go 
language. It's an excellent article even if you don't agree with 
some of those decisions:

http://talks.golang.org/2012/splash.article

I suggest all people interested in language design to read that 
article. Go is a simple language after all, so that page is never 
hard to understand.

One group of Go design decisions is about the strictness of its 
module system. One example of such strictness is that unused 
imports are a compilation error! (Another example is that Go 
module system does not allow cycles, and this is enforced both at 
compiler and linker level.)

Recently the good Andrej Mitrovic has closed this old diagnostic 
bug report of mine, marking it as dupe of another issue:

http://d.puremagic.com/issues/show_bug.cgi?id=3972


The bug report presents a case, composed of two modules:


-------------

// File name: foo.d
module bar;
enum int x = 10;

-------------

// File name: spam.d
module test;
import foo: x;
void main() {}

-------------


After the patch by Andrej Mitrovic dmd is expected to generate a 
longer and more refined error message:

spam.d(2): Error: module bar from file foo.d must be imported as 
module 'bar'


Is this error message meaning that the correct spam.d is like 
this?


// File name: spam.d
module test;
import bar: x;
void main() {}


But how can dmd/rdmd know the file name of the "bar" module if 
it's written no where? I guess they can't, so you have to give 
them the file name manually to the compiler, in some way.

I don't like all this. After almost three years since that bug 
report I still think that letting D accept module names different 
from their file names is a mess, it's a "flexibility" (as Walter 
said in an answer) mostly useful to confuse programmers. A price 
paid by everyone for few special situations.

That nice article about the Go language shows that in the long 
run and for larger projects a little bit more strictness is a 
better decision. Think having a large D project with 2000 or 
20000 modules, where module names are randomly different from 
their file names.

If that naming flexibility Walter talks about is so essential, 
then I suggest to introduce a special way to get it without 
allowing in the general case module names to differ from their 
file names.

Bye,
bearophile
Dec 20 2012
next sibling parent "Rob T" <rob ucora.com> writes:
On Friday, 21 December 2012 at 01:25:00 UTC, bearophile wrote:
 That nice article about the Go language shows that in the long 
 run and for larger projects a little bit more strictness is a 
 better decision. Think having a large D project with 2000 or 
 20000 modules, where module names are randomly different from 
 their file names.

 If that naming flexibility Walter talks about is so essential, 
 then I suggest to introduce a special way to get it without 
 allowing in the general case module names to differ from their 
 file names.

 Bye,
 bearophile

I've not yet ever thought about naming a module different than the file name. I suppose such a thing can come in handy but I'm not sure how as it would make finding your modules more difficult as was stated. I wonder if anyone does rename their modules differently than the files? --rt
Dec 20 2012
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 21 December 2012 at 01:25:00 UTC, bearophile wrote:
 I don't like all this.

I *love* all this. It's very useful for various compile time config features. You can swap out modules on the command line and things just work. Even in Go, the package path doesn't have to match the filesystem path. "The meaning of "path" is not specified by the language, but in practice and by convention it is the slash-separated directory path of the source package in the repository"
Dec 20 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/20/2012 6:41 PM, Adam D. Ruppe wrote:
 On Friday, 21 December 2012 at 01:25:00 UTC, bearophile wrote:
 I don't like all this.

I *love* all this. It's very useful for various compile time config features. You can swap out modules on the command line and things just work.

There'd also be a revolt here if circular importing were removed.
Dec 20 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/20/12 10:06 PM, bearophile wrote:
 Walter Bright:

 There'd also be a revolt here if circular importing were removed.

I didn't ask for the removal of circular importing. (But I suggest to read the rationale of the Go designers.)

I did read the piece and found it surprisingly weak. The problems with C's modularity are misidentified. The entire discussion on include guards is irrelevant because it's been obsoleted by today's compilers, which trivially recognize include guards. The problem of bloated includes in C and C++ does exist but its causes are different. Then, the approach to simplifying smacks of making the lives of the implementer easier while passing the buck to the user. Andrei
Dec 20 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/20/2012 8:06 PM, Andrei Alexandrescu wrote:
 On 12/20/12 10:06 PM, bearophile wrote:
 Walter Bright:

 There'd also be a revolt here if circular importing were removed.

I didn't ask for the removal of circular importing. (But I suggest to read the rationale of the Go designers.)

I did read the piece and found it surprisingly weak. The problems with C's modularity are misidentified. The entire discussion on include guards is irrelevant because it's been obsoleted by today's compilers, which trivially recognize include guards. The problem of bloated includes in C and C++ does exist but its causes are different. Then, the approach to simplifying smacks of making the lives of the implementer easier while passing the buck to the user.

Other issues: 1. Error for unused imports. This can be extremely irritating if you're trying to find the source of a bug by commenting out swaths of code. Also, Go doesn't have conditional compilation, another large source of irritation if unused imports are errors. 2. Name for module must match file name. Again, a nuisance if you're trying to rearrange code looking for a problem. If you want to always have the module name match the file name, just omit the module statement.
 That nice article about the Go language shows that in the long run and for 

It makes a claim, it does not show it. D has an excellent module system. No, I don't think Go or anyone else has a better one.
Dec 20 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/21/2012 06:41 AM, Walter Bright wrote:
 ....

 D has an excellent module system.

... modulo the private symbol clash issue. For all I know it is deliberate, which is embarrassing. Other than obviously breaking modularity, it severely restricts the usefulness of symbol disambiguation (which it makes necessary when it should not be), because the disambiguating alias may introduce more conflicts even if it is private, all over the code base. Eg: https://github.com/D-Programming-Language/druntime/pull/298#discussion_r1691013
 No, I don't think Go or anyone else has a better one.

Other languages that support modules usually get hiding of private symbols (or equivalent) right.
Dec 21 2012
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
12/21/2012 12:44 PM, Timon Gehr пишет:
 On 12/21/2012 06:41 AM, Walter Bright wrote:
 ....

 D has an excellent module system.

... modulo the private symbol clash issue. For all I know it is deliberate, which is embarrassing. Other than obviously breaking modularity, it severely restricts the usefulness of symbol disambiguation (which it makes necessary when it should not be), because the disambiguating alias may introduce more conflicts even if it is private, all over the code base.

+1. It never made any sense to me that private is visible but not accessible. A carryover from C++ I guess (but there we just hide stuff out of the header file, use awful internal namespaces etc.).
 Eg:

 https://github.com/D-Programming-Language/druntime/pull/298#discussion_r1691013


 No, I don't think Go or anyone else has a better one.

Other languages that support modules usually get hiding of private symbols (or equivalent) right.

-- Dmitry Olshansky
Dec 21 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 12:44 AM, Timon Gehr wrote:
 ... modulo the private symbol clash issue. For all I know it is deliberate,
 which is embarrassing. Other than obviously breaking modularity, it severely
 restricts the usefulness of symbol disambiguation (which it makes necessary
when
 it should not be), because the disambiguating alias may introduce more
conflicts
 even if it is private, all over the code base.

The reason it is that way is to avoid having it behave gratuitously differently than how visibility works within classes and structs.
Dec 21 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/22/2012 02:44 AM, Walter Bright wrote:
 On 12/21/2012 12:44 AM, Timon Gehr wrote:
 ... modulo the private symbol clash issue. For all I know it is
 deliberate,
 which is embarrassing. Other than obviously breaking modularity, it
 severely
 restricts the usefulness of symbol disambiguation (which it makes
 necessary when
 it should not be), because the disambiguating alias may introduce more
 conflicts
 even if it is private, all over the code base.

The reason it is that way is to avoid having it behave gratuitously differently than how visibility works within classes and structs.

I do not get that. The problem is that private symbols clash with public symbols in different modules. class and struct members are not even liable to inter-module overloadset-overlapping, which is necessary for this to happen. How it works within classes and structs only affects the exact contents of error messages anyway, right? (not accessible vs. not defined) I'd consider that a compiler implementation detail. Furthermore, I do not think there can be any kind of justification for the current behaviour in the first place.
Dec 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 6:55 PM, Timon Gehr wrote:
 How it works within classes and structs only affects the exact contents of
error
 messages anyway, right? (not accessible vs. not defined) I'd consider that a
 compiler implementation detail.

No, it affects the list of candidates for function overloading.
Dec 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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++.
Dec 22 2012
next sibling parent reply =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

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 priva=


 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?

=20 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++.
=20

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 --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Dec 22 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/22/2012 1:29 AM, "Jérôme M. Berger" wrote:
 Walter Bright wrote:
 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++.

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.

I was talking about inside struct/class scope.
Dec 28 2012
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
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
Dec 22 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/22/12 6:13 AM, Dmitry Olshansky wrote:
 See e.g. Boost c++, as an example of code using this _workaround_
 everywhere.

http://boost.2283326.n4.nabble.com/Name-of-namespace-detail-td2667953.html Andrei
Dec 22 2012
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/22/12 3:21 AM, Walter Bright wrote:
 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 think this is a fallacious argument because it concludes that apples should be peeled because oranges should. The impossibility to define a symbol really private in D will lead to awkward idioms like prefixing every private symbol with _p_ or something. Andrei
Dec 22 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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++: foo.cpp:6: error: âvoid S::foo(float)â is private (I used g++ so nobody would complain this is a defect in dmc++.) Why does this never come up on peoples' complaints about C++? I spent some time googling it, and came up with nothing. I don't think it can be dismissed as fallacious unless the why's have a rationale.
Dec 22 2012
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/22/2012 6:35 PM, 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); };

err, forgot the semicolon
Dec 22 2012
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/23/2012 03:35 AM, 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++: foo.cpp:6: error: âvoid S::foo(float)â is private (I used g++ so nobody would complain this is a defect in dmc++.)

structs and classes are utterly irrelevant at this point of the discussion. Are you aware what the problem Andrei was referring to is?
 Why does this never come up on peoples' complaints about C++? I spent
 some time googling it, and came up with nothing.

This is not the primary problem, because it can be avoided by not overloading public vs. private against each other. This is the problem: module a; private void foo(){} module b; public void foo(){} module c; import a,b; void main() { foo(); // error: conflict } The error message is misleading. There is no conflict. Nor is there a problem. The error is completely spurious.
 I don't think it can be dismissed as fallacious unless the why's have a
 rationale.

Modularity is achieved in rather ad-hoc ways in C++. Why do you think C++ is relevant?
Dec 22 2012
prev sibling next sibling parent Martin Nowak <dawg dawgfoto.de> writes:
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.
Dec 23 2012
prev sibling parent reply Martin Nowak <dawg dawgfoto.de> writes:
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
Dec 23 2012
parent Martin Nowak <dawg dawgfoto.de> writes:
On 12/24/12 06:20, 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

Symbols with private protection are hidden when searching through imported modules. Symbols with package protection are hidden when searching through imported modules from a different package. The visibility of an overload set is determined by it's most visible member. Protection does NOT alter overload resolution, i.e. matching within a visible overload set. Members of classes and structs are always visible. This mainly fixes #1238, i.e. name collisions in non static imports. http://d.puremagic.com/issues/show_bug.cgi?id=1238
Dec 24 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/22/2012 12:46 AM, Jonathan M Davis wrote:
 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.

This has been discussed before, and the same people wanted private functions removed from overload sets in classes. So why does this never come up in C++ if it's such a problem? Like I said, I've never seen this come up on peoples' lists of what they don't like about C++, and it isn't because they're shy about complaining about C++ :-)
Dec 22 2012
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/22/12 9:29 PM, Walter Bright wrote:
 On 12/22/2012 12:46 AM, Jonathan M Davis wrote:
 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.

This has been discussed before, and the same people wanted private functions removed from overload sets in classes. So why does this never come up in C++ if it's such a problem? Like I said, I've never seen this come up on peoples' lists of what they don't like about C++, and it isn't because they're shy about complaining about C++ :-)

The scope is very different. We're talking classes vs. entire modules and, by percolation of symbols, entire applications. The comparison would be inappropriate, as would be deriving conclusions applicable to D from it. Private inside a module must mean what the person on the street thinks. No visibility outside the module at all. There are no two ways about it. Andrei
Dec 22 2012
prev sibling parent reply =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Walter Bright wrote:
 On 12/22/2012 12:46 AM, Jonathan M Davis wrote:
 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.

This has been discussed before, and the same people wanted private functions removed from overload sets in classes. =20 So why does this never come up in C++ if it's such a problem? Like I said, I've never seen this come up on peoples' lists of what they don't=

 like about C++, and it isn't because they're shy about complaining abou=

 C++ :-)

Because C++ *can* hide symbols from other modules with the anonymous namespace. D has no equivalent. Jerome --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Dec 23 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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.
Dec 23 2012
parent reply Jacob Carlborg <doob me.com> writes:
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
Dec 24 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/24/12 6:20 AM, 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

Has anyone started a DIP on this? Let's not let things scroll away from the institutional memory. Andrei
Dec 28 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/28/12 4:45 PM, Jonathan M Davis wrote:
 On Friday, December 28, 2012 16:12:47 Andrei Alexandrescu wrote:
 Has anyone started a DIP on this? Let's not let things scroll away from
 the institutional memory.

I've only gotten as far as thinking about it and leaving the relevant e-mails marked as unread.

Well given your passion in the matter I'd say everybody is waiting on the proverbial poster (i.e. you) to deliver! Andrei
Dec 28 2012
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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).
Dec 22 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
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.
Dec 22 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 12:58 AM, bearophile wrote:
 Walter Bright:
 D has an excellent module system. No, I don't think Go or anyone else has a
 better one.

I think D module system is a primitive tool compared to (S)ML module system. http://en.wikipedia.org/wiki/Standard_ML#Module_system

Then why did you bother with the Go module system?
Dec 21 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 4:16 AM, bearophile wrote:
 Walter Bright:

 Then why did you bother with the Go module system?

The Go and D module systems are comparable, while the SML module system is something quite different and another (higher) level.

From your wikipedia link, the SML module system is just a way to symbolically import things. Just like with D imports. I didn't see anything wow about it.
Dec 21 2012
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 5:19 AM, Peter Alexander wrote:
 On Friday, 21 December 2012 at 08:58:03 UTC, bearophile wrote:
 Walter Bright:

 another large source of irritation if unused imports are errors.

In Go even unused variables are *errors* :-)

This is a tricky one. On one hand, it *is* a useful way to catch errors, but on the other it's a constant source of irritation when you are tinkering with code during development/debugging.

Such a change may also make dustmite unworkable. https://github.com/CyberShadow/DustMite/wiki
Dec 21 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 5:40 AM, eles wrote:
 However, it is reasonable to include something like strictness
 levels as part of the compiler? (think gcc with MISRA-C
 integrated).

Having multiple languages via a switch leads to much confusion and cost. I try to avoid such as much as possible.
Dec 21 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 1:40 PM, Jonathan M Davis wrote:
 I would point out that -w does exactly that thanks to conditional compilation
 and compile-time introspection.

I know, and there are threads here where I opposed warnings very strongly.
Dec 21 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 2:33 PM, David Nadlinger wrote:
 On Friday, 21 December 2012 at 22:25:51 UTC, Walter Bright wrote:
 On 12/21/2012 1:40 PM, Jonathan M Davis wrote:
 I would point out that -w does exactly that thanks to conditional compilation
 and compile-time introspection.

I know, and there are threads here where I opposed warnings very strongly.

Why not just make warnings a different class from normal errors, i.e. not increment global.errors for them? In fact, I seem to remember that we are doing this already?

Considering all the discussion and debate about what to do with warnings and deprecations, I can't help but think the whole thing was a bad idea.
Dec 21 2012
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 6:52 AM, Andrej Mitrovic wrote:
 It seems the compiler doesn't complain about invalid import statements
 when it tries to find the module via its import path. Bug?

I'd have to say that's a bug.
Dec 21 2012
prev sibling parent reply Tobias Pfaff <no sp.am> writes:
Jonathan M. Davis wrote:
 A lint-like tool is free to point them out for you, and maybe an IDE could 
 highlight them, but actually making the compiler consider unused variables to 
 be either a warning or an error would be an incredibly bad idea for D - on top 
 of the fact that it would be really annoying.

I find the notion of warnings with brazillions of compiler flags to be outdated, anyways. I do want the possibility to obtain more information from the compiler (in the lint-like fashion), but not in a way that spams the console and I miss serious information. So the nice thing to have here would be a standardized interface to the compiler, or even compiler as a library, with direct data access to this kind of information. An IDE could then process that, mark unused variables and other possible errors in funky colors if desired, list them somewhere, or even show it as an error info in the IDE if the user really wants that. The user can then directly fade out warnings for code parts known to be correct on IDE level. Same thing could be done with custom scripts for the command line folks.
Dec 23 2012
parent Tobias Pfaff <no sp.am> writes:
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...
Dec 24 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 There'd also be a revolt here if circular importing were 
 removed.

I didn't ask for the removal of circular importing. (But I suggest to read the rationale of the Go designers.) Bye, bearophile
Dec 20 2012
prev sibling next sibling parent "Rob T" <rob ucora.com> writes:
On Friday, 21 December 2012 at 02:41:38 UTC, Adam D. Ruppe wrote:
 I *love* all this. It's very useful for various compile time 
 config features. You can swap out modules on the command line 
 and things just work.

OK, I hadn't thought of that possibility. I suppose to find modules not named the same as their host file, you can just perform a search on "module path.name" and it would be good enough. --rt
Dec 20 2012
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Friday, 21 December 2012 at 05:42:04 UTC, Walter Bright wrote:
 On 12/20/2012 8:06 PM, Andrei Alexandrescu wrote:
 On 12/20/12 10:06 PM, bearophile wrote:
 Walter Bright:

 There'd also be a revolt here if circular importing were 
 removed.

I didn't ask for the removal of circular importing. (But I suggest to read the rationale of the Go designers.)

I did read the piece and found it surprisingly weak. The problems with C's modularity are misidentified. The entire discussion on include guards is irrelevant because it's been obsoleted by today's compilers, which trivially recognize include guards. The problem of bloated includes in C and C++ does exist but its causes are different. Then, the approach to simplifying smacks of making the lives of the implementer easier while passing the buck to the user.

Other issues: 1. Error for unused imports. This can be extremely irritating if you're trying to find the source of a bug by commenting out swaths of code. Also, Go doesn't have conditional compilation, another large source of irritation if unused imports are errors.

Actually it does have one, it is part of Go's toolchain. Go developers favor the way I advocate to write portable C and C++ code. No preprocessor, instead create OS/Compiler specific files for the platform, for example: btree.c btree_windows.c btree_linux.c btree_solaris.c The toolchain will then pick all required files depending on your target architecture. The less one uses the preprocessor the better, specially when working in code that outlives programmers. Personally I hate #ifdef hell. As for the other points, you're right. -- Paulo
Dec 20 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 another large source of irritation if unused imports are errors.

In Go even unused variables are *errors* :-)
 D has an excellent module system. No, I don't think Go or 
 anyone else has a better one.

I think D module system is a primitive tool compared to (S)ML module system. http://en.wikipedia.org/wiki/Standard_ML#Module_system More info on SML module system can be found with Google. Bye, bearophile
Dec 21 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 12:57:10 Dmitry Olshansky wrote:
 +1. It never made any sense to me that private is visible but not
 accessible. A carryover from C++ I guess (but there we just hide stuff
 out of the header file, use awful internal namespaces etc.).

It also makes stuff like private aliases useless. I don't really know of any reason _not_ to fix it. At minimum, private symbols should be removed from overload sets outside of their module, though they may need to remain visible (but inaccessible) in dealing with stuff other than overload sets. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 Then why did you bother with the Go module system?

The Go and D module systems are comparable, while the SML module system is something quite different and another (higher) level. Bye, bearophile
Dec 21 2012
prev sibling next sibling parent "jerro" <a a.com> writes:
On Friday, 21 December 2012 at 08:58:03 UTC, bearophile wrote:
 Walter Bright:

 another large source of irritation if unused imports are 
 errors.

In Go even unused variables are *errors* :-)
 D has an excellent module system. No, I don't think Go or 
 anyone else has a better one.

I think D module system is a primitive tool compared to (S)ML module system. http://en.wikipedia.org/wiki/Standard_ML#Module_system More info on SML module system can be found with Google. Bye, bearophile

SML modules are something entirely different from D modules. If you want SML module like functionality in D, the closest thing are actually structs with all members static (or just wrapping your functions in a template), not modules.
Dec 21 2012
prev sibling next sibling parent "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Friday, 21 December 2012 at 08:58:03 UTC, bearophile wrote:
 Walter Bright:

 another large source of irritation if unused imports are 
 errors.

In Go even unused variables are *errors* :-)

This is a tricky one. On one hand, it *is* a useful way to catch errors, but on the other it's a constant source of irritation when you are tinkering with code during development/debugging.
Dec 21 2012
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Friday, 21 December 2012 at 13:19:32 UTC, Peter Alexander
wrote:
 On Friday, 21 December 2012 at 08:58:03 UTC, bearophile wrote:
 Walter Bright:

 another large source of irritation if unused imports are 
 errors.

In Go even unused variables are *errors* :-)

This is a tricky one. On one hand, it *is* a useful way to catch errors, but on the other it's a constant source of irritation when you are tinkering with code during development/debugging.

I would consider those not as (language, compile-time) errors but (not-)compliance with strictness-levels. However, it is reasonable to include something like strictness levels as part of the compiler? (think gcc with MISRA-C integrated).
Dec 21 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
jerro:

 SML modules are something entirely different from D modules.

Yep. (That's what I have said to Walter).
 If you want SML module like functionality in D,

I don't. I (did) want modules to have the same name as their files. Bye, bearophile
Dec 21 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/21/12, bearophile <bearophileHUGS lycos.com> wrote:
 Walter Bright:

 another large source of irritation if unused imports are errors.

In Go even unused variables are *errors* :-)

There was a long blost post somewhat recently (well, it might be from this year at least) where the author complained how the Go compiler likes to error on the most trivial things, and how it interrupts the workflow of the programmer. The link is somewhere on reddit. If I really want to get all the warnings I would want to have a special flag for these kinds of trivial things (which will probably never happen), but then again I might as well use another tool for it. Speaking of tools: you could fork DMD, add all the warnings you want in the front-end and provide a script for users that automatically git clones your repo and builds the custom DMD, which can then be used as a lint tool. That way you avoid having to create something from scratch, and avoid redistribution issues.
Dec 21 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Peter Alexander:

 This is a tricky one. On one hand, it *is* a useful way to 
 catch errors, but on the other it's a constant source of 
 irritation when you are tinkering with code during 
 development/debugging.

I agree. I think a simple way to solve this problem is to put "unused variables" among the warnings. So when you are tinkering with code you don't use -wi, if you want. ------------- eles:
 However, it is reasonable to include something like strictness
 levels as part of the compiler? (think gcc with MISRA-C
 integrated).

I think this to implement that there is a lot of work to do. D tries to improve over C/C++ regarding static code safety, but there's a good way to go still (recently I have written a small article on this). Bye, bearophile
Dec 21 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/21/12, Walter Bright <newshound2 digitalmars.com> wrote:
 snip

Walter, can you verify if this is or isn't a bug: .\main.d .\foo.d main.d: module main; import foo; void main() { test(); } foo.d: module bar; void test() { } This is OK: $ dmd -c main.d foo.d
 main.d(2): Error: module bar from file foo.d must be imported as

But this is questionable: $ dmd -c main.d
 // no complaints

It seems the compiler doesn't complain about invalid import statements when it tries to find the module via its import path. Bug?
Dec 21 2012
prev sibling next sibling parent "mist" <nvm none.none> writes:
I remember having very weird issues with rdmd when module is 
called "main". May be this one is similar?

On Friday, 21 December 2012 at 14:52:27 UTC, Andrej Mitrovic 
wrote:
 On 12/21/12, Walter Bright <newshound2 digitalmars.com> wrote:
 snip

Walter, can you verify if this is or isn't a bug: .\main.d .\foo.d main.d: module main; import foo; void main() { test(); } foo.d: module bar; void test() { } This is OK: $ dmd -c main.d foo.d
 main.d(2): Error: module bar from file foo.d must be imported 
 as

But this is questionable: $ dmd -c main.d
 // no complaints

It seems the compiler doesn't complain about invalid import statements when it tries to find the module via its import path. Bug?

Dec 21 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 14:19:32 Peter Alexander wrote:
 On Friday, 21 December 2012 at 08:58:03 UTC, bearophile wrote:
 Walter Bright:
 another large source of irritation if unused imports are
 errors.

In Go even unused variables are *errors* :-)

This is a tricky one. On one hand, it *is* a useful way to catch errors, but on the other it's a constant source of irritation when you are tinkering with code during development/debugging.

It also doesn't work with stuff like RAII and a lot of conditional compilation. Particularly with eponymous templates, it's _very_ common to have unused variables. Warnings or errors for unused variables would be highly detrimental to D. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 It also doesn't work with stuff like RAII and a lot of 
 conditional compilation.
 Particularly with eponymous templates, it's _very_ common to 
 have unused
 variables. Warnings or errors for unused variables would be 
 highly detrimental to D.

A warning for unused variables will also help D programmers avoid some bugs and keep their code tidy. Bye, bearophile
Dec 21 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 18:46:20 bearophile wrote:
 Jonathan M Davis:
 It also doesn't work with stuff like RAII and a lot of
 conditional compilation.
 Particularly with eponymous templates, it's _very_ common to
 have unused
 variables. Warnings or errors for unused variables would be
 highly detrimental to D.

A warning for unused variables will also help D programmers avoid some bugs and keep their code tidy.

It doesn't work with the language - not with -w anyway. I know that you like the idea, but it just doesn't fly. Adding such a warning would literally change what code would and wouldn't compile and which branches of static ifs and whatnot were used. Some language features and idioms pretty much literally rely on the ability to have unused variables. As such, it's a horrible idea. A lint-like tool is free to point them out for you, and maybe an IDE could highlight them, but actually making the compiler consider unused variables to be either a warning or an error would be an incredibly bad idea for D - on top of the fact that it would be really annoying. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 12/21/2012 06:59 PM, Jonathan M Davis wrote:
 A lint-like tool is free to point them out for you, and maybe an IDE could
 highlight them, but actually making the compiler consider unused variables to
 be either a warning or an error would be an incredibly bad idea for D - on top
 of the fact that it would be really annoying.

How about a separate compiler flag to warn about this issue alone? Useful for those who want these checks, doesn't affect those who don't.
Dec 21 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 20:29:43 Joseph Rushton Wakeling wrote:
 On 12/21/2012 06:59 PM, Jonathan M Davis wrote:
 A lint-like tool is free to point them out for you, and maybe an IDE could
 highlight them, but actually making the compiler consider unused variables
 to be either a warning or an error would be an incredibly bad idea for D
 - on top of the fact that it would be really annoying.

How about a separate compiler flag to warn about this issue alone? Useful for those who want these checks, doesn't affect those who don't.

Not only are there perfectly legitimate uses for having used variables (e.g. RAII), but if used in combination with -w, such a flag would actually change the semantics of programs (due to have it affects conditional compilation), which is a major no-no. That and the fact that Walter has previously shown distaste both for warning about unused variables and for having lots of compiler flags, and I'd be very surprised if he added it. IDEs or or other tools are free to warn about it, but I think that it's a _very_ bad idea for the compiler itself to do so. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Friday, 21 December 2012 at 19:37:58 UTC, Jonathan M Davis 
wrote:
 Not only are there perfectly legitimate uses for having used 
 variables (e.g.
 RAII) […]

Destructors with side effects could simply count as a "use" – problem solved.
 […] change
 the semantics of programs (due to have it affects conditional 
 compilation),

Warnings should not affect conditional compilation, even if the user has warnings as errors turned on. The whole difference of warnings compared to errors is that they are not part of the language. David
Dec 21 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 20:58:02 David Nadlinger wrote:
 […] change
 the semantics of programs (due to have it affects conditional
 compilation),

Warnings should not affect conditional compilation, even if the user has warnings as errors turned on. The whole difference of warnings compared to errors is that they are not part of the language.

The problem is -w, which plenty of people use. The effect is that any warning which can't be an error, can't be a warning. Warnings can therefore only be things that are definitively wrong but which are okay to let happen in some cases (as opposed to something which _might_ be wrong). If we didn't have -w, then we could use warnings for stuff which was probably but not definitively wrong and which was okay to force people to change (the fact that leaving in warnings is never good practice means that you can't warn for anything which it isn't reasonable to force people to change regardless of -w). But because of -w, you can't have any warnings where it would not be reasonable to treat them as an error. And it would be completely broken to treat warning about unused variables as an error. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Friday, 21 December 2012 at 20:33:47 UTC, Jonathan M Davis 
wrote:
 If we didn't have -w,
 then we could use warnings for stuff which was probably but not 
 definitively
 wrong and which was okay to force people to change […] But 
 because
 of -w, you can't […]

I don't think this is a valid argument: GCC has a similar flag (-Werror) too that many people use – for eaxmple, Google build all their code with it enabled, and other companies probably just as well – but still the compiler has quite a number of "best practices" warnings, e.g. regarding operator precedence rules. David
Dec 21 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 12:41:42 Walter Bright wrote:
 On 12/21/2012 5:40 AM, eles wrote:
 However, it is reasonable to include something like strictness
 levels as part of the compiler? (think gcc with MISRA-C
 integrated).

Having multiple languages via a switch leads to much confusion and cost. I try to avoid such as much as possible.

I would point out that -w does exactly that thanks to conditional compilation and compile-time introspection. Perfectly valid code can not only become invalid, but it can end up with very different semantics when -w and conditional compilation are combined. In the case of unused variables, if we were to warn for it and use -w, it would completely break Phobos due to many traits which have unused variables. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Friday, 21 December 2012 at 22:25:51 UTC, Walter Bright wrote:
 On 12/21/2012 1:40 PM, Jonathan M Davis wrote:
 I would point out that -w does exactly that thanks to 
 conditional compilation
 and compile-time introspection.

I know, and there are threads here where I opposed warnings very strongly.

Why not just make warnings a different class from normal errors, i.e. not increment global.errors for them? In fact, I seem to remember that we are doing this already? David
Dec 21 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 14:25:28 Walter Bright wrote:
 On 12/21/2012 1:40 PM, Jonathan M Davis wrote:
 I would point out that -w does exactly that thanks to conditional
 compilation and compile-time introspection.

I know, and there are threads here where I opposed warnings very strongly.

I tend to agree that warnings were a bad idea and that they should never have been introduced, if nothing else, because I don't think that it's ever good practice to leave warnings in your code, making them almost the same as errors anyway. However, what every other compiler I have ever seen does is what the -wi flag does - always print warnings but never have them affect compilation. If we're going to have them, I would expect that that's how they would always work (so, no -wi or -w flags would be required, and warnings would never affect compilation). The -w flag just makes things worse, because of how it affects what will and won't compile. It may be too late to change it now, but if we could, I would think that it would be best to make -wi the default behavior and deprecate both -w and -wi. Then we'd function like pretty much every other compiler on the planet, and we wouldn't have issues with compiler flags affecting conditional compilation. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 17:44:43 Walter Bright wrote:
 On 12/21/2012 12:44 AM, Timon Gehr wrote:
 ... modulo the private symbol clash issue. For all I know it is
 deliberate,
 which is embarrassing. Other than obviously breaking modularity, it
 severely restricts the usefulness of symbol disambiguation (which it
 makes necessary when it should not be), because the disambiguating alias
 may introduce more conflicts even if it is private, all over the code
 base.

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. That way, you don't have problems where adding a private function to a module breaks existing code, because it clashes with a public symbol in another module when a third module imports both modules. For instance, right now, private aliases are useless, because they're pretty much exactly the same as public aliases, because they introduce name clashes. There is _zero_ value as far as I can see in having private symbols in one module affect the symbols in another. private symbols should be implementation details and not affect the compilation of other modules. I would expect it to be exactly the same with private member functions and UFCS. So, if a new private member function is added to a class or struct, and code was using a free function with UFCS with that type, the code wouldn't change behavior or otherwise break because of the conflicting function which was added. The private function _wouldn't_ conflict, because it's private. So, I don't see anything different here about how private would be handled between free functions and structs/classes. It seems to me like it would be exactly the same rather than gratuitously different. And even if it _were_ somehow different, the current behavior makes it frustratingly easy to break code when simply changing the names of the private functions of a module - functions which are supposed to be implementation detalis, and I would think that the difference would be well worth it. Given how much you abhor breaking users' code, putting inaccessible symbols in overload sets seems like a rather odd choice to me. I understand how it stems from C++, but C++ doesn't have module-level access modifiers, and it doesn't have UFCS. The result in D is far more fragile. It makes it way too easy to break other people's code. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 22:12:31 David Nadlinger wrote:
 On Friday, 21 December 2012 at 20:33:47 UTC, Jonathan M Davis
=20
 wrote:
 If we didn't have -w,
 then we could use warnings for stuff which was probably but not
 definitively
 wrong and which was okay to force people to change [=E2=80=A6] But
 because
 of -w, you can't [=E2=80=A6]

I don't think this is a valid argument: GCC has a similar flag (-Werror) too that many people use =E2=80=93 for eaxmple, Google buil=

 all their code with it enabled, and other companies probably just
 as well =E2=80=93 but still the compiler has quite a number of "best
 practices" warnings, e.g. regarding operator precedence rules.

gcc also warns by default rather than not giving warnings at all, so th= e=20 situation is a bit different. -w used to be the _only_ way to even get = warnings=20 with dmd. Also, you have to be _way_ more careful with stuff like that = in D=20 because of all of the conditional compilation and compile-time introspe= ction=20 that it does. Using -w can drastically change the semantics of your cod= e. And=20 in the case of unused variables, it would completely break Phobos, beca= use so=20 many traits legitimately use unused variables. If anything, I think tha= t it=20 makes having -w at all a big mistake, but we have it, and I very much d= oubt=20 that it's going away. - Jonathan M Davis
Dec 21 2012
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
Dec 22 2012
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/21/2012 11:19 PM, Jonathan M Davis wrote:
 but generally the worst that
 they'll do is create slight overhead because of the cost of default
 initializing them.

This is not an issue. An optimization called "dead assignment elimination" has been in compilers since the 1980's, including dmd.
Dec 22 2012
prev sibling next sibling parent "Rob T" <rob ucora.com> writes:
On Saturday, 22 December 2012 at 04:21:06 UTC, Jonathan M Davis 
wrote:
 I tend to agree that warnings were a bad idea and that they 
 should never have
 been introduced, if nothing else, because I don't think that 
 it's ever good
 practice to leave warnings in your code, making them almost the 
 same as errors
 anyway.

That's exactly how I treat warnings as errors, so to me they may as well be errors. The *only* time I treat a warning not as an error, is when I'm quickly messing around testing something out, but in the end I don't want to see any warnings at all. --rt
Dec 21 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 And in the case of unused variables, it would completely break 
 Phobos, because so many traits legitimately use unused 
 variables.

Given how important is to spot unused variables in user code, then maybe some solution can be invented for library code that has legitimate uses of unused variables, like creating a built-in attribute to mark an unused variable that the compiler will not report as unused. Like used, a bit like "used" function attribute of GCC:
 used
     This attribute, attached to a function, means that code 
 must be
     emitted for the function even if it appears that the 
 function is
     not referenced. This is useful, for example, when the 
 function
     is referenced only in inline assembly.

Bye, bearophile
Dec 21 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, December 22, 2012 07:54:06 bearophile wrote:
 Jonathan M Davis:
 And in the case of unused variables, it would completely break
 Phobos, because so many traits legitimately use unused
 variables.

Given how important is to spot unused variables in user code, then maybe some solution can be invented for library code that has legitimate uses of unused variables, like creating a built-in attribute to mark an unused variable that the compiler will not report as unused. Like used, a bit like "used" function

I think that unused variables fall squarely in the realm of a lint-like tool and that it's serious overkill to add something to the language to mark variables that appear to be unused as actually being used just so that the compiler can complain about unused variables. But I also disagree that unused variables are a big deal. Certainly, I'd prefer not to have unused variables in my code, because it's messy to have them, but generally the worst that they'll do is create slight overhead because of the cost of default initializing them. I certainly don't think that it's worth having the compiler complain about them - _especially_ if that means jumping through hoops to get to not complain about legitimate unused variables. - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 21, 2012 22:42:54 Walter Bright wrote:
 On 12/21/2012 6:55 PM, Timon Gehr wrote:
 How it works within classes and structs only affects the exact contents of
 error messages anyway, right? (not accessible vs. not defined) I'd
 consider that a compiler implementation detail.

No, it affects the list of candidates for function overloading.

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? - Jonathan M Davis
Dec 21 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
Dec 22 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 22 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/22/2012 1:04 AM, Jonathan M Davis wrote:
 Walter has completely convinced me with regards to how bad an idea
 compiler warnings are.

Wow!
Dec 22 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 22 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
Dec 22 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 22 2012
prev sibling next sibling parent "Rob T" <rob ucora.com> writes:
On Saturday, 22 December 2012 at 08:47:44 UTC, Jonathan M Davis 
wrote:
 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

I had no idea this was going on. If "private" symbols are not really private then they shouldn't be called private because that is very misleading and can lead to subtle mistakes that will be difficult to understand and avoid. When I've defined something to be private, I really expect it to be private to the outside, or at best a friend within the same module. --rt
Dec 22 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, December 22, 2012 20:11:25 Rob T wrote:
 I had no idea this was going on. If "private" symbols are not
 really private then they shouldn't be called private because that
 is very misleading and can lead to subtle mistakes that will be
 difficult to understand and avoid.
 
 When I've defined something to be private, I really expect it to
 be private to the outside, or at best a friend within the same
 module.

They're private in the same way that they're private in C++. They're inaccessible (i.e. can't be called), but they're not actually hidden. Accessibility is only taken into account after overloading has been sorted out. About the only place I'm aware of that this has any practical effect in C++ is the fact that you can overload private functions (which doesn't affect D, because private functions are never virtual in D). If they were actually hidden, you couldn't. Everywhere else, the difference is academic - primarily because only classes have any concept of access level. In D, on the other hand, the problem is very much _not_ academic, because rather than having a global namespace, we have modules, and each of those modules has access levels for its symbols. We also have UFCS, which effectively makes it possible to add member functions to a class or struct without its permission, which isn't possible in C++. So, in D, it becomes possible to have functions which are inaccessible but which are quite visible and are considered in overload sets along with accessible functions. Because accessibility is determined _after_ the overloading is sorted out, simply adding a private function to your module or class can break existing code in other modules, because you've changed the overload set, causing there to be a name clash or resulting in a function which better matches the set of arguments in one of the calls to it but which then results in an error, because the new function is uncallable. Similarly, it makes private aliases useless, because it pollutes other modules just as much as public aliases do. So, the situation is _very_ different from C++ even though the way that access levels are handled is essentially the same. And pretty much everyone calls foul as soon as they figure out that that's what's going on. Most people initially don't have any clue about it anymore than most people do with C++, because it's not how people think. In C++, many people never figure it out. Only more knowledgeable C++ probgrammers are likely to know, because the difference is almost entirely academic. But in D, many programmers find out about it because they run into problems because of it, and I don't think that I've ever seen anyone other than Walter who thought that it was a good idea. But unfortunately, no one has been able to convince Walter of the need to change things yet. A couple of related bug reports are: http://d.puremagic.com/issues/show_bug.cgi?id=1238 http://d.puremagic.com/issues/show_bug.cgi?id=2991 I thought that there was one with a lengthier discussion on it, but that's all that I could find at the moment. And here's another thread on the issue: http://forum.dlang.org/post/mailman.266.1329071322.20196.digitalmars- d puremagic.com - Jonathan M Davis
Dec 22 2012
prev sibling next sibling parent "Rob T" <rob ucora.com> writes:
On Saturday, 22 December 2012 at 20:24:54 UTC, Jonathan M Davis 
wrote:
 They're private in the same way that they're private in C++. 
 They're
 inaccessible (i.e. can't be called), but they're not actually 
 hidden.
 Accessibility is only taken into account after overloading has 
 been sorted
 out. About the only place I'm aware of that this has any 
 practical effect in
 C++ is the fact that you can overload private functions (which 
 doesn't affect
 D, because private functions are never virtual in D). If they 
 were actually
 hidden, you couldn't. Everywhere else, the difference is 
 academic - primarily
 because only classes have any concept of access level.

Thanks for taking the time to explain all that. The thread on the subject was a very interesting read and is a eye opener for me because I was mostly unaware of the issue. I'm happy I now know about it because it is something you have to know about otherwise you can run into difficult to understand problems. So the problem is that "private" affects accessibility but does not affect visibility, and for various practical reasons most people will prefer it to affect (by limiting) visibility in a similar way as it does with accessibility. Here's my thinking, After we've installed the new development process, one of the things I am hoping we can work towards cleaning up, is the methods used for maintaining the D specification so that it is done in a much more efficient and accessible way. Also the process for making decisions that affect the specification are not at all clear and seems to follow an ad-hoc method of endless discussions, often to no effect with poor retention, and that is a *lot* of wasted effort, so this is an area where a clear formalized process can have a lot of benefit for the community in terms of making it operate much more effectively given the limited resources. Perhaps at some point after the next dmd version is released and stabilized, will be a good time to start working on implementing a process for managing the D specification, assuming of course we have enough consensus that this is a priority area in need of a solution. I sure hope most people think so! --rt
Dec 22 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, December 22, 2012 18:35:47 Walter Bright wrote:
 On 12/22/2012 8:03 AM, Andrei Alexandrescu wrote:
 I think this is a fallacious argument because it concludes that app=


 should be peeled because oranges should.

Given, in C++: =20 struct S { public: void foo(int); private: void foo(float); } =20 void bar() { S s; s.foo(1.0f); } =20 This is an error in C++: =20 foo.cpp:6: error: =C3=A2void S::foo(float)=C3=A2 is private =20 (I used g++ so nobody would complain this is a defect in dmc++.) =20 Why does this never come up on peoples' complaints about C++? I spent=

 time googling it, and came up with nothing.
=20
 I don't think it can be dismissed as fallacious unless the why's have=

 rationale.

Probably because both functions are in the same place, and C++ is far l= ess=20 picky about implicit conversions, meaning that it's _much_ more likely = to=20 simply select the public function rather than complain about a conflict= (though=20 as your code demonstrates, such a conflict is still possible). Contrast= this=20 with D where the compiler is extremely quick to give you an error about= =20 functions conflicting rather than trying to guess which one you meant. Also, with C++, this is restricted to the class that you're dealing wit= h.=20 Derived classes generally won't have the problem (if they overload foo,= it'll=20 just call the derived one IIRC rather than complaining about the privat= e one=20 in the base class). So, any breakage you get is directly related to tha= t=20 class. Whereas in D, simply adding a private function to a module can c= ause a=20 conflict with a completely different module. Such functions in C++ woul= dn't even=20 be visible, because they'd be hidden in the cpp file, so you only get t= hat=20 problem when you add more "public" functions (quotes, since there aren'= t=20 really any access levels for free functions in C++). In addition, in my experience, it's quite rare for classes to have publ= ic and=20 private functions with the same name, meaning that you just don't hit t= his=20 problem very often. That's probably why it doesn't garner many complain= ts in=20 C++. Contrast this with D, where with modules, it's trivial to have com= pletely=20 unrelated free functions with the same name which end up conflicting wh= ere one=20 is private and another is public. At least with a class, the functions = would=20 be related. With modules, the functions are likely to be completely unr= elated=20 and much more like to be written by completely different people. I don't think that D programmers generally complain about this with cla= sses,=20 though UFCS will probably increase those complaints. They mostly compla= in=20 about this with modules - a problem that C++ doesn't have. And it's the= module=20 situation which desparately needs to be fixed. But UFCS will make it so= that=20 the problem crops up far more with classes as well, since now anyone ca= n=20 effectively add a function to a class, potentially causing conflicts no= t only=20 with other functions used with UFCS but also causing problems when the = class=20 maintainer adds private functions to the class which would conflict. In= C++,=20 you can only get a conflict with derived classes, and in general, the o= verload=20 rules there make it so that it's not a problem if the public function b= eing=20 clashed with is overridden in the derived class. And more of the proble= ms that=20 you do have are less obvious when they happen and are hard to catch due= to=20 C++'s greater laxity with implicit conversions and overload selection. So, while C++ has the problem, it's on a much, much smaller scale - hen= ce why=20 you don't see a lot of complaints about it in C++. Whereas in D, it hap= pens=20 rather frequently, so plenty of people complain. So, I really think tha= t we=20 would be far better off to make it so that inaccessible functions are n= ever in=20 overload sets. Carrying overy C++'s behavior in this case is just going= to=20 cause us grief. - Jonathan M Davis
Dec 22 2012
prev sibling next sibling parent "Rob T" <rob ucora.com> writes:
On Sunday, 23 December 2012 at 02:35:46 UTC, 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++: foo.cpp:6: error: âvoid S::foo(float)â is private (I used g++ so nobody would complain this is a defect in dmc++.) Why does this never come up on peoples' complaints about C++? I spent some time googling it, and came up with nothing. I don't think it can be dismissed as fallacious unless the why's have a rationale.

I don't see how that example can be compared with the issue Jonathan is raising. If I understood the issue correctly, the visibility of all module members are global in scope, and that's why two modules may have names that clash. What people want are private module members not to be visible outside of the module. We're speaking about D rather than C++, but I can give you an example of how a somewhat analogous situation can cause serious problems in C++. When using dlopen() with the RTLD_GLOBAL flag, it causes all symbols from the loaded library to become visible to subsequently loaded libraries. When there are symbol clashes, instead of an error, one of the symbols is used rather than the other, causing the application to behave in unexpected ways. For dlopen() the default behavior is RTLD_LOCAL, which makes all symbols from loaded libs private to their respective libs. This is the default behavior to ensure predictable execution behaviors, and it's the same default behavior that modules should have. --rt
Dec 22 2012
prev sibling next sibling parent "Rob T" <rob ucora.com> writes:
On Sunday, 23 December 2012 at 04:43:27 UTC, Rob T wrote:
 For dlopen() the default behavior is RTLD_LOCAL, which makes 
 all symbols from loaded libs private to their respective libs. 
 This is the default behavior to ensure predictable execution 
 behaviors, and it's the same default behavior that modules 
 should have.

 --rt

I meant: "it's the same default behavior that private module members should have.", ie, they should not be visible outside of the module.
Dec 22 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, December 23, 2012 05:56:07 Timon Gehr wrote:
 structs and classes are utterly irrelevant at this point of the discussion.

That's mostly true, but UFCS probably makes it so that structs and classes are in the same boat as free functions in modules are. Without UFCS, it's a relatively minor issue. But since C++ doesn't have UFCS, once again, this is an issue that D has that C++ doesn't, making the fact that people don't complain about this much in C++ pretty much irrelevant. - Jonathan M Davis
Dec 22 2012
prev sibling next sibling parent "Rob T" <rob ucora.com> writes:
On Sunday, 23 December 2012 at 12:20:01 UTC, Tobias Pfaff wrote:
 So the nice thing to have here would be a standardized 
 interface to the
 compiler, or even compiler as a library, with direct data 
 access to this
 kind of information.

Yes the concept of what a complier is, how how it is implemented should be redefined. The current concept is monolithic, you cannot easily extend it (no one can, not even the compiler devs), or make use of it outside of an extremely narrow usage range. Restructuring the compiler into a much more flexible and extensible tool is something that should be dealt at a later point, but there is a much bigger problem that needs to be taken on concerning how the language specification is being managed. Without a clear language specification that is accessible to everyone (try downloading it), and without a defined process to manage it, no one really knows fully what the language is supposed to be doing, and that limits severely what people are able to do in many areas. There's also a huge amount of endless discussions that never seem to conclude, and when there is a conclusion often the conclusion is not implemented or even retained for future reference. --rt
Dec 23 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, December 23, 2012 12:20:01 Tobias Pfaff wrote:
 So the nice thing to have here would be a standardized interface to the
 compiler, or even compiler as a library, with direct data access to this
 kind of information.

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. - Jonathan M Davis
Dec 23 2012
prev sibling next sibling parent "Phil Lavoie" <maidenphil hotmail.com> writes:
I'd like to add that I have programmed with google Go for some 
time and moved to D for various reasons. It is true that unused 
imports and variables may be a hint that something was done 
wrong, or forgotten, and a review might be desirable. I am all 
for being warned about this. However, it is absolutely true that 
tagging those as errors can 1) become a nuisance when debugging 
2) might not even be applicable for D (you mentioned some things 
about traits using them).

Now, the question became: "who's responsibility is it to warn 
about those messages?". I do like the idea of having an interface 
to the lexer and parser to make it easy for IDEs to identify 
those problems because 1) it makes finding those errors easier 
and 2) provides the possibility to move the responsibility from 
the compiler to another tool, which is flexible. If I am not 
mistaken, such an API is implemented in Go's standard lib.

So my take on this would be: give (not you personally) all the 
third party tools the means to identify those things easily 
because I am a 100% for the fact that those warnings CAN BE 
USEFUL.

By the way, would anyone be kind enough to tell me what UFCS are?

Phil
Dec 23 2012
prev sibling next sibling parent "Phil Lavoie" <maidenphil hotmail.com> writes:
Never mind my last question. Found that it stands for: uniform 
function call syntax. Now I am going to look into what that means 
and how it affects the "no accessibility but visibility" thingy.
Dec 23 2012
prev sibling next sibling parent "Phil Lavoie" <maidenphil hotmail.com> writes:
Ok so it's the feature that allows you to write something like 
myObject.notInClassDeclarationMethod( zeParam );
Which is awesome.

I'd like to know if there is any functionality provided by having 
private functions/methods being visible? Does it mean you can 
override them in your module (for module scope privates)?

Thanks,

Phil
Dec 23 2012
prev sibling next sibling parent "Phil Lavoie" <maidenphil hotmail.com> writes:
Ok so it's the feature that allows you to write something like
myObject.notInClassDeclarationMethod( zeParam );
Which is awesome.

I'd like to know if there is any functionality provided by having
private functions/methods being visible? Does it mean you can
override them in your module (for module scope privates)?

Thanks,

Phil
Dec 23 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, December 23, 2012 21:36:34 Phil Lavoie wrote:
 Never mind my last question. Found that it stands for: uniform
 function call syntax. Now I am going to look into what that means
 and how it affects the "no accessibility but visibility" thingy.

It means that any free function can be called as if it were a member function of the type that it takes as its first argument. So, it's possible to do something like auto result = range.find(subRange); instead of auto result = find(range, subRange); For better or worse, you can even do things like int i = 5.min(12); As for accessibility, if I had struct S { } auto foo(S) {...} and code which did s.foo(); if I added a private function named foo to S struct S { private auto foo() {...} } then all of a sudden, the s.foo() call would be illegal, because in UFCS, the member function always wins when there's a conflict. However, if private were hidden (or at least didn't factor into overload sets), then s.foo() wouldn't break as long as it was outside of the module that S was in, because the foo function in S then wouldn't affect anything outside of that module, since it would be inaccessible to anything outside of that module. - Jonathan M Davis
Dec 23 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, December 23, 2012 21:47:13 Phil Lavoie wrote:
 Ok so it's the feature that allows you to write something like
 myObject.notInClassDeclarationMethod( zeParam );
 Which is awesome.
 
 I'd like to know if there is any functionality provided by having
 private functions/methods being visible? Does it mean you can
 override them in your module (for module scope privates)?

private is _always_ module scope. Regardless can't override private functions even within a module, because in D, private and package functions are never virtual and therefore cannot be overridden. If you want to be able to override them, you have to make them public or protected. In C++, you can make private functions virtual and override them, but that's not possible in D, primarily because we took the simpler route of tying the virtuality of a function to its access level rather than having to explicitly mark functions as virtual. - Jonathan M Davis
Dec 23 2012
prev sibling next sibling parent "Phil Lavoie" <maidenphil hotmail.com> writes:
 private is _always_ module scope.

if that would be allowed: module a; public auto aFunc( T )( T t ) { cantSeeMe( t ); } private auto canSeeMe( SomeType t ) { ... } module b; import a; alias a.canSeeMe canSeeMe public auto canSeeMe( SomeOtherType t ) { ... } //Can this be called by afunc? module c; void main( ... ) { ... SomeOtherType t; t.aFunc(); ... } If so, I am guessing it is made possible by said particularity? Phil
Dec 23 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, December 23, 2012 22:12:17 Phil Lavoie wrote:
 private is _always_ module scope.

Ooops I meant private functions inside a module. I was wondering if that would be allowed: module a; public auto aFunc( T )( T t ) { cantSeeMe( t ); } private auto canSeeMe( SomeType t ) { ... } module b; import a; alias a.canSeeMe canSeeMe public auto canSeeMe( SomeOtherType t ) { ... } //Can this be called by afunc?

No. cantSeeMe is looked up in aFunc's scope, which means that it sees a.cantSeeMe, not b.canSeeMe, so it'll call a.cantSeeMe. If b.cantSeeMe were called, it would be a compiler bug. Templates do symbol look up in their original scope, not in the scope that they're instantiated. They only do symbol lookup in the scope that they're instantiated in if they're mixed in, which you're obviously not doing here. - Jonathan M Davis
Dec 23 2012
prev sibling next sibling parent "Phil Lavoie" <maidenphil hotmail.com> writes:
In this case, I am convinced that there is no use of having the 
"no accessibility but visibility" particularity, because I cannot 
find any reason for it to stay like that (feature/exploit wise). 
On the other hand, I don't work on the compiler and I have no 
idea of what difficulties in would imply to change this. So the 
question I guess would be if changing its behaviour to make it 
predictable justifies the cost/work, for now (priority wise)?
Dec 23 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, December 23, 2012 23:34:41 Phil Lavoie wrote:
 In this case, I am convinced that there is no use of having the
 "no accessibility but visibility" particularity, because I cannot
 find any reason for it to stay like that (feature/exploit wise).
 On the other hand, I don't work on the compiler and I have no
 idea of what difficulties in would imply to change this. So the
 question I guess would be if changing its behaviour to make it
 predictable justifies the cost/work, for now (priority wise)?

If a function is truly hidden, then it wouldn't even be available for error messages and whatnot, and in some cases, it might be useful to give an error that a function is private rather than that it doesn't exist. All we really need to do is make it so that inaccessible functions aren't put into overload sets. How big a change that is, I don't know, but it's not necessarily a small one, because right now, the access level is taken into account _after_ function overloading has been sorted out, and we'd have to change it so that it was taken into account before function overloading. I wouldn't expect this to be a huge priority given some of what else needs to be done, but I really think that it should be fixed soon (prior to 2.062). The real trick is convincing Walter that it should be changed (though someone else like Kenji may end up actually implementing it). - Jonathan M Davis
Dec 23 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 23 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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++:

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
Dec 23 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
Dec 24 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 24 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 24 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Sunday, 23 December 2012 at 19:55:15 UTC, Jonathan M Davis 
wrote:
 On Sunday, December 23, 2012 12:20:01 Tobias Pfaff wrote:
 So the nice thing to have here would be a standardized 
 interface to the
 compiler, or even compiler as a library, with direct data 
 access to this
 kind of information.

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. - Jonathan M Davis

I stopped all work on that and am waiting for it. I've done a crappy wrapper around some existing code on the subject. I'd love you if something come out of your project !
Dec 28 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 28, 2012 16:12:47 Andrei Alexandrescu wrote:
 Has anyone started a DIP on this? Let's not let things scroll away from
 the institutional memory.

I've only gotten as far as thinking about it and leaving the relevant e-mails marked as unread. - Jonathan M Davis
Dec 28 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 28 December 2012 at 21:12:48 UTC, Andrei Alexandrescu 
wrote:
 On 12/24/12 6:20 AM, 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

Has anyone started a DIP on this? Let's not let things scroll away from the institutional memory. Andrei

I feel like the issue is much deeper. I have no clue what the priorities are when resolving some identifiers, and the doc is unclear about it, and dmd is sometime inconsistent, or some other time don't implement the feature (for instance multiple alias this). In a.b , b can be : 1 a member of a. 2 a member of an alias this of a. 3 any recursion of the case 2. 4 an UFCS function. 5 an UFCS function using an alias this of a as argument. 6 any recursion of 5. 7 an imported symbol at scope level. 8 repeat 4, 5 and 6 with that imported symbol. 9 an imported symbol at module level. 10 repeat 4, 5 and 6 with that imported symbol. 11 all cases I have forgotten as I wrote that quickly. It is unclear when they take priorities over each other and when they collide. Visibility is another variable to the equation, but in a first place, this is unclear without them.
Dec 28 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 28, 2012 16:52:32 Andrei Alexandrescu wrote:
 On 12/28/12 4:45 PM, Jonathan M Davis wrote:
 On Friday, December 28, 2012 16:12:47 Andrei Alexandrescu wrote:
 Has anyone started a DIP on this? Let's not let things scroll away from
 the institutional memory.

I've only gotten as far as thinking about it and leaving the relevant e-mails marked as unread.

Well given your passion in the matter I'd say everybody is waiting on the proverbial poster (i.e. you) to deliver!

The wiki.dlang.org DIP page claims that it's only a placeholder page (until all of them are copied over?). So, should I put the new DIP in both places, or should I just put it on the new one in spite of the fact that it claims that it's a placeholder? http://wiki.dlang.org/DIPs http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs - Jonathan M Davis
Dec 29 2012
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 24 December 2012 at 15:36:47 UTC, Jonathan M Davis 
wrote:
 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.

Stopping to conflate visibility with virtuality would solve it in a more simple way.
Jan 27 2013