import from subdir

Jonathan M Davis jmdavisProg at gmx.com
Thu Dec 23 17:25:54 PST 2010


On Thursday 23 December 2010 16:42:15 spir wrote:
> On Thu, 23 Dec 2010 12:54:42 -0800
> 
> Jonathan M Davis <jmdavisProg at gmx.com> wrote:
> > What you're trying to do is pretty abnormal really, as far as your
> > average module goes. I assume that you're writing a test app which needs
> > access to the main body of code and are trying to find a way to point it
> > to that code without mixing the two.
> 
> What is then abnormal in having test modules in their own dir? And indeed
> they need to import the module(s) they're supposed to test (and possibly
> ordinary and test data from another dir). AFAIK, this is very ordinary lib
> structuration for the sake of clarity. Dunno.

What is abnormal is having your test code rely where your normal code is on 
disk. Also, depending on what you're doing for testing, normally you'd just have 
the unit tests alongside your normal code and do a unittest build to test your 
code. So, you wouldn't even need separate test code unless you're doing 
something more exotic that you don't want in your unit tests.

> > The normal way to deal with that would be -I. The same goes for
> > C++ actually. Not to mention, you probably don't want your tests to rely
> > on where they are on disk in comparison to the rest of your code. If you
> > later want to change where you put your test code, it could be a big
> > hassle to have to go change all of your imports. Just use -I. It makes
> > your test code properly portable and is really the intended way to do
> > the sort of thing that you're trying to do.
> 
> Hem, I do not find a hassle to change one a few import once if ever I move
> a test module in the dir tree. But I find very unconvenient to have
> different compile/link command lines for every module just because of the
> lack of an importing syntax, requiring the use of -I. Instead of a
> command-line option, I would prefere to write it down once and for in the
> module itself. Maybe we could have something like pathlevel 2;
> saying that (when an imported module is not found) the indicated path is to
> be understood as relative to 2 dir levels higher (which would probably be
> the root of the lib).
> 
> By the way, when I write "import data.foo", the language actually searches
> and inside /data (relative to the current module's dir) and find foo.d
> there. (Even if the module is not explicitely named at all.) So, there is
> still an implicite or default relationship between dir tree structure and
> module denomination. Or do I misinterpret your words?

You misunderstand. From the module's perspective, import foo.bar; imports a 
module with the name foo.bar. It knows that bar is in the foo package, so unless 
the module doing the importing is in the foo package, it can't access the 
package-restricted functions and types from foo.bar or any other module in foo. 
It knows that bar is the module. But it doesn't care at all about what that 
means for files on disk. Consider the fact that you can have this directory 
structure:

dir/dir1/foo/bar.d
dir/dir2/dir3/hello/world.d
dir/dir2/dir3/foo/silly.d

where you're compiling from dir/dir2/dir3 and have -I../../dir1/. bar.d and 
silly.d are considered to be in the same package in spite of the fact that the 
fact that they're in different directories. When hello.world imports foo.bar, it 
doesn't care that it's not in the same directory as foo.silly. If foo.silly 
calls a package-restricted function in foo.bar, it's allowed to because they're 
in the same package, but it doesn't care that they're not in the same directory.

The directory structure relates to the package hierarchy. The compiler finds files 
using that structure/hierarchy. It knows that if a module is importing foo.bar, 
that there is a directory foo either in  the directory where compilation is 
taking place or in one of the directories given by the -I flag, and it knows that 
bar.d (or bar.di) will be in the foo directory. If there are multiple such 
directories (because of the -I flag being used), then it knows that bar.d is in 
one of them (if it were in more than one, then there would be an ambiguity 
error). The package hiercharcy tells the compiler where the source files are.

However, the imports themselves don't care at all about the directory structure. 
As shown in the example above, you could have each module in a package in a 
different directory as long as it was in the appropriate place in the directory 
structure given all of the -I flags being used. So, importing has no concept of 
directories or files - only packages and modules. The compiler is able to 
translate that to directories and files, but the imports don't care about it. 
From the language's perspective, it would be perfectly possible to change it so 
that all files were always in the same directory but used dots to separate 
packages and modules:

dir/dir1/foo.bar.d
dir/dir2/dir3/hello.world.d
dir/dir2/dir3/foo.silly.d

Now, no compiler is going to function that way, but conceptually, it could. So, 
trying to use .. and the like in an import statement to walk directory structure 
doesn't really make sense.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list