July 09, 2006
kris wrote:
> The use of alias, regarding imports, should very likely be kept to a bare minimum in anything other than Q&D development. Ideally zero.

I really don't understand your pov. I can't help but think you regard alias as like C++'s #define:

	alias foo bar;
	#define bar foo

Such #define's I would agree are a terrible hack that don't belong in professional code. But aliasing isn't like that, it's a sane and well-behaved replacement.

> It's like the use of goto ~ use it where it can really help, but otherwise consider alternatives instead. I don't know what kind of development-scales you have in mind for D, but I'll happily testify that a boatload of aliases littering the imports would have no place in any project I'm responsible for; nor in those of the people I learned from. Here's why:
> 
> Quantities of alias do little but complicate ones comprehension of the code. Having a second-step (import then alias) is not only messy for each import, it does nothing to /encourage/ smart usage of namespace seperation. In fact, the extra step will likely discourage everyone but the diehards from using anything but the current global namespace, and we'll end up right back at square one.

With the "static import", there is no longer any possibility of name collisions, so we're not at square one. With no aliases, fully qualified module contents lookup will be needed.


> At that point, the language would be lacking. And why? This is all about maturity and usability of the language in specific areas. Why the rollback to something that can be considered "arcane" instead?

I don't see it as arcane or a workaround. Symbolic aliasing is a very powerful feature - yet it's very simple.


> Hey ~ if you'd actually roll in the changes, I'd be happy to make them myself ... I'd add both selective import and the "as" variation ~ a flexible combination to handle all cases, including the one Derek astutely pointed out. No aliases required by the user:
> 
> // import as we know it today, and with a required prefix "locale."
> import lib.text.locale;
> import lib.text.locale as locale;
> 
> // selective import of one entity, and alternatively with an alias
> import lib.text.locale.Time;
> import lib.text.locale.Time as otherTime;
> 
> ==================================

But those *are* aliases. It's just using a different keyword, "as" instead of "alias", and a slightly rearranged syntax. So what's the difference between:

import lib.text.locale.Time as otherTime;

and:

alias lib.text.locale.Time otherTime;

? Absolutely none, unless I am totally misunderstanding your proposal.


> Okay. Let's reflect for a moment?
> 
> The functionality is there, but the syntax could probably be better? There's a number of other posts proposing the use of "with" and so on, which look rather promising (from Kirk & Derek):
> 
> with lib.text.locale import Time, Date;
> 
> Seems pretty darned clear what's going on there. Seems to me that's a much more user-focused solution for selective imports. Let's combine this with a means to import an entire module under a prefix, as we've previously seen:
> 
>      // import as we know it today
> import lib.text.locale;
> auto time = new Time;
> 
>      // "locale." prefix required (great for IFTI modules)
> import lib.text.locale as locale;
> auto utc = locale.utcTime();
> auto dst = locale.daylightSavings();
> 
>      // selective import
> with lib.text.locale import Time, Date;
> auto time = new Time;
> auto date = new Date;
> 
>      // selective import with alias
> with lib.text.locale import Time, Date as MyDate;
> auto time = new Time;
> auto date = new MyDate;
> 
> ==================================
> 
> How about it?

      // "locale." prefix required (great for IFTI modules)
static import lib.text.locale;
alias lib.text.locale locale;
auto utc = locale.utcTime();
auto dst = locale.daylightSavings();

     // selective import
static import lib.text.locale;
alias lib.text.locale.Time Time;
alias lib.text.locale.Date Date;
auto time = new Time;
auto date = new Date;

     // selective import with alias
static import lib.text.locale;
alias lib.text.locale.Time Time;
alias lib.text.locale.Date MyDate;
auto time = new Time;
auto date = new MyDate;

These are semantically identical. The "static import" is a bit ugly looking, ok. It's a little wordier, ok. But it does work and produces exactly the results you asked for.

Let's harken back to the special regexp syntax I tried out a few months ago. It was a bit of syntactic sugar that reduced typing significantly. But it was soundly rejected by the community as adding complexity (in the form of more language to learn) while actually adding little to no extra power.

The "with" and "as" syntaxes add no power - they just save a little typing at the expense of adding more complexity to the grammar. Is that a worthwhile tradeoff? I don't know, but my inclination is to be conservative about such things.

I suggest trying out the "static import" for a while. See how it works and looks.
July 09, 2006
John Reimer wrote:
> The use of "alias" still looks like a hack.  We know you've always been firm in
> your belief that "alias" is the way to do it.  I doubt that all these people
> would be discussing options here if they were satisfied with that solution
> (which has been around for a looong time).
> 
> We know it can be done with alias. Kris knows. We don't think it's good enough.
> That's why this whole topic is being wrangled.  
> 
> So if you choose to make the internal machinery do it with alias, fine!  We just
> want something that's better, nicer, more professional looking! :) (please not
> "static import," though).

What I don't get is what is "unprofessional" or hackish about alias? Is it (as I posted to Kris) that it looks too much like #define?


> While I do agree that D would suffer if you followed the communities whim for
> every little feature suggested, yet I think you are far too independent minded
> most of the time.  The quote in your recent interview at Bitwise -- "D is going
> wherever the D community wants it to go" -- is really a farce.  D is going where
> /you/ want it to go, Walter.

If it was only what I wanted, there'd be exactly one D user - me. D really is a community effort, and it really does go where the community wants it to go (although it may not seem that way at times). Every day, and I mean every day, there are feature proposals. I have no choice but to say "no" to 99% of them, which sure comes off as me sounding like Negative Nellie or Dr. No.

This is despite the fact that many of them are incredibly good ideas, like Don's idea on temporaries.

Each idea goes through a gauntlet of:
1) is lack of this idea turning users away from D
2) how much power it adds
3) how much complexity it adds
4) is it consistent with the rest of D
5) how hard is it to implement
6) how does it rank in importance against all the other ideas

Here's one example: I'm not personally enamored with inner classes. There are better ways to do the same thing. But Kris made a compelling argument that supporting inner classes would open the door wide to mass conversion of Java code to D. That's a lot of leverage for a fairly modest implementation effort.


> And there's nothing wrong with admitting that.  I just think a honesty is
> important here.  This is your language.  You've made that very plain over the
> years, and most of us who have stuck around have accepted that. You strongly
> disfavour committees and bureaucracy, which is completely understandable; but,
> your over-protectiveness and fear of them may be doing the same sort of damage
> on the opposite end of the spectrum.

Sure, at the moment I make the final decisions. But that only is possible because the D community suffers me to do it. If I cease to act in the best interests of the D community, then the community can easily take D off in their own direction (D is GPL).

> Don't take this wrong:  I'm very thankful about all you've done with D; I just
> get a little frustrated at how hard you are to convince of anything, a trait
> that may do well for you in some ways but probably hurts you so much more in
> other ways.

Being hard to convince is the only practical way to find the 1% that must be done out of the 99% that I am forced to say no to.

P.S. If you think I'm hard to convince, try convincing the C++ standards committee of something <g>.

P.P.S. Don't think of it as just convincing me. You have to make an argument that is compelling to current and potential future users of D. The latter group is predisposed to be very skeptical about new languages. I've seen them in the audience of my talks, with arms crossed and head back. I have to present a pretty darned convincing case to get their attention.
July 09, 2006
Walter Bright wrote:
> kris wrote:
>> // import as we know it today, and with a required prefix "locale."
>> import lib.text.locale;
>> import lib.text.locale as locale;
>>
>> // selective import of one entity, and alternatively with an alias
>> import lib.text.locale.Time;
>> import lib.text.locale.Time as otherTime;
>>
>> ==================================
> 
> But those *are* aliases. It's just using a different keyword, "as" instead of "alias", and a slightly rearranged syntax. So what's the difference between:
> 
> import lib.text.locale.Time as otherTime;
> 
> and:
> 
> alias lib.text.locale.Time otherTime;
> 
> ? Absolutely none, unless I am totally misunderstanding your proposal.

There should be a big difference (if I understand things correctly):
A simple example:

If I have:

module m1;

int func(){return 1;}

and

module mainmodule;

import m1;

void main()
{
  writefln(func());
  writefln(m1.func());
}

there are no problems with that!

But if I add:

module m2;

int func(){return 2;}

and change mainmodule to:

import m1;
import m2;

void main()
{
  writefln(func());     //<- conflict
  writefln(m1.func());
  writefln(m2.func());
}

And suddenly I get a lot of conflicts.

Sure there is a way to solve it by adding:

alias m1.func func;

And then use m2.func to use func from m2.

But what if I wanted to give m2.func a totally different name to avoid confusion, i can try to add this:

alias m2.func someOtherName; instead of alias m1.func func;

But then once again I would get an error about a conflict:

Once again there is a solution:

alias m1.func func;
alias m2.func f2;

And it works OK, but the intention here is a bit hidden.

Conclusion:

import m2.func as f2;

is not the same as:

import m2;
alias m2.func f2;

but is equivalent to:

import m2;
alias m2.func f2;
//insert here a possibly huge number of aliases to avoid conflicts of
m2.func with func from other imported modules.
July 09, 2006
Ivan Senji wrote:
> There should be a big difference (if I understand things correctly):
> A simple example:
> 
> If I have:
> 
> module m1;
> 
> int func(){return 1;}
> 
> and
> 
> module mainmodule;
> 
> import m1;
> 
> void main()
> {
>   writefln(func());
>   writefln(m1.func());
> }
> 
> there are no problems with that!
> 
> But if I add:
> 
> module m2;
> 
> int func(){return 2;}
> 
> and change mainmodule to:
> 
> import m1;
> import m2;
> 
> void main()
> {
>   writefln(func());     //<- conflict
>   writefln(m1.func());
>   writefln(m2.func());
> }
> 
> And suddenly I get a lot of conflicts.

I agree, but the "static import" resolves that.


> Sure there is a way to solve it by adding:
> 
> alias m1.func func;
> 
> And then use m2.func to use func from m2.
> 
> But what if I wanted to give m2.func a totally different name to avoid
> confusion, i can try to add this:
> 
> alias m2.func someOtherName; instead of alias m1.func func;
> 
> But then once again I would get an error about a conflict:
> 
> Once again there is a solution:
> 
> alias m1.func func;
> alias m2.func f2;
> 
> And it works OK, but the intention here is a bit hidden.
> 
> Conclusion:
> 
> import m2.func as f2;
> 
> is not the same as:
> 
> import m2;
> alias m2.func f2;
> 
> but is equivalent to:
> 
> import m2;
> alias m2.func f2;
> //insert here a possibly huge number of aliases to avoid conflicts of
> m2.func with func from other imported modules.

If "static import" is used, there aren't any conflicts.

There are two issues here:

1) the "second class name lookup" characteristic of import.
2) inserting a name from one scope into another (possibly renaming it in the process)

static import does (1) by importing but disabling the second class lookup.
alias does (2).
July 09, 2006
Walter Bright wrote:
> kris wrote:
> 
>> The use of alias, regarding imports, should very likely be kept to a bare minimum in anything other than Q&D development. Ideally zero.
> 
> 
> I really don't understand your pov. I can't help but think you regard alias as like C++'s #define:
> 
>     alias foo bar;
>     #define bar foo
> 
> Such #define's I would agree are a terrible hack that don't belong in professional code. But aliasing isn't like that, it's a sane and well-behaved replacement.
> 
>> It's like the use of goto ~ use it where it can really help, but otherwise consider alternatives instead. I don't know what kind of development-scales you have in mind for D, but I'll happily testify that a boatload of aliases littering the imports would have no place in any project I'm responsible for; nor in those of the people I learned from. Here's why:
>>
>> Quantities of alias do little but complicate ones comprehension of the code. Having a second-step (import then alias) is not only messy for each import, it does nothing to /encourage/ smart usage of namespace seperation. In fact, the extra step will likely discourage everyone but the diehards from using anything but the current global namespace, and we'll end up right back at square one.
> 
> 
> With the "static import", there is no longer any possibility of name collisions, so we're not at square one. With no aliases, fully qualified module contents lookup will be needed.


That's assuming anyone would use it? Who's gonna do that when you insist that (a) they have to always use the FQN for safe imports or (b) use an alias along with every static import?

Suppose people actually used static-import? We'd start migrating to the shortest import paths possible to avoid the long names, or have an alias sitting beside every import.

These two belong together ~ the idea is to /encourage/ people to use this safer alternative, not turn them away.


>> At that point, the language would be lacking. And why? This is all about maturity and usability of the language in specific areas. Why the rollback to something that can be considered "arcane" instead?
> 
> 
> I don't see it as arcane or a workaround. Symbolic aliasing is a very powerful feature - yet it's very simple.


Perhaps you ought to stop for a moment and take a look at all the people here asking you to combine these features together? Then go back over the last two years and just count how many posts there are about this one specific aspect: import. Do we really have to beg? Does D go where the community wants it to? Take a look at /all/ these posts ~ please?


>> Hey ~ if you'd actually roll in the changes, I'd be happy to make them myself ... I'd add both selective import and the "as" variation ~ a flexible combination to handle all cases, including the one Derek astutely pointed out. No aliases required by the user:
>>
>> // import as we know it today, and with a required prefix "locale."
>> import lib.text.locale;
>> import lib.text.locale as locale;
>>
>> // selective import of one entity, and alternatively with an alias
>> import lib.text.locale.Time;
>> import lib.text.locale.Time as otherTime;
>>
>> ==================================
> 
> 
> But those *are* aliases. It's just using a different keyword, "as" instead of "alias", and a slightly rearranged syntax. So what's the difference between:
> 
> import lib.text.locale.Time as otherTime;
> 
> and:
> 
> alias lib.text.locale.Time otherTime;
> 
> ? Absolutely none, unless I am totally misunderstanding your proposal.


Under the covers? Does it matter?


>> Okay. Let's reflect for a moment?
>>
>> The functionality is there, but the syntax could probably be better? There's a number of other posts proposing the use of "with" and so on, which look rather promising (from Kirk & Derek):
>>
>> with lib.text.locale import Time, Date;
>>
>> Seems pretty darned clear what's going on there. Seems to me that's a much more user-focused solution for selective imports. Let's combine this with a means to import an entire module under a prefix, as we've previously seen:
>>
>>      // import as we know it today
>> import lib.text.locale;
>> auto time = new Time;
>>
>>      // "locale." prefix required (great for IFTI modules)
>> import lib.text.locale as locale;
>> auto utc = locale.utcTime();
>> auto dst = locale.daylightSavings();
>>
>>      // selective import
>> with lib.text.locale import Time, Date;
>> auto time = new Time;
>> auto date = new Date;
>>
>>      // selective import with alias
>> with lib.text.locale import Time, Date as MyDate;
>> auto time = new Time;
>> auto date = new MyDate;
>>
>> ==================================
>>
>> How about it?
> 
> 
>       // "locale." prefix required (great for IFTI modules)
> static import lib.text.locale;
> alias lib.text.locale locale;
> auto utc = locale.utcTime();
> auto dst = locale.daylightSavings();
> 
>      // selective import
> static import lib.text.locale;
> alias lib.text.locale.Time Time;
> alias lib.text.locale.Date Date;
> auto time = new Time;
> auto date = new Date;
> 
>      // selective import with alias
> static import lib.text.locale;
> alias lib.text.locale.Time Time;
> alias lib.text.locale.Date MyDate;
> auto time = new Time;
> auto date = new MyDate;
> 
> These are semantically identical. The "static import" is a bit ugly looking, ok. It's a little wordier, ok. But it does work and produces exactly the results you asked for.


And at the cost of making life harder for anyone who has to work on a large-scale project containing hundreds or thousands of modules. Without being disrespectful, I have to ask when was the last time you worked on a large-scale application with more than three people involved? Now how about several million lines with 500 engineers? Do you really want them plonking aliases all over the place when it's basically trivial for the compiler to deal with this in a clean and precise manner? Isn't this wehre you want D to be? Or is it intended to compete with Python only? (and IIRC python actually has a better import system).

Skip to the next section if you want to avoid overflowing frustration.

I don't get it, Walter. I really don't. I would have thought you'd be more that considerate toward making things easy for the end-user, but you seem to be insisting they take multiple steps with something that pretty much /every/ module will do multiple times: import other modules. To do so in the safest manner possible should be made as easy for the user as possible. Not in some manner that discourages anyone from using the safe approach.


> Let's harken back to the special regexp syntax I tried out a few months ago. It was a bit of syntactic sugar that reduced typing significantly. But it was soundly rejected by the community as adding complexity (in the form of more language to learn) while actually adding little to no extra power.


Just don't know how I can explain this to you in a way that you'll understand; But I'll give it one last try:

* Regex is used rarely in modules. Even in apps with heavy regex usage, the functionality tends to get wrapped anyway. On the other hand, import is used in pretty much every module. It's something that's almost always there, and the safest manner of using import should obviously be made easy to use, easy to follow, and easy to maintain.

* Regex is perfectly suited to library functionality. One cannot do that with import ~ it's part of the module declaration. Isn't that the case?

* Embedding Regex in the language itself tend to reduce the motivation to provide alternate implementations. The Template Regex is just one such example, which you proudly displayed at a presentation. I don't think import can really be compared to this aspect either; can it?

The embedded regex was rejected for at least the latter two reasons, and not because it added extra complexity to learn the language. Given that import will be used mutliple times by pretty much every single module, and Regex by almost zero in comparison, it would appear overtly reckless to consider them as equivalent in any form or manner.

======= idea =========

Perhaps we should count how many imports there are in the current D language base, and then compare that to the number of import std.Regex? What would you guess? Perhaps 5000 to 1? Maybe 100,000 to 1? Perhaps more? How many does it have to be?

I truly hope this makes the distinction clear enough for you?

======================


> The "with" and "as" syntaxes add no power - they just save a little typing at the expense of adding more complexity to the grammar. Is that a worthwhile tradeoff? I don't know, but my inclination is to be conservative about such things.
> 
> I suggest trying out the "static import" for a while. See how it works and looks.

I earnestly suggest you consider how many people are currently and have been asking for you to address this concern, and to place overall usability of daily-language usage above whatever is stopping you from considering this beyond the need for yet more alias usage.

Think about it ... import is used /all/ the time. Perhaps an average of three times per module? Would you rather make the safe method of import hard to use, or easy to use?
July 09, 2006
Walter Bright wrote:
> Ivan Senji wrote:
>> There should be a big difference (if I understand things correctly):
>> A simple example:
>>
>> If I have:
>>
>> module m1;
>>
>> int func(){return 1;}
>>
>> and
>>
>> module mainmodule;
>>
>> import m1;
>>
>> void main()
>> {
>>   writefln(func());
>>   writefln(m1.func());
>> }
>>
>> there are no problems with that!
>>
>> But if I add:
>>
>> module m2;
>>
>> int func(){return 2;}
>>
>> and change mainmodule to:
>>
>> import m1;
>> import m2;
>>
>> void main()
>> {
>>   writefln(func());     //<- conflict
>>   writefln(m1.func());
>>   writefln(m2.func());
>> }
>>
>> And suddenly I get a lot of conflicts.
> 
> I agree, but the "static import" resolves that.

It does, but I thought your original example was solving the isue by only importing one name from a module?

> 
> 
>> Sure there is a way to solve it by adding:
>>
>> alias m1.func func;
>>
>> And then use m2.func to use func from m2.
>>
>> But what if I wanted to give m2.func a totally different name to avoid confusion, i can try to add this:
>>
>> alias m2.func someOtherName; instead of alias m1.func func;
>>
>> But then once again I would get an error about a conflict:
>>
>> Once again there is a solution:
>>
>> alias m1.func func;
>> alias m2.func f2;
>>
>> And it works OK, but the intention here is a bit hidden.
>>
>> Conclusion:
>>
>> import m2.func as f2;
>>
>> is not the same as:
>>
>> import m2;
>> alias m2.func f2;
>>
>> but is equivalent to:
>>
>> import m2;
>> alias m2.func f2;
>> //insert here a possibly huge number of aliases to avoid conflicts of
>> m2.func with func from other imported modules.
> 
> If "static import" is used, there aren't any conflicts.

OK.

> 
> There are two issues here:
> 
> 1) the "second class name lookup" characteristic of import.
> 2) inserting a name from one scope into another (possibly renaming it in
> the process)
> 
> static import does (1) by importing but disabling the second class lookup.
> alias does (2).

Sure I could use

static import m2;
alias m2.func f2;

And that would be an improvement but it is still longer (and arguably
less understandable) than:

import m2.func as f2; ;) :)
July 09, 2006
Ivan Senji wrote:
> Sure I could use
> 
> static import m2;
> alias m2.func f2;
> 
> And that would be an improvement but it is still longer (and arguably
> less understandable) than:
> 
> import m2.func as f2; ;) :)

Let's say you're going to do more than one:

static import m2;
alias m2.func f2;
alias m2.abcd f3;
alias m2.efgh f4;

vs:

import m2.func as f2;
import m2.abcd as f3;
import m2.efgh as f4;

Not much of a difference. I'm also not understanding why alias is hard to understand.
July 09, 2006
Walter Bright wrote:
> Ivan Senji wrote:
> 
>> Sure I could use
>>
>> static import m2;
>> alias m2.func f2;
>>
>> And that would be an improvement but it is still longer (and arguably
>> less understandable) than:
>>
>> import m2.func as f2; ;) :)
> 
> 
> Let's say you're going to do more than one:
> 
> static import m2;
> alias m2.func f2;
> alias m2.abcd f3;
> alias m2.efgh f4;
> 
> vs:
> 
> import m2.func as f2;
> import m2.abcd as f3;
> import m2.efgh as f4;
> 
> Not much of a difference. I'm also not understanding why alias is hard to understand.


You've seen the requested syntax for this option, Walter. Let's revisit it again:

# with m2 import func, abcd, efgh;




July 09, 2006
On Sun, 09 Jul 2006 19:52:15 +1000, Walter Bright <newshound@digitalmars.com> wrote:

> Ivan Senji wrote:
>> Sure I could use
>>  static import m2;
>> alias m2.func f2;
>>  And that would be an improvement but it is still longer (and arguably
>> less understandable) than:
>>  import m2.func as f2; ;) :)
>
> Let's say you're going to do more than one:
>
> static import m2;
> alias m2.func f2;
> alias m2.abcd f3;
> alias m2.efgh f4;
>
> vs:
>
> import m2.func as f2;
> import m2.abcd as f3;
> import m2.efgh as f4;
>
> Not much of a difference. I'm also not understanding why alias is hard to understand.

One very important purpose of programming languages is to help make sense to human readers and writers. Redundant repetition is distracting in everything except poetry.

Consider this instead ...

 from m2 import f2,f3,f4;

or

 with m2 import f2,f3,f4;

Much easier to write, reead and understand. And probably easier for the compiler too.

*Please* do not overload the "static" keyword with yet another definition. I have no idea what "static inport" means as a natural phrase. It does not imply or suggest anything to me. Is it an import that is down at compile time (of course it is 'cos that's when import statements are used), or is it something that doesn't change size during the run-time, or is it something that retains its place in RAM during the life of the execution? Oh no, that's right - in this context it means that you have to FQN references. Doh! Bloody obvious isn't it?

-- 
Derek Parnell
Melbourne, Australia
July 09, 2006
On Sun, 09 Jul 2006 17:59:36 +1000, Walter Bright <newshound@digitalmars.com> wrote:

> kris wrote:
>> The use of alias, regarding imports, should very likely be kept to a bare minimum in anything other than Q&D development. Ideally zero.
>
> I really don't understand your pov. I can't help but think you regard alias as like C++'s #define:
>
> 	alias foo bar;
> 	#define bar foo

I'm hope I'm not messing up Kris' words here but I think he is saying that we need to cut down on the amount of typing and reading people *must* do in a program. Keep it to a minimum. Try and work the syntax so that the common and mandatory things are short, easy, and intuitive to do. Make the unusual and 'special' things have more detail in the syntax.

> Such #define's I would agree are a terrible hack that don't belong in professional code. But aliasing isn't like that, it's a sane and well-behaved replacement.

I don't think we are talking so much about the semantics of alias but more about how to code it efficiently.

> With the "static import", there is no longer any possibility of name collisions, so we're not at square one. With no aliases, fully qualified module contents lookup will be needed.

"static import" is not an intuitive syntax. I doesn't mean much until one explicitly learns it.


>>  // import as we know it today, and with a required prefix "locale."
>> import lib.text.locale;
>> import lib.text.locale as locale;
>>  // selective import of one entity, and alternatively with an alias
>> import lib.text.locale.Time;
>> import lib.text.locale.Time as otherTime;
>>  ==================================
>
> But those *are* aliases. It's just using a different keyword, "as" instead of "alias", and a slightly rearranged syntax. So what's the difference between:
>
> import lib.text.locale.Time as otherTime;
>
> and:
>
> alias lib.text.locale.Time otherTime;
>
> ? Absolutely none, unless I am totally misunderstanding your proposal.

Not really. Firstly "import ... as ...;" is a single statement but "import ...; alias ...;" is two which can be separated and 'hidden' in the clutter. Secondly, the proposed syntax is not redundant - the module name is typed in only once.

> The "static import" is a bit ugly looking, ok. It's a little wordier, ok. But it does work and produces exactly the results you asked for.

*NOT* ok. Why encourage mediocrity. You can do us and future D coders a favour by giving us a better syntax than something that is admittedly ugly and too wordy.

-- 
Derek Parnell
Melbourne, Australia