June 14, 2003
> After separated decisions about the language space from the actual
> source written, it must be possible to use the selected functions
> in their native form. The problem I started this thread with,
> that the variable
>    char c;
> created a problem to call
>    fgets(...)
> can't be considered solved when a syntactical solution like
>    .c.stdio.fgets(...)
> is possible. (The compiler builder will think so)
>
> It would be solved, when I can decide:
>    prefer c.stdio over phobos.file;
> or:
>    priorities: variable.namespace,c.stdio,phobos.file,....;
>
> where I can direct the compiler how to resolve ambiguities on a project level or a higher level.
>
> Solving such things at the source or module level creates
> "local language" and makes code dependant on these local decisions.
> This makes code hard to read, move, refactor and reuse.

So does, IMHO, your prioritizing solution; while this solves the problem on a project-granular basis, it makes it hard to transfer code from one project to another, especially if you can't just copy the priorities over because the rest of your code assumes different ones. You don't get rid of this with moving it to user-level preferences or site-level preferences either - all this does is move what you call "local language" to a higher level, while not solving the actual problem at all; this is, in my opinion, unaccep- table.

Other problems with that approach include that it introduces quite dubious name lookup rules (the point was getting it easier than C++, not more complicated, no? :) and actually suggests writing ambiguous code and resolving that ambiguities with priorities later.

This kind of collisions should, ideally, either be disallowed by the language (like with redefinition of local variables) or atleast made harder to happen, which would be possible using coding standards only.

To explain the coding standards point: Using a one-character identifier for a module ("c"), while convenient, is still a Bad Thing; was it named "clib" or something similar instead, the whole issue most likely wouldn't exist. While this doesn't solve the actual problem, I still think it would be a good idea to change the standard libraries and coding conventions to use atleast 3-character names; anything lower than that is bound to cause problems like this one.

Now, for the language approach: I'd be for disallowing *any* kind of identifier to be identical to a (known, that is, imported in the module and scope being compiled) module name. This makes the ".c.stdio.fgets" notation unnecessary - such collisions simply cannot happen that way. This only solves the problem in the module being compiled, which means the following case could still be considered problematic:

    // a.d
    module a;
    // ...

    // b.d
    int a=3;

    // main.d
    import b;
    import a;

Now, what is a? Obviously, it *should* be the module a in that case, because b's a can still be reached by using b.a, while the opposite is not true. There are two ways to solve the problem - either issue an error while compiling main.d, or introducing another rule that module names "hide" symbols defined in other modules.

Both aren't particularly clean, but I consider the first to be the worse alternative, for three reasons:

1. It basically suggests that there can be errors in b's code that
   cannot necessarily be found while compiling b, because they are
   dependent on the context in which b is being used. This would be
   quite an awkward situation.
2. It's not orthogonal with the way D normally handles such ambi-
   guities - namely, *not* issuing an error, just requiring full
   qualification to resolve which symbol is meant.
3. Existing and perfectly valid code can break any time in the future
   when someone, somewhere adds another module that causes conflicting
   identifiers. That issue should have to be resolved by either the
   author of that module or by the one who attempts to use both modules.

The second solution can never break existing code (unless there are issues I'm not aware of), and I think requiring module names to be unique is a good idea in any case.

-fg


June 15, 2003

Fabian Giesen wrote:
> 
> > After separated decisions about the language space from the actual
> > source written, it must be possible to use the selected functions
> > in their native form. The problem I started this thread with,
> > that the variable
> >    char c;
> > created a problem to call
> >    fgets(...)
> > can't be considered solved when a syntactical solution like
> >    .c.stdio.fgets(...)
> > is possible. (The compiler builder will think so)
> >
> > It would be solved, when I can decide:
> >    prefer c.stdio over phobos.file;
> > or:
> >    priorities: variable.namespace,c.stdio,phobos.file,....;
> >
> > where I can direct the compiler how to resolve ambiguities on a project level or a higher level.
> >
> > Solving such things at the source or module level creates
> > "local language" and makes code dependant on these local decisions.
> > This makes code hard to read, move, refactor and reuse.
> 
> So does, IMHO, your prioritizing solution; while this solves the problem on a project-granular basis, it makes it hard to transfer code from one project to another, especially if you can't just copy the priorities over because the rest of your code assumes different ones. You don't get rid of this with moving it to user-level preferences or site-level preferences either - all this does is move what you call "local language" to a higher level, while not solving the actual problem at all; this is, in my opinion, unaccep- table.
> 
> Other problems with that approach include that it introduces quite dubious name lookup rules (the point was getting it easier than C++, not more complicated, no? :) and actually suggests writing ambiguous code and resolving that ambiguities with priorities later.
> 
> This kind of collisions should, ideally, either be disallowed by the language (like with redefinition of local variables) or atleast made harder to happen, which would be possible using coding standards only.
> 
> To explain the coding standards point: Using a one-character identifier for a module ("c"), while convenient, is still a Bad Thing; was it named "clib" or something similar instead, the whole issue most likely wouldn't exist. While this doesn't solve the actual problem, I still think it would be a good idea to change the standard libraries and coding conventions to use atleast 3-character names; anything lower than that is bound to cause problems like this one.
> 
> Now, for the language approach: I'd be for disallowing *any* kind of identifier to be identical to a (known, that is, imported in the module and scope being compiled) module name. This makes the ".c.stdio.fgets" notation unnecessary - such collisions simply cannot happen that way. This only solves the problem in the module being compiled, which means the following case could still be considered problematic:
> 
>     // a.d
>     module a;
>     // ...
> 
>     // b.d
>     int a=3;
> 
>     // main.d
>     import b;
>     import a;
> 
> Now, what is a? Obviously, it *should* be the module a in that case, because b's a can still be reached by using b.a, while the opposite is not true. There are two ways to solve the problem - either issue an error while compiling main.d, or introducing another rule that module names "hide" symbols defined in other modules.
> 
> Both aren't particularly clean, but I consider the first to be the worse alternative, for three reasons:
> 
> 1. It basically suggests that there can be errors in b's code that
>    cannot necessarily be found while compiling b, because they are
>    dependent on the context in which b is being used. This would be
>    quite an awkward situation.
> 2. It's not orthogonal with the way D normally handles such ambi-
>    guities - namely, *not* issuing an error, just requiring full
>    qualification to resolve which symbol is meant.
> 3. Existing and perfectly valid code can break any time in the future
>    when someone, somewhere adds another module that causes conflicting
>    identifiers. That issue should have to be resolved by either the
>    author of that module or by the one who attempts to use both modules.
> 
> The second solution can never break existing code (unless there are issues I'm not aware of), and I think requiring module names to be unique is a good idea in any case.

Rethinking the problem based on your excellent arguments...

I think that the current problem has two parts. One is syntactical,
because the system treats
   c.size  (property or method of an "object")
the same as
   c.stdio (module from a package)
which feels not quite right.

Using a different syntax for modules, e. g.
   c:stdio
the problem would go away. (I do not suggest this solution)

On the other hand, there is the semantical problem how to deal with
ambiguities. This problem turns up here, but there is at least one
other place where I met the same problem (parameter matching).
The way that D currently chooses is that of complete qualification:
in case of an ambiguity (and that is handled very strictly) you have
to exactly say what you want.
E. g. if you have a
   sqrt(long x) and sqrt(real x)
doing
   float f; x=sqrt(f);
is considered ambiguous and has to be resolved by
   float f; x=sqrt((real)f);
This philosophical decision will turn up as a PITA in the future.
Having a sqrt(real) in a distributed library and adding sqrt(long)
will break the code of hundreds of developers and force them to
exactly qualify what they now - after the library update - want.

In the current case there is only an ambiguity at the first level,
because we don't know what
  c (the variable ? the module?)
is. But the way it is used
  c.stdio...
there is no ambiguity, because only the module has this property.
It would be nice if the D compiler had enough intelligence to cope
with this situation.

--
Helmut Leitner    leitner@hls.via.at Graz, Austria   www.hls-software.com
June 15, 2003
> On the other hand, there is the semantical problem how to deal with
> ambiguities. This problem turns up here, but there is at least one
> other place where I met the same problem (parameter matching).
> The way that D currently chooses is that of complete qualification:
> in case of an ambiguity (and that is handled very strictly) you have
> to exactly say what you want.
> E. g. if you have a
>    sqrt(long x) and sqrt(real x)
> doing
>    float f; x=sqrt(f);
> is considered ambiguous and has to be resolved by
>    float f; x=sqrt((real)f);
> This philosophical decision will turn up as a PITA in the future.
> Having a sqrt(real) in a distributed library and adding sqrt(long)
> will break the code of hundreds of developers and force them to
> exactly qualify what they now - after the library update - want.

Yeah, but you have *that* problem with overload resolution in e.g. C++, too. Just because C++ compilers make somewhat more ambitious attempts at deducing which overload is the best alternative it doesn't mean that kind of problem doesn't exist - quite on the con- trary, actually. C++ has rules that disambiguate such cases, but this can break code in very nonobvious ways: assume that there is already a double sqrt(double) and at some point later in time someone adds a int sqrt(int) routine.

Every code that previously called sqrt with an int parameter will now use the version that returns an integer - even in fp expressions. C++ will silently do that and not even issue a warning, because the over- load resolution is completely unambiguous. Of course this will totally break any code assuming that you get a double return value.

Bottom line: Overloads are a very picky thing no matter what you do. The whole point of overloading is to allow some kind of ambiguity to make writing code easier or more intuitive. However, it can *very* easily backfire, in circumstances as illustrated above, and, as you see, in very non-intuitive ways. In this case, I think D's choice to expli- citly force nonambiguous qualification is the right one; especially since you normally CANNOT add new overloads without the risk of breaking tons of existing code anyway. This is a design problem with overloads itself - and there's nothing one can do about it except being very care- ful when using overloads and not adding new overloads later when they're not absolutely necessary (this only goes for overloads with the same number of parameters; a different number is obviously not quite as dangerous).

-fg


June 16, 2003

Fabian Giesen wrote:
> 
> > On the other hand, there is the semantical problem how to deal with
> > ambiguities. This problem turns up here, but there is at least one
> > other place where I met the same problem (parameter matching).
> > The way that D currently chooses is that of complete qualification:
> > in case of an ambiguity (and that is handled very strictly) you have
> > to exactly say what you want.
> > E. g. if you have a
> >    sqrt(long x) and sqrt(real x)
> > doing
> >    float f; x=sqrt(f);
> > is considered ambiguous and has to be resolved by
> >    float f; x=sqrt((real)f);
> > This philosophical decision will turn up as a PITA in the future.
> > Having a sqrt(real) in a distributed library and adding sqrt(long)
> > will break the code of hundreds of developers and force them to
> > exactly qualify what they now - after the library update - want.
> 
> Yeah, but you have *that* problem with overload resolution in e.g. C++, too. Just because C++ compilers make somewhat more ambitious attempts at deducing which overload is the best alternative it doesn't mean that kind of problem doesn't exist - quite on the con- trary, actually. C++ has rules that disambiguate such cases, but this can break code in very nonobvious ways: assume that there is already a double sqrt(double) and at some point later in time someone adds a int sqrt(int) routine.

I never liked C++ enough to use it in a project. Changing the strategy
because A causes problems doesn't guarantee that "not A" doesn't
produce the same amount of problems (or more). Remember MS-Windows
going in and of of the "central config repository" idea.

> Every code that previously called sqrt with an int parameter will now use the version that returns an integer - even in fp expressions. C++ will silently do that and not even issue a warning, because the over- load resolution is completely unambiguous. Of course this will totally break any code assuming that you get a double return value.

My example wasn't well chosen, I just wanted a function that I didn't have to explain.

But: sqrt is by definition a floating point function. If overloaded
it must return a FP value. Otherwise it changes the semantics and
should be names something like SqrtFloor(...). A sqrt(long x) might be
some function that uses tables for small values of x to increase
performance and fall back to the normal sqrt.

> Bottom line: Overloads are a very picky thing no matter what you do. The whole point of overloading is to allow some kind of ambiguity to make writing code easier or more intuitive. However, it can *very* easily backfire, in circumstances as illustrated above, and, as you see, in very non-intuitive ways. In this case, I think D's choice to expli- citly force nonambiguous qualification is the right one; especially since you normally CANNOT add new overloads without the risk of breaking tons of existing code anyway. This is a design problem with overloads itself - and there's nothing one can do about it except being very care- ful when using overloads and not adding new overloads later when they're not absolutely necessary (this only goes for overloads with the same number of parameters; a different number is obviously not quite as dangerous).

I'm no overloading fan. It seems that OO languages can't live without it.

I deliver libraries. I don't want a new library to break any old code. If a language can't gurantee me a way - however complicated - to do that, it is no use for me.

I can't avoid to create tons of modules. If these modules will share
some namespace with variables, then the module names will have to be
pretty unique to reduce the risc of conflict. E. g. one could name
them
   p__c.m__stdio (package _ _ c).(module _ _ stdio)
This is so ugly that after some time Walter will feel a need to
invent something to avoid it.

--
Helmut Leitner    leitner@hls.via.at Graz, Austria   www.hls-software.com
June 16, 2003
> My example wasn't well chosen, I just wanted a function that I didn't have to explain.
>
> But: sqrt is by definition a floating point function. If overloaded it must return a FP value. Otherwise it changes the semantics and should be names something like SqrtFloor(...). A sqrt(long x) might be some function that uses tables for small values of x to increase performance and fall back to the normal sqrt.

It is crucial to realize that the problem itself is absolutely independent of function chosen (though the probability of it happening isn't).

As soon as you start to allow ambiguities, things do, well, get ambiguous :) Adding a new overloaded function with the same number of parameters and different types always has the potential to break existing code - unless the set of types reachable via implicit conversions by the two is disjoint; for example, overloading f(char) with f(char[]) is always safe, since there's no way any implicit conversion should happen that changes the meaning of existing code.

However, there IS an easy solution to get rid of that problem - once you know of that issue, just never do that and rather name the function differently. Problem solved :)

> I'm no overloading fan. It seems that OO languages can't live without it.

It's a nice feature, but as always, it comes with a price.

> I deliver libraries. I don't want a new library to break any old code. If a language can't gurantee me a way - however complicated - to do that, it is no use for me.
>
> I can't avoid to create tons of modules. If these modules will share
> some namespace with variables, then the module names will have to be
> pretty unique to reduce the risc of conflict. E. g. one could name
> them
>    p__c.m__stdio (package _ _ c).(module _ _ stdio)
> This is so ugly that after some time Walter will feel a need to
> invent something to avoid it.

Not all module names need to have different names than variables, only
the top-level ones do. The rest is reachable via full qualification in any
case and doesn't require additional syntax such as a global scope operator.

Besides, prefixing is really the worst method to solve the unique identifier problem - clib.stdio would do just fine IMHO.

-fg


June 21, 2003
>> >In the next version, I've added a module scope operator, ., which should resolve this problem properly, as in: .c.stdio.fgets(&buf[0],buf.size,.c.stdio.stdin);
>> >
>> >It works analogously to the C++ global scope operator ::.
>>
>> IMHO this looks really ugly,  doesn't "import" give enough info to avoid
>this ??
>
>No.
>
>> I thought the whole idea was to be cleaner than C++.
>
>If there's a better way to resolve that problem, I want to know about it!
==================
import c.stdio;
..
char c;
char buf[256];
c.stdio.fgets(&buf[0],buf.size,c.stdio.stdin);
c=buf[0];

won't compile because of an

no property 'stdio' for type 'char'
===========================
let's get back to basics here:
the "c"  in c.stdio is a package name, it seems that the compilation system
should be able to resolve this name versus the variable name "c" from char c.
Since in D this "c" is only a reference on how to locate module "stdio".

Shouldn't each of package, module, class, variable, etc have it's own name space (whether through name mangling or other means)?

I worked with the Ada language for several years and it was easy to resolve  any
name conflicts between imports by prepending the package name to the function or
variable name (assume 'with' and 'use').
Package_1.Function(x)  vs  Package_2.Function(x)
note: Ada package is a module










June 21, 2003
Walter wrote:
> "Mark T" <Mark_member@pathlink.com> wrote in message
> news:bc9r3j$1bpm$1@digitaldaemon.com...
> 
>>In article <bc3343$1dgn$1@digitaldaemon.com>, Walter says...
>>
>>>In the next version, I've added a module scope operator, ., which should
>>>resolve this problem properly, as in:
>>>.c.stdio.fgets(&buf[0],buf.size,.c.stdio.stdin);
>>>
>>>It works analogously to the C++ global scope operator ::.
>>
>>IMHO this looks really ugly,  doesn't "import" give enough info to avoid
> 
> this ??
> 
> No.
> 
> 
>>I thought the whole idea was to be cleaner than C++.
> 
> 
> If there's a better way to resolve that problem, I want to know about it!

Yeah, don't use too-short module names, and don't put kludges into a language solving a problem that shouldn't exist if the language were being correctly used.

I think there's two mistakes going on here.  First, we should be applying package organisation to Phobos and other libraries.  Second, we should be using capital letters in module names when appropriate. Intuitively, lowercase feels better.  But in practice, it results in ugly names, lots of collisions, and seems to result in more curious acronyms and cut words than capitalised (java.rmi.dgc, for example). One naming scheme could be like this:

aaA -> D.Internal.AArray;
achar -> D.Internal.AChar;
adi -> D.Internal.Array;
alloca -> D.Internal.alloca;
array -> D.Exception.ArrayBoundsError;
arraycast -> D.Internal.ArrayCast;
arraycat -> D.Internal.ArrayCat;
assert -> D.Exception.AssertError; (It's not even a valid module name for goodness' sake!)
cast -> D.Internal.Cast; (Ditto!)
cmath -> D.System.ComplexMath;
cmath2 -> D.Internal.ComplexArithmetic;
com -> D.Phobos.COM;
compiler -> D.Phobos.Compiler;
conv -> D.Phobos.Conv;
crc32 -> D.Phobos.CRC32;
ctype -> D.Phobos.CharType;
date -> D.Phobos.Date;
dateparse -> D.Phobos.DateParse;
deh2 -> D.Internal.ExceptionHandling;
dmain2 -> D.Internal.Main;
file -> D.Phobos.File;
gc -> D.Phobos.GC;
gcstats (merge with gc)
intrinsic -> D.Internal.Intrinsic; (put aliases in D.Phobos.Math)
invariant -> D.Internal.Invariant;
iunknown -> D.Phobos.IUnknown;
linux -> D.CRT.Linux;
linuxextern -> D.CRT.LinuxExtern;
llmath -> D.Internal.LongArithmetic;
math -> D.Phobos.Math;
math2 (merge with D.Phobos.Math)
memset -> D.Internal.memset;
moduleinit -> D.Internal.ModuleInit;
obj -> D.Internal.Object;
object -> D.Phobos.Object;
outbuffer -> D.Phobos.OutBuffer;
outofmemory -> D.Error.OutOfMemory;
path -> D.Phobos.Path;
qsort -> D.Internal.Sort;
random -> D.Phobos.Random;
regexp -> D.Phobos.RegExp;
stdint -> D.Phobos.StandardTypes;
stream -> D.Phobos.Stream;
string -> D.Phobos.String;
switch -> D.Internal.Switch; (again the name!)
switcherr -> D.Exception.SwitchError;
syserror -> D.Exception.SystemError;
system -> D.Phobos.System;
thread -> D.Phobos.Thread;
time -> D.Phobos.Time;
ti_* -> D.Internal.*;
uri -> D.Phobos.URI;
utf -> D.Phobos.UTF8;
windows -> D.CRT.windows;
c.stdio -> D.CRT.stdio;
c.stdlib -> D.CRT.stdlib;
gc.* -> D.Internal.GC.*;

dig would be put in the "D.Dig" package.  I could use "D.Dig.Main" for what "import dig" does now.  Or some other prefix than D.  In any case, it's much clearer about what I'm referring to; when I type "string.tolower" it's ambiguous as to whether I'm referring to a module or an object, as I use it for both heavily.  XYZ.Phobos.String.tolower is completely unambiguous, and if it gets too much (module "string."'s used 43 times throughout dig, so that can happen) I can alias it to something more manageable.  And with full package names, I can alias more selectively - "private alias XYZ.Phobos P;" would allow me to use "P.String.tolower", which can often be enough.

June 22, 2003
Windows should go into D.Platform.windows or D.SDK.windows;  it is most certainly not standard C runtime library material.  Same with Linux.

I don't care if you use capital letters or not.  Personally I like MixedCase, but it really doesn't matter to me.

I do like the idea of moving all this stuff into the D module umbrella. Prevents many many clashes, prevents cluttering up the global namespace.  It gives people a clear idea of whether a module is 1st-party or 3rd-party. But then why would Dig go under D?  DigitalMars should reserve the entire D.* module namespace.  Library writers can make their own, such as BRadons.Dig.  ;)

Why the "Internal" module group?  I'm kinda surprised that there are so many low-level support libraries;  I'd expect more of this to be built in, or unnecessary.

What's the difference between complex math and complex arithmetic?  Why are they separate?  They're not even in the same branch... that's just wierd.

I agree that Intrinsic should have aliases in Math.  I suggest that users should not have to care whether something is an intrinsic or not;  this is entirely a choice that should be left up to the compiler, possibly affected by some kind of speed vs. size switch.  It is an implementation detail and users shouldn't be forced to deal with it.

Why is there D.Exception.* and D.Internal.Exception?

Rename Conv to Convert.  Saving 3 characters is not worth it.  Or maybe Conversion.

Sean

"Burton Radons" <loth@users.sourceforge.net> wrote in message news:bd1r3s$1s87$1@digitaldaemon.com...
> Yeah, don't use too-short module names, and don't put kludges into a language solving a problem that shouldn't exist if the language were being correctly used.
>
> I think there's two mistakes going on here.  First, we should be applying package organisation to Phobos and other libraries.  Second, we should be using capital letters in module names when appropriate. Intuitively, lowercase feels better.  But in practice, it results in ugly names, lots of collisions, and seems to result in more curious acronyms and cut words than capitalised (java.rmi.dgc, for example). One naming scheme could be like this:
>
> aaA -> D.Internal.AArray;
> achar -> D.Internal.AChar;
> adi -> D.Internal.Array;
> alloca -> D.Internal.alloca;
> array -> D.Exception.ArrayBoundsError;
> arraycast -> D.Internal.ArrayCast;
> arraycat -> D.Internal.ArrayCat;
> assert -> D.Exception.AssertError; (It's not even a valid module name
> for goodness' sake!)
> cast -> D.Internal.Cast; (Ditto!)
> cmath -> D.System.ComplexMath;
> cmath2 -> D.Internal.ComplexArithmetic;
> com -> D.Phobos.COM;
> compiler -> D.Phobos.Compiler;
> conv -> D.Phobos.Conv;
> crc32 -> D.Phobos.CRC32;
> ctype -> D.Phobos.CharType;
> date -> D.Phobos.Date;
> dateparse -> D.Phobos.DateParse;
> deh2 -> D.Internal.ExceptionHandling;
> dmain2 -> D.Internal.Main;
> file -> D.Phobos.File;
> gc -> D.Phobos.GC;
> gcstats (merge with gc)
> intrinsic -> D.Internal.Intrinsic; (put aliases in D.Phobos.Math)
> invariant -> D.Internal.Invariant;
> iunknown -> D.Phobos.IUnknown;
> linux -> D.CRT.Linux;
> linuxextern -> D.CRT.LinuxExtern;
> llmath -> D.Internal.LongArithmetic;
> math -> D.Phobos.Math;
> math2 (merge with D.Phobos.Math)
> memset -> D.Internal.memset;
> moduleinit -> D.Internal.ModuleInit;
> obj -> D.Internal.Object;
> object -> D.Phobos.Object;
> outbuffer -> D.Phobos.OutBuffer;
> outofmemory -> D.Error.OutOfMemory;
> path -> D.Phobos.Path;
> qsort -> D.Internal.Sort;
> random -> D.Phobos.Random;
> regexp -> D.Phobos.RegExp;
> stdint -> D.Phobos.StandardTypes;
> stream -> D.Phobos.Stream;
> string -> D.Phobos.String;
> switch -> D.Internal.Switch; (again the name!)
> switcherr -> D.Exception.SwitchError;
> syserror -> D.Exception.SystemError;
> system -> D.Phobos.System;
> thread -> D.Phobos.Thread;
> time -> D.Phobos.Time;
> ti_* -> D.Internal.*;
> uri -> D.Phobos.URI;
> utf -> D.Phobos.UTF8;
> windows -> D.CRT.windows;
> c.stdio -> D.CRT.stdio;
> c.stdlib -> D.CRT.stdlib;
> gc.* -> D.Internal.GC.*;
>
> dig would be put in the "D.Dig" package.  I could use "D.Dig.Main" for what "import dig" does now.  Or some other prefix than D.  In any case, it's much clearer about what I'm referring to; when I type "string.tolower" it's ambiguous as to whether I'm referring to a module or an object, as I use it for both heavily.  XYZ.Phobos.String.tolower is completely unambiguous, and if it gets too much (module "string."'s used 43 times throughout dig, so that can happen) I can alias it to something more manageable.  And with full package names, I can alias more selectively - "private alias XYZ.Phobos P;" would allow me to use "P.String.tolower", which can often be enough.
>


July 09, 2003
Is there _any_ chance of having a .. module scope operator. One of the things I've always wanted in C++ is to be able to say "one namespace above". Hence

int x;

namespace L1
{
    int x;

    namespace L2
    {
          int     x;

        x = 0; // Does (in C++ speak) L1::L2::x
        .x = 0; // Does (in C++ speak) ::x
        ..x = 0; // Does (in C++ speak) L1::x
    }
}


Having looked at that, though, I'd actually like . to mean "this namespace", so how would we get to the root?

What about

 /x is the x in the global namespace
 ./x is the x in the current namespace
 ../x is the x in the enclosing namespace
 x is whatever is determined as happens now in unadorned C++/D

You may wonder why this would be good. In a word, templates.

You may want an example demonstrating the utility. Alas, I can't think of one atm, but it's definitely something I've wanted many times in C++


"Walter" <walter@digitalmars.com> wrote in message news:bc3343$1dgn$1@digitaldaemon.com...
> In the next version, I've added a module scope operator, ., which should resolve this problem properly, as in:
>
> .c.stdio.fgets(&buf[0],buf.size,.c.stdio.stdin);
>
> It works analogously to the C++ global scope operator ::.
>
>
> "Helmut Leitner" <helmut.leitner@chello.at> wrote in message news:3EE2FA45.29B11971@chello.at...
> > Currently code like
> >
> >    import c.stdio;
> >    ...
> >    char c;
> >    char buf[256];
> >    c.stdio.fgets(&buf[0],buf.size,c.stdio.stdin);
> >    c=buf[0];
> >
> > won't compile because of an
> >
> >    no property 'stdio' for type 'char'
> >
> > error.
> >
> > Could this be changed, so that the compiler checks for an interpretation that makes sense if there a more than one? Otherwise any module in any library is a potential candidate for such collisions!
> >
> > --
> > Helmut Leitner    leitner@hls.via.at
> > Graz, Austria   www.hls-software.com
>
>


July 09, 2003
"Georg Wrede" <Georg_member@pathlink.com> wrote in message news:bcbt1u$ao3$1@digitaldaemon.com...
> >> >It works analogously to the C++ global scope operator ::.
> >>
> >> IMHO this looks really ugly,  doesn't "import" give enough info to
avoid
> >this ??
> >
> >No.
> >
> >> I thought the whole idea was to be cleaner than C++.
> >
> >If there's a better way to resolve that problem, I want to know about it!
>
> I think this should be studied together with the Private Import b.a.A issue.
>
> Maybe a lot of folks have reasoned deeply into this, but so far the
> recent discussion here about this has been shallow, almost like
> "this looks nice, lets do it this way", when we should really
> consider the _meaning_ of imports, private imports, indirect
> inclusion (i.e. the b.a.A issue), visibility, and propagation
> of visibility, as manifestations of a single concept.
> Like _what_ is one really attempting to acheve with all these.
>
> We ought to get a crystal clear understanding, not least because if this is done wrong now then later there'll be hell to pay.

Strongly agree

>
> Once we understand this, then the separate answers to these "separate" issues, I believe, will become obvious.
>
>