July 11, 2006
Rioshin an'Harthen wrote:
> This would allow for example the following syntaxes:
> 
> private import module.name;
> import module.name alias mn;
> import in module.name member1, member2;
> import in module.name alias mn member1, member2 alias m2;
> private static import in module.name alias mn member1 alias m1, member2
> alias m2, member3 alias m3;
> 
> (where I would probably write the last one as something like
> 
>     private static import
>         in module.name alias mn
>             member1 alias m1,
>             member2 alias m2,
>             member3 alias m3;
> 
> , but I digress).
> 
> It could even be considered that any occurence of alias be replaced with alias|as, where | denotes that either but not both be used, and the difference being alias allowing the use of both forms (FQN or aliased name), while as requiring the use of the aliased name. However, this would be a complexity I would not want to write into the compiler. :)

I guess that pretty much says that it's not appropriate to incorporate such a complex syntax in D either. Remember, D is supposed to be "simple" language. :)

I don't get it - why does one have to be able to access a symbol using three different naming conventions *at the same time*. Why does not 'alias' and/or 'as' imply 'static'?  What's the benefit of using 'as' instead of 'alias'? Why does one need to import individual module members or alias those module members in the import statement?

I think 90% of that functionality can be achieved using only two attributes/keywords: 'private' and 'alias'. Personally I would prefer 'public' over 'private' but I guess the default behaviour of imports is not going to change anymore. I might understand why you would like to have this complex syntax: to shorten/remove the annoying prefixes preceding foreign module members, but it only makes the code less robust.

Consider a situation where one of the imported modules on the same namespace gets an additional public member that conflicts with another imported member. That leads to difficult exceptions logic in the import statements. I would rather make the count of public module members as small as possible and import the whole module to the top level namespace (non-static, not as/alias) or give it an own namespace (static, alias, not as). If needs be, there could also be an ability to import separate members by concatenating the member name the member name with a leading dot to the module name in the import statement. Much easier. In my experience if your having more than 1-2 conflicting members, you're doing something wrong.

-- 
Jari-Matti
July 11, 2006
Lars Ivar Igesund wrote:

> You couldn't be more right. I have been looking into the possibilities for a startup using D as a core technology. This is based on seeing the potential of D, using D and talking to other people using D. However, I am becoming doubtful that this is something I will even try to go through with. If it is something D need, then it is that the continued shaping of the language use the actual experience starting to be contained in the D community.
> 
> Walter, you seem unable to listen to (or understand) the issues met when developing libraries in D (which is a different thing from porting an application from C++), we are talking 2-3 years of solid experience writing libraries in D, Ant, Kris and others, they _know_ what the problems are, which I belive is much more important knowledge in this respect, than what was done in C++ many years ago. C++ experience don't help much when developing with D, D experience do. You don't want language committees, then for the sake of those actually using D, LISTEN TO THEM! I am not willing to flog a dead horse.
> 

I believe I might have been a bit rash here, but I got somewhat pissed pouring over all the posts for the last few days. I will therefore restate some of my thoughts in a calmer manner:

If we for a second ignore the language issues chatted about recently, most people agree that D is missing libraries to be able to really compete with other languages. It is therefore unfathomable to me why you Walter don't actively try to make it easy to create good libraries in D. Libraries that can be made stable, failsafe and predictable. You have said many enough times that D is different enough to need different solutions to problems already solved in other languages. Why is it then that you seemingly refuse to listen to those that have tried to solve these problems in D over the years? Those that have found that the language features in D probably need to be refined to not only make libraries in D possible, but fun to write, fun to use, safe to use and with a predictable usage pattern.

Writing a compiler is an impressive feat in my eyes, but AFAICS not the way to get experience writing libraries in D. Here you'll need to listen to those that have. Frankly, all the problems posted on symbol conflicts in phobos itself should have told you that something is amiss and should be fixed.

Since I'm getting the impression that the issue might be fixed soon, it is then getting down to how. Reusing words like static and alias (that have nothing to do in this company) is the wrong way, especially when there are tried and tested solutions in languages like Python with a clear and perfectly understandable syntax not confused by unrelated words. Why should something that can be said unamibigiously in one statement have to be divided into several unclear (static this, alias that)?

I wholeheartedly stand behind Kris' RFC elsewhere in the NG.

-- 
Lars Ivar Igesund
blog at http://larsivi.net
DSource & #D: larsivi
July 11, 2006
On Tue, 11 Jul 2006 23:20:39 +0300, Jari-Matti Mäkelä wrote:

> In my
> experience if your having more than 1-2 conflicting members, you're
> doing something wrong.

That might be true if all the modules you use are under your direct control. However, the times I've had name clashes have been due to using libraries written by other people who, independently, decided to use the same name. Thus in my code, I am forced to disambiguate them.

Consider the simple situation in Phobos

 std.string.find
 std.regexp.find
 internal.gc.gcx.find

then add the various other 'find' members in external libraries.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
12/07/2006 9:34:15 AM
July 11, 2006
Derek Parnell wrote:
> On Tue, 11 Jul 2006 23:20:39 +0300, Jari-Matti Mäkelä wrote:
> 
>> In my
>> experience if your having more than 1-2 conflicting members, you're
>> doing something wrong.
> 
> That might be true if all the modules you use are under your direct control. However, the times I've had name clashes have been due to using libraries written by other people who, independently, decided to use the same name. Thus in my code, I am forced to disambiguate them.
> 
> Consider the simple situation in Phobos
> 
>  std.string.find
>  std.regexp.find
>  internal.gc.gcx.find
> 
> then add the various other 'find' members in external libraries.

Ok, have to admit that's true. But do you really use them all in the same module? If there's only a small amount of conflicting names, the import syntax does not have to be so incredibly complex.
July 12, 2006
Jari-Matti Mäkelä wrote:
> Derek Parnell wrote:
> 
>>On Tue, 11 Jul 2006 23:20:39 +0300, Jari-Matti Mäkelä wrote:
>>
>>
>>>In my
>>>experience if your having more than 1-2 conflicting members, you're
>>>doing something wrong.
>>
>>That might be true if all the modules you use are under your direct
>>control. However, the times I've had name clashes have been due to using
>>libraries written by other people who, independently, decided to use the
>>same name. Thus in my code, I am forced to disambiguate them. 
>>
>>Consider the simple situation in Phobos
>>
>> std.string.find
>> std.regexp.find
>> internal.gc.gcx.find
>>
>>then add the various other 'find' members in external libraries.
> 
> 
> Ok, have to admit that's true. But do you really use them all in the
> same module? If there's only a small amount of conflicting names, the
> import syntax does not have to be so incredibly complex.


It can and will happen. The larger the project, the better the chance for conflicts. There's probably some logarithmic-style graph describing the relationship between the number of modules and the resulting number of potential conflicts. The issue does not really arise within small or personal projects to the same extent. Primarily because you personally have full control over the entire namespace.

The syntax itself does not need to be complex at all. It's downright simple:

import w.x.y.z as z;

or

import w.x.y.z : z;


Where z represents whatever you wish the required prefix to be.

No static, no alias. Looks very much like the existing import, and is almost as effortless to use. Perhaps you might like to read the "Import RFC" posted? It explains the issues in a little more depth.
July 12, 2006
On Wed, 12 Jul 2006 02:51:08 +0300, Jari-Matti Mäkelä wrote:

>> Consider the simple situation in Phobos
>> 
>>  std.string.find
>>  std.regexp.find
>>  internal.gc.gcx.find
>> 
>> then add the various other 'find' members in external libraries.
> 
> Ok, have to admit that's true. But do you really use them all in the same module?

Apparently, as that's how I got the error messages. ;-)

> If there's only a small amount of conflicting names, the import syntax does not have to be so incredibly complex.

Totally agree. Currently I'm using this sort of syntax ...

 import std.string;
 alias std.string.find str_find;
 alias std.string.replace str_replace;

 import std.regexp;
 alias std.regexp.find re_find;
 alias std.regexp.replace re_replace;

 import util.str;
 alias util.str.find utl_find;

 . . .

 re_find( ... );
 . . .
 str_find( ... );
 . . .
 utl_find( ... );


Yes, there has to be a better (something that is less costly to write,
read, and maintain) solution.

 import std.string alias str;
 import std.regexp alias re;
 import util.str alias utl;
 . . .
 re.find( ... );
 . . .
 str.find( ... );
 . . .
 utl.find( ... );

would do nicely, thank you.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
12/07/2006 10:12:04 AM
July 12, 2006
kris wrote:
> Jari-Matti Mäkelä wrote:
>> Derek Parnell wrote:
>>
>>> On Tue, 11 Jul 2006 23:20:39 +0300, Jari-Matti Mäkelä wrote:
>>>
>>>
>>>> In my
>>>> experience if your having more than 1-2 conflicting members, you're
>>>> doing something wrong.
>>>
>>> That might be true if all the modules you use are under your direct
>>> control. However, the times I've had name clashes have been due to using
>>> libraries written by other people who, independently, decided to use the
>>> same name. Thus in my code, I am forced to disambiguate them.
>>> Consider the simple situation in Phobos
>>>
>>> std.string.find
>>> std.regexp.find
>>> internal.gc.gcx.find
>>>
>>> then add the various other 'find' members in external libraries.
>>
>>
>> Ok, have to admit that's true. But do you really use them all in the same module? If there's only a small amount of conflicting names, the import syntax does not have to be so incredibly complex.
> 
> 
> It can and will happen. The larger the project, the better the chance for conflicts. There's probably some logarithmic-style graph describing the relationship between the number of modules and the resulting number of potential conflicts. The issue does not really arise within small or personal projects to the same extent. Primarily because you personally have full control over the entire namespace.

Of course. But I only wanted to say that this does not justify the use
of a complex import statement syntax (the one Rioshin proposed). I
though the whole issue now was that Rioshin's syntax is better because
it requires less typing, when multiple members of the same module conflict:

static import
        in very.long.module.name alias mn
            member1 alias m1,
            member2 alias m2,
            member3 alias m3;

versus

import very.long.module.name as mn,
       very.long.module.name.member1 as m1,
       very.long.module.name.member2 as m2,
       very.long.module.name.member3 as m3;


IMHO the latter version is much better. Simpler compiler implementation, less syntax rules, less reserved symbols - one can easily replace 'as' with : as you said earlier. And the best of all is that this is fully backwards compatible with the current syntax.

The thing I was saying was that when there's a common guideline to create as little public members to the module as possible, it's much easier to import the whole module either to the global namespace or to a custom namespace

import very.long.module.name as mn; // or
import very.long.module.name;

and not import individual members at all (if possible). That way the syntax I proposed would not cause so much typing. AFAICS it's pretty much the same to use

  import module as a, module2 as b;
  a.foo();
  b.foo();

as

  import module.foo as afoo, module2.foo as bfoo;
  afoo();
  bfoo();


> The syntax itself does not need to be complex at all.

Right. I only meant that the syntax does not have to be a monster like this

[<protection>] [static] import {[in]} <FQN Module> [alias <Module Alias>] {[<<Member> [alias <Member Alias>]>[, ...]]};

(I think Rioshin even forgot to include 'as' keyword to the syntax above - that would probably make it a pain to implement if it isn't already)

My own proposal (actually it's partly stolen from many other proposals)
is to have only

[private] import <fqn module / module member> as <local module namespace / imported member name>, ...;

The Derek's problem could be then solved by doing:

  import std.string.find as find1,
         std.regexp.find as find2,
         internal.gc.gcx.find as find3;
  find1(...);
  find2(...);
  find3(...);

or

  import std.string as s, std.regexp as r, internal.gc.gcx as g;
  s.find(...);
  r.find(...);
  g.find(...);


> No static, no alias. Looks very much like the existing import, and is almost as effortless to use. Perhaps you might like to read the "Import RFC" posted? It explains the issues in a little more depth.

kris, I read it already. It seems that I have overlooked the name conflict issue. I'm sorry, I'm not a library guru yet. I'll try to shut up when I don't get it, but here I though a simple solution would help. I agree with you fully, but don't get it why Derek's or Rioshin's proposal is "good" in any way.

-- 
Jari-Matti
July 12, 2006
Derek Parnell wrote:
> On Wed, 12 Jul 2006 02:51:08 +0300, Jari-Matti Mäkelä wrote:
> 
>>> Consider the simple situation in Phobos
>>>
>>>  std.string.find
>>>  std.regexp.find
>>>  internal.gc.gcx.find
>>>
>>> then add the various other 'find' members in external libraries.
>> Ok, have to admit that's true. But do you really use them all in the same module?
> 
> Apparently, as that's how I got the error messages. ;-)

Yup. No problem, I was not thinking clearly here. Better get some sleep - it's already almost 4am here :)

>> If there's only a small amount of conflicting names, the import syntax does not have to be so incredibly complex.
> 
> Totally agree. Currently I'm using this sort of syntax ...
> 
>  import std.string;
>  alias std.string.find str_find;
>  alias std.string.replace str_replace;
> 
>  import std.regexp;
>  alias std.regexp.find re_find;
>  alias std.regexp.replace re_replace;
> 
>  import util.str;
>  alias util.str.find utl_find;

This is clearly an ad-hoc solution and I also use it.

> Yes, there has to be a better (something that is less costly to write,
> read, and maintain) solution.
> 
>  import std.string alias str;
>  import std.regexp alias re;
>  import util.str alias utl;
>  . . .
>  re.find( ... );
>  . . .
>  str.find( ... );
>  . . .
>  utl.find( ... );
> 
> would do nicely, thank you.

Yay, this is exactly the same syntax I though about. I suppose we totally agree now :)

-- 
Jari-Matti
July 12, 2006
Lars Ivar Igesund wrote:
> I believe I might have been a bit rash here, but I got somewhat pissed pouring over all the posts for the last few days. I will therefore restate some of my thoughts in a calmer manner:
> 
> If we for a second ignore the language issues chatted about recently, most people agree that D is missing libraries to be able to really compete with other languages. It is therefore unfathomable to me why you Walter don't actively try to make it easy to create good libraries in D. Libraries that can be made stable, failsafe and predictable. You have said many enough times that D is different enough to need different solutions to problems already solved in other languages. Why is it then that you seemingly refuse to listen to those that have tried to solve these problems in D over the years? Those that have found that the language features in D probably need to be refined to not only make libraries in D possible, but fun to write, fun to use, safe to use and with a predictable usage pattern.

I think you're a bit too harsh on Walter now. In the recent two week or so Walter has fixed many important things like most of the import bugs. The only thing left are:

 * some people thing that imports should be private by default
   - changing this would break some old code, but does it matter?
    (statistically private imports are much more common)

 * most of the people want an additional safe import syntax that allows
importing to a custom namespace.

 * some general show-stopper bugs

The first two of these are luckily easy to fix. We're not far from 1.0. If were not in a hurry, I would like the interface things to be fixed (that double lookup implementation) too before reaching stable. Then D will be perfect for real production level use.

-- 
Jari-Matti
July 12, 2006
Derek Parnell wrote:
> Yes, there has to be a better (something that is less costly to write,
> read, and maintain) solution.
> 
>  import std.string alias str;
>  import std.regexp alias re;
>  import util.str alias utl;
>  . . .
>  re.find( ... );
>  . . .
>  str.find( ... );
>  . . .
>  utl.find( ... );
> 
> would do nicely, thank you.

I've yet to read something from anyone who feels this approach, in general, is not a good one. Doesn't really matter whether the symbol used is "alias", "as", ":", "=", or whatever.

It is clean, elegant, trivially maintained and modified, and is simple enough to be unburdensome for a developer. This is important, if for no other reason than it tends to encourage the use of safe imports. I know I keep harping on about that; and on, and on, and on, and on, and on.

Although, this is prefix-importing rather than selective-importing. The former is far and away the more important variety, IMO.