June 29, 2006
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
June 29, 2006
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
June 30, 2006
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
June 30, 2006
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
June 30, 2006
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
June 30, 2006
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
June 30, 2006
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
June 30, 2006
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
June 30, 2006
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
June 30, 2006
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. :-)