July 09, 2006
John Reimer wrote:
> In article <e8qjkf$2tqc$1@digitaldaemon.com>, Walter Bright says...
>> 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.
> 
> Well, your example is just showing selective renaming from /one/ module.
> Naturally these two are going to be very similar.  Please look at Kris'
> suggestion, thoroughly.  The whole system is vastly superior once one starts
> referencing selective importing from multiple modules.  The total number of
> lines are cut in half verses using static import and alias.
> 
> Also, for selective import, I think using "from" instead of "with" looks much
> better.

I agree that 'from' is better than 'with', but I just don't see the advantage of

from m2 import func,abcd,efgh;

over the likes of

import m2.func, m2.abcd, m2.efgh as f4;
import std.stdio, this.other.cool.db.lib as dblib;

because then you get the aliasing in there as well. True, there's a little redundant typing of 'm2'.

Also,

from m2 private import func,abcd,efgh;

or

private from m2 import func,abcd,efgh;

sucks IMO.

> 
> -JJR
> 
July 09, 2006
kris wrote:
> Dave wrote:
>> kris wrote:
>>> You've seen the requested syntax for this option, Walter. Let's revisit it again:
>>>
>>> # with m2 import func, abcd, efgh;
>>>
>>>
>>
>> That doesn't address the aliasing if I'm understanding correctly (what if m3 is imported and has an 'abcd' and 'efgh' also)?
> 
> 
> The proposed syntax for that has been noted as the following:
> 
> # with m3 import func, abcd as myabcd, efgh as myefgh;
> 
> or
> 
> # from m3 import func, abcd as myabcd, efgh as myefgh;

Thanks for the clarification - I had missed where the aliasing could also be done with 'from'.
July 09, 2006
John Reimer wrote:
> Also, for selective import, I think using "from" instead of "with" looks much better.
> 

"from" is a quite common variable name though, so introducing it as a keyword would probably break a lot of code.

For the same reason I suggested "in" instead of "as", even though the meaning may not be quite as obvious.
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.

I think Kris was merely suggesting that the need for a separate alias declaration for each import was the problem, not the idea of aliasing itself.  If a particular module imports 10 others, that's 10 separate aliases required as well, and there's no good way to write them in a way that makes for easy readability and maintenance.  This is the point he was trying to make below.

>> 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.

As above, the issue here was the need for a separate alias line to accomplish what was suggested by the "as" syntax, not the aliasing concept itself.

>> 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.

And I think we all agree here.

>> 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.

The alias version actually requires two lines, given current compiler behavior:

import lib.text.locale;
alias  lib.text.locale locale;

(I'm focusing on the module "as" syntax here since it's what was discussed above)

I think Kris is saying that although the "as" syntax just syntactic sugar for the above, it's also more readable and more maintainable.  And its presence as a language feature would encourage use of what is a good programming practice--anything too unwieldy will only be common among the truly fastidious.

>> 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();

Assuming just the static import line, symbols must be fully qualified, yes?  So to allow just a "locale." prefix the additional alias line is still required?  This doesn't seem to address Kris' concerns regarding maintenance and readability.

>      // 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.

A normal import followed by an alias works nearly as well as the above, too, but neither is nearly as elegant as the "as" syntax, which I believe is a significant issue here.  If you don't mind my asking, what's wrong with Kris' proposal?  Are there parsing issues, do you feel there's a problem with its impact on code readability, etc?

> 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.

Regarding the Regexp syntax, my only personal objection was to the bindings the default implementation created between runtime and standard library code (and I remember this being an issue for Kris as well). Another issue I remember was that the current Regexp implementation lacks robust Unicode support, and tying a specific (arguably lacking) implementation into the language didn't appeal to some.  But I don't remember anyone complaining about the need to learn more language syntax.  Perhaps that was after I stopped paying close attention to the discussion as things degenerated?

> 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 think this may be the crux of the issue.  Kris is approaching things from a user's standpoint while you're approaching things from an implementer's standpoint.  I believe Kris feels strongly about this because it appears to provide a good bit of additional clarity and utility (in the form of reduced maintenance and encouraging good programming practice) for an apparently small amount of additional complexity on the compiler side.  You, however, see little point in adding this complexity if it doesn't provide anything that is not technically possible now.  Is this correct?

You said to John R. that you do listen to convincing arguments and I know this is true from experience, but we're at the point with 1.0 features where the outstanding issues concern utility and aesthetics--areas where it's nearly impossible to make an argument on purely logical grounds.  I think one aspect of D that most of us find incredibly appealing is its sense of aesthetics--the language tends to naturally encourage the production of elegant code--and it's clear you agree that this results in code that has fewer bugs and is more easily maintainable than its C++/Java/whatever counterpart.

Kris' argument, to me, seems built on this ideal by attempting to provide simple extensions that would further enhance what many of us see as the primary strength of this language.  Therefore, I don't understand the resistance to his suggestions, and I'm at a loss for how to back up an argument that can only be made on aesthetic, predictive, and hypothetical grounds.  I believe, as Kris does, that his suggestions would reduce maintenance cost and to do so in a way that seems consistent with the design goals of this language.  But until D gets to the point where it is actually used for large projects over a period of years, it will be difficult to point at a use case and say "if we'd have had this feature these problems would not have occurred."  Here, I can only defer to Kris' experience, supported by my own, and say that I believe his suggestions are good ones and that they would more than justify their presence when D reaches this level of maturity.

> I suggest trying out the "static import" for a while. See how it works and looks.

I can tell you right now that I don't like the way "static import" looks, and I'm not terribly happy that I would need to continue maintaining a separate "alias" line for each import.  And that won't change with experience.  Might I ask why "static import" was chosen as the syntax for this feature?  Prepending "static" to "import" doesn't convey any meaning to me as a user about what's actually happening, so I can only conclude that this syntax was chosen because it's easy to implement and doesn't add any new keywords to the language?  I don't suppose any subset of Kris' suggestions could be implemented for comparison?  Or perhaps GDC would make a more appropriate testing ground for user-driven feature requests?  You've suggested we try out "static import" for a while, but that hardly puts Kris' proposal on equal footing for comparison.  And I personally don't want to feel I'm settling for "static import" simply because it was the only option we were offered.


Sean
July 09, 2006
In article <e8rhud$1cca$1@digitaldaemon.com>, Deewiant says...
>
>John Reimer wrote:
>> Also, for selective import, I think using "from" instead of "with" looks much better.
>> 
>
>"from" is a quite common variable name though, so introducing it as a keyword would probably break a lot of code.
>


It is?  I don't see "from" very often.  Seems like an unusual name for a variable.  Saying it will break "a lot" of code seems like an exaggeration.


>For the same reason I suggested "in" instead of "as", even though the meaning may not be quite as obvious.


"in" seems inappropriate in this situation.  "as" perfectly correlates to a renaming or aliasing action.  "in" is confusing and looks more like an action on a set.

-JJR


July 09, 2006
Dave wrote:
> John Reimer wrote:
>> In article <e8qjkf$2tqc$1@digitaldaemon.com>, Walter Bright says...
>>> 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.
>>
>> Well, your example is just showing selective renaming from /one/ module.
>> Naturally these two are going to be very similar.  Please look at Kris'
>> suggestion, thoroughly.  The whole system is vastly superior once one starts
>> referencing selective importing from multiple modules.  The total number of
>> lines are cut in half verses using static import and alias.
>>
>> Also, for selective import, I think using "from" instead of "with" looks much
>> better.
> 
> I agree that 'from' is better than 'with', but I just don't see the advantage of
> 
> from m2 import func,abcd,efgh;
> 
> over the likes of
> 
> import m2.func, m2.abcd, m2.efgh as f4;
> import std.stdio, this.other.cool.db.lib as dblib;
> 
> because then you get the aliasing in there as well. True, there's a little redundant typing of 'm2'.

If 'm2' is actually 'some.guys.super.cool.library.module' then the redundant typing adds up.

> Also,
> 
> from m2 private import func,abcd,efgh;
> 
> or
> 
> private from m2 import func,abcd,efgh;
> 
> sucks IMO.

I don't really mind the former, and I wouldn't terribly mind the latter if expressed differently:

private
{
    from m2 import func, abcd, efgh;
}

Though I think the real utility with the from/with syntax is that it would allow for selective public exposure of symbols to importing modules.


Sean
July 09, 2006
Sean Kelly wrote:
> I can tell you right now that I don't like the way "static import" looks, and I'm not terribly happy that I would need to continue maintaining a separate "alias" line for each import.  And that won't change with experience.  Might I ask why "static import" was chosen as the syntax for this feature?

I'm afraid that it was my suggestion originally:
http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39407

> Prepending "static" to "import" doesn't convey any meaning to me as a user about what's actually happening, so I can only conclude that this syntax was chosen because it's easy to implement and doesn't add any new keywords to the language?  

That was in fact why I suggested it. Reaction to it has been so negative that I'm wishing I'd thought of something else. :-)

> I don't suppose any subset of Kris' suggestions could be implemented for comparison?  Or perhaps GDC would make a more appropriate testing ground for user-driven feature requests?  You've suggested we try out "static import" for a while, but that hardly puts Kris' proposal on equal footing for comparison.  And I personally don't want to feel I'm settling for "static import" simply because it was the only option we were offered.

I actually feel the best solution is full-on Python-style imports, with "from" and "as", and "import" meaning FQN import. The only thing I think is stopping it is the introduction of two new keywords and the fact that this change in semantics would totally break essentially all existing code. By suggesting "static import" it leaves the old meaning for import, which does not break quite as much code. Alternatively, we could introduce some other new keyword like "qualified" to make "qualified import", though this isn't really that nice *either*.

Another suggestion for a way to represent FQN import that someone had was an "fqnimport" keyword (quite unlikely to be used in any existing code).

-- 
Kirk McDonald
Pyd: Wrapping Python with D
http://dsource.org/projects/pyd/wiki
July 09, 2006
Deewiant wrote:
> John Reimer wrote:
>> Also, for selective import, I think using "from" instead of "with" looks much
>> better.
>>
> 
> "from" is a quite common variable name though, so introducing it as a keyword
> would probably break a lot of code.

Yup, thus the suggestion of using "with" instead: it's already a keyword with similar meaning, and it should be fairly easy to disambiguate at the parse stage by looking ahead for "import".


Sean
July 09, 2006
Kirk McDonald wrote:
> 
> I actually feel the best solution is full-on Python-style imports, with "from" and "as", and "import" meaning FQN import. The only thing I think is stopping it is the introduction of two new keywords and the fact that this change in semantics would totally break essentially all existing code.

Why is that?  Wouldn't the old import syntax still be available?  Or are you concerned about the addition of 'from', 'with', or 'as' as keywords?


Sean
July 09, 2006
Walter Bright wrote:
> kris wrote:
>>      // "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.

Are they really semantically identical ?



with lib.text.locale import Time, Date;
auto time = new Time;
auto date = new Date;

auto foo  = new lib.text.locale.Foo;    // error




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;

auto foo  = new lib.text.locale.Foo;    // no error



If I understand the 'static import' proposal correctly, these are not equivalent :)

Anyway, what is being discussed here is what Python has been doing for quite some time. The following seems to work: http://docs.python.org/ref/import.html


-- 
Tomasz Stachowiak  /+ a.k.a. h3r3tic +/