www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - import decalrations

reply Ant <Ant_member pathlink.com> writes:
(We have had some suggestions to change the import declarations.
many inspired from other languages.)

In D we are able to declare imports at the module top level
and on the class body.

Walter says he doesn't recomend the latter. Why?

I once said:

 work around:

 move the import to inside the class body.


and Walter responded:
I strongly recommend against doing that. There must be a better solution
than that.

so I'm saying: Why shouldn't it be supported, unless if difficult to maintain? On OO coding I'm going to use the imported symbols only on inside the body of the class so it makes perfect sence that the import is declared inside the class body. People just aren't use to it. I don't see this has an hack to avoid other problems but as the logic scope to insert the import decalration. Java doesn't need this because (almost) nothing else goes outside class bodies. when declared inside the class body the simbols should be available only to subclasses (unless they are private...). So who's with me to try to convince Walter to continue to support import declarations inside the class body? Ant
Aug 25 2004
next sibling parent reply Andy Friesen <andy ikagames.com> writes:
Ant wrote:

 Why shouldn't it be supported, unless if difficult to maintain?
 On OO coding I'm going to use the imported symbols only on inside the body of
 the class so it makes perfect sence that the import is declared
 inside the class body. People just aren't use to it. I don't see this
 has an hack to avoid other problems but as the logic scope to insert
 the import decalration.
 Java doesn't need this because (almost) nothing else goes outside class bodies.
 
 when declared inside the class body the simbols should
 be available only to subclasses (unless they are private...).
 
 So who's with me to try to convince Walter to continue to support 
 import declarations inside the class body?

I think Walter was talking about using class-level imports to resolve circular reference issues. I agree with him: it's a terrible, terrible hack around the problem and it introduces all manner of problems later on down the line. The problem may be that the import statement does two distinct, unrelated things instead of just one. First, import tells DMD to scan some source file, in some directory. The symbols in this file are made available to the source program. Second, import pulls all of those symbols into the current scope. The second of these behaviours sounds suspiciously like a mass-alias to me. Such a thing would be useful in its own right, and it would be a good thing to separate the two concepts into distinct statements. ie import std.string; // std.string is added to the known scopes alias std.string.*;// alias all of std.string into the present scope This makes it clearer that you /want/ all of those symbols to be part of the class definition. It also helps keep the global namespace cleaner by making it much more realistic to say that the only things in a module's scope are declared there explicitly. (unless you use alias x.*;) Doing this presently is a bit of a chore: private struct std { struct string { import std.string; } -- andy
Aug 25 2004
next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
 First, import tells DMD to scan some source file, in some directory.
 The symbols in this file are made available to the source program.

 Second, import pulls all of those symbols into the current scope.

It does? I thought a symbol in an imported module will only be searched for if DMD can't find the symbol in the current scope. So import doesn't bring symbols into the current scope- it just says where to look if the symbol isn't in the current scope. Alias defines a new symbol in the current scope.
 The second of these behaviours sounds suspiciously like a mass-alias to
 me.  Such a thing would be useful in its own right, and it would be a
 good thing to separate the two concepts into distinct statements. ie

      import std.string; // std.string is added to the known scopes
      alias std.string.*;// alias all of std.string into the present scope

 This makes it clearer that you /want/ all of those symbols to be part of
 the class definition.  It also helps keep the global namespace cleaner
 by making it much more realistic to say that the only things in a
 module's scope are declared there explicitly. (unless you use alias
 x.*;) Doing this presently is a bit of a chore:

      private struct std { struct string {
          import std.string;
      }

   -- andy

Aug 25 2004
next sibling parent reply Ant <Ant_member pathlink.com> writes:
In article <cgil87$2cn3$1 digitaldaemon.com>, Ben Hinkle says...
 First, import tells DMD to scan some source file, in some directory.
 The symbols in this file are made available to the source program.

 Second, import pulls all of those symbols into the current scope.

It does? I thought a symbol in an imported module will only be searched for if DMD can't find the symbol in the current scope.

that changed on 0.91 (the start of the stall for my projects)
 So import doesn't bring
symbols into the current scope- it just says where to look if the symbol
isn't in the current scope.

No, the imported will overide the locals! Ant
Aug 25 2004
next sibling parent Sean Kelly <sean f4.ca> writes:
In article <cgimgj$2dap$1 digitaldaemon.com>, Ant says...
In article <cgil87$2cn3$1 digitaldaemon.com>, Ben Hinkle says...
 First, import tells DMD to scan some source file, in some directory.
 The symbols in this file are made available to the source program.

 Second, import pulls all of those symbols into the current scope.

It does? I thought a symbol in an imported module will only be searched for if DMD can't find the symbol in the current scope.

that changed on 0.91 (the start of the stall for my projects)
 So import doesn't bring
symbols into the current scope- it just says where to look if the symbol
isn't in the current scope.

No, the imported will overide the locals!

Really? That sounds broken to me. Sean
Aug 25 2004
prev sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Ant" <Ant_member pathlink.com> wrote in message
news:cgimgj$2dap$1 digitaldaemon.com...
 In article <cgil87$2cn3$1 digitaldaemon.com>, Ben Hinkle says...
 First, import tells DMD to scan some source file, in some directory.
 The symbols in this file are made available to the source program.

 Second, import pulls all of those symbols into the current scope.

It does? I thought a symbol in an imported module will only be searched


if DMD can't find the symbol in the current scope.

that changed on 0.91 (the start of the stall for my projects)

Here's a little test case with two files, mod1.d and mod2.d: file mod1.d: module mod1; void foo(int x){}; file mod2.d: module mod2; class A{ import mod1; void foo(){}; void bar(){ foo(); } } void main(){}; This compiles fine since foo inside A resolves to A.foo. If bar is changed to void bar(){foo(100);} then it no longer compiles because mod1.foo is not part of the overload resolution for foo inside A. So I'm a bit confused about the statement that "import pulls all the symbols into the current scope". I'm not sure what "pulls" means. You give a small example of what is going wrong in your code?
 So import doesn't bring
symbols into the current scope- it just says where to look if the symbol
isn't in the current scope.

No, the imported will overide the locals!

what do you mean by "override"? Do you mean overload (as in function overloading)? Overload resolution happens after the name resolution.
Aug 25 2004
next sibling parent reply Ant <Ant_member pathlink.com> writes:
In article <cgiqb8$2f8e$1 digitaldaemon.com>, Ben Hinkle says...
Here's a little test case with two files, mod1.d and mod2.d:

file mod1.d:
module mod1;
void foo(int x){};

file mod2.d:
module mod2;
class A{
  import mod1;
  void foo(){};
  void bar(){ foo(); }
}
void main(){};

I don't have D here. try print out something different on A.foo() and a new function void foo() in module mod1. I'm saying that the method called from A.bar() will be the one from mod1.
This compiles fine since foo inside A resolves to A.foo.

not if there is a method void foo() on mod1. If bar is changed
to
  void bar(){foo(100);}
then it no longer compiles because mod1.foo is not part of the overload
resolution for foo inside A.

this is a surprise to me! it makes import useless (????)
 So I'm a bit confused about the statement that
"import pulls all the symbols into the current scope". I'm not sure what
"pulls" means. You give a small example of what is going wrong in your code?

 So import doesn't bring
symbols into the current scope- it just says where to look if the symbol
isn't in the current scope.

No, the imported will overide the locals!

what do you mean by "override"?

I mean hide, kill, make disapear... in your example you overload foo, I thought that was OK but you say it doesn't compile(?) Ant
Aug 25 2004
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Ant" <Ant_member pathlink.com> wrote in message
news:cgirvn$2g0t$1 digitaldaemon.com...
 In article <cgiqb8$2f8e$1 digitaldaemon.com>, Ben Hinkle says...
Here's a little test case with two files, mod1.d and mod2.d:

file mod1.d:
module mod1;
void foo(int x){};

file mod2.d:
module mod2;
class A{
  import mod1;
  void foo(){};
  void bar(){ foo(); }
}
void main(){};

I don't have D here. try print out something different on A.foo() and a new function void foo() in module mod1. I'm saying that the method called from A.bar() will be the one from mod1.

I tried again with file mod1.d: module mod1; void foo(){printf("hello\n");}; file mod2.d: module mod2; class A { import mod1; void foo(){printf("in A\n");}; void bar(){ foo(); } } void main(){ A a = new A; a.bar(); }; and it prints "in A" as I would expect. So it looks like the right one is found.
This compiles fine since foo inside A resolves to A.foo.

not if there is a method void foo() on mod1.

Hmm. I could compile ok with foo() instead of foo(int x).
 If bar is changed
to
  void bar(){foo(100);}
then it no longer compiles because mod1.foo is not part of the overload
resolution for foo inside A.

this is a surprise to me! it makes import useless (????)

why useless? import is for name resolution and not overload resolution.
 So I'm a bit confused about the statement that
"import pulls all the symbols into the current scope". I'm not sure what
"pulls" means. You give a small example of what is going wrong in your


 So import doesn't bring
symbols into the current scope- it just says where to look if the




isn't in the current scope.

No, the imported will overide the locals!

what do you mean by "override"?

I mean hide, kill, make disapear... in your example you overload foo, I thought that was OK but you say it doesn't compile(?) Ant

Without code it's hard to get into the details - words tend to be imprecise and this name/overloading resolution stuff tends to get confusing without concrete examples. I afraid I still don't get the problem.
Aug 25 2004
next sibling parent Ant <Ant_member pathlink.com> writes:
In article <cgitmo$2gpm$1 digitaldaemon.com>, Ben Hinkle says...
"Ant" <Ant_member pathlink.com> wrote in message
news:cgirvn$2g0t$1 digitaldaemon.com...
 In article <cgiqb8$2f8e$1 digitaldaemon.com>, Ben Hinkle says...

I tried again with

ok!, the new example you reported sounds good. as you expected, and I, and every body else expected until dmd 0.91. all other considerations I made have no base now.
I afraid I still don't get the problem.

You just prove I have no problem. I'll try the modified example with 0.98 (the one I'm using) and if I still have it with 0.91 (just to save my face...) Ant
Aug 25 2004
prev sibling parent Ant <Ant_member pathlink.com> writes:
In article <cgitmo$2gpm$1 digitaldaemon.com>, Ben Hinkle says...

just for reference here is when I first panicked: digitalmars.D.bugs/323 Ant
Aug 25 2004
prev sibling parent reply John Reimer <brk_6502 NOSP_AM.yahoo.com> writes:
Ben Hinkle wrote:
 "Ant" <Ant_member pathlink.com> wrote in message
 news:cgimgj$2dap$1 digitaldaemon.com...
 
In article <cgil87$2cn3$1 digitaldaemon.com>, Ben Hinkle says...

First, import tells DMD to scan some source file, in some directory.
The symbols in this file are made available to the source program.

Second, import pulls all of those symbols into the current scope.

It does? I thought a symbol in an imported module will only be searched


for
if DMD can't find the symbol in the current scope.

that changed on 0.91 (the start of the stall for my projects)

Here's a little test case with two files, mod1.d and mod2.d: file mod1.d: module mod1; void foo(int x){}; file mod2.d: module mod2; class A{ import mod1; void foo(){}; void bar(){ foo(); } } void main(){}; This compiles fine since foo inside A resolves to A.foo. If bar is changed to void bar(){foo(100);}

This has been discussed before. In some obscure situation (specifically a past mango internal issue), importing mod1.d within the class scope would have caused A.foo() to be hidden completely. Any calls to A.foo() with or without an argument would call the mod1.d foo(). It appears that nobody could actually replicate the problem that mango was experiencing. Small examples such as yours always seem to work as expected.
 then it no longer compiles because mod1.foo is not part of the overload
 resolution for foo inside A. So I'm a bit confused about the statement that
 "import pulls all the symbols into the current scope". I'm not sure what
 "pulls" means. You give a small example of what is going wrong in your code?
 

When it comes to overloading, I believe you are correct. Imported modules are not included in the overload resolution. What he meant about class scope import "pulling" names into the module, I beleive, is this: all method names imported into class scope seem to become part of the classes symbol; by this I mean that all imported functions can actually be called as if they are class methods. An example: class C { import std.random; void func1() {} void func2() {} void func3() {} } void main() { C c = new C; uint = c.rand(); // calls std.rand() } I believe this is what Andy meant by names being "pulled" into the class. And this is why internal imports do the equivalent to a mass alias in this situation.
So import doesn't bring
symbols into the current scope- it just says where to look if the symbol
isn't in the current scope.

No, the imported will overide the locals!

what do you mean by "override"? Do you mean overload (as in function overloading)? Overload resolution happens after the name resolution.

No, not overload. Like I mentioned above, some "big" projects have had issues with the import within the class causing a hiding of method names with the same name as an imported function, no matter what the method signature. That is, using my example above, if class C also defined it's own rand() method, this method would be hidden by the local import's rand() even if the signatures were completely different. Once again it's been hard to demonstrate in a small example what's actually happening in those projects. The small examples always seem to work as expected. I've kind of given up trying to figure it why it sometimes works and sometimes doesn't. And, yes, Walter has explained the rules for name resolution several times. This issue used to be a problem, but it may have changed with new dmd revisions. Ant seems to be still be experiencing it, so maybe it is still lurking in the bigger projects. - John
Aug 25 2004
next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Wed, 25 Aug 2004 15:23:31 -0700, John Reimer 
<brk_6502 NOSP_AM.yahoo.com> wrote:

<snip>

 Here's a little test case with two files, mod1.d and mod2.d:

 file mod1.d:
 module mod1;
 void foo(int x){};

 file mod2.d:
 module mod2;
 class A{
   import mod1;
   void foo(){};
   void bar(){ foo(); }
 }
 void main(){};

 This compiles fine since foo inside A resolves to A.foo. If bar is 
 changed
 to
   void bar(){foo(100);}

This has been discussed before. In some obscure situation (specifically a past mango internal issue), importing mod1.d within the class scope would have caused A.foo() to be hidden completely. Any calls to A.foo() with or without an argument would call the mod1.d foo(). It appears that nobody could actually replicate the problem that mango was experiencing. Small examples such as yours always seem to work as expected.

IIRC it was that the import was overloading a base class method, like 'pause' in threads or 'read' in a buffer class? This small example exhibits that behaviour: --[mod1.d]-- module mod1; void read() { printf("read\n"); } --[mod2.d]-- module mod2; class Base { void read() { printf("Base::read\n"); } } class Child : Base { import mod1; void foo() { read(); } } void main() { Child c = new Child(); c.foo(); } c.foo calls 'read' which calls mod1.read, NOT, mod2.Base.read. <snip> Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 25 2004
next sibling parent reply Ant <duitoolkit yahoo.ca> writes:
On Thu, 26 Aug 2004 11:49:49 +1200, Regan Heath wrote:

 
 This small example exhibits that behaviour:

That shows the same as my original example. Walter confirmed this is the desired behaviour. That's when I decided that D can't be used with anything else but strict 00. Which suit me fine! Ant
Aug 25 2004
next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Wed, 25 Aug 2004 22:05:58 -0400, Ant <duitoolkit yahoo.ca> wrote:
 On Thu, 26 Aug 2004 11:49:49 +1200, Regan Heath wrote:

 This small example exhibits that behaviour:

That shows the same as my original example. Walter confirmed this is the desired behaviour.

Can Walter please re-confim that for me... Walter, Ant is saying that this code: <ben's example> I tried again with file mod1.d: module mod1; void foo(){printf("hello\n");}; file mod2.d: module mod2; class A { import mod1; void foo(){printf("in A\n");}; void bar(){ foo(); } } void main(){ A a = new A; a.bar(); }; and it prints "in A" as I would expect. So it looks like the right one is found. </ben's example> and this code <my example> --[mod1.d]-- module mod1; void read() { printf("read\n"); } --[mod2.d]-- module mod2; class Base { void read() { printf("Base::read\n"); } } class Child : Base { import mod1; void foo() { read(); } } void main() { Child c = new Child(); c.foo(); } c.foo calls 'read' which calls mod1.read, NOT, mod2.Base.read. </my example> Exhibit the desired behaviour? It appears it's the name resolution rules again. In my example it finds the imported symbol before it finds the base class symbol. In ben's it finds the local symbol before the imported symbol. I believe Ant desires that the base symbol would be found before the imported symbol. Are imports supposed to overload (correct term?) class methods? If so, why doesn't it overload in bens example?
 That's when I decided that D can't be used
 with anything else but strict 00. Which suit me fine!

I've not given up on this yet.. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 25 2004
next sibling parent reply Ant <duitoolkit yahoo.ca> writes:
On Thu, 26 Aug 2004 14:28:32 +1200, Regan Heath wrote:

 On Wed, 25 Aug 2004 22:05:58 -0400, Ant <duitoolkit yahoo.ca> wrote:
 On Thu, 26 Aug 2004 11:49:49 +1200, Regan Heath wrote:

 This small example exhibits that behaviour:

That shows the same as my original example. Walter confirmed this is the desired behaviour.

Can Walter please re-confim that for me...

I knew my reputation was low, but... ;) follow the link I provided for the bugs group until; " The idea of name lookup happening, *then* overload resolution, operates the same as in C++. It's a chicken-and-egg problem to try to do it based on type signatures because of implicit conversions. " Ant
Aug 25 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Wed, 25 Aug 2004 22:41:10 -0400, Ant <duitoolkit yahoo.ca> wrote:
 On Thu, 26 Aug 2004 14:28:32 +1200, Regan Heath wrote:

 On Wed, 25 Aug 2004 22:05:58 -0400, Ant <duitoolkit yahoo.ca> wrote:
 On Thu, 26 Aug 2004 11:49:49 +1200, Regan Heath wrote:

 This small example exhibits that behaviour:

That shows the same as my original example. Walter confirmed this is the desired behaviour.

Can Walter please re-confim that for me...

I knew my reputation was low, but... ;) follow the link I provided for the bugs group until; " The idea of name lookup happening, *then* overload resolution, operates the same as in C++. It's a chicken-and-egg problem to try to do it based on type signatures because of implicit conversions. "

Yeah.. I remember those discussions.. I don't think the statement above is 100% to do with this particular example because there is no implicit conversion going on. Instead, it simply appears to pick the imported 'read' symbol in favour of the base class 'read' (which hasn't been overloaded in the child). If you _do_ overload the base 'read' in child then it gets it right, presumably for the same reason as in bens example. The import drags the symbols into the current scope, so the imported 'read' is technically overloading the base class 'read'. BUT. why then doesn't this cause an error when the current scope already has a read symbol? (as in bens example) Something is just not quite right. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 25 2004
next sibling parent Regan Heath <regan netwin.co.nz> writes:
I have gone one step further in this problem, this code...

--[mod1.d]--
module mod1;

void read() {
   printf("read\n");
}

--[mod2.d]--
module mod2;

class Base {
   final void read() {
     printf("Base::read\n");
   }
}

class Child : Base {
   import mod1;

/*  void read() {
     printf("Child::read\n");
   }*/

   void foo() {
     read();
   }
}

void main()
{
   Child c = new Child();
   c.foo();
}

compiles, runs and prints "read".

so the import overloads the 'final' read class from the Base class.
Uncommenting the 'read' in the Child causes the expected compile error.

Regan

On Thu, 26 Aug 2004 14:57:31 +1200, Regan Heath <regan netwin.co.nz> wrote:

 On Wed, 25 Aug 2004 22:41:10 -0400, Ant <duitoolkit yahoo.ca> wrote:
 On Thu, 26 Aug 2004 14:28:32 +1200, Regan Heath wrote:

 On Wed, 25 Aug 2004 22:05:58 -0400, Ant <duitoolkit yahoo.ca> wrote:
 On Thu, 26 Aug 2004 11:49:49 +1200, Regan Heath wrote:

 This small example exhibits that behaviour:

That shows the same as my original example. Walter confirmed this is the desired behaviour.

Can Walter please re-confim that for me...

I knew my reputation was low, but... ;) follow the link I provided for the bugs group until; " The idea of name lookup happening, *then* overload resolution, operates the same as in C++. It's a chicken-and-egg problem to try to do it based on type signatures because of implicit conversions. "

Yeah.. I remember those discussions.. I don't think the statement above is 100% to do with this particular example because there is no implicit conversion going on. Instead, it simply appears to pick the imported 'read' symbol in favour of the base class 'read' (which hasn't been overloaded in the child). If you _do_ overload the base 'read' in child then it gets it right, presumably for the same reason as in bens example. The import drags the symbols into the current scope, so the imported 'read' is technically overloading the base class 'read'. BUT. why then doesn't this cause an error when the current scope already has a read symbol? (as in bens example) Something is just not quite right. Regan

-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 25 2004
prev sibling parent reply John Reimer <brk_6502 NOSP_AM.yahoo.com> writes:
Yes, that does describe the issue quite succintly.  The non-overriden 
read from the base class is hidden by the import statement.  It's funny 
I could never work up an example that showed this.  Good to know!
Aug 25 2004
parent "antiAlias" <fu bar.com> writes:
"John Reimer" <brk_6502 NOSP_AM.yahoo.com> wrote in message
news:cgjpu1$2u4u$1 digitaldaemon.com...
 Yes, that does describe the issue quite succintly.  The non-overriden
 read from the base class is hidden by the import statement.  It's funny
 I could never work up an example that showed this.  Good to know!

Right. And as was pointed out in the past, A D programmer would be expected to 'alias' the base-class method into the current scope so that it gets picked up for the argument-matching phase ... because it's "not quite visible enough" as a superclass method. Apparently, this path is that of the enlightened and the chosen-few.
Aug 25 2004
prev sibling parent reply Ben Hinkle <bhinkle4 juno.com> writes:
Regan Heath wrote:

 On Wed, 25 Aug 2004 22:05:58 -0400, Ant <duitoolkit yahoo.ca> wrote:
 On Thu, 26 Aug 2004 11:49:49 +1200, Regan Heath wrote:

 This small example exhibits that behaviour:

That shows the same as my original example. Walter confirmed this is the desired behaviour.

Can Walter please re-confim that for me... Walter, Ant is saying that this code: <ben's example> I tried again with file mod1.d: module mod1; void foo(){printf("hello\n");}; file mod2.d: module mod2; class A { import mod1; void foo(){printf("in A\n");}; void bar(){ foo(); } } void main(){ A a = new A; a.bar(); }; and it prints "in A" as I would expect. So it looks like the right one is found. </ben's example> and this code <my example> --[mod1.d]-- module mod1; void read() { printf("read\n"); } --[mod2.d]-- module mod2; class Base { void read() { printf("Base::read\n"); } } class Child : Base { import mod1; void foo() { read(); } } void main() { Child c = new Child(); c.foo(); } c.foo calls 'read' which calls mod1.read, NOT, mod2.Base.read. </my example> Exhibit the desired behaviour? It appears it's the name resolution rules again. In my example it finds the imported symbol before it finds the base class symbol. In ben's it finds the local symbol before the imported symbol.

I can't find the message now but a while ago Walter listed the steps involved in name lookup and it went a little something like this: - symbols in current scope - symbols in imports in current scope - symbols in base classes - repeat with next outer scope The function search() in files src/dmd/class.c, dsymbol.c and scope.d probably are where the logic lies. Basically look at Scope::search, ScopeDsymbol::search and ClassDeclaration::search. I don't know if Walter really wanted that behavior or if it just does what it does without having strong language reasons why imports take precedence over superclasses. It does seem a little wierd that imports are searched before superclasses - maybe that's why Walter discourages them.
 I believe Ant desires that the base symbol would be found before the
 imported symbol.
 
 Are imports supposed to overload (correct term?) class methods? If so, why
 doesn't it overload in bens example?
 
 That's when I decided that D can't be used
 with anything else but strict 00. Which suit me fine!

I've not given up on this yet.. Regan

Aug 25 2004
parent J C Calvarese <jcc7 cox.net> writes:
Ben Hinkle wrote:
 Regan Heath wrote:
 

It appears it's the name resolution rules again. In my example it finds
the imported symbol before it finds the base class symbol. In ben's it
finds the local symbol before the imported symbol.

I can't find the message now but a while ago Walter listed the steps

I think I tracked it down: digitalmars.D/6978 <quote> How name lookup happens in a scope is a multi-stage process, each proceeding to the next if the name is not found in the current stage: 1) look for a member with the name 2) look in any imports *in this scope* 3) if current scope is a class scope, recursively look in base classes 4) repeat the process with the most enclosing scope I think it would be very strange to have base class symbols override imports in the current scope, i.e. if imports were looked up in some other scope than the one in which they were imported. </quote>
 involved in name lookup and it went a little something like this:
 - symbols in current scope
 - symbols in imports in current scope
 - symbols in base classes
 - repeat with next outer scope
 
 The function search() in files src/dmd/class.c, dsymbol.c and scope.d
 probably are where the logic lies. Basically look at Scope::search,
 ScopeDsymbol::search and ClassDeclaration::search. I don't know if Walter
 really wanted that behavior or if it just does what it does without having
 strong language reasons why imports take precedence over superclasses. It
 does seem a little wierd that imports are searched before superclasses -
 maybe that's why Walter discourages them.

-- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Aug 25 2004
prev sibling parent reply Andy Friesen <andy ikagames.com> writes:
Ant wrote:
 On Thu, 26 Aug 2004 11:49:49 +1200, Regan Heath wrote:
 
 
This small example exhibits that behaviour:

That shows the same as my original example. Walter confirmed this is the desired behaviour. That's when I decided that D can't be used with anything else but strict 00. Which suit me fine!

I've never had any problems before. I just keep imports private and at the module level. Everything works exactly as I expect it. Also, what's "strict OO"? -- andy
Aug 25 2004
parent Ant <duitoolkit yahoo.ca> writes:
On Wed, 25 Aug 2004 20:32:16 -0700, Andy Friesen wrote:

 Ant wrote:
 On Thu, 26 Aug 2004 11:49:49 +1200, Regan Heath wrote:
 
 
This small example exhibits that behaviour:

That shows the same as my original example. Walter confirmed this is the desired behaviour. That's when I decided that D can't be used with anything else but strict 00. Which suit me fine!

I've never had any problems before.

are you kiding? I've never NOT had any problems before.
 I just keep imports private and at 
 the module level.

tried that, didn't work.
  Everything works exactly as I expect it.

lucky
 
 Also, what's "strict OO"?

just my way of saying NO to global/free/independent functions. well, my original idea is completly lost on this thread... Ant
Aug 25 2004
prev sibling parent reply John Reimer <brk_6502 NOSP_AM.yahoo.com> writes:
 
 IIRC it was that the import was overloading a base class method, like 
 'pause' in threads or 'read' in a buffer class?
 
 This small example exhibits that behaviour:
 --[mod1.d]--
 module mod1;
 
 void read() {
   printf("read\n");
 }
 
 --[mod2.d]--
 module mod2;
 
 class Base {
   void read() {
     printf("Base::read\n");
   }
 }
 
 class Child : Base {
   import mod1;
 
   void foo() {
     read();
   }
 }
 
 void main()
 {
   Child c = new Child();
   c.foo();
 }
 
 c.foo calls 'read' which calls mod1.read, NOT, mod2.Base.read.
 
 <snip>
 
 Regan
 

Ah yes! That was the example I was looking for. It seems I forgot the exact nature of the issue. Thanks for pointing that out. The issue must still exists then.
Aug 25 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Wed, 25 Aug 2004 21:39:04 -0700, John Reimer 
<brk_6502 NOSP_AM.yahoo.com> wrote:

 IIRC it was that the import was overloading a base class method, like 
 'pause' in threads or 'read' in a buffer class?

 This small example exhibits that behaviour:
 --[mod1.d]--
 module mod1;

 void read() {
   printf("read\n");
 }

 --[mod2.d]--
 module mod2;

 class Base {
   void read() {
     printf("Base::read\n");
   }
 }

 class Child : Base {
   import mod1;

   void foo() {
     read();
   }
 }

 void main()
 {
   Child c = new Child();
   c.foo();
 }

 c.foo calls 'read' which calls mod1.read, NOT, mod2.Base.read.

 <snip>

 Regan

Ah yes! That was the example I was looking for. It seems I forgot the exact nature of the issue. Thanks for pointing that out. The issue must still exists then.

Yes, it's the intended behaviour: <quote> How name lookup happens in a scope is a multi-stage process, each proceeding to the next if the name is not found in the current stage: 1) look for a member with the name 2) look in any imports *in this scope* 3) if current scope is a class scope, recursively look in base classes 4) repeat the process with the most enclosing scope I think it would be very strange to have base class symbols override imports in the current scope, i.e. if imports were looked up in some other scope than the one in which they were imported. </quote> Why is why Walter discourages import inside a class. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 25 2004
parent reply "antiAlias" <fu bar.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote ...
 Why [sic] is why Walter discourages import inside a class.

Well; you forget that he once encouraged them. That aside, if Walter believes that inner-imports cause name-resolution problems then perhaps he should fix it? Suggestions: a) change the resolution rules with respect to inner imports. b) change the method-name resolution rules. There's so many ways in which that is broken, or special-case'd. AJ's example with opCmp() would have been truly hilarious were the consequences not so sad. c) make inner imports illegal. d) leave everything just as it is. Q: how does one do an emoticon for the "bird" ?
Aug 25 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Wed, 25 Aug 2004 22:31:36 -0700, antiAlias <fu bar.com> wrote:

 "Regan Heath" <regan netwin.co.nz> wrote ...
 Why [sic] is why Walter discourages import inside a class.

Well; you forget that he once encouraged them.

Yes.. I did. I suspect it was more a case of the first soln that came to mind, which appeared to work at the time.
 That aside, if Walter
 believes that inner-imports cause name-resolution problems then perhaps 
 he
 should fix it? Suggestions:

 a) change the resolution rules with respect to inner imports.

I think any special-case stuff should be avoided where possible.. I'm not saying we don't consider adding a special-case but the benefit aquired needs to be quite decent.
 b) change the method-name resolution rules. There's so many ways in which
 that is broken, or special-case'd. AJ's example with opCmp() would have 
 been truly hilarious were the consequences not so sad.

I say, collate these examples, and the ones against changing (the bug caused by the change you want mentioned in the other thread) allow anyone to submit to the list, then present the list to Walter. Only by weight of evidence will you change his mind, I suspect.
 c) make inner imports illegal.

This is the most likely course, given everything I know and have assumed about this topic.
 d) leave everything just as it is.  Q: how does one do an emoticon for 
 the "bird" ?

No idea.. how bout: /´¯/) ,/¯ / / / /´¯/' '/´¯¯`·¸ /'/ / / /¨¯\ ('( ´ ´ ¯~/' ') \ ' / '' \ _ ·´ \ ( \ \ <g> Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 26 2004
parent reply "antiAlias" <fu bar.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote
 d) leave everything just as it is.  Q: how does one do an emoticon for
 the "bird" ?

No idea.. how bout: //) ,/ / / / //' '/` /'/ / / /\ ('( ~/' ') \ ' / '' \ _ \ ( \ \ <g>

Hey! Nice work, man :-)
Aug 26 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Thu, 26 Aug 2004 17:40:50 -0700, antiAlias <fu bar.com> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote
 d) leave everything just as it is.  Q: how does one do an emoticon for
 the "bird" ?

No idea.. how bout: /´¯/) ,/¯ / / / /´¯/' '/´¯¯`·¸ /'/ / / /¨¯\ ('( ´ ´ ¯~/' ') \ ' / '' \ _ ·´ \ ( \ \ <g>

Hey! Nice work, man :-)

I can't claim credit for it. Someone sent it to me at some stage in the past, I just kept it for those 'special' occasions. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 26 2004
parent Ilya Minkov <minkov cs.tum.edu> writes:
Regan Heath schrieb:

 Hey! Nice work, man :-)

I can't claim credit for it. Someone sent it to me at some stage in the past, I just kept it for those 'special' occasions. Regan

Looke like an "ohase was there". And mind you, you don't want to get to know ohase. He is paranoid and terorrizes people on the net all the time. But don't worry, we are no our way to get his real name and adress. :) -eye
Aug 30 2004
prev sibling parent John Reimer <brk_6502 NOSP_AM.yahoo.com> writes:
John Reimer wrote:
 ... all method names imported into class scope seem to become part of 
 the classes symbol; by this I mean that all imported functions can 
 actually be called as if they are class methods. An example:

I must be half asleep... I meant "class symbol list."
 class C {
 import std.random;
 void func1() {}
 void func2() {}
 void func3() {}
 }
 
 void main() {
   C c = new C;
   uint = c.rand();    // calls std.rand()
 }
 

and here the line: uint = c.rand(); // calls std.rand() should have been: uint i = c.rand(); // calls std.rand) Just had to correct these. I couldn't stand reading my mistakes. :-P
Aug 26 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Ben Hinkle" <bhinkle mathworks.com> wrote in message
news:cgil87$2cn3$1 digitaldaemon.com...
 First, import tells DMD to scan some source file, in some directory.
 The symbols in this file are made available to the source program.

 Second, import pulls all of those symbols into the current scope.

It does? I thought a symbol in an imported module will only be searched

 if DMD can't find the symbol in the current scope. So import doesn't bring
 symbols into the current scope- it just says where to look if the symbol
 isn't in the current scope. Alias defines a new symbol in the current

That's true. But the import will be searched before the base class, and before the other symbols outside the class. This is usually not what was intended.
Aug 26 2004
parent "antiAlias" <fu bar.com> writes:
"Walter" <newshound digitalmars.com> wrote
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message
 news:cgil87$2cn3$1 digitaldaemon.com...
 First, import tells DMD to scan some source file, in some directory.
 The symbols in this file are made available to the source program.

 Second, import pulls all of those symbols into the current scope.

It does? I thought a symbol in an imported module will only be searched

 if DMD can't find the symbol in the current scope. So import doesn't


 symbols into the current scope- it just says where to look if the symbol
 isn't in the current scope. Alias defines a new symbol in the current

That's true. But the import will be searched before the base class, and before the other symbols outside the class. This is usually not what was intended.

Does that "usually not what was intended" aspect not ring any alarm bells?
Aug 26 2004
prev sibling parent reply Ant <Ant_member pathlink.com> writes:
In article <cgid2l$28fg$1 digitaldaemon.com>, Andy Friesen says...
The second of these behaviours sounds suspiciously like a mass-alias to 
me.  Such a thing would be useful in its own right, and it would be a 
good thing to separate the two concepts into distinct statements. ie

     import std.string; // std.string is added to the known scopes
     alias std.string.*;// alias all of std.string into the present scope

(alias is evil) maybe that could be done on the import: import std.string; // std.string is added to the known scopes import std.string.*;// all of std.string into the present scope (not to be mistaken for import std.*;) Ant
Aug 25 2004
next sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Ant schrieb:
 (alias is evil)

It might also impose a parsing problem - 1 vs 2 arguments depending on a type of the alias.
 maybe that could be done on the import:
 
 import std.string; // std.string is added to the known scopes
 import std.string.*;// all of std.string into the present scope
 
 (not to be mistaken for import std.*;)

yup, makes sense to me. But i would think that usually it's more comfy to replace the long scope name by a short one: import std.string as sstr; or even multiple such statements to put many imports into the same scope. perhaps this could also be done with a scope alias afterwards, but "as" seems more descriptive to me. this may be stupid example but with longer hierarchies it would really matter.
Aug 25 2004
parent reply Ant <Ant_member pathlink.com> writes:
In article <cgiqie$2fa3$1 digitaldaemon.com>, Ilya Minkov says...
Ant schrieb:
 
 import std.string; // std.string is added to the known scopes
 import std.string.*;// all of std.string into the present scope
 
 (not to be mistaken for import std.*;)

yup, makes sense to me. But i would think that usually it's more comfy to replace the long scope name by a short one: import std.string as sstr;

I suggested this a long time ago. I added that the "std.string" should no longer be valid on this scope. (I think I was inspired by Oberon) but I'm not sure anymore, it's a diskised alias. Ant
Aug 25 2004
parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Ant schrieb:
 I suggested this a long time ago.
 I added that the "std.string" should no longer be valid on this scope.
 (I think I was inspired by Oberon)
 
 but I'm not sure anymore, it's a diskised alias.

It is a better documented alias. Besides, it would hide the symbols from the current scope. So what's wrong? What do you have against alias anyway? (not that the D scoping difficulties would not exist, but just saying "i'm against alias" is a plain stupid position) BTW, this would also make sense: import std.c.stdio, std.c.stdlib as stdc; and all modules imported with this statement would be in one namespace stdc, which makes sense when they are related. The opposite, namely that only the last one would get namespaced, would only be confusing. Besides, this allows you to save a few rows of alias statements. -eye
Aug 26 2004
parent Ilya Minkov <minkov cs.tum.edu> writes:
Ilya Minkov schrieb:
 import std.c.stdio, std.c.stdlib as stdc;

Alternative evil wordy syntax could be: alias private import std.c.stdio, std.c.stdlib; stdc; Something ugly that already works: --- 8< --- struct cbase{ import std.c.stdlib, std.c.stdio; } int main(){ cbase.printf("%d is a nice number", cbase.rand()); return 0; } --- >8 --- -eye
Aug 26 2004
prev sibling parent reply Andy Friesen <andy ikagames.com> writes:
Ant wrote:
 In article <cgid2l$28fg$1 digitaldaemon.com>, Andy Friesen says...
 
The second of these behaviours sounds suspiciously like a mass-alias to 
me.  Such a thing would be useful in its own right, and it would be a 
good thing to separate the two concepts into distinct statements. ie

    import std.string; // std.string is added to the known scopes
    alias std.string.*;// alias all of std.string into the present scope

(alias is evil)

Why?
 maybe that could be done on the import:
 
 import std.string; // std.string is added to the known scopes
 import std.string.*;// all of std.string into the present scope

It's still an alias, whether you use the 'alias' keyword or not. -- andy
Aug 25 2004
parent reply Ant <Ant_member pathlink.com> writes:
In article <cgj2dr$2j1i$1 digitaldaemon.com>, Andy Friesen says...
Ant wrote:
 In article <cgid2l$28fg$1 digitaldaemon.com>, Andy Friesen says...
 
The second of these behaviours sounds suspiciously like a mass-alias to 
me.  Such a thing would be useful in its own right, and it would be a 
good thing to separate the two concepts into distinct statements. ie

    import std.string; // std.string is added to the known scopes
    alias std.string.*;// alias all of std.string into the present scope

(alias is evil)

Why?

because you'll end up with more then one designation for the same entity. entropy doesn't need the programmer's help, it will grow by it self. (but I'm afraid it's a necessary evil)
 maybe that could be done on the import:
 
 import std.string; // std.string is added to the known scopes
 import std.string.*;// all of std.string into the present scope

It's still an alias, whether you use the 'alias' keyword or not.

sure (see my other post on this thread) but at least we get rid of the token... it's not necessary here. Ant
Aug 25 2004
parent reply Andy Friesen <andy ikagames.com> writes:
Ant wrote:
maybe that could be done on the import:

import std.string; // std.string is added to the known scopes
import std.string.*;// all of std.string into the present scope

It's still an alias, whether you use the 'alias' keyword or not.

sure (see my other post on this thread) but at least we get rid of the token... it's not necessary here.

I think it is necessary. Something that behaves like an alias really should look like one. "Explicit is better than implicit." -- The Zen of Python, by Tim Peters -- andy
Aug 25 2004
parent Peter Prohaska <pitrp wg78.de> writes:
On Wed, 25 Aug 2004 16:30:38 -0700, Andy Friesen wrote:

 Ant wrote:
maybe that could be done on the import:

import std.string; // std.string is added to the known scopes
import std.string.*;// all of std.string into the present scope

It's still an alias, whether you use the 'alias' keyword or not.

sure (see my other post on this thread) but at least we get rid of the token... it's not necessary here.

I think it is necessary. Something that behaves like an alias really should look like one. "Explicit is better than implicit." -- The Zen of Python, by Tim Peters

And here we go... alias x.y.* /* to what? */ In this case i would vote for complete python aliasing and using "from x import y" because that makes the operation even more explicit :) peter.
Aug 26 2004
prev sibling parent "Walter" <newshound digitalmars.com> writes:
"Ant" <Ant_member pathlink.com> wrote in message
news:cgi9sa$2715$1 digitaldaemon.com...
 Why shouldn't it be supported, unless if difficult to maintain?
 On OO coding I'm going to use the imported symbols only on inside the body

 the class so it makes perfect sence that the import is declared
 inside the class body. People just aren't use to it. I don't see this
 has an hack to avoid other problems but as the logic scope to insert
 the import decalration.
 Java doesn't need this because (almost) nothing else goes outside class

 when declared inside the class body the simbols should
 be available only to subclasses (unless they are private...).

 So who's with me to try to convince Walter to continue to support
 import declarations inside the class body?

They are supported. What happens, though, is confusion about how symbol lookup rules work with modules, for example, the names in an imported module will then override names in the base class.
Aug 26 2004