www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Thoughts about modules

reply "Andrei Khropov" <andkhropov nospam_mtu-net.ru> writes:
Hi all,

I just want to share some thoughts about modules and their import.

When we want to import a module we should decide on 2 things:

1) do we want to import names from the module to the local namespace?

2) do we want this import to be propagated to the files that include the module 
we import in?

In D the second question can be answered "no" by adding "private" modifier to
the import statement, but the first question is always answered "Yes".
I think it's not a good idea. My opinion is that notions 
"I want to use a module" and "I want names in the module to be imported in the
current scope" should be separated.

Like in C++ we have (of course C++ don't have true modules but I want to show
an example):
---------------------------
#include <iostream>		// "Import" a module

using namespace std;		// import declarations in "std" in the current scope
---------------------------

So I would like to see a possibility to answer "no" to the first question and
use fully qualified names if I want to avoid name conflicts.

So maybe default behavior of "import" should be changed (and later symbols
could be imported to the current scope by some kind of "alias" statement) or an
alternative declaration to import modules ("using" ?) could be added to mean
"use declarations from the module but keep them in that module's namespace".

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

Another thing I would like (maybe a beyond 1.0 feature) is that compiled
modules should contain both the module interface and implementation so we don't
need to have separate "d/di" interface files and "lib" with implementation.

When compiler finds an "import" declaration it finds a module (or maybe whole
package of modules in one file), imports its symbol table and also passes
module name to the linker so we don't have to pass module name as the linker's
parameter explicitly as it has already been declared in the source files.
 

-- 
AKhropov
Jun 27 2006
parent reply "Derek Parnell" <derek psych.ward> writes:
On Wed, 28 Jun 2006 01:18:31 +1000, Andrei Khropov  =

<andkhropov nospam_mtu-net.ru> wrote:

 Hi all,

 I just want to share some thoughts about modules and their import.

 When we want to import a module we should decide on 2 things:

 1) do we want to import names from the module to the local namespace?

 2) do we want this import to be propagated to the files that include t=

 module
 we import in?

 In D the second question can be answered "no" by adding "private"  =

 modifier to
 the import statement, but the first question is always answered "Yes".=

I'm trying to make sure that I understand your terminology here. By the phrase "import names from the module to the local namespace", I = read that as saying that if names from an imported module come into the = = importing module's namespace, it would mean that the importing module = cannot declare a name that is contained in the imported module - because= = that would be a duplicated name in the same namespace. But that's not what happens with D so therefore I'm not sure what you me= an = by "import names from the module to the local namespace". To access a name from an imported module that has the same name as a = member in the importing module, you must qualify the imported name with = = the module name. -----------EXAMPLE --------- module mod1; public int AA =3D 2; ---------------------------- module sample; import std.stdio; import mod1; public real AA =3D 3.21; void main() { writefln("%s %s", AA, mod1.AA); } ----------------- Am I misunderstanding you? -- = Derek Parnell Melbourne, Australia
Jun 27 2006
parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Derek Parnell wrote:
 On Wed, 28 Jun 2006 01:18:31 +1000, Andrei Khropov 
 <andkhropov nospam_mtu-net.ru> wrote:
 
 Hi all,

 I just want to share some thoughts about modules and their import.

 When we want to import a module we should decide on 2 things:

 1) do we want to import names from the module to the local namespace?

 2) do we want this import to be propagated to the files that include 
 the module
 we import in?

 In D the second question can be answered "no" by adding "private" 
 modifier to
 the import statement, but the first question is always answered "Yes".

I'm trying to make sure that I understand your terminology here. By the phrase "import names from the module to the local namespace", I read that as saying that if names from an imported module come into the importing module's namespace, it would mean that the importing module cannot declare a name that is contained in the imported module - because that would be a duplicated name in the same namespace. But that's not what happens with D so therefore I'm not sure what you mean by "import names from the module to the local namespace". To access a name from an imported module that has the same name as a member in the importing module, you must qualify the imported name with the module name. -----------EXAMPLE --------- module mod1; public int AA = 2; ---------------------------- module sample; import std.stdio; import mod1; public real AA = 3.21; void main() { writefln("%s %s", AA, mod1.AA); } ----------------- Am I misunderstanding you? --Derek Parnell Melbourne, Australia

I'm betting he means being able to import a module in a way that it's names (entities) are available only as fully-qualified names, and so the base names are not "imported" to the importing module namespace/scope. It's the FQN import. Andrei, (and others) if you want to check out some previous discussion on this matter: http://www.digitalmars.com/d/archives/digitalmars/D/28423.html -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jun 27 2006
parent reply "Andrei Khropov" <andkhropov nospam_mtu-net.ru> writes:
Bruno Medeiros wrote:

 I'm betting he means being able to import a module in a way that it's names
 (entities) are available only as fully-qualified names, and so the base names
 are not "imported" to the importing module namespace/scope. It's the FQN
 import.
 
 Andrei, (and others) if you want to check out some previous discussion on
 this matter:  http://www.digitalmars.com/d/archives/digitalmars/D/28423.html

Yes, you're right. Thank you for the link, I'm quite new to D so I haven't already read all the 40000+ newsgroup messages huh :-). Basically your message is similar to mine in its subject but is much more detailed. But anyway, as far as I can see Walter's opinion is unknown. Is he satisfied with the present situation? -- AKhropov
Jun 27 2006
parent reply "Derek Parnell" <derek psych.ward> writes:
On Wed, 28 Jun 2006 08:18:40 +1000, Andrei Khropov  
<andkhropov nospam_mtu-net.ru> wrote:

 Bruno Medeiros wrote:

 I'm betting he means being able to import a module in a way that it's  
 names
 (entities) are available only as fully-qualified names, and so the base  
 names
 are not "imported" to the importing module namespace/scope. It's the FQN
 import.

 Andrei, (and others) if you want to check out some previous discussion  
 on
 this matter:   
 http://www.digitalmars.com/d/archives/digitalmars/D/28423.html

Yes, you're right.

 But anyway, as far as I can see Walter's opinion is unknown.
  Is he satisfied with the present situation?

I believe so. The curent situation is a syntax shortcut. No one is prevented from using FQN syntax, and in fact I try to use that form in my code, with the main exception being 'writefln' of course ;-) The benefit I can see from the shortcut form is that one can change modules without having to change references to members in that module, whereas with FQN usage one has to do a global find/replace over all your source code. The cost of not using FQN though is it does not keep well over time in terms of reading the code and have an understanding of it. Plus you can get caught out sometimes when introducing another import that causes name clashes. I'm not an advocate of either style of coding and I won't dictate to others either on this matter. I have a preference, as my fellow coders also have a preference, which may be different, and I'm okay with that. Why do you think that FQN syntax is demonstrable better than the current shortcut syntax? -- Derek Parnell Melbourne, Australia
Jun 27 2006
next sibling parent reply Sjoerd van Leent <svanleent gmail.com> writes:
Derek Parnell schreef:
 On Wed, 28 Jun 2006 08:18:40 +1000, Andrei Khropov 
 <andkhropov nospam_mtu-net.ru> wrote:
 
 Bruno Medeiros wrote:

 I'm betting he means being able to import a module in a way that it's 
 names
 (entities) are available only as fully-qualified names, and so the 
 base names
 are not "imported" to the importing module namespace/scope. It's the FQN
 import.

 Andrei, (and others) if you want to check out some previous 
 discussion on
 this matter:  
 http://www.digitalmars.com/d/archives/digitalmars/D/28423.html

Yes, you're right.

 But anyway, as far as I can see Walter's opinion is unknown.
  Is he satisfied with the present situation?

I believe so. The curent situation is a syntax shortcut. No one is prevented from using FQN syntax, and in fact I try to use that form in my code, with the main exception being 'writefln' of course ;-) The benefit I can see from the shortcut form is that one can change modules without having to change references to members in that module, whereas with FQN usage one has to do a global find/replace over all your source code. The cost of not using FQN though is it does not keep well over time in terms of reading the code and have an understanding of it. Plus you can get caught out sometimes when introducing another import that causes name clashes. I'm not an advocate of either style of coding and I won't dictate to others either on this matter. I have a preference, as my fellow coders also have a preference, which may be different, and I'm okay with that. Why do you think that FQN syntax is demonstrable better than the current shortcut syntax? --Derek Parnell Melbourne, Australia

The thing I'd see useful here would be: import fb : foo.bar; Indicates all methods from module "foo.bar" are in local namespace "fb" import $ : foo.bar; Would be the same as import foo.bar : foo.bar; Regards, Sjoerd
Jun 29 2006
next sibling parent reply kris <foo bar.com> writes:
Sjoerd van Leent wrote:
 The curent situation is a syntax shortcut. No one is prevented from 
 using FQN syntax, and in fact I try to use that form in my code, with 
 the main exception being 'writefln' of course ;-)

 The benefit I can see from the shortcut form is that one can change 
 modules without having to change references to members in that module, 
 whereas with FQN usage one has to do a global find/replace over all 
 your source code.

 The cost of not using FQN though is it does not keep well over time in 
 terms of reading the code and have an understanding of it. Plus you 
 can get caught out sometimes when introducing another import that 
 causes name clashes.

 I'm not an advocate of either style of coding and I won't dictate to 
 others either on this matter. I have a preference, as my fellow coders 
 also have a preference, which may be different, and I'm okay with that.

 Why do you think that FQN syntax is demonstrable better than the 
 current shortcut syntax?

 --Derek Parnell
 Melbourne, Australia

The thing I'd see useful here would be: import fb : foo.bar; Indicates all methods from module "foo.bar" are in local namespace "fb" import $ : foo.bar; Would be the same as import foo.bar : foo.bar; Regards, Sjoerd

or perhaps import x.y.z as foo; Where the "as <name>" is optional
Jun 29 2006
parent Johan Granberg <lijat.meREM OVEgmail.com> writes:
kris wrote:
 or perhaps import x.y.z as foo;
 
 Where the "as <name>" is optional

implements this.
Jun 29 2006
prev sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Sjoerd van Leent wrote:
 The thing I'd see useful here would be:
 
 import fb : foo.bar;
 
 Indicates all methods from module "foo.bar" are in local namespace "fb"
 
 import $ : foo.bar;
 
 Would be the same as
 
 import foo.bar : foo.bar;
 
 Regards,
 Sjoerd

It is worth reviewing the Python syntax for imports here, I think. Python uses the FQN import by default, but supports importing unqualified names as well. So, given a module foo.bar with a function inside named baz, we can say:
 import foo.bar
 foo.bar.baz()



To import a module and make it available as an alias, you'd say:
 import foo.bar as fb
 fb.baz()



To only import a specific name from a module, you'd say:
 from foo.bar import baz
 baz()



(This is a feature I'd love to see in D, actually. The ability to only import a specific name from a module would be great.) To import a specific name under an alias, you'd say:
 from foo.bar import baz as b
 b()      # calls foo.bar.baz()



If you want to import all names from a module into the current namespace (the D style of import), you can say:
 from foo.bar import *
 baz()



It's worth noting that, for all of these except the last form, all names that are imported are explicitly mentioned in the import statement. I think this is a highly desirable state of affairs. It is for this reason that frivolous use of the "from x import *" form is somewhat frowned upon. It is quite useful for importing some large libraries, however (certain GUI libraries, for instance), so there are certainly valid uses for it. The visibility of imported names, then, follows naturally: # blah.py from foo.bar import baz # EOF
 import blah
 blah.baz()   # calls foo.bar.baz
 from blah import baz
 baz()        # calls foo.bar.baz



-Kirk McDonald
Jun 29 2006
next sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Kirk McDonald wrote:
 Sjoerd van Leent wrote:
 
 The thing I'd see useful here would be:

 import fb : foo.bar;

 Indicates all methods from module "foo.bar" are in local namespace "fb"

 import $ : foo.bar;

 Would be the same as

 import foo.bar : foo.bar;

 Regards,
 Sjoerd

It is worth reviewing the Python syntax for imports here, I think. Python uses the FQN import by default, but supports importing unqualified names as well.

Some additional features of Python. :-)
 So, given a module foo.bar with a function inside named baz, we can say:
 
  >>> import foo.bar
  >>> foo.bar.baz()
 

Like D, you can say e.g.:
 import foo.bar, foo.baz, foo.boo



 To import a module and make it available as an alias, you'd say:
 
  >>> import foo.bar as fb
  >>> fb.baz()
 
 To only import a specific name from a module, you'd say:
 
  >>> from foo.bar import baz
  >>> baz()
 

You can also say:
 from foo.bar import baz, boo, blah



Which is quite useful if you just need a handful of names from a module.
 (This is a feature I'd love to see in D, actually. The ability to only 
 import a specific name from a module would be great.)
 
 To import a specific name under an alias, you'd say:
 
  >>> from foo.bar import baz as b
  >>> b()      # calls foo.bar.baz()
 

This can similiarly be expanded as:
 from foo.bar import baz as b, boo as o, blah as a



 If you want to import all names from a module into the current namespace 
 (the D style of import), you can say:
 
  >>> from foo.bar import *
  >>> baz()
 
 It's worth noting that, for all of these except the last form, all names 
 that are imported are explicitly mentioned in the import statement. I 
 think this is a highly desirable state of affairs. It is for this reason 
 that frivolous use of the "from x import *" form is somewhat frowned 
 upon. It is quite useful for importing some large libraries, however 
 (certain GUI libraries, for instance), so there are certainly valid uses 
 for it.
 
 The visibility of imported names, then, follows naturally:
 
 # blah.py
 from foo.bar import baz
 # EOF
 
  >>> import blah
  >>> blah.baz()   # calls foo.bar.baz
  >>> from blah import baz
  >>> baz()        # calls foo.bar.baz
 
 -Kirk McDonald

Jun 29 2006
parent reply "Derek Parnell" <derek psych.ward> writes:
On Fri, 30 Jun 2006 07:09:47 +1000, Kirk McDonald  
<kirklin.mcdonald gmail.com> wrote:


 Some additional features of Python. :-)

But back to the question I asked ... Why is FQN syntax demonstrable better than the current shortcut syntax? Alternatively, why is ... import std.stdio; writefln( ... ); a bad thing? -- Derek Parnell Melbourne, Australia
Jun 29 2006
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Derek Parnell wrote:
 On Fri, 30 Jun 2006 07:09:47 +1000, Kirk McDonald  
 <kirklin.mcdonald gmail.com> wrote:
 
 
 Some additional features of Python. :-)

But back to the question I asked ... Why is FQN syntax demonstrable better than the current shortcut syntax? Alternatively, why is ... import std.stdio; writefln( ... ); a bad thing?

Here is a more illustrative example: [test1.d] module test1; const int foo = 10; // EOF [test2.d] import test1; import std.stdio; void main() { writefln("%s", foo); } // EOF The name "foo" comes from the module test1, of course. We know this because we are familiar with test1, and because it is a small module that we can easily examine the contents of. It is fairly obvious where "foo" comes from. However, imagine that "test1" is actually the main import point of a large package. Say it in turn imports dozens of modules, and foo actually comes from one of them. Now say you're importing more than one huge package like this, so now foo might come from anywhere. Now say that this is someone else's code, or even your own code from a few months after you wrote it. Goodness gracious, what does "foo" mean? Now, you might fully-qualify the name to make this obvious, but this can easily get cumbersome if you are using foo more than once. It suddenly becomes useful to write an alias: alias test1.foo foo; Now the person reading your source file can see this alias, right there in the same file, and they can know where this "foo" comes from. The Python syntax
 from test1 import foo



is simply a shortcut for this alias. By making it mandatory, we can always know where any name comes from, whether they are being fully-qualified, or imported on their own. Now, for something like writefln, which is a well-known name that everyone will recognize instantly, this is a bit of a burden. You'd have to type it a whole extra time at the top of the file! (Python manages to escape this by having the "print" keyword.) However, I feel this method scales better. -Kirk McDonald
Jun 29 2006
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Thu, 29 Jun 2006 14:45:23 -0700, Kirk McDonald wrote:

 Derek Parnell wrote:
 Why is FQN syntax demonstrable better than the current shortcut syntax?


 ...
 By making it mandatory, we can 
 always know where any name comes from, whether they are being 
 fully-qualified, or imported on their own.
 
 Now, for something like writefln, which is a well-known name that 
 everyone will recognize instantly, this is a bit of a burden. You'd have 
 to type it a whole extra time at the top of the file! 

So to summarize ... Mandatory fully qualified names makes it simple for a code reader to know in which module a member is located. But because that could be a burden to the code writer, the alias (or something similar) can be used to 'register' the FQN once in the code and allows the writer to use a short form of the name. Anyhow, I tried this coding style on Build just now and ended up with this... ------------------ import source; // Source File class alias source.ActivateVersion ActivateVersion; alias source.ActivateDebug ActivateDebug; alias source.SetKnownVersions SetKnownVersions; import util.str; // non-standard string routines. alias util.str.SetEnv SetEnv; alias util.str.GetEnv GetEnv; alias util.str.Expand Expand; alias util.str.ExpandEnvVar ExpandEnvVar; alias util.str.ends ends; alias util.str.begins begins; alias util.str.enquote enquote; alias util.str.strip ustrip; alias util.str.stripr ustripr; alias util.str.IsLike IsLike; alias util.str.YesNo YesNo; alias util.str.TranslateEscapes TranslateEscapes; import util.fdt; // File Date-Time class alias util.fdt.GetFileTime GetFileTime; import util.pathex; // Extended Path routines. alias util.pathex.GetBaseName GetBaseName; alias util.pathex.MakePath MakePath; alias util.pathex.CanonicalPath CanonicalPath; alias util.pathex.AbbreviateFileName AbbreviateFileName; alias util.pathex.LocateFile LocateFile; alias util.pathex.IsRelativePath IsRelativePath; alias util.pathex.FindFileInPathList FindFileInPathList; alias util.pathex.GetInitCurDir GetInitCurDir; import util.fileex; // Extended File routines. alias util.fileex.CreateTextFile CreateTextFile; alias util.fileex.FindInFile FindInFile; alias util.fileex.GetTextLines GetTextLines; alias util.fileex.GetOpt GetOpt; import util.file2; alias util.file2.FileExists FileExists; import util.macro; // Macro processing routines. alias util.macro.ConvertFile ConvertFile; import util.booltype; // definition of True and False alias util.booltype.True True; alias util.booltype.False False; import std.utf; alias std.utf.toUTF32 toUTF32; import std.file; alias std.file.remove remove; alias std.file.write write; import std.regexp; alias std.regexp.search search; alias std.regexp.find refind; import std.path; alias std.path.sep sep; alias std.path.linesep linesep; alias std.path.getDirName getDirName; alias std.path.getExt getExt; alias std.path.addExt addExt; alias std.path.getName getName; alias std.path.getBaseName getBaseName; import std.stdio; alias std.stdio.writefln writefln; import std.string; alias std.string.find find; alias std.string.rfind rfind; alias std.string.format format; alias std.string.replace replace; alias std.string.split split; alias std.string.tolower tolower; alias std.string.strip strip; version(Windows) { import std.c.windows.windows; alias std.c.windows.windows.GetVersion GetVersion; } ------------------ I had to disambiguate std.string.find and std.regex.find, plus a couple of others, but no big drama. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 30/06/2006 9:26:58 AM
Jun 29 2006
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Derek Parnell wrote:
 On Thu, 29 Jun 2006 14:45:23 -0700, Kirk McDonald wrote:
 
 
Derek Parnell wrote:

Why is FQN syntax demonstrable better than the current shortcut syntax?


...
By making it mandatory, we can 
always know where any name comes from, whether they are being 
fully-qualified, or imported on their own.

Now, for something like writefln, which is a well-known name that 
everyone will recognize instantly, this is a bit of a burden. You'd have 
to type it a whole extra time at the top of the file! 

So to summarize ... Mandatory fully qualified names makes it simple for a code reader to know in which module a member is located. But because that could be a burden to the code writer, the alias (or something similar) can be used to 'register' the FQN once in the code and allows the writer to use a short form of the name. Anyhow, I tried this coding style on Build just now and ended up with this...

[snipped some examples...]
 import util.str;        // non-standard string routines.
 alias util.str.SetEnv           SetEnv;
 alias util.str.GetEnv           GetEnv;
 alias util.str.Expand           Expand;
 alias util.str.ExpandEnvVar     ExpandEnvVar;
 alias util.str.ends             ends;
 alias util.str.begins           begins;
 alias util.str.enquote          enquote;
 alias util.str.strip            ustrip;
 alias util.str.stripr           ustripr;
 alias util.str.IsLike           IsLike;
 alias util.str.YesNo            YesNo;
 alias util.str.TranslateEscapes TranslateEscapes;

Note that with the shortcut that Python provides, this beomes the much less redundant: from util.str import SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, enquote, ustrip, ustripr, IsLike, YesNo, TranslateEscapes; I don't feel I could endorse this practice unless the language supports it like this. I don't feel this is a really serious issue. :-) "private import" provides all the sandboxing I think is needed in the absence of C++ namespaces. This is just an orginizational nicety. -Kirk McDonald
Jun 29 2006
next sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Kirk McDonald wrote:
 Derek Parnell wrote:
 
 On Thu, 29 Jun 2006 14:45:23 -0700, Kirk McDonald wrote:


 Derek Parnell wrote:

 Why is FQN syntax demonstrable better than the current shortcut syntax?


 ...
 By making it mandatory, we can always know where any name comes from, 
 whether they are being fully-qualified, or imported on their own.

 Now, for something like writefln, which is a well-known name that 
 everyone will recognize instantly, this is a bit of a burden. You'd 
 have to type it a whole extra time at the top of the file! 

So to summarize ... Mandatory fully qualified names makes it simple for a code reader to know in which module a member is located. But because that could be a burden to the code writer, the alias (or something similar) can be used to 'register' the FQN once in the code and allows the writer to use a short form of the name. Anyhow, I tried this coding style on Build just now and ended up with this...

[snipped some examples...]
 import util.str;        // non-standard string routines.
 alias util.str.SetEnv           SetEnv;
 alias util.str.GetEnv           GetEnv;
 alias util.str.Expand           Expand;
 alias util.str.ExpandEnvVar     ExpandEnvVar;
 alias util.str.ends             ends;
 alias util.str.begins           begins;
 alias util.str.enquote          enquote;
 alias util.str.strip            ustrip;
 alias util.str.stripr           ustripr;
 alias util.str.IsLike           IsLike;
 alias util.str.YesNo            YesNo;
 alias util.str.TranslateEscapes TranslateEscapes;

Note that with the shortcut that Python provides, this beomes the much less redundant: from util.str import SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, enquote, ustrip, ustripr, IsLike, YesNo, TranslateEscapes; I don't feel I could endorse this practice unless the language supports it like this. I don't feel this is a really serious issue. :-) "private import" provides all the sandboxing I think is needed in the absence of C++ namespaces. This is just an orginizational nicety.

While I'm proposing things, might I also propose static import x; to mean FQN import. (This would be the same as Sjoerd's proposed "import $ : foo.bar;".) It has the advantage of looking more like D code, I think. :-) The "as" keyword is also a good idea, as in static import x.y as z; -- Kirk McDonald
Jun 29 2006
next sibling parent Carlos Santander <csantander619 gmail.com> writes:
Kirk McDonald escribió:
 Kirk McDonald wrote:
 Derek Parnell wrote:

 On Thu, 29 Jun 2006 14:45:23 -0700, Kirk McDonald wrote:


 Derek Parnell wrote:

 Why is FQN syntax demonstrable better than the current shortcut 
 syntax?


 ...
 By making it mandatory, we can always know where any name comes 
 from, whether they are being fully-qualified, or imported on their own.

 Now, for something like writefln, which is a well-known name that 
 everyone will recognize instantly, this is a bit of a burden. You'd 
 have to type it a whole extra time at the top of the file! 

So to summarize ... Mandatory fully qualified names makes it simple for a code reader to know in which module a member is located. But because that could be a burden to the code writer, the alias (or something similar) can be used to 'register' the FQN once in the code and allows the writer to use a short form of the name. Anyhow, I tried this coding style on Build just now and ended up with this...

[snipped some examples...]
 import util.str;        // non-standard string routines.
 alias util.str.SetEnv           SetEnv;
 alias util.str.GetEnv           GetEnv;
 alias util.str.Expand           Expand;
 alias util.str.ExpandEnvVar     ExpandEnvVar;
 alias util.str.ends             ends;
 alias util.str.begins           begins;
 alias util.str.enquote          enquote;
 alias util.str.strip            ustrip;
 alias util.str.stripr           ustripr;
 alias util.str.IsLike           IsLike;
 alias util.str.YesNo            YesNo;
 alias util.str.TranslateEscapes TranslateEscapes;

Note that with the shortcut that Python provides, this beomes the much less redundant: from util.str import SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, enquote, ustrip, ustripr, IsLike, YesNo, TranslateEscapes; I don't feel I could endorse this practice unless the language supports it like this. I don't feel this is a really serious issue. :-) "private import" provides all the sandboxing I think is needed in the absence of C++ namespaces. This is just an orginizational nicety.

While I'm proposing things, might I also propose static import x;

I like that, and it would also be backwards compatible (no changes to import)
 to mean FQN import. (This would be the same as Sjoerd's proposed "import 
 $ : foo.bar;".) It has the advantage of looking more like D code, I 
 think. :-) The "as" keyword is also a good idea, as in
 
 static import x.y as z;
 

IIRC, what was suggested long ago was to use alias, but I don't remember where alias was supposed to be: alias import x.y z; import alias x.y z; import x.y alias z;
 -- 
 Kirk McDonald

-- Carlos Santander Bernal
Jun 30 2006
prev sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Kirk McDonald wrote:
 
 While I'm proposing things, might I also propose
 
 static import x;
 
 to mean FQN import. (This would be the same as Sjoerd's proposed "import 
 $ : foo.bar;".) It has the advantage of looking more like D code, I 
 think. :-) The "as" keyword is also a good idea, as in
 
 static import x.y as z;
 
 -- 
 Kirk McDonald

I find that name crappy, there is nothing "static" about a FQN import... X-P -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 01 2006
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Bruno Medeiros wrote:
 Kirk McDonald wrote:
 
 While I'm proposing things, might I also propose

 static import x;

 to mean FQN import. (This would be the same as Sjoerd's proposed 
 "import $ : foo.bar;".) It has the advantage of looking more like D 
 code, I think. :-) The "as" keyword is also a good idea, as in

 static import x.y as z;

 -- 
 Kirk McDonald

I find that name crappy, there is nothing "static" about a FQN import... X-P

What do you think of "final import" to mean FQN import? -- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wiki
Jul 01 2006
parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Kirk McDonald wrote:
 Bruno Medeiros wrote:
 Kirk McDonald wrote:

 While I'm proposing things, might I also propose

 static import x;

 to mean FQN import. (This would be the same as Sjoerd's proposed 
 "import $ : foo.bar;".) It has the advantage of looking more like D 
 code, I think. :-) The "as" keyword is also a good idea, as in

 static import x.y as z;

 -- 
 Kirk McDonald

I find that name crappy, there is nothing "static" about a FQN import... X-P

What do you think of "final import" to mean FQN import?

Actually, I don't agree that is best to recycle an existing keyword, I would prefer a new keyword (if the syntax were to be that way, but like I said in the OP to Derek, there many things to consider). -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 02 2006
prev sibling next sibling parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Thu, 29 Jun 2006 21:09:42 -0700, Kirk McDonald wrote:
 I don't feel this is a really serious issue. :-) "private import" 
 provides all the sandboxing I think is needed in the absence of C++ 
 namespaces. This is just an orginizational nicety.

If only it worked though. "private import" is not conforming to the specifications. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 30/06/2006 3:16:27 PM
Jun 29 2006
parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Derek Parnell wrote:
 On Thu, 29 Jun 2006 21:09:42 -0700, Kirk McDonald wrote:
 
I don't feel this is a really serious issue. :-) "private import" 
provides all the sandboxing I think is needed in the absence of C++ 
namespaces. This is just an orginizational nicety.

If only it worked though. "private import" is not conforming to the specifications.

Okay, "private import" /would/ provide all the sandboxing needed, if it worked. :-)
Jun 30 2006
prev sibling next sibling parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Thu, 29 Jun 2006 21:09:42 -0700, Kirk McDonald wrote:

 from util.str import SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, 
 enquote, ustrip, ustripr, IsLike, YesNo, TranslateEscapes;

Unfortunately this is not completely adequate because one can't always import the existing name verbatim, sometimes you need an alias to disambiguate it. Maybe something more like ... import from util.str SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, enquote, strip as ustrip, stripr as ustripr, IsLike, YesNo, TranslateEscapes; The "from" key would tell D that only the listed names are to come into the namespace and all others are excluded, such that any attempt to reference them in the code would cause an error. The current semantics could still exists by not using the "from" keyword. And notice the "strip as ustrip". This is because the real name is util.str.strip but this clashes with std.string.strip so we have to create an alias for one of them. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 30/06/2006 3:19:07 PM
Jun 29 2006
parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Derek Parnell wrote:
 On Thu, 29 Jun 2006 21:09:42 -0700, Kirk McDonald wrote:
 
 
from util.str import SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, 
enquote, ustrip, ustripr, IsLike, YesNo, TranslateEscapes;

Unfortunately this is not completely adequate because one can't always import the existing name verbatim, sometimes you need an alias to disambiguate it. Maybe something more like ... import from util.str SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, enquote, strip as ustrip, stripr as ustripr, IsLike, YesNo, TranslateEscapes;

Except for the rearranging of "import" and "from", this is exactly Python's behavior.
 
 The "from" key would tell D that only the listed names are to come into the
 namespace and all others are excluded, such that any attempt to reference
 them in the code would cause an error. The current semantics could still
 exists by not using the "from" keyword.
 

This could work (for both "from" and "as"), though I can't help but wonder what the consequences of having a module named "from" would be. :-) (If it's not a keyword, then this must be allowed.) import from from a, b, c as d;
 And notice the "strip as ustrip". This is because the real name is
 util.str.strip but this clashes with std.string.strip so we have to create
 an alias for one of them.
 

-- Kirk McDonald
Jun 30 2006
prev sibling parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Kirk McDonald wrote:
 Derek Parnell wrote:
 
 On Thu, 29 Jun 2006 14:45:23 -0700, Kirk McDonald wrote:


 Derek Parnell wrote:

 Why is FQN syntax demonstrable better than the current shortcut syntax?


 ...
 By making it mandatory, we can always know where any name comes from, 
 whether they are being fully-qualified, or imported on their own.

 Now, for something like writefln, which is a well-known name that 
 everyone will recognize instantly, this is a bit of a burden. You'd 
 have to type it a whole extra time at the top of the file! 

So to summarize ... Mandatory fully qualified names makes it simple for a code reader to know in which module a member is located. But because that could be a burden to the code writer, the alias (or something similar) can be used to 'register' the FQN once in the code and allows the writer to use a short form of the name. Anyhow, I tried this coding style on Build just now and ended up with this...

[snipped some examples...]
 import util.str;        // non-standard string routines.
 alias util.str.SetEnv           SetEnv;
 alias util.str.GetEnv           GetEnv;
 alias util.str.Expand           Expand;
 alias util.str.ExpandEnvVar     ExpandEnvVar;
 alias util.str.ends             ends;
 alias util.str.begins           begins;
 alias util.str.enquote          enquote;
 alias util.str.strip            ustrip;
 alias util.str.stripr           ustripr;
 alias util.str.IsLike           IsLike;
 alias util.str.YesNo            YesNo;
 alias util.str.TranslateEscapes TranslateEscapes;

Note that with the shortcut that Python provides, this beomes the much less redundant: from util.str import SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, enquote, ustrip, ustripr, IsLike, YesNo, TranslateEscapes; I don't feel I could endorse this practice unless the language supports it like this. I don't feel this is a really serious issue. :-) "private import" provides all the sandboxing I think is needed in the absence of C++ namespaces. This is just an orginizational nicety. -Kirk McDonald

I have worked with Python a bit, but it has been a few years so I don't recall. Is there an allowance for: # from my.lib import Foo, Bar, Baz as x.* ; Such that Foo is referred to as x.Foo, and so forth. Also, I support your idea of 'static import'. It seems fitting, and it prevents having to invent a new keyword. (Yes, the poor 'static' keyword is starting to get overloaded a bit, but I think its fair.) -- Chris Nicholson-Sauls
Jun 29 2006
parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Chris Nicholson-Sauls wrote:
 Kirk McDonald wrote:
 
 Derek Parnell wrote:

 On Thu, 29 Jun 2006 14:45:23 -0700, Kirk McDonald wrote:


 Derek Parnell wrote:

 Why is FQN syntax demonstrable better than the current shortcut 
 syntax?


 ...
 By making it mandatory, we can always know where any name comes 
 from, whether they are being fully-qualified, or imported on their own.

 Now, for something like writefln, which is a well-known name that 
 everyone will recognize instantly, this is a bit of a burden. You'd 
 have to type it a whole extra time at the top of the file! 

So to summarize ... Mandatory fully qualified names makes it simple for a code reader to know in which module a member is located. But because that could be a burden to the code writer, the alias (or something similar) can be used to 'register' the FQN once in the code and allows the writer to use a short form of the name. Anyhow, I tried this coding style on Build just now and ended up with this...

[snipped some examples...]
 import util.str;        // non-standard string routines.
 alias util.str.SetEnv           SetEnv;
 alias util.str.GetEnv           GetEnv;
 alias util.str.Expand           Expand;
 alias util.str.ExpandEnvVar     ExpandEnvVar;
 alias util.str.ends             ends;
 alias util.str.begins           begins;
 alias util.str.enquote          enquote;
 alias util.str.strip            ustrip;
 alias util.str.stripr           ustripr;
 alias util.str.IsLike           IsLike;
 alias util.str.YesNo            YesNo;
 alias util.str.TranslateEscapes TranslateEscapes;

Note that with the shortcut that Python provides, this beomes the much less redundant: from util.str import SetEnv, GetEnv, Expand, ExpandEnvVar, ends, begins, enquote, ustrip, ustripr, IsLike, YesNo, TranslateEscapes; I don't feel I could endorse this practice unless the language supports it like this. I don't feel this is a really serious issue. :-) "private import" provides all the sandboxing I think is needed in the absence of C++ namespaces. This is just an orginizational nicety. -Kirk McDonald

I have worked with Python a bit, but it has been a few years so I don't recall. Is there an allowance for: # from my.lib import Foo, Bar, Baz as x.* ;

You'd say:
 import my.lib as x



Then you could access Foo as x.Foo, etc. There's no reason to selectively import parts of the module in this case, as they are all inside of the module's own (aliased) namespace, anyway.
 
 Such that Foo is referred to as x.Foo, and so forth.  Also, I support 
 your idea of 'static import'.  It seems fitting, and it prevents having 
 to invent a new keyword.  (Yes, the poor 'static' keyword is starting to 
 get overloaded a bit, but I think its fair.)
 

I just looked at the keywords already used as attributes and picked the one that seemed to work best. (It was a tossup between static and final, actually.)
 -- Chris Nicholson-Sauls

-Kirk McDonald
Jun 30 2006
prev sibling parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Kirk McDonald wrote:
 Sjoerd van Leent wrote:
 The thing I'd see useful here would be:

 import fb : foo.bar;

 Indicates all methods from module "foo.bar" are in local namespace "fb"

 import $ : foo.bar;

 Would be the same as

 import foo.bar : foo.bar;

 Regards,
 Sjoerd

It is worth reviewing the Python syntax for imports here, I think. Python uses the FQN import by default, but supports importing unqualified names as well. ...

Thanks for the info on Python. Indeed, it might be insightful to look at the naming system of other languages. Eventually (but not right now) I would to look at how it works in other OO languages that I don't know yet. (such as Ruby for example) -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 02 2006
prev sibling parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Derek Parnell wrote:
 On Wed, 28 Jun 2006 08:18:40 +1000, Andrei Khropov 
 <andkhropov nospam_mtu-net.ru> wrote:
 
 Bruno Medeiros wrote:

 I'm betting he means being able to import a module in a way that it's 
 names
 (entities) are available only as fully-qualified names, and so the 
 base names
 are not "imported" to the importing module namespace/scope. It's the FQN
 import.

 Andrei, (and others) if you want to check out some previous 
 discussion on
 this matter:  
 http://www.digitalmars.com/d/archives/digitalmars/D/28423.html

Yes, you're right.

 But anyway, as far as I can see Walter's opinion is unknown.
  Is he satisfied with the present situation?

I believe so. The curent situation is a syntax shortcut. No one is prevented from using FQN syntax, and in fact I try to use that form in my code, with the main exception being 'writefln' of course ;-) The benefit I can see from the shortcut form is that one can change modules without having to change references to members in that module, whereas with FQN usage one has to do a global find/replace over all your source code. The cost of not using FQN though is it does not keep well over time in terms of reading the code and have an understanding of it. Plus you can get caught out sometimes when introducing another import that causes name clashes. I'm not an advocate of either style of coding and I won't dictate to others either on this matter. I have a preference, as my fellow coders also have a preference, which may be different, and I'm okay with that. Why do you think that FQN syntax is demonstrable better than the current shortcut syntax? --Derek Parnell Melbourne, Australia

First of all, I didn't mean to say that one had to strictly use just one method syntax all over the code. For instance I think functions (or any other entity) that are used often across modules would be fine accessed by base name only (such as writefln or others, not just std lib ones)
 The benefit I can see from the shortcut form is that one can change
 modules without having to change references to members in that module,
 whereas with FQN usage one has to do a global find/replace over all your
 source code.

That may currently be an issue, but with a proper and complete toolchain, namely a full-featured IDE (or even a stand-alone code editing and refactoring tool), that won't be an issue at all. And as I've stated before, I think D, as the modern, future language it aims to be, should be designed with this target usage scenario, where one has such complete toolchain. (Analogously to how certain D aspects were designed considering sufficiently advanced compiler technology, like methods being virtual by default and possible optimizations left to the compiler).
 Why do you think that FQN syntax is demonstrable better than the current
 shortcut syntax?

Like I said before, I don't think one should use just one syntax over the other in all of the program. So then, what is the problem? Summarizing from the other thread. If I want to access a set of entities of a given module by FQN, there is no way to specify that to the module statement (or any other statement), so that the module won't import the base names (aka: "won't import the names locally"). This is a conceptual problem. So what are it's practical ramifications? Well, one problem is if you make some sort of typo, you may erroneously access locally(by base name) an entity which should only be available by the FQN, and if there is no mismatch the compiler might not detect it. This may be a very rare occurrence, so I guess it may not have much importance. A more significant and surely common problem is in IDE code auto-completion. Since you cannot express in the source code if your imports should be just for FQN access or not, then the local module namespace is "polluted" with the base names of the imported module's entities, thus creating a garbage of excess names when using auto-completion. An example: --------------------------------------- module foobar; void DoStuff() { ... } void DoStuff2() { ... } --------------------------------------- module whatever; import foobar; void DoThings() { ... } void DoMoreThings() { ... } int func(){ ... Do| <- press key combination here for code-completion } --------------------------------------- In this example you want to access entities from foobar by FQN, such as "foobar.DoStuff()" . However, the base name (DoStuff, DoStuff2, etc.) of the entities of foobar is also made availabe in the current module scope by the import. So when you want to use code-completion, (in this example with the cursor right after Do where the "|" symbol is), you will be presented the the local options (DoThings, DoMoreThings), plus DoStuff and DoStuff2, which you do not want to be presented. Now imagine this in a real case scenario, where modules will may have lots of names and imports.. I say this would be surely a common problem because I believe accessing module functions by FQN may be the most common scenario. Note that there this problem doesn't quite happen with class methods, since you can't "import a class", so method names are never imported anywhere, only the class name is, if it is at the root of the module. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 01 2006