www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 3503] New: [module] Imports should be static by default

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503

           Summary: [module] Imports should be static by default
           Product: D
           Version: future
          Platform: Other
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: llucax gmail.com


--- Comment #0 from Leandro Lucarella <llucax gmail.com> 2009-11-13 16:19:15
PST ---
Importing all symbols of a module in the current namespace is usually a bad
idea (except for very small things or scripting-like programs).

The semantics of:
import foo;

should be replaced by:
static import foo;

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 13 2009
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #1 from Leandro Lucarella <llucax gmail.com> 2009-11-13 16:24:36
PST ---
See bug 3504 for an alternative syntax to get the old behavior.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 13 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #2 from Leandro Lucarella <llucax gmail.com> 2009-11-13 16:30:19
PST ---
See bug 3505 for a related enhancement that will play very well with this
suggestion.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 13 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503


Bill Baxter <wbaxter gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |wbaxter gmail.com


--- Comment #3 from Bill Baxter <wbaxter gmail.com> 2009-11-14 06:39:51 PST ---
I'm torn on this one.  I used to be all for it, but looking over my code,
non-static imports are by far the majority.

But I know in Python static default works out well.  And Python folks generally
encourage to always use either static or renamed import.

But I think Python does not have the ability to report about conflicting
symbols in different modules.  That's a huge difference.  If module "foo" and
module "bar" both have a blarf() function, then I think it's just the last
import who's definition wins.   That's a recipe for disaster.  So Python users
have to be very very careful about what they stick in the default namespace.

D doesn't have that problem since the compiler will tell you if two symbols
with the same name get imported.

Still, static/renamed imports are certainly good for making code more readable.
 If there are 20 imports and I see a call to "format()" somewhere, it's a pain
to try to track down which of those modules defines "format()".  But this is
something a good IDE remedy, with a "Go to definition" button.  


Another thing to consider is that usually D modules have at least a package,
like foo.bar.  And in the case of Tango often several. In most cases that makes
the full module name too long for you to want to type it again and again.   So
static import is almost never what you want.  You either want full import, or
you want renamed import.  So by making this change you make the default the
least useful thing, which just seems the wrong choice for a default.

If the default were something like a renamed import, using the leaf name as the
name, that might be reasonable:
I.e.

     import std.stdio;

Would mean the same as this currently:

     import stdio = std.stdio;

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #4 from Leandro Lucarella <llucax gmail.com> 2009-11-14 08:21:45
PST ---
(In reply to comment #3)
 Another thing to consider is that usually D modules have at least a package,
 like foo.bar.  And in the case of Tango often several. In most cases that makes
 the full module name too long for you to want to type it again and again.   So
 static import is almost never what you want.  You either want full import, or
 you want renamed import.  So by making this change you make the default the
 least useful thing, which just seems the wrong choice for a default.
 
 If the default were something like a renamed import, using the leaf name as the
 name, that might be reasonable:
 I.e.
 
      import std.stdio;
 
 Would mean the same as this currently:
 
      import stdio = std.stdio;

Exactly, that's what bug 3505 is all about, I think if this is implemented, bug 3505 should be implemented too (and maybe bug 3504). I filled 2 separated bugs for them because they are indeed orthogonal features, even when they play better together. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #5 from Bill Baxter <wbaxter gmail.com> 2009-11-14 08:34:15 PST ---
(In reply to comment #4)
 I.e.
 
      import std.stdio;
 
 Would mean the same as this currently:
 
      import stdio = std.stdio;

Exactly, that's what bug 3505 is all about, I think if this is implemented, bug 3505 should be implemented too (and maybe bug 3504). I filled 2 separated bugs for them because they are indeed orthogonal features, even when they play better together.

Ah, I saw #3504 but missed #3505. I see. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #6 from Leandro Lucarella <llucax gmail.com> 2009-11-14 09:49:29
PST ---
This is an example of how things should work if this bug and bug 3504 and bug
3505 gets implemented:

mod.d:  
    void f() {}

pkg/a.d:
    void f() {}

pkg/pkg.d:
    void f() {}

some/large/package/a_module.d:
    void f() {}

x.d:
1   import mod: *; // doesn't introduce the symbol 'mod'
2   import pkg: *; // introduce the symbol 'pkg' but refering to pkg.pkg
3   import some.large.package.a_module; // introduce the symbol 'a_module'
4   static import some.large.package.a_module;
5               
6   void main() {              
7       f();          // mod.f (from line 1)
8       a.f();        // pkg.a.f (from line 2)
9       pkg.f();      // pkg.pkg.f (from line 2)     
10      a_module.f(); // some.large.package.a_module (from line 3)
11      some.large.package.a_module.f(); // (from line 4)
12  }

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503


David Simcha <dsimcha yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dsimcha yahoo.com


--- Comment #7 from David Simcha <dsimcha yahoo.com> 2009-11-14 10:09:24 PST ---
IMHO the purpose of a module system is to stay the heck out of the user's way
and let the user get on w/ solving the real problem.  It should only make noise
when there's a real ambiguity.  Making imports unnecessarily verbose,
complicated, or fine-grained is just a bad idea.  D already deals well with
collisions.  When there's not a collision, I personally prefer to have stuff
"just work" without having to care that there are namespaces.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #8 from Leandro Lucarella <llucax gmail.com> 2009-11-14 10:32:18
PST ---
(In reply to comment #7)
 IMHO the purpose of a module system is to stay the heck out of the user's way
 and let the user get on w/ solving the real problem.  It should only make noise
 when there's a real ambiguity.  Making imports unnecessarily verbose,
 complicated, or fine-grained is just a bad idea.  D already deals well with
 collisions.  When there's not a collision, I personally prefer to have stuff
 "just work" without having to care that there are namespaces.

What you say is good for *writing* code, but it's *really* bad for *reading* code and tracking dependencies. It's subject to highjacking too (in very, very weird and special cases, I'm aware of that ;). Anyways, in conjunction with bug 3504 and 3505 I'm suggesting just a change on the default, you can get the same behavior with import *. They idea is to make the default safer and less typing. Now if you want the "unsafe" (pollute everything) behavior you type: import std.stdio; import std.algorithm; import std.conv; writeln(); sort(); to(); And if you want a safe way (but very verbose) to import things, you have to do: static { // not so much extra typing import std.stdio; import std.algorithm; import std.conv; } // lot of extra typing (repeating std.) std.stdio.writeln(); std.algorithm.sort(); std.conv.to(); If you want a reasonable, not-so-much-typing safe way to import things, you have to do: // some extra typing (and repeated code) import stdio = std.stdio; import algorithm = std.algorithm; import conv = std.conv; } // no repetition, not so much typing stdio.writeln(); algorithm.sort(); conv.to(); If all the features I'm proposing are implemented, the reasonable, not-so-much-typing safe way to import things is the default: import std.stdio; import std.algorithm; import std.conv; stdio.writeln(); algorithm.sort(); conv.to(); And you can get the promiscous old behavior with a little more typing (3 chars per import): import std.stdio: *; import std.algorithm: *; import std.conv: *; writeln(); sort(); to(); -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #9 from David Simcha <dsimcha yahoo.com> 2009-11-14 10:54:07 PST ---
(In reply to comment #8)
 (In reply to comment #7)
 IMHO the purpose of a module system is to stay the heck out of the user's way
 and let the user get on w/ solving the real problem.  It should only make noise
 when there's a real ambiguity.  Making imports unnecessarily verbose,
 complicated, or fine-grained is just a bad idea.  D already deals well with
 collisions.  When there's not a collision, I personally prefer to have stuff
 "just work" without having to care that there are namespaces.

What you say is good for *writing* code, but it's *really* bad for *reading* code and tracking dependencies. It's subject to highjacking too (in very, very weird and special cases, I'm aware of that ;).

As for reading code, I totally disagree. Syntactic noise and unnecessary verbosity makes code harder to read. As far as dependency tracking, 1. That's what IDEs are for. If D gets off the ground, it will eventually have a good IDE. 2. What do you do more, write/read code or track dependencies? A fundamental tenet of good interface design is that you should not have to tell the interface stuff it already knows. If there are no collisions, then the language (which is the interface to the code generator in this case) already knows what function you're referring to when you call, for example, sort(). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #10 from Bill Baxter <wbaxter gmail.com> 2009-11-14 11:06:28 PST ---
(In reply to comment #7)
 IMHO the purpose of a module system is to stay the heck out of the user's way
 and let the user get on w/ solving the real problem.  It should only make noise
 when there's a real ambiguity.  Making imports unnecessarily verbose,
 complicated, or fine-grained is just a bad idea.  D already deals well with
 collisions.  When there's not a collision, I personally prefer to have stuff
 "just work" without having to care that there are namespaces.

With this proposal you could keep using them the same way just by adding ":*" at the end of each module name. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #11 from Leandro Lucarella <llucax gmail.com> 2009-11-14 12:34:31
PST ---
(In reply to comment #9)
 (In reply to comment #8)
 (In reply to comment #7)
 IMHO the purpose of a module system is to stay the heck out of the user's way
 and let the user get on w/ solving the real problem.  It should only make noise
 when there's a real ambiguity.  Making imports unnecessarily verbose,
 complicated, or fine-grained is just a bad idea.  D already deals well with
 collisions.  When there's not a collision, I personally prefer to have stuff
 "just work" without having to care that there are namespaces.

What you say is good for *writing* code, but it's *really* bad for *reading* code and tracking dependencies. It's subject to highjacking too (in very, very weird and special cases, I'm aware of that ;).

As for reading code, I totally disagree. Syntactic noise and unnecessary verbosity makes code harder to read.

I think you're mistaking syntactic noise with semantic information. Writing the module name *does* have semantic information, even when you can find it too verbose. It's not the same to use, for example, path.join() than string.join(), the module carries semantic information. Of course you can name the functions path_join() and string_join(), but that kind of defeat the point of a module system.
 As far as dependency tracking,
 
 1.  That's what IDEs are for.  If D gets off the ground, it will eventually
 have a good IDE.

I don't think a language should depend on a good IDE, if you take that too far you end up with Java. I really think the "the IDE should do that" is the worse argument ever. I don't even use a IDE (not because there is no good IDE for D, I just don't use IDEs for any languages). But this is besides the point, because this discussion is just about personal preferences.
 2.  What do you do more, write/read code or track dependencies?

read the code and track dependencies.
 A fundamental tenet of good interface design is that you should not have to
 tell the interface stuff it already knows.  If there are no collisions, then
 the language (which is the interface to the code generator in this case)
 already knows what function you're referring to when you call, for example,
 sort().

But I don't know where that sort came from. I'm missing important information (when reading a program). You either have very long and descriptive function names, or you use the module system properly. I agree that when you use a symbol a lot is desirable to have it imported in the main namespace, but in that case you can always use selective imports. With selective imports you get the less typing for things you use a lot *plus* you can know where every symbol came from. And again, we are only talking about changing the *default*, you can always use import * if you want to. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 14 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503


Nick Sabalausky <cbkbbejeap mailinator.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |cbkbbejeap mailinator.com


--- Comment #12 from Nick Sabalausky <cbkbbejeap mailinator.com> 2009-11-15
23:46:52 PST ---
Another problem with this idea is that the default behavior would kill array
property syntax:

-------
module foo;
void useArray(int[] a) {...}
-------
module main;
import foo;
void main()
{
    int a = [1,2,3];
    a.useArray(); // Breaks under this proposal
    a.foo.useArray(); // Invalid regardless
}
-------

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 15 2009
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3503



--- Comment #13 from Leandro Lucarella <llucax gmail.com> 2009-11-16 12:46:55
PST ---
(In reply to comment #12)
 Another problem with this idea is that the default behavior would kill array
 property syntax:
 
 -------
 module foo;
 void useArray(int[] a) {...}
 -------
 module main;
 import foo;
 void main()
 {
     int a = [1,2,3];
     a.useArray(); // Breaks under this proposal
     a.foo.useArray(); // Invalid regardless
 }
 -------

Doesn't kills it, it only make it more explicit: module main; import foo: useArray; void main() { int a = [1,2,3]; a.useArray(); // Breaks under this proposal } Again, bug 3504 is a good companion for this proposal for some special cases (like std.string). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 16 2009