www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - public import and bugs it causes

reply Alex Makhotin <alex bitprox.com> writes:
Hello.

Today I found a strange bug in my code which was caused by 'public 
import' declaration from the wxD library.

The library imports publicly the 'std.compiler' module from Phobos.
And it has the 'const string name;' declaration.
Some of the code of my program imported the library headers.
None of the classes of the program have the 'name' member or any static 
analogs. I just wanted to know why in some cases the program printed the 
magic "Digital Mars D" words :). At that time I found the public import 
of the 'std.compiler' module in the code of the library.

Well, I'm not against the additional promotion of the Digital Mars D 
compiler :)

But, I don't want such occasions any more. Is there a solution, except 
to avoid public imports(by the way, I avoid, it's the library code from 
the third party)? The ideal would be a warning from the compiler, at least.
I also would like the compiler to force me to use fully qualified module 
path to the member in the mentioned case.


-- 
Alex Makhotin,
the founder of BITPROX,
http://bitprox.com
May 14 2010
next sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Alex Makhotin wrote:

 Today I found a strange bug in my code which was caused by 'public 
 import' declaration from the wxD library.
 
 The library imports publicly the 'std.compiler' module from Phobos.
 And it has the 'const string name;' declaration.

I removed the 'std.compiler' import and replaced it with __VERSION__... http://wxd.cvs.sourceforge.net/viewvc/wxd/wxd/wx/common.d?r1=1.18&r2=1.19 Hopefully that should work around the issue. Wonder what else it breaks. --anders
May 14 2010
parent Alex Makhotin <alex bitprox.com> writes:
Anders F Björklund wrote:
 Alex Makhotin wrote:
 
 Today I found a strange bug in my code which was caused by 'public 
 import' declaration from the wxD library.

 The library imports publicly the 'std.compiler' module from Phobos.
 And it has the 'const string name;' declaration.

I removed the 'std.compiler' import and replaced it with __VERSION__... http://wxd.cvs.sourceforge.net/viewvc/wxd/wxd/wx/common.d?r1=1.18&r2=1.19 Hopefully that should work around the issue. Wonder what else it breaks. --anders

Hi, Anders. Thank you for help. The issue was that the code in my program passed the variable 'name' to the method as a parameter instead of the variable 'value'. Where the variable 'name' doesn't present in any of my classes. I just replaced it with the right one and it worked. It was not so much of a pleasure to find out that I mistyped the argument of the member function and it *matched* with the external declaration of public import hierarchy. Therefore I would like to get support from the compiler on the issue not to repeat this bug any more. By the way, I modified the wxD(including the fix for this bug) and added new functionality for my needs. I'm going to use this wrapper as a base for the BDE GUI library and will make this available(including the source) in version 2 with the GUI editor in the box. -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 14 May 2010 13:16:06 -0400, Alex Makhotin <alex bitprox.com> wrote:

 Hello.

 Today I found a strange bug in my code which was caused by 'public  
 import' declaration from the wxD library.

 The library imports publicly the 'std.compiler' module from Phobos.
 And it has the 'const string name;' declaration.
 Some of the code of my program imported the library headers.
 None of the classes of the program have the 'name' member or any static  
 analogs. I just wanted to know why in some cases the program printed the  
 magic "Digital Mars D" words :). At that time I found the public import  
 of the 'std.compiler' module in the code of the library.

 Well, I'm not against the additional promotion of the Digital Mars D  
 compiler :)

 But, I don't want such occasions any more. Is there a solution, except  
 to avoid public imports(by the way, I avoid, it's the library code from  
 the third party)? The ideal would be a warning from the compiler, at  
 least.
 I also would like the compiler to force me to use fully qualified module  
 path to the member in the mentioned case.

name is too common an identifier. I think std.compiler should not use it, it should be something like compiler_name. FYI, this can be forced by wxD library using something like: public import std.compiler : compiler_name = name; -Steve
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
Steven Schveighoffer wrote:
 name is too common an identifier.  I think std.compiler should not use 
 it, it should be something like compiler_name.

You cannot force all the vendors of all the libraries to be so diligent. Due to I have the source code, I fixed it fast. What if I don't and only have the headers which cannot modify? The compiler warning would eliminate such issue.
 
 FYI, this can be forced by wxD library using something like:
 
 public import std.compiler : compiler_name = name;
 
 -Steve

To substitute one one problem with the potential of another? -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
I think this is a bad design of the language.
Global variables are bad things.
C# doesn't have them.
In this sense I like C# which prohibits any fields or methods in namespaces.

And few words considering public imports in D.
Excerpt from the C# 4.0 language specification
(http://www.microsoft.com/downloads/details.aspx?FamilyID=dfbf523c-f98c-4804-afbd-459e846b268e&disp
aylang=en#filelist) 
says:

 A using-namespace-directive imports the types contained in the given
namespace, but specifically does not import nested namespaces. In the example
 namespace N1.N2
 {
 	class A {}
 }
 namespace N3
 {
 	using N1;
 	class B: N2.A {}		// Error, N2 unknown
 }
 the using-namespace-directive imports the types contained in N1, but not the
namespaces nested in N1. Thus, the reference to N2.A in the declaration of B
results in a compile-time error because no members named N2 are in scope.

In D I can achieve similar(?) behavior by using 'import'('private import' by default). But I also can evade by using explicit 'public import'. This leads to bugs. Globals lead to bugs. -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Alex Makhotin:

 I think this is a bad design of the language.
 Global variables are bad things.
 C# doesn't have them.
 In this sense I like C# which prohibits any fields or methods in namespaces.

Global variables are tricky and it's better to minimize them, but they are sometimes useful, or they can give some extra performance, etc. Global functions (not called methods if they aren't inside a function) are very useful. You have to learn that there is more than OOP in the life of a programmer. Not all my programs contain classes. Bye, bearophile
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
bearophile wrote:
 You have to learn that there is more than OOP in the life of a programmer. Not
all my programs contain classes.

You know, I'm just trying to learn that there is more than *bugs* in the life of a programmer. That's it. -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Alex Makhotin:

 You know, I'm just trying to learn that there is more than *bugs* in the 
 life of a programmer. That's it.

I don't understand what you are trying to say here, sorry. If you mean that functions global in a module are a bug-prone feature, then you are wrong. Bye, bearophile
May 14 2010
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Simen kjaeraas:
 In short: Public imports have their place, but don't use them
 if there's no need. (like with just about everything else)

OK :-) But I suggest to limit the usage of public imports to the minimum, just as casts. (I like to limit the public imports in my dlibs1 to the "all" module (the one that imports everything)). The problem with similar coding/idiom "suggestions" is that programmers often ignore them, even when there is "no need", as you say. I have seen D code with all kind of ugly things inside. This is why a bit of bondage is sometimes necessary for the less disciplined developers. It's a matter of balance. Bye, bearophile
May 14 2010
prev sibling parent reply div0 <div0 users.sourceforge.net> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Alex Makhotin wrote:
 I think this is a bad design of the language.
 Global variables are bad things.
 C# doesn't have them.

Actually C# does have global variables; any public static member of a class is a global variable. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFL7b4NT9LetA9XoXwRAk6mAKCPCEEqqIyXwKMlcW3XO013ohfl8wCcCMET Pyu1O2S19UNG41rK4293dfM= =4EHj -----END PGP SIGNATURE-----
May 14 2010
parent div0 <div0 users.sourceforge.net> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Simen kjaeraas wrote:
 div0 <div0 users.sourceforge.net> wrote:
 
 Actually C# does have global variables;
 any public static member of a class is a global variable.

And here we are down to arguing semantics. Is a variable global if it does not pollute the global namespace?

Yes it is. Global means having a single address in the application's static data segment and accessible to all functions & threads.
 I believe this to have been Alex's intention, and it is
 a fairly common definition of global variable.

It's a fairly common mistake.
 One could certainly argue otherwise, but I hardly see the
 value in such a discussion, be the truth this way or the
 other.

Importing symbols into your codes current scope is entirely different from discussion of global vars. It doesn't need to be a global variable to cause the same problems, it can be a class or a function. The problem as stated is about name high jacking, which you yourself have pointed out in one of your later posts. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFL7qYMT9LetA9XoXwRAg8JAJ94kzFFopWFkn321wJIzN1mChF4bACeMyGU 2Jxrd5kXgCg9W3254smdttQ= =NEQu -----END PGP SIGNATURE-----
May 15 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Alex Makhotin:

 Today I found a strange bug in my code which was caused by 'public 
 import' declaration from the wxD library.

I can enjoy seeing public imports removed from D. They are a failed idea. Bye, bearophile
May 14 2010
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:hsk3rk$1rb8$1 digitalmars.com...
 Alex Makhotin:

 Today I found a strange bug in my code which was caused by 'public
 import' declaration from the wxD library.

I can enjoy seeing public imports removed from D. They are a failed idea.

1. The problem he had had nothing to do with public imports. Any of the modules he was importing could just as easily had a global var named "name" and would have caused the same problem. 2. Public imports are very useful. I never want to see them go. Examples: ------------------------------------- // Vastly superior alternative to "import foolib.*;" which D // (fortunately) doesn't even have anyway. module foolib.all; public import foolib.blah1; public import foolib.blah2; // Ignore foolib.privateFooLibModule; public import foolib.blah3; //etc... ------------------------------------- module aToolIAmWritingThatMakesItEasyToUseDForScriptStyleProgramming; // Obviously only intended for short apps, not big projects. public import superUsefulStdModule1; public import superUsefulStdModule2; // A few workarounds for symbol conflicts here ------------------------------------- module foolib.osWrapper; version(Windows) public import foolib.osWrapper_win; else public import foolib.osWrapper_unix; -------------------------------------
May 14 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Nick Sabalausky:

 1. The problem he had had nothing to do with public imports. Any of the 
 modules he was importing could just as easily had a global var named "name" 

Yes, that's caused by another hole in the design of D module system, that I hope to see fixed someday. It's almost three years from the first time I have reported it, probably in my second post on D newsgroups.
 2. Public imports are very useful.

They are useful as casts between signed and unsigned values. But usually they are not a clean solution. A module system has right the opposite purpose :-)
 // Vastly superior alternative to "import foolib.*;" which D
 // (fortunately) doesn't even have anyway.
 module foolib.all;

What's vastly superior in it? Its unformalized nature? Bye, bearophile
May 14 2010
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
bearophile wrote:
 Nick Sabalausky:
 
 1. The problem he had had nothing to do with public imports. Any of the 
 modules he was importing could just as easily had a global var named "name"
 

Yes, that's caused by another hole in the design of D module system, that I hope to see fixed someday. It's almost three years from the first time I have reported it, probably in my second post on D newsgroups.

I don't agree that it's a hole or a bug. The designer of an imported module has complete control over what names will be visible to the importer and which aren't. This is as it should be.
May 14 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Walter Bright:
 I don't agree that it's a hole or a bug. The designer of an imported module
has 
 complete control over what names will be visible to the importer and which 
 aren't. This is as it should be.

Giving you answers here is not useful. You can take a look in Bugzilla for bug reports that contain details about the many holes of the D module system. Bye, bearophile
May 14 2010
prev sibling parent reply Alex Makhotin <alex bitprox.com> writes:
Walter Bright wrote:

 I don't agree that it's a hole or a bug. 

I disagree.
 The designer of an imported
 module has complete control over what names will be visible to the 
 importer and which aren't. This is as it should be.

I don't want to deal with the bad design of someone's module. For example.
 module Server.TestM2;
 const string name = "New Name";

 module Server.TestM1;
 public import Server.TestM2;

 module Server.Main;
 private import Server.TestM1;

In the scope of Server.Main module the global variable 'name' is visible. That should not be so. The Server.Main module should explicitly import module Server.TestM2 to be able to use of variable 'name'. It's much better to make restriction in the language specification to eliminate misuse. The use of globals is error prone. I consider it a bad practice. In the extreme case I would like to see D's specification restricting globals as C# does. -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Alex Makhotin wrote:
 The designer of an imported
 module has complete control over what names will be visible to the 
 importer and which aren't. This is as it should be.


You're always going to be stuck with the design of someone else's module if you choose to use it.
 For example.
 
 module Server.TestM2;
 const string name = "New Name";

 module Server.TestM1;
 public import Server.TestM2;

 module Server.Main;
 private import Server.TestM1;

In the scope of Server.Main module the global variable 'name' is visible. That should not be so.

That's up to the author of TestM1. If he doesn't want the names in TestM2 to be visible, he should privately import TestM2.
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
Walter Bright wrote:
 That's up to the author of TestM1. If he doesn't want the names in 
 TestM2 to be visible, he should privately import TestM2.

That requires the access to the source code or the desire of the author of the third party library. What if I don't have that? Deal with bugs or abandon the use of the library. I would choose to abandon. I generated the headers:
 // D import file generated from 'TestM2.d'
 module Server.TestM2;
 const 
 {
     string name = "New Name";
 }

 // D import file generated from 'TestM1.d'
 module Server.TestM1;
 public 
 {
     import Server.TestM2;
 }

I don't want to tolerate the unnecessary global variable 'name' in my code when I privately import the Server.TestM1 module. And whatever other countless unnecessary global variables the author of that(closed source, commercial) module leaved for me. My proposal for fixing this are: 1. Require the fully qualified path to the member of the module. To be able to operate with the variable 'name' the user should access it explicitly as 'Server.TestM2.name'. 2. Require the user of the imported third party module to explicitly import module Server.TestM2 to be able to use simple access method without the namespace prefix. 3. The D compiler must warn about the use of the global variable from the public import module. 4. Extreme case would be to get rid of globals which as a I understand is not possible. -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Alex Makhotin wrote:
 Walter Bright wrote:
 That's up to the author of TestM1. If he doesn't want the names in 
 TestM2 to be visible, he should privately import TestM2.

That requires the access to the source code or the desire of the author of the third party library. What if I don't have that? Deal with bugs or abandon the use of the library. I would choose to abandon.

There's no getting away from problems caused by bugs in third party libraries. (That's why I prefer open source libraries.)
 I don't want to tolerate the unnecessary global variable 'name' in my 
 code when I privately import the Server.TestM1 module. And whatever 
 other countless unnecessary global variables the author of that(closed 
 source, commercial) module leaved for me.

You can import only those names you wish. See static imports, renamed imports and selective imports in http://www.digitalmars.com/d/2.0/module.html
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
Walter Bright wrote:
 You can import only those names you wish. See static imports, renamed 
 imports and selective imports in 
 http://www.digitalmars.com/d/2.0/module.html

OK, 'static import' combination seems to force use of fully qualified name. Requires a lot of typing of the fully names for imported classes. A lot of typing only for the sake of one global variable. The renamed import also requires countless typing using the renamed prefix. The specific imports require me to select what to import(again all the work on me, not the tool I use). Oh no. Every time I desire to use some member of the import I type 'import module : memberiwant'. As far as I know the C# hasn't such complications, why should D? -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Alex Makhotin:
 As far as I know the C# hasn't such complications, why should D?

Note that D module system is not modelled on C#. I think (but I can be wrong) D module system is a partially ignorant implementation of the Python module system (with "partially ignorant" I mean that it looks like D module system doesn't fully understand the Python module system and why it's designed that way, so some parts of it are left out for no good reason or badly implemented, so it lacks coherence. This comment doesn't consider the implementation bugs). Bye, bearophile
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
bearophile wrote:
 Note that D module system is not modelled on C#.

I think that to become successful competitor for such languages as C#, the D language requires improvement. In the bug I encountered, I mistyped the variable and it *matched the global variable accidentally*. I was unaware of it because the compiler was silent, but IMHO it, at least, should give me a warning. It's not possible in C#. That's what I meant. -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Alex Makhotin wrote:
 bearophile wrote:
 Note that D module system is not modelled on C#.

I think that to become successful competitor for such languages as C#, the D language requires improvement. In the bug I encountered, I mistyped the variable and it *matched the global variable accidentally*. I was unaware of it because the compiler was silent, but IMHO it, at least, should give me a warning. It's not possible in C#. That's what I meant.

Your headers start include the following: Path: digitalmars.com!not-for-mail From: Alex Makhotin <alex bitprox.com> Newsgroups: digitalmars.D Subject: Re: public import and bugs it causes Date: Sat, 15 May 2010 04:46:08 +0300 That's a bit in the future. Any chance I could impose on you to change your system time? Andrei
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
Andrei Alexandrescu wrote:
 
 Date: Sat, 15 May 2010 04:46:08 +0300
 
 That's a bit in the future. Any chance I could impose on you to change 
 your system time?

Every time I set the local time in Linux and then reload to Windows, the Windows resets it in BIOS. So I set the Linux to use the UTC(as in BIOS). To use the local time it requires me to set the clock back on 2 hours. I don't know why Windows resets BIOS clock... -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Alex Makhotin wrote:
 Andrei Alexandrescu wrote:
 Date: Sat, 15 May 2010 04:46:08 +0300

 That's a bit in the future. Any chance I could impose on you to change 
 your system time?

Every time I set the local time in Linux and then reload to Windows, the Windows resets it in BIOS. So I set the Linux to use the UTC(as in BIOS). To use the local time it requires me to set the clock back on 2 hours. I don't know why Windows resets BIOS clock...

Interesting. Can you instruct Windows to sync using the Internet? And does Windows have the right time zone set? Andrei
May 14 2010
parent Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 Funny anecdote (actually not really funny at the time):  Our windows 
 test image for previously mentioned customer was set to use UTC time, 
 but had the checkbox set for "adjust for daylight savings"  Well, there 
 is no daylight savings in UTC, but Windows still seemed to think during 
 sysprep that it was a good idea during certain dates of year to set the 
 BIOS clock ahead one hour.  Since we booted twice during sysprep, all 
 clocks went out the door off by 2 hours.  This did not go over well with 
 said customer, and we had to recall all the systems so they could be set 
 properly (yes, I'm not making this up, we had to boot these systems to 
 our network, which automatically set the time, and then shut them down).

If I was Prez my first Executive Order would be to get rid of daylight savings time. Just doing that would probably add 1% to the GDP! "Dear Mr. President, there are too many states nowadays. Please eliminate three. I am not a crackpot." -- Grandpa Simpson
May 14 2010
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Alex Makhotin wrote:
 Walter Bright wrote:
 You can import only those names you wish. See static imports, renamed 
 imports and selective imports in 
 http://www.digitalmars.com/d/2.0/module.html

OK, 'static import' combination seems to force use of fully qualified name.

Isn't that exactly what you asked for? I'm confused.
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
Walter Bright wrote:
 Isn't that exactly what you asked for? I'm confused.

I'm confused of lots of typing. I prefer simplicity. -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Alex Makhotin wrote:
 Walter Bright wrote:
 Isn't that exactly what you asked for? I'm confused.

I'm confused of lots of typing. I prefer simplicity.

Program in C# without an IDE and then come back and say that again :-P
May 14 2010
parent reply Alex Makhotin <alex bitprox.com> writes:
Ary Borenszweig wrote:
 Program in C# without an IDE and then come back and say that again :-P

I know what you mean. But I mainly dislike the C# because of the large performance hit(especially in program with several threads which use DllImports etc.). Till there's available hardware IL native processors(if they are planned). -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 14 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Alex Makhotin

Till there's available hardware IL native processors(if they are planned).<

I think Sun did plan something like a Java processor, but the idea has not produced something good and usable. So I am kinda sure there are no plans for that. Bye, bearophile
May 14 2010
prev sibling next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-05-14 21:19:38 -0400, Alex Makhotin <alex bitprox.com> said:

 OK, 'static import' combination seems to force use of fully qualified 
 name. Requires a lot of typing of the fully names for imported classes.
 A lot of typing only for the sake of one global variable.

Instead of using 'static import' you can also do a *selective* import, like this: import Server.TestM1 : name; Now, only the 'name' symbol is imported (and if there is no public 'name' symbol, you get an error). Isn't that what you want? I do this all the time when importing symbols from modules not under my control. It's a good way to document what you're actually using, and it also prevents conflicts in the event the external module is updated. But for modules which are tightly coupled together, importing specifically each and every name is quite tiresome and often pointless, so I do not specify the list of symbols. I really like the way import works in D. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
May 14 2010
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 C# sucks when importing conflicting names.  I've dealt with it, and you 
 simply have to refer to the fully qualified name to be unambiguous.  
 With D, I can rename the less used one at import time to only have to 
 rewrite some of them.  This does not ruin the experience for anyone else 
 who uses only one of the modules.  Note that D refuses to compile 
 ambiguous symbols, so the problem is not that it blindly chooses one.

D actually does one better for functions of the same name appearing in multiple imports. It will still compile them as long as the overloads do not conflict, i.e. the space of arguments each will accept is disjoint. Only if the overloads conflict is an ambiguity error generated. For example: --- module a --- void foo(long i); --- module b --- void foo(ulong i); void foo(char[3] a); ---------------- import a, b; foo(1); // error, ambiguous char[3] a; foo(a); // no problem, chooses b.foo(char[3]) ----------------- I don't know any other language that handles this nearly as nicely. As for misspelling a name where the misspelling matches a name in another scope, or not declaring a name and that name matches a name in another scope, I don't see any way the compiler could detect such mistakes.
May 14 2010
prev sibling parent reply Alex Makhotin <alex bitprox.com> writes:
In previous post I was unsatisfied about the much typing in the D 
language to solve the globals problem.
And what came next is I realized the alternative: Go Programming Language.
Among the other significant advantages(goroutines etc.) it claims *less 
typing*. Reading the newsgroups, finally I go strait to the specification:

Excerpt from http://golang.org/doc/go_spec.html
 Assume we have compiled a package containing the package clause package math,
which exports function Sin, and installed the compiled package in the file
identified by "lib/math". This table illustrates how Sin may be accessed in
files that import the package after the various types of import declaration.
 
 Import declaration          Local name of Sin
 
 import   "lib/math"         math.Sin
 import M "lib/math"         M.Sin
 import . "lib/math"         Sin
 

I think that's better than in D. By default it requires me to access fully qualified name of the global. Renamed import doesn't require '= '. Explicit period required to use exported name without prefix. I like less typing, I like the Go! -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
May 15 2010
parent Walter Bright <newshound1 digitalmars.com> writes:
Alex Makhotin wrote:
 Excerpt from http://golang.org/doc/go_spec.html
 Assume we have compiled a package containing the package clause 
 package math, which exports function Sin, and installed the compiled 
 package in the file identified by "lib/math". This table illustrates 
 how Sin may be accessed in files that import the package after the 
 various types of import declaration.

 Import declaration          Local name of Sin

 import   "lib/math"         math.Sin
 import M "lib/math"         M.Sin
 import . "lib/math"         Sin

I think that's better than in D. By default it requires me to access fully qualified name of the global. Renamed import doesn't require '= '. Explicit period required to use exported name without prefix. I like less typing, I like the Go!

Yeah, but you have to type the two quotes. Too much typing for me!
May 15 2010
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:hsk611$1utm$1 digitalmars.com...
 Nick Sabalausky:

 // Vastly superior alternative to "import foolib.*;" which D
 // (fortunately) doesn't even have anyway.
 module foolib.all;

What's vastly superior in it? Its unformalized nature?

In Java circles, and probably some others too, "import foo.*;" is widely considered bad practice. They have a number of reasons for avoiding its use. I don't mean to avoid mentioning them, but I don't have much time ATM, I'm sure you can easily google it though. But basically, there are known problems with it, and those problems are mitigated by using the "import foo.all;" idiom.
May 14 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Nick Sabalausky:
 In Java circles, and probably some others too, "import foo.*;" is widely 
 considered bad practice.

I know this problem in Python and I know about a similar (but not equal, because Java is statically typed) problem in Java. But I think you have not grasped the whole D module situation yet. In a system lot of complexity comes from interactions between its subsystems. If some of such interactions are unwanted the system behaviour can become unpredictable. The subsystems in a D program are its modules. The purpose of a well designed module system is to remove a source of unwanted complexity, it must remove unwanted interactions between modules. Explicit is better than implicit. You want to explicitly state what interactions you want. Sometimes static imports can be useful, but they are the antitheses of a module system (just as casts are ways to punch holes in a type system). Bye, bearophile
May 14 2010
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Leandro Lucarella wrote:
 Python have import foo.*; and you can controll it the same way you can in
 D, except that if you don't do any fine control the default is to export
 everything.
 
 I think D is missing a feature here, not fixing or mitigating anything.

It's deliberately missing it. If the designer of a package wants a convenient way for the user to import everything in the package, all he has to do is create an all.d module which publicly imports everything.
May 14 2010
parent Walter Bright <newshound1 digitalmars.com> writes:
Leandro Lucarella wrote:
 Yes, that's exactly what Nick said in the mail I was replying, I just
 wanted to note that Nick was not right saying that not having import
 foo.*; is better because people say is a "bad practice" in Java. You can
 do better than hava and have the feature in a safe, useful way. Then, you
 might still like it or not. I guess you and Nick don't like; I do (even
 when I practically never use it, I like knowing it's there for the few
 quick & dirty stuff where is handy =P).

You're right in that I don't like it. It's just too sloppy for me. For example, if the user's directory is missing a file for whatever reason, you're not going to get a useful error message out of the compiler. The compiler cannot know that foo.bar is required for successful compilation with foo.* And yes, having the wrong set of files in a directory, missing files, extra files, etc., is a very common problem, even for experienced programmers. I had that problem just the other day when I tried to do a compile on my laptop and discovered that my script to copy files to the laptop had errored out on a couple of them.
May 14 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Alex Makhotin <alex bitprox.com> wrote:

 I don't want to deal with the bad design of someone's module.
 For example.

You're gonna have to deal with that in all other ways. Why is this functionality so important to get rid of?
 module Server.TestM2;
 const string name = "New Name";

 module Server.TestM1;
 public import Server.TestM2;

 module Server.Main;
 private import Server.TestM1;

In the scope of Server.Main module the global variable 'name' is visible. That should not be so.

Yes it should. The designer of TestM1 decided so. Just like he decided so for all classes, structs, enums, and whatnots in TestM1. Perhaps you only want TestM1.foo? Then import it properly, so you don't need to worry about it (That would be import TestM1 : foo. Or, if you want your bondage: static import).
 The use of globals is error prone. I consider it a bad practice.
 In the extreme case I would like to see D's specification restricting  
 globals as C# does.

Gods, no. -- Simen
May 14 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 14 May 2010 21:19:38 -0400, Alex Makhotin <alex bitprox.com> wrote:

 Walter Bright wrote:
 You can import only those names you wish. See static imports, renamed  
 imports and selective imports in  
 http://www.digitalmars.com/d/2.0/module.html

OK, 'static import' combination seems to force use of fully qualified name. Requires a lot of typing of the fully names for imported classes. A lot of typing only for the sake of one global variable. The renamed import also requires countless typing using the renamed prefix. The specific imports require me to select what to import(again all the work on me, not the tool I use). Oh no. Every time I desire to use some member of the import I type 'import module : memberiwant'.

You are blowing this way out of proportion. I don't ever remember having to rename or statically import std.stdio. D's default is to import all names into your local namespace, that is good enough 99% of the time. Sometimes you need to rename things, or force static resolution. In those cases, the tools are there. But you want to require globals to be referred to by fully qualified names? How does it sound that you have to write std.stdio.writeln every time you want to write something? The problem as I see it is that std.compiler has a poorly named global variable. You can rename that variable when importing, lessening your pain, or you can statically import it, making your job a little more difficult, but more precise. Or you can get the author to change it. There are several options, and all of them seem way way more attractive than ruining the syntax for the rest of the well-named module globals. 'name' just is a single bad global name, it does not make all globals badly named.
 As far as I know the C# hasn't such complications, why should D?

C# sucks when importing conflicting names. I've dealt with it, and you simply have to refer to the fully qualified name to be unambiguous. With D, I can rename the less used one at import time to only have to rewrite some of them. This does not ruin the experience for anyone else who uses only one of the modules. Note that D refuses to compile ambiguous symbols, so the problem is not that it blindly chooses one. You also have to refer to all functions and symbols inside a class, if it's not the class you are writing. Without the IDE, this would be torture. A good example is writing output -- Console.WriteLine(x). I'll take writeln(x) any day over that. C# is not the model to follow. -Steve
May 14 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 14 May 2010 21:01:15 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Alex Makhotin wrote:
 Andrei Alexandrescu wrote:
 Date: Sat, 15 May 2010 04:46:08 +0300

 That's a bit in the future. Any chance I could impose on you to change  
 your system time?

the Windows resets it in BIOS. So I set the Linux to use the UTC(as in BIOS). To use the local time it requires me to set the clock back on 2 hours. I don't know why Windows resets BIOS clock...

Interesting. Can you instruct Windows to sync using the Internet? And does Windows have the right time zone set?

Having dealt with a customer that insisted we always have the time set properly, I can tell you that Windows uses the BIOS time as local time, Linux *can* use the BIOS time as local time, but generally assumes it is set to UTC (and adjusts it's working clock accordingly). During halt, it saves the clock back to the BIOS in case anything has changed, and generally uses UTC. What is actually happening is that Windows *is* setting the time via the internet, and then overwriting the BIOS time :) AFAIK, the only way to fix this is to configure linux to treat the BIOS time as local time. Do a man on hwclock, and read the notes at the bottom. Since every Linux system has its own init scheme, it probably varies from system to system. I'm pretty sure the kernel reads the HW clock the first time, but once it reads it, it doesn't use it anymore. halt usually sets the clock using hwclock. You can probably override the kernel time by doing a hwclock read very early in the process, but that means the kernel will think the time is off by whatever your timezone is when it is starting up. This would probably best be done in the initrd before the filesystem is mounted. There may be kernel parameters that force this mode of reading the clock. Funny anecdote (actually not really funny at the time): Our windows test image for previously mentioned customer was set to use UTC time, but had the checkbox set for "adjust for daylight savings" Well, there is no daylight savings in UTC, but Windows still seemed to think during sysprep that it was a good idea during certain dates of year to set the BIOS clock ahead one hour. Since we booted twice during sysprep, all clocks went out the door off by 2 hours. This did not go over well with said customer, and we had to recall all the systems so they could be set properly (yes, I'm not making this up, we had to boot these systems to our network, which automatically set the time, and then shut them down). -Steve
May 14 2010
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Alex Makhotin <alex bitprox.com> wrote:

 bearophile wrote:
 Note that D module system is not modelled on C#.

I think that to become successful competitor for such languages as C#, the D language requires improvement. In the bug I encountered, I mistyped the variable and it *matched the global variable accidentally*. I was unaware of it because the compiler was silent, but IMHO it, at least, should give me a warning. It's not possible in C#. That's what I meant.

Example: ------------------ module a; class foo { } ------------------ module b; import a; class fool { } void bar( ) { auto f = new foo( ); // Oh noes, I meant fool, not foo! } ------------------ As you can see, this is perfectly possible with things other than global variables. One could even imagine mistyping a module name and still getting a program that compiles. Now how does C# make that impossible? -- Simen
May 15 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Alex Makhotin <alex bitprox.com> wrote:

 I think this is a bad design of the language.
 Global variables are bad things.
 C# doesn't have them.
 In this sense I like C# which prohibits any fields or methods in  
 namespaces.

Gods, I hate that. I like to restrict bondage to my bedroom, thank you very much. This is one of the reasons I try to avoid C#/Java when I can. There are functions that do not belong in a silly namespace, and there should be ways to define those.
 But I also can evade by using explicit 'public import'. This leads to  
 bugs.

At the same time, if one module should be a superset of another, public import is the right way to do just that. If one has to provide aliases to everything in the submodule, a lot of work goes to waste, and one must keep the modules synced. In short: Public imports have their place, but don't use them if there's no need. (like with just about everything else) -- Simen
May 14 2010
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Nick Sabalausky, el 14 de mayo a las 15:56 me escribiste:
 "bearophile" <bearophileHUGS lycos.com> wrote in message 
 news:hsk611$1utm$1 digitalmars.com...
 Nick Sabalausky:

 // Vastly superior alternative to "import foolib.*;" which D
 // (fortunately) doesn't even have anyway.
 module foolib.all;

What's vastly superior in it? Its unformalized nature?

In Java circles, and probably some others too, "import foo.*;" is widely considered bad practice. They have a number of reasons for avoiding its use. I don't mean to avoid mentioning them, but I don't have much time ATM, I'm sure you can easily google it though. But basically, there are known problems with it, and those problems are mitigated by using the "import foo.all;" idiom.

Python have import foo.*; and you can controll it the same way you can in D, except that if you don't do any fine control the default is to export everything. I think D is missing a feature here, not fixing or mitigating anything. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ----------------------------------------------------------------------
May 14 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
div0 <div0 users.sourceforge.net> wrote:

 Actually C# does have global variables;
 any public static member of a class is a global variable.

And here we are down to arguing semantics. Is a variable global if it does not pollute the global namespace? I believe this to have been Alex's intention, and it is a fairly common definition of global variable. One could certainly argue otherwise, but I hardly see the value in such a discussion, be the truth this way or the other. Simen
May 14 2010
prev sibling parent Leandro Lucarella <llucax gmail.com> writes:
Walter Bright, el 14 de mayo a las 14:54 me escribiste:
 Leandro Lucarella wrote:
Python have import foo.*; and you can controll it the same way you can in
D, except that if you don't do any fine control the default is to export
everything.

I think D is missing a feature here, not fixing or mitigating anything.

It's deliberately missing it.

I didn't say it's deliberate. I know is deliberate =) I just don't think is a good idea.
 If the designer of a package wants a convenient way for the user to
 import everything in the package, all he has to do is create an all.d
 module which publicly imports everything.

Yes, that's exactly what Nick said in the mail I was replying, I just wanted to note that Nick was not right saying that not having import foo.*; is better because people say is a "bad practice" in Java. You can do better than hava and have the feature in a safe, useful way. Then, you might still like it or not. I guess you and Nick don't like; I do (even when I practically never use it, I like knowing it's there for the few quick & dirty stuff where is handy =P). -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ----------------------------------------------------------------------
May 14 2010